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