sqlx_exasol/types/
iter.rs

1use sqlx_core::{
2    database::Database,
3    encode::{Encode, IsNull},
4    error::BoxDynError,
5    types::Type,
6};
7
8use crate::{arguments::ExaBuffer, Exasol};
9
10/// Adapter allowing any iterator of encodable values to be passed
11/// as a parameter set / array to Exasol.
12///
13/// Note that the iterator must implement [`Clone`] because
14/// it's used in multiple places. Therefore, prefer using iterators over
15/// references than owning variants.
16///
17/// ```rust
18/// use sqlx_exasol::ExaIter;
19///
20/// // Don't do this, as the iterator gets cloned internally.
21/// let vector = vec![1, 2, 3];
22/// let owned_iter = ExaIter::from(vector);
23///
24/// // Rather, prefer using something cheaper to clone, like:
25/// let vector = vec![1, 2, 3];
26/// let borrowed_iter = ExaIter::from(vector.as_slice());
27/// ```
28#[derive(Debug)]
29pub struct ExaIter<I, T>
30where
31    I: IntoIterator<Item = T> + Clone,
32    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
33{
34    value: I,
35}
36
37impl<I, T> From<I> for ExaIter<I, T>
38where
39    I: IntoIterator<Item = T> + Clone,
40    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
41{
42    fn from(value: I) -> Self {
43        Self { value }
44    }
45}
46
47impl<T, I> Type<Exasol> for ExaIter<I, T>
48where
49    I: IntoIterator<Item = T> + Clone,
50    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
51{
52    fn type_info() -> <Exasol as Database>::TypeInfo {
53        T::type_info()
54    }
55
56    fn compatible(ty: &<Exasol as Database>::TypeInfo) -> bool {
57        <Self as Type<Exasol>>::type_info().compatible(ty)
58    }
59}
60
61impl<T, I> Encode<'_, Exasol> for ExaIter<I, T>
62where
63    I: IntoIterator<Item = T> + Clone,
64    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
65{
66    fn produces(&self) -> Option<<Exasol as Database>::TypeInfo> {
67        self.value
68            .clone()
69            .into_iter()
70            .next()
71            .as_ref()
72            .and_then(Encode::produces)
73            .or_else(|| Some(T::type_info()))
74    }
75
76    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
77        buf.append_iter(self.value.clone())?;
78        Ok(IsNull::No)
79    }
80
81    fn size_hint(&self) -> usize {
82        self.value
83            .clone()
84            .into_iter()
85            .fold(0, |sum, item| sum + item.size_hint())
86    }
87}
88
89impl<'a, T> Type<Exasol> for &'a [T]
90where
91    T: Type<Exasol> + 'a,
92{
93    fn type_info() -> <Exasol as Database>::TypeInfo {
94        T::type_info()
95    }
96
97    fn compatible(ty: &<Exasol as Database>::TypeInfo) -> bool {
98        <Self as Type<Exasol>>::type_info().compatible(ty)
99    }
100}
101
102impl<T> Encode<'_, Exasol> for &[T]
103where
104    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
105{
106    fn produces(&self) -> Option<<Exasol as Database>::TypeInfo> {
107        self.first()
108            .and_then(Encode::produces)
109            .or_else(|| Some(T::type_info()))
110    }
111
112    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
113        buf.append_iter(self.iter())?;
114        Ok(IsNull::No)
115    }
116
117    fn size_hint(&self) -> usize {
118        self.iter().fold(0, |sum, item| sum + item.size_hint())
119    }
120}
121
122impl<'a, T> Type<Exasol> for &'a mut [T]
123where
124    T: Type<Exasol> + 'a,
125{
126    fn type_info() -> <Exasol as Database>::TypeInfo {
127        T::type_info()
128    }
129
130    fn compatible(ty: &<Exasol as Database>::TypeInfo) -> bool {
131        <Self as Type<Exasol>>::type_info().compatible(ty)
132    }
133}
134
135impl<T> Encode<'_, Exasol> for &mut [T]
136where
137    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
138{
139    fn produces(&self) -> Option<<Exasol as Database>::TypeInfo> {
140        (&**self).produces()
141    }
142
143    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
144        (&**self).encode_by_ref(buf)
145    }
146
147    fn size_hint(&self) -> usize {
148        (&**self).size_hint()
149    }
150}
151
152impl<T, const N: usize> Type<Exasol> for [T; N]
153where
154    T: Type<Exasol>,
155{
156    fn type_info() -> <Exasol as Database>::TypeInfo {
157        T::type_info()
158    }
159
160    fn compatible(ty: &<Exasol as Database>::TypeInfo) -> bool {
161        <Self as Type<Exasol>>::type_info().compatible(ty)
162    }
163}
164
165impl<T, const N: usize> Encode<'_, Exasol> for [T; N]
166where
167    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
168{
169    fn produces(&self) -> Option<<Exasol as Database>::TypeInfo> {
170        self.as_slice().produces()
171    }
172
173    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
174        self.as_slice().encode_by_ref(buf)
175    }
176
177    fn size_hint(&self) -> usize {
178        self.as_slice().size_hint()
179    }
180}
181
182impl<T> Type<Exasol> for Vec<T>
183where
184    T: Type<Exasol>,
185{
186    fn type_info() -> <Exasol as Database>::TypeInfo {
187        T::type_info()
188    }
189
190    fn compatible(ty: &<Exasol as Database>::TypeInfo) -> bool {
191        <Self as Type<Exasol>>::type_info().compatible(ty)
192    }
193}
194
195impl<T> Encode<'_, Exasol> for Vec<T>
196where
197    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
198{
199    fn produces(&self) -> Option<<Exasol as Database>::TypeInfo> {
200        (&**self).produces()
201    }
202
203    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
204        (&**self).encode_by_ref(buf)
205    }
206
207    fn size_hint(&self) -> usize {
208        (&**self).size_hint()
209    }
210}
211
212impl<T> Type<Exasol> for Box<[T]>
213where
214    T: Type<Exasol>,
215{
216    fn type_info() -> <Exasol as Database>::TypeInfo {
217        T::type_info()
218    }
219
220    fn compatible(ty: &<Exasol as Database>::TypeInfo) -> bool {
221        <Self as Type<Exasol>>::type_info().compatible(ty)
222    }
223}
224
225impl<T> Encode<'_, Exasol> for Box<[T]>
226where
227    for<'q> T: Encode<'q, Exasol> + Type<Exasol>,
228{
229    fn produces(&self) -> Option<<Exasol as Database>::TypeInfo> {
230        (&**self).produces()
231    }
232
233    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
234        (&**self).encode_by_ref(buf)
235    }
236
237    fn size_hint(&self) -> usize {
238        (&**self).size_hint()
239    }
240}