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 let cols = cols.first_chunk::<$count>()
56 .ok_or_else(|| Error::Decode("not enough columns for tuple".into()))?;
57 let mut iter = row.iter();
58 Ok(($(
59 decode_column_text(&cols[$idx], iter.next().flatten())?,
60 )+))
61 }
62
63 fn from_row_binary(cols: &[FieldDescription], row: DataRow<'a>) -> Result<Self> {
64 let cols = cols.first_chunk::<$count>()
65 .ok_or_else(|| Error::Decode("not enough columns for tuple".into()))?;
66 let mut iter = row.iter();
67 Ok(($(
68 decode_column_binary(&cols[$idx], iter.next().flatten())?,
69 )+))
70 }
71 }
72 };
73}
74
75impl_from_row_tuple!(1: 0 => T1);
76impl_from_row_tuple!(2: 0 => T1, 1 => T2);
77impl_from_row_tuple!(3: 0 => T1, 1 => T2, 2 => T3);
78impl_from_row_tuple!(4: 0 => T1, 1 => T2, 2 => T3, 3 => T4);
79impl_from_row_tuple!(5: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5);
80impl_from_row_tuple!(6: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6);
81impl_from_row_tuple!(7: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7);
82impl_from_row_tuple!(8: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8);
83impl_from_row_tuple!(9: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8, 8 => T9);
84impl_from_row_tuple!(10: 0 => T1, 1 => T2, 2 => T3, 3 => T4, 4 => T5, 5 => T6, 6 => T7, 7 => T8, 8 => T9, 9 => T10);
85impl_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);
86impl_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);