samling_clorinde/
domain.rs1use super::{type_traits::ArraySql, utils::escape_domain};
4use postgres_protocol::types::{array_to_sql, ArrayDimension};
5use postgres_types::{private::BytesMut, IsNull, Kind, ToSql, Type};
6use std::{
7 error::Error,
8 fmt::{Debug, Formatter},
9};
10pub struct Domain<T: ToSql>(pub T);
11impl<T: ToSql + Debug> Debug for Domain<T> {
12 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
13 f.debug_tuple("DomainWrapper").field(&self.0).finish()
14 }
15}
16impl<T: ToSql> ToSql for Domain<T> {
17 fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
18 where
19 Self: Sized,
20 {
21 postgres_types::ToSql::to_sql(&self.0, escape_domain(ty), out)
22 }
23 fn accepts(ty: &Type) -> bool
24 where
25 Self: Sized,
26 {
27 T::accepts(escape_domain(ty))
28 }
29 fn to_sql_checked(
30 &self,
31 ty: &Type,
32 out: &mut BytesMut,
33 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
34 postgres_types::__to_sql_checked(self, ty, out)
35 }
36}
37pub struct DomainArray<'a, T: ToSql + Sync, A: ArraySql<Item = T>>(pub &'a A);
38impl<T: ToSql + Sync, A: ArraySql<Item = T>> Debug for DomainArray<'_, T, A> {
39 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40 f.debug_tuple("ArrayDomain").field(&self.0).finish()
41 }
42}
43impl<'a, T: ToSql + Sync + 'a, A: ArraySql<Item = T>> ToSql for DomainArray<'a, T, A> {
44 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
45 self.0.escape_domain_to_sql(ty, w)
46 }
47 fn accepts(ty: &Type) -> bool {
48 match *ty.kind() {
49 Kind::Array(ref member) => T::accepts(escape_domain(member)),
50 _ => false,
51 }
52 }
53 fn to_sql_checked(
54 &self,
55 ty: &Type,
56 out: &mut BytesMut,
57 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
58 postgres_types::__to_sql_checked(self, ty, out)
59 }
60}
61pub fn escape_domain_to_sql<T: ToSql>(
62 ty: &Type,
63 w: &mut BytesMut,
64 iter: impl ExactSizeIterator<Item = T>,
65) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
66 let member_type = match *ty.kind() {
67 Kind::Array(ref member) => escape_domain(member),
68 _ => panic!("expected array type got {ty}"),
69 };
70 let dimension = ArrayDimension {
71 len: downcast(iter.len())?,
72 lower_bound: 1,
73 };
74 array_to_sql(
75 Some(dimension),
76 member_type.oid(),
77 iter,
78 |e, w| match Domain(e).to_sql(member_type, w)? {
79 IsNull::No => Ok(postgres_protocol::IsNull::No),
80 IsNull::Yes => Ok(postgres_protocol::IsNull::Yes),
81 },
82 w,
83 )?;
84 Ok(IsNull::No)
85}
86fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
87 if len > i32::MAX as usize {
88 Err("value too large to transmit".into())
89 } else {
90 Ok(len as i32)
91 }
92}