sqlx_core_oldapi/postgres/
value.rs

1use crate::error::{BoxDynError, UnexpectedNullError};
2use crate::postgres::{PgTypeInfo, Postgres};
3use crate::value::{Value, ValueRef};
4use bytes::{Buf, Bytes};
5use std::borrow::Cow;
6use std::str::from_utf8;
7
8#[derive(Debug, Clone, Copy, Eq, PartialEq)]
9#[repr(u8)]
10pub enum PgValueFormat {
11    Text = 0,
12    Binary = 1,
13}
14
15/// Implementation of [`ValueRef`] for PostgreSQL.
16#[derive(Clone)]
17pub struct PgValueRef<'r> {
18    pub(crate) value: Option<&'r [u8]>,
19    pub(crate) row: Option<&'r Bytes>,
20    pub(crate) type_info: PgTypeInfo,
21    pub(crate) format: PgValueFormat,
22}
23
24/// Implementation of [`Value`] for PostgreSQL.
25#[derive(Clone)]
26pub struct PgValue {
27    pub(crate) value: Option<Bytes>,
28    pub(crate) type_info: PgTypeInfo,
29    pub(crate) format: PgValueFormat,
30}
31
32impl<'r> PgValueRef<'r> {
33    pub(crate) fn get(buf: &mut &'r [u8], format: PgValueFormat, type_info: PgTypeInfo) -> Self {
34        if let Ok(element_len) = usize::try_from(buf.get_i32()) {
35            let value = Some(&buf[..(element_len)]);
36            buf.advance(element_len);
37            PgValueRef {
38                value,
39                row: None,
40                type_info,
41                format,
42            }
43        } else {
44            PgValueRef {
45                value: None,
46                row: None,
47                type_info,
48                format,
49            }
50        }
51    }
52
53    pub fn format(&self) -> PgValueFormat {
54        self.format
55    }
56
57    pub fn as_bytes(&self) -> Result<&'r [u8], BoxDynError> {
58        match &self.value {
59            Some(v) => Ok(v),
60            None => Err(UnexpectedNullError.into()),
61        }
62    }
63
64    pub fn as_str(&self) -> Result<&'r str, BoxDynError> {
65        Ok(from_utf8(self.as_bytes()?)?)
66    }
67}
68
69impl Value for PgValue {
70    type Database = Postgres;
71
72    #[inline]
73    fn as_ref(&self) -> PgValueRef<'_> {
74        PgValueRef {
75            value: self.value.as_deref(),
76            row: None,
77            type_info: self.type_info.clone(),
78            format: self.format,
79        }
80    }
81
82    fn type_info(&self) -> Cow<'_, PgTypeInfo> {
83        Cow::Borrowed(&self.type_info)
84    }
85
86    fn is_null(&self) -> bool {
87        self.value.is_none()
88    }
89}
90
91impl<'r> ValueRef<'r> for PgValueRef<'r> {
92    type Database = Postgres;
93
94    fn to_owned(&self) -> PgValue {
95        let value = match (self.row, self.value) {
96            (Some(row), Some(value)) => Some(row.slice_ref(value)),
97
98            (None, Some(value)) => Some(Bytes::copy_from_slice(value)),
99
100            _ => None,
101        };
102
103        PgValue {
104            value,
105            format: self.format,
106            type_info: self.type_info.clone(),
107        }
108    }
109
110    fn type_info(&self) -> Cow<'_, PgTypeInfo> {
111        Cow::Borrowed(&self.type_info)
112    }
113
114    fn is_null(&self) -> bool {
115        self.value.is_none()
116    }
117}
118
119#[cfg(feature = "any")]
120impl<'r> From<PgValueRef<'r>> for crate::any::AnyValueRef<'r> {
121    #[inline]
122    fn from(value: PgValueRef<'r>) -> Self {
123        crate::any::AnyValueRef {
124            type_info: value.type_info.clone().into(),
125            kind: crate::any::value::AnyValueRefKind::Postgres(value),
126        }
127    }
128}
129
130#[cfg(feature = "any")]
131impl From<PgValue> for crate::any::AnyValue {
132    #[inline]
133    fn from(value: PgValue) -> Self {
134        crate::any::AnyValue {
135            type_info: value.type_info.clone().into(),
136            kind: crate::any::value::AnyValueKind::Postgres(value),
137        }
138    }
139}