zero_postgres/conversion/
mod.rs1mod bytes;
7mod numeric_util;
8mod primitives;
9pub mod ref_row;
10mod row;
11mod string;
12
13pub use numeric_util::numeric_to_string;
14
15#[cfg(feature = "with-chrono")]
16mod chrono;
17#[cfg(feature = "with-rust-decimal")]
18mod decimal;
19#[cfg(feature = "with-time")]
20mod time;
21#[cfg(feature = "with-uuid")]
22mod uuid;
23
24use crate::error::{Error, Result};
25use crate::protocol::types::Oid;
26pub use row::FromRow;
27
28pub const PG_EPOCH_JULIAN_DAY: i32 = 2_451_545;
30
31pub trait FromWireValue<'a>: Sized {
41 fn from_null() -> Result<Self> {
46 Err(Error::Decode("unexpected NULL value".into()))
47 }
48
49 fn from_text(oid: Oid, bytes: &'a [u8]) -> Result<Self>;
54
55 fn from_binary(oid: Oid, bytes: &'a [u8]) -> Result<Self>;
60}
61
62pub trait ToWireValue {
73 fn natural_oid(&self) -> Oid;
77
78 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()>;
93}
94
95pub trait ToParams {
97 fn param_count(&self) -> usize;
99
100 fn natural_oids(&self) -> Vec<Oid>;
102
103 fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()>;
108}
109
110impl<'a, T: FromWireValue<'a>> FromWireValue<'a> for Option<T> {
113 fn from_null() -> Result<Self> {
114 Ok(None)
115 }
116
117 fn from_text(oid: Oid, bytes: &'a [u8]) -> Result<Self> {
118 T::from_text(oid, bytes).map(Some)
119 }
120
121 fn from_binary(oid: Oid, bytes: &'a [u8]) -> Result<Self> {
122 T::from_binary(oid, bytes).map(Some)
123 }
124}
125
126impl<T: ToWireValue> ToWireValue for Option<T> {
127 fn natural_oid(&self) -> Oid {
128 match self {
129 Some(v) => v.natural_oid(),
130 None => 0, }
132 }
133
134 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
135 match self {
136 Some(v) => v.encode(target_oid, buf),
137 None => {
138 buf.extend_from_slice(&(-1_i32).to_be_bytes());
140 Ok(())
141 }
142 }
143 }
144}
145
146impl<T: ToWireValue + ?Sized> ToWireValue for &T {
149 fn natural_oid(&self) -> Oid {
150 (*self).natural_oid()
151 }
152
153 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
154 (*self).encode(target_oid, buf)
155 }
156}
157
158impl ToParams for () {
161 fn param_count(&self) -> usize {
162 0
163 }
164
165 fn natural_oids(&self) -> Vec<Oid> {
166 vec![]
167 }
168
169 fn encode(&self, _target_oids: &[Oid], _buf: &mut Vec<u8>) -> Result<()> {
170 Ok(())
171 }
172}
173
174impl<T: ToParams + ?Sized> ToParams for &T {
175 fn param_count(&self) -> usize {
176 (*self).param_count()
177 }
178
179 fn natural_oids(&self) -> Vec<Oid> {
180 (*self).natural_oids()
181 }
182
183 fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
184 (*self).encode(target_oids, buf)
185 }
186}
187
188impl<T: ToWireValue> ToParams for [T] {
189 fn param_count(&self) -> usize {
190 self.len()
191 }
192
193 fn natural_oids(&self) -> Vec<Oid> {
194 self.iter().map(|v| v.natural_oid()).collect()
195 }
196
197 fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
198 for (v, &oid) in self.iter().zip(target_oids) {
199 v.encode(oid, buf)?;
200 }
201 Ok(())
202 }
203}
204
205impl<T: ToWireValue> ToParams for Vec<T> {
206 fn param_count(&self) -> usize {
207 self.as_slice().param_count()
208 }
209
210 fn natural_oids(&self) -> Vec<Oid> {
211 self.as_slice().natural_oids()
212 }
213
214 fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
215 self.as_slice().encode(target_oids, buf)
216 }
217}
218
219macro_rules! impl_to_params {
221 ($count:expr, $($idx:tt: $T:ident),+) => {
222 impl<$($T: ToWireValue),+> ToParams for ($($T,)+) {
223 fn param_count(&self) -> usize {
224 $count
225 }
226
227 fn natural_oids(&self) -> Vec<Oid> {
228 vec![$(self.$idx.natural_oid()),+]
229 }
230
231 fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
232 let mut _idx = 0;
233 $(
234 self.$idx.encode(target_oids[_idx], buf)?;
235 _idx += 1;
236 )+
237 Ok(())
238 }
239 }
240 };
241}
242
243impl_to_params!(1, 0: T0);
244impl_to_params!(2, 0: T0, 1: T1);
245impl_to_params!(3, 0: T0, 1: T1, 2: T2);
246impl_to_params!(4, 0: T0, 1: T1, 2: T2, 3: T3);
247impl_to_params!(5, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4);
248impl_to_params!(6, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5);
249impl_to_params!(7, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6);
250impl_to_params!(8, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7);
251impl_to_params!(9, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8);
252impl_to_params!(10, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9);
253impl_to_params!(11, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10);
254impl_to_params!(12, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11);
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259 use crate::protocol::types::oid;
260
261 #[test]
262 fn option_null() {
263 assert_eq!(Option::<i32>::from_null().unwrap(), None);
264 }
265
266 #[test]
267 fn slice_to_params() {
268 let params: &[i32] = &[1, 2, 3];
269 assert_eq!(params.param_count(), 3);
270 assert_eq!(params.natural_oids(), vec![oid::INT4, oid::INT4, oid::INT4]);
271
272 let mut buf = Vec::new();
273 params
274 .encode(&[oid::INT4, oid::INT4, oid::INT4], &mut buf)
275 .unwrap();
276 assert_eq!(buf.len(), 3 * 8);
278 }
279
280 #[test]
281 fn vec_to_params() {
282 let params: Vec<i64> = vec![10, 20];
283 assert_eq!(params.param_count(), 2);
284 assert_eq!(params.natural_oids(), vec![oid::INT8, oid::INT8]);
285
286 let mut buf = Vec::new();
287 params.encode(&[oid::INT8, oid::INT8], &mut buf).unwrap();
288 assert_eq!(buf.len(), 2 * 12);
290 }
291
292 #[test]
293 fn empty_slice_to_params() {
294 let params: &[i32] = &[];
295 assert_eq!(params.param_count(), 0);
296 assert_eq!(params.natural_oids(), vec![]);
297
298 let mut buf = Vec::new();
299 params.encode(&[], &mut buf).unwrap();
300 assert!(buf.is_empty());
301 }
302}