sqlx_build_trust_postgres/
value.rs

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