1use std::num::NonZeroU32;
2use std::ops::Range;
34/// Raw postgres value as received from the database
5#[derive(Clone, Copy)]
6#[allow(missing_debug_implementations)]
7#[cfg(feature = "postgres_backend")]
8pub struct PgValue<'a> {
9 raw_value: &'a [u8],
10 type_oid_lookup: &'a dyn TypeOidLookup,
11}
1213/// This is a helper trait to defer a type oid
14/// lookup to a later point in time
15///
16/// This is mainly used in the `PgConnection`
17/// implementation so that we do not need to call
18/// into libpq if we do not need the type oid.
19///
20/// Backend implementations based on pure rustc
21/// database connection crates can likely reuse
22/// the implementation for `NonZeroU32` here instead
23/// of providing their own custom implementation
24#[cfg_attr(
25 docsrs,
26 doc(cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))
27)]
28#[allow(unreachable_pub)]
29pub trait TypeOidLookup {
30/// Lookup the type oid for the current value
31fn lookup(&self) -> NonZeroU32;
32}
3334impl<F> TypeOidLookup for F
35where
36F: Fn() -> NonZeroU32,
37{
38fn lookup(&self) -> NonZeroU32 {
39 (self)()
40 }
41}
4243impl TypeOidLookup for PgValue<'_> {
44fn lookup(&self) -> NonZeroU32 {
45self.type_oid_lookup.lookup()
46 }
47}
4849impl TypeOidLookup for NonZeroU32 {
50fn lookup(&self) -> NonZeroU32 {
51*self
52}
53}
5455impl<'a> PgValue<'a> {
56#[cfg(test)]
57pub(crate) fn for_test(raw_value: &'a [u8]) -> Self {
58#[allow(unsafe_code)] // that's actual safe
59static FAKE_OID: NonZeroU32 = unsafe {
60// 42 != 0, so this is actually safe
61NonZeroU32::new_unchecked(42)
62 };
63Self {
64 raw_value,
65 type_oid_lookup: &FAKE_OID,
66 }
67 }
6869/// Create a new instance of `PgValue` based on a byte buffer
70 /// and a way to receive information about the type of the value
71 /// represented by the buffer
72#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
73pub fn new(raw_value: &'a [u8], type_oid_lookup: &'a dyn TypeOidLookup) -> Self {
74Self::new_internal(raw_value, type_oid_lookup)
75 }
7677pub(in crate::pg) fn new_internal(
78 raw_value: &'a [u8],
79 type_oid_lookup: &'a dyn TypeOidLookup,
80 ) -> Self {
81Self {
82 raw_value,
83 type_oid_lookup,
84 }
85 }
8687/// Get the underlying raw byte representation
88pub fn as_bytes(&self) -> &[u8] {
89self.raw_value
90 }
9192/// Get the type oid of this value
93pub fn get_oid(&self) -> NonZeroU32 {
94self.type_oid_lookup.lookup()
95 }
9697pub(crate) fn subslice(&self, range: Range<usize>) -> Self {
98Self {
99 raw_value: &self.raw_value[range],
100 ..*self
101}
102 }
103}