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