samling_clorinde/
array_iterator.rs1use super::utils::escape_domain;
4use fallible_iterator::FallibleIterator;
5use postgres_protocol::types::{array_from_sql, ArrayValues};
6use postgres_types::{FromSql, Kind, Type};
7use std::fmt::Debug;
8use std::marker::PhantomData;
9pub struct ArrayIterator<'a, T: FromSql<'a>> {
12 values: ArrayValues<'a>,
13 ty: Type,
14 _type: PhantomData<T>,
15}
16impl<'a, T: FromSql<'a>> Debug for ArrayIterator<'a, T> {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("ArrayIterator")
19 .field("values", &"[T]")
20 .field("ty", &self.ty)
21 .field("_type", &self._type)
22 .finish()
23 }
24}
25impl<'a, T: FromSql<'a>> Iterator for ArrayIterator<'a, T> {
26 type Item = T;
27 fn next(&mut self) -> Option<Self::Item> {
28 self.values
29 .next()
30 .unwrap()
31 .map(|raw| T::from_sql_nullable(&self.ty, raw).unwrap())
32 }
33}
34impl<'a, T: FromSql<'a>> FromSql<'a> for ArrayIterator<'a, T> {
35 fn from_sql(
36 ty: &Type,
37 raw: &'a [u8],
38 ) -> Result<ArrayIterator<'a, T>, Box<dyn std::error::Error + Sync + Send>> {
39 let member_type = match *escape_domain(ty).kind() {
40 Kind::Array(ref member) => escape_domain(member),
41 _ => panic!("expected array type got {ty}"),
42 };
43 let array = array_from_sql(raw)?;
44 if array.dimensions().count()? > 1 {
45 return Err("array contains too many dimensions".into());
46 }
47 Ok(ArrayIterator {
48 ty: member_type.clone(),
49 values: array.values(),
50 _type: PhantomData,
51 })
52 }
53 fn accepts(ty: &Type) -> bool {
54 match *ty.kind() {
55 Kind::Array(ref inner) => T::accepts(escape_domain(inner)),
56 _ => false,
57 }
58 }
59}