Skip to main content

rbdc_pg/
value.rs

1use crate::type_info::PgTypeInfo;
2use bytes::Buf;
3use rbdc::Error;
4use std::borrow::Cow;
5use std::str::from_utf8;
6
7#[derive(Debug, Clone, Copy, Eq, PartialEq)]
8#[repr(u8)]
9pub enum PgValueFormat {
10    Text = 0,
11    Binary = 1,
12}
13
14/// Implementation of [`ValueRef`] for PostgreSQL.
15#[derive(Clone)]
16pub struct PgValueRef<'r> {
17    pub value: Option<&'r [u8]>,
18    pub type_info: PgTypeInfo,
19    pub format: PgValueFormat,
20    /// Session timezone offset in seconds from UTC, used for TIMESTAMPTZ decoding
21    pub timezone_sec: Option<i32>,
22}
23
24/// Implementation of [`Value`] for PostgreSQL.
25#[derive(Clone)]
26pub struct PgValue {
27    pub value: Option<Vec<u8>>,
28    pub type_info: PgTypeInfo,
29    pub format: PgValueFormat,
30    /// Session timezone offset in seconds from UTC, used for TIMESTAMPTZ decoding
31    pub timezone_sec: Option<i32>,
32}
33
34impl<'r> PgValueRef<'r> {
35    pub(crate) fn get(
36        buf: &mut &'r [u8],
37        format: PgValueFormat,
38        ty: PgTypeInfo,
39        timezone_sec: Option<i32>,
40    ) -> Self {
41        let mut element_len = buf.get_i32();
42
43        let element_val = if element_len == -1 {
44            element_len = 0;
45            None
46        } else {
47            Some(&buf[..(element_len as usize)])
48        };
49
50        buf.advance(element_len as usize);
51
52        PgValueRef {
53            value: element_val,
54            type_info: ty,
55            format,
56            timezone_sec,
57        }
58    }
59
60    pub fn format(&self) -> PgValueFormat {
61        self.format
62    }
63
64    pub fn as_bytes(&self) -> Result<&'r [u8], Error> {
65        match &self.value {
66            Some(v) => Ok(v),
67            None => Err(Error::from("UnexpectedNullError")),
68        }
69    }
70
71    pub fn as_str(&self) -> Result<&'r str, Error> {
72        Ok(from_utf8(self.as_bytes()?)?)
73    }
74}
75
76impl PgValue {
77    pub fn get(
78        buf: &mut &[u8],
79        format: PgValueFormat,
80        ty: PgTypeInfo,
81        timezone_sec: Option<i32>,
82    ) -> Self {
83        let mut element_len = buf.get_i32();
84
85        let element_val = if element_len == -1 {
86            element_len = 0;
87            None
88        } else {
89            Some(buf[..(element_len as usize)].to_vec())
90        };
91
92        buf.advance(element_len as usize);
93
94        PgValue {
95            value: element_val,
96            type_info: ty,
97            format,
98            timezone_sec,
99        }
100    }
101
102    #[inline]
103    pub fn as_ref(&self) -> PgValueRef<'_> {
104        PgValueRef {
105            value: self.value.as_deref(),
106            type_info: self.type_info.clone(),
107            format: self.format,
108            timezone_sec: self.timezone_sec,
109        }
110    }
111
112    pub fn type_info(&self) -> Cow<'_, PgTypeInfo> {
113        Cow::Borrowed(&self.type_info)
114    }
115
116    pub fn is_null(&self) -> bool {
117        self.value.is_none()
118    }
119
120    pub fn format(&self) -> PgValueFormat {
121        self.format
122    }
123    pub fn as_str(&self) -> Result<&str, Error> {
124        Ok(from_utf8(self.as_bytes()?)?)
125    }
126
127    pub fn as_bytes(&self) -> Result<&[u8], Error> {
128        match &self.value {
129            Some(v) => Ok(v),
130            None => Err(Error::from("UnexpectedNullError")),
131        }
132    }
133
134    pub fn into_bytes(self) -> Result<Vec<u8>, Error> {
135        match self.value {
136            Some(v) => Ok(v),
137            None => Err(Error::from("UnexpectedNullError")),
138        }
139    }
140}
141
142impl<'r> PgValueRef<'r> {
143    pub fn to_owned(&self) -> PgValue {
144        let value = match self.value {
145            Some(value) => Some(value.to_vec()),
146            _ => None,
147        };
148        PgValue {
149            value: value,
150            format: self.format,
151            type_info: self.type_info.clone(),
152            timezone_sec: self.timezone_sec,
153        }
154    }
155
156    pub fn type_info(&self) -> Cow<'_, PgTypeInfo> {
157        Cow::Borrowed(&self.type_info)
158    }
159
160    pub fn is_null(&self) -> bool {
161        self.value.is_none()
162    }
163}