1use crate::{Error, Result, Value};
4use std::borrow::Cow;
5
6mod sealed {
7 pub trait Sealed {}
8}
9
10use sealed::Sealed;
11
12pub trait IntoParams: Sealed {
91 #[doc(hidden)]
94 fn into_params(self) -> Result<Params>;
95}
96
97#[derive(Debug, Clone)]
98#[doc(hidden)]
99pub enum Params {
100 None,
101 Positional(Vec<Value>),
102 Named(Vec<(Cow<'static, str>, Value)>),
109}
110
111pub fn params_from_iter<I>(iter: I) -> impl IntoParams
130where
131 I: IntoIterator,
132 I::Item: IntoValue,
133{
134 iter.into_iter().collect::<Vec<_>>()
135}
136
137impl Sealed for () {}
138impl IntoParams for () {
139 fn into_params(self) -> Result<Params> {
140 Ok(Params::None)
141 }
142}
143
144impl Sealed for Params {}
145impl IntoParams for Params {
146 fn into_params(self) -> Result<Params> {
147 Ok(self)
148 }
149}
150
151impl<T: IntoValue> Sealed for Vec<T> {}
152impl<T: IntoValue> IntoParams for Vec<T> {
153 fn into_params(self) -> Result<Params> {
154 let values = self
155 .into_iter()
156 .map(|i| i.into_value())
157 .collect::<Result<Vec<_>>>()?;
158
159 Ok(Params::Positional(values))
160 }
161}
162
163impl<T: IntoValue> Sealed for Vec<(String, T)> {}
164impl<T: IntoValue> IntoParams for Vec<(String, T)> {
165 fn into_params(self) -> Result<Params> {
166 let values = self
167 .into_iter()
168 .map(|(k, v)| Ok((Cow::Owned(k), v.into_value()?)))
169 .collect::<Result<Vec<_>>>()?;
170
171 Ok(Params::Named(values))
172 }
173}
174
175impl<T: IntoValue, const N: usize> Sealed for [T; N] {}
176impl<T: IntoValue, const N: usize> IntoParams for [T; N] {
177 fn into_params(self) -> Result<Params> {
178 self.into_iter().collect::<Vec<_>>().into_params()
179 }
180}
181
182impl<T: IntoValue, const N: usize> Sealed for [(&'static str, T); N] {}
183impl<T: IntoValue, const N: usize> IntoParams for [(&'static str, T); N] {
184 fn into_params(self) -> Result<Params> {
185 let values = self
189 .into_iter()
190 .map(|(k, v)| Ok((Cow::Borrowed(k), v.into_value()?)))
191 .collect::<Result<Vec<_>>>()?;
192
193 Ok(Params::Named(values))
194 }
195}
196
197impl<T: IntoValue + Clone, const N: usize> Sealed for &[T; N] {}
198impl<T: IntoValue + Clone, const N: usize> IntoParams for &[T; N] {
199 fn into_params(self) -> Result<Params> {
200 self.iter().cloned().collect::<Vec<_>>().into_params()
201 }
202}
203
204macro_rules! tuple_into_params {
206 ($count:literal : $(($field:tt $ftype:ident)),* $(,)?) => {
207 impl<$($ftype,)*> Sealed for ($($ftype,)*) where $($ftype: IntoValue,)* {}
208 impl<$($ftype,)*> IntoParams for ($($ftype,)*) where $($ftype: IntoValue,)* {
209 fn into_params(self) -> Result<Params> {
210 let params = Params::Positional(vec![$(self.$field.into_value()?),*]);
211 Ok(params)
212 }
213 }
214 }
215}
216
217macro_rules! named_tuple_into_params {
218 ($count:literal : $(($field:tt $ftype:ident)),* $(,)?) => {
219 impl<$($ftype,)*> Sealed for ($((&'static str, $ftype),)*) where $($ftype: IntoValue,)* {}
220 impl<$($ftype,)*> IntoParams for ($((&'static str, $ftype),)*) where $($ftype: IntoValue,)* {
221 fn into_params(self) -> Result<Params> {
222 let params = Params::Named(vec![$((Cow::Borrowed(self.$field.0), self.$field.1.into_value()?)),*]);
225 Ok(params)
226 }
227 }
228 }
229}
230
231named_tuple_into_params!(2: (0 A), (1 B));
232named_tuple_into_params!(3: (0 A), (1 B), (2 C));
233named_tuple_into_params!(4: (0 A), (1 B), (2 C), (3 D));
234named_tuple_into_params!(5: (0 A), (1 B), (2 C), (3 D), (4 E));
235named_tuple_into_params!(6: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F));
236named_tuple_into_params!(7: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G));
237named_tuple_into_params!(8: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H));
238named_tuple_into_params!(9: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I));
239named_tuple_into_params!(10: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J));
240named_tuple_into_params!(11: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K));
241named_tuple_into_params!(12: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L));
242named_tuple_into_params!(13: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M));
243named_tuple_into_params!(14: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N));
244named_tuple_into_params!(15: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O));
245named_tuple_into_params!(16: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O), (15 P));
246
247tuple_into_params!(2: (0 A), (1 B));
248tuple_into_params!(3: (0 A), (1 B), (2 C));
249tuple_into_params!(4: (0 A), (1 B), (2 C), (3 D));
250tuple_into_params!(5: (0 A), (1 B), (2 C), (3 D), (4 E));
251tuple_into_params!(6: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F));
252tuple_into_params!(7: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G));
253tuple_into_params!(8: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H));
254tuple_into_params!(9: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I));
255tuple_into_params!(10: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J));
256tuple_into_params!(11: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K));
257tuple_into_params!(12: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L));
258tuple_into_params!(13: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M));
259tuple_into_params!(14: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N));
260tuple_into_params!(15: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O));
261tuple_into_params!(16: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O), (15 P));
262
263pub trait IntoValue {
268 fn into_value(self) -> Result<Value>;
269}
270
271impl<T> IntoValue for T
272where
273 T: TryInto<Value>,
274 T::Error: Into<crate::BoxError>,
275{
276 fn into_value(self) -> Result<Value> {
277 self.try_into()
278 .map_err(|e| Error::ToSqlConversionFailure(e.into()))
279 }
280}
281
282impl IntoValue for Result<Value> {
283 fn into_value(self) -> Result<Value> {
284 self
285 }
286}
287
288#[macro_export]
290macro_rules! params {
291 () => {
292 ()
293 };
294 ($($value:expr),* $(,)?) => {{
295 use $crate::params::IntoValue;
296 [$($value.into_value()),*]
297
298 }};
299}
300
301#[macro_export]
303macro_rules! named_params {
304 () => {
305 ()
306 };
307 ($($param_name:literal: $value:expr),* $(,)?) => {{
308 use $crate::params::IntoValue;
309 [$(($param_name, $value.into_value())),*]
310 }};
311}
312
313#[cfg(test)]
314mod tests {
315 use crate::Value;
316
317 #[test]
318 fn test_serialize_array() {
319 assert_eq!(
320 params!([0; 16])[0].as_ref().unwrap(),
321 &Value::Blob(vec![0; 16])
322 );
323 }
324}