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