zero_postgres/conversion/
row.rs1use crate::conversion::FromWireValue;
4use crate::error::{Error, Result};
5use crate::protocol::backend::query::{DataRow, FieldDescription};
6
7pub trait FromRow<'a>: Sized {
9 fn from_row_text(cols: &[FieldDescription], row: DataRow<'a>) -> Result<Self>;
11
12 fn from_row_binary(cols: &[FieldDescription], row: DataRow<'a>) -> Result<Self>;
14}
15
16fn decode_column_text<'a, T: FromWireValue<'a>>(
18 field: &FieldDescription,
19 value: Option<&'a [u8]>,
20) -> Result<T> {
21 match value {
22 None => T::from_null(),
23 Some(bytes) => T::from_text(field.type_oid(), bytes),
24 }
25}
26
27fn decode_column_binary<'a, T: FromWireValue<'a>>(
29 field: &FieldDescription,
30 value: Option<&'a [u8]>,
31) -> Result<T> {
32 match value {
33 None => T::from_null(),
34 Some(bytes) => T::from_binary(field.type_oid(), bytes),
35 }
36}
37
38impl FromRow<'_> for () {
42 fn from_row_text(_cols: &[FieldDescription], _row: DataRow<'_>) -> Result<Self> {
43 Ok(())
44 }
45
46 fn from_row_binary(_cols: &[FieldDescription], _row: DataRow<'_>) -> Result<Self> {
47 Ok(())
48 }
49}
50
51macro_rules! impl_from_row_tuple {
52 ($count:literal: $($idx:tt => $T:ident),+) => {
53 impl<'a, $($T: FromWireValue<'a>),+> FromRow<'a> for ($($T,)+) {
54 fn from_row_text(cols: &[FieldDescription], row: DataRow<'a>) -> Result<Self> {
55 if cols.len() < $count {
56 return Err(Error::Decode("not enough columns for tuple".into()));
57 }
58 let mut iter = row.iter();
59 Ok(($(
60 decode_column_text(&cols[$idx], iter.next().flatten())?,
61 )+))
62 }
63
64 fn from_row_binary(cols: &[FieldDescription], row: DataRow<'a>) -> Result<Self> {
65 if cols.len() < $count {
66 return Err(Error::Decode("not enough columns for tuple".into()));
67 }
68 let mut iter = row.iter();
69 Ok(($(
70 decode_column_binary(&cols[$idx], iter.next().flatten())?,
71 )+))
72 }
73 }
74 };
75}
76
77impl_from_row_tuple!(1: 0 => T1);
78impl_from_row_tuple!(2: 0 => T1, 1 => T2);
79impl_from_row_tuple!(3: 0 => T1, 1 => T2, 2 => T3);
80impl_from_row_tuple!(4: 0 => T1, 1 => T2, 2 => T3, 3 => T4);
81impl_from_row_tuple!(5: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5);
82impl_from_row_tuple!(6: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6);
83impl_from_row_tuple!(7: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7);
84impl_from_row_tuple!(8: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8);
85impl_from_row_tuple!(9: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8, 8 => T9);
86impl_from_row_tuple!(10: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8, 8 => T9, 9 => T10);
87impl_from_row_tuple!(11: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8, 8 => T9, 9 => T10, 10 => T11);
88impl_from_row_tuple!(12: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8, 8 => T9, 9 => T10, 10 => T11, 11 => T12);