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