1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use std::error::Error;
use postgres_types::{private, FromSql, Kind, Type, WrongType};
#[derive(Debug, PartialEq, Eq)]
pub struct Record<T>(pub T);
macro_rules! impl_tuple {
($n:expr; $($ty_ident:ident),*; $($var_ident:ident),*) => {
impl<'a, $($ty_ident),*> FromSql<'a> for Record<($($ty_ident,)*)>
where
$($ty_ident: FromSql<'a>),*
{
fn from_sql(
_: &Type,
mut raw: &'a [u8],
) -> Result<Record<($($ty_ident,)*)>, Box<dyn Error + Sync + Send>> {
let num_fields = private::read_be_i32(&mut raw)?;
let num_fields = u32::try_from(num_fields).map_err(|_| format!("number of fields cannot be negative: {}", num_fields))?;
if num_fields != $n {
return Err(format!(
"Postgres record field count does not match Rust tuple length: {} vs {}",
num_fields,
$n,
).into());
}
$(
let oid = private::read_be_i32(&mut raw)?;
let oid = u32::try_from(oid).map_err(|_| format!("OIDs cannot be negative: {}", oid))?;
let ty = match Type::from_oid(oid) {
None => {
return Err(format!(
"cannot decode OID {} inside of anonymous record",
oid,
).into());
}
Some(ty) if !$ty_ident::accepts(&ty) => {
return Err(Box::new(WrongType::new::<$ty_ident>(ty.clone())));
}
Some(ty) => ty,
};
let $var_ident = private::read_value(&ty, &mut raw)?;
)*
Ok(Record(($($var_ident,)*)))
}
fn accepts(ty: &Type) -> bool {
match ty.kind() {
Kind::Pseudo => *ty == Type::RECORD,
Kind::Composite(fields) => fields.len() == $n,
_ => false,
}
}
}
};
}
impl_tuple!(0; ; );
impl_tuple!(1; T0; v0);
impl_tuple!(2; T0, T1; v0, v1);
impl_tuple!(3; T0, T1, T2; v0, v1, v2);
impl_tuple!(4; T0, T1, T2, T3; v0, v1, v2, v3);