sqlx_exasol_impl/types/
array.rs1use std::{marker::PhantomData, rc::Rc, sync::Arc};
2
3use sqlx_core::{
4 database::Database,
5 encode::{Encode, IsNull},
6 error::BoxDynError,
7 types::Type,
8};
9
10use crate::{arguments::ExaBuffer, Exasol};
11
12pub trait ExaHasArrayType: Type<Exasol> {}
18
19impl<T> ExaHasArrayType for &T where T: ExaHasArrayType {}
20
21#[derive(Debug)]
43#[repr(transparent)]
44pub struct ExaIter<I, T> {
45 into_iter: I,
46 _marker: PhantomData<fn() -> T>,
47}
48
49impl<I, T> ExaIter<I, T>
50where
51 I: IntoIterator<Item = T> + Clone,
52 T: for<'q> Encode<'q, Exasol> + ExaHasArrayType + Copy,
53{
54 pub fn new(into_iter: I) -> Self {
55 Self {
56 into_iter,
57 _marker: PhantomData,
58 }
59 }
60}
61
62impl<I, T> Type<Exasol> for ExaIter<I, T>
63where
64 I: IntoIterator<Item = T> + Clone,
65 T: ExaHasArrayType + Copy,
66{
67 fn type_info() -> <Exasol as Database>::TypeInfo {
68 T::type_info()
69 }
70}
71
72impl<I, T> Encode<'_, Exasol> for ExaIter<I, T>
73where
74 I: IntoIterator<Item = T> + Clone,
75 T: for<'q> Encode<'q, Exasol> + Copy,
76{
77 fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
78 buf.append_iter(self.into_iter.clone())?;
79 Ok(IsNull::No)
80 }
81
82 fn size_hint(&self) -> usize {
83 2 + self
85 .into_iter
86 .clone()
87 .into_iter()
88 .fold(0, |sum, item| sum + item.size_hint())
89 }
90}
91
92macro_rules! forward_arr_type_impl {
93 ($for_type:ty, $($generics:tt)*) => {
94 impl<T, $($generics)*> Type<Exasol> for $for_type
95 where
96 T: ExaHasArrayType,
97 {
98 fn type_info() -> <Exasol as Database>::TypeInfo {
99 T::type_info()
100 }
101 }
102 };
103 ($for_type:ty) => {
104 forward_arr_type_impl!($for_type,);
105 }
106}
107
108macro_rules! forward_arr_encode_impl {
109 ($for_type:ty, $($generics:tt)*) => {
110 impl<T, $($generics)*> Encode<'_, Exasol> for $for_type
111 where
112 for<'q> T: Encode<'q, Exasol> + ExaHasArrayType,
113 {
114 fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
115 ExaIter::new(AsRef::<[T]>::as_ref(&self)).encode_by_ref(buf)
116 }
117
118 fn size_hint(&self) -> usize {
119 ExaIter::new(AsRef::<[T]>::as_ref(&self)).size_hint()
120 }
121 }
122 };
123 ($for_type:ty) => {
124 forward_arr_encode_impl!($for_type,);
125 }
126}
127
128forward_arr_type_impl!([T]);
129forward_arr_type_impl!([T; N], const N: usize);
130forward_arr_type_impl!(Vec<T>);
131
132forward_arr_encode_impl!(&[T]);
133forward_arr_encode_impl!([T; N], const N: usize);
134forward_arr_encode_impl!(Vec<T>);
135forward_arr_encode_impl!(Box<[T]>);
136forward_arr_encode_impl!(Rc<[T]>);
137forward_arr_encode_impl!(Arc<[T]>);