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 Sealed for &Params {}
145impl IntoParams for &Params {
146 fn into_params(self) -> Result<Params> {
147 Ok(self.clone())
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((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 [(&str, T); N] {}
183impl<T: IntoValue, const N: usize> IntoParams for [(&str, T); N] {
184 fn into_params(self) -> Result<Params> {
185 self.into_iter()
186 .map(|(k, v)| Ok((k.to_string(), v.into_value()?)))
190 .collect::<Result<Vec<_>>>()?
191 .into_params()
192 }
193}
194
195impl<T: IntoValue + Clone, const N: usize> Sealed for &[T; N] {}
196impl<T: IntoValue + Clone, const N: usize> IntoParams for &[T; N] {
197 fn into_params(self) -> Result<Params> {
198 self.iter().cloned().collect::<Vec<_>>().into_params()
199 }
200}
201
202macro_rules! tuple_into_params {
204 ($count:literal : $(($field:tt $ftype:ident)),* $(,)?) => {
205 impl<$($ftype,)*> Sealed for ($($ftype,)*) where $($ftype: IntoValue,)* {}
206 impl<$($ftype,)*> IntoParams for ($($ftype,)*) where $($ftype: IntoValue,)* {
207 fn into_params(self) -> Result<Params> {
208 let params = Params::Positional(vec![$(self.$field.into_value()?),*]);
209 Ok(params)
210 }
211 }
212 }
213}
214
215macro_rules! named_tuple_into_params {
216 ($count:literal : $(($field:tt $ftype:ident)),* $(,)?) => {
217 impl<$($ftype,)*> Sealed for ($((&str, $ftype),)*) where $($ftype: IntoValue,)* {}
218 impl<$($ftype,)*> IntoParams for ($((&str, $ftype),)*) where $($ftype: IntoValue,)* {
219 fn into_params(self) -> Result<Params> {
220 let params = Params::Named(vec![$((self.$field.0.to_string(), self.$field.1.into_value()?)),*]);
221 Ok(params)
222 }
223 }
224 }
225}
226
227named_tuple_into_params!(2: (0 A), (1 B));
228named_tuple_into_params!(3: (0 A), (1 B), (2 C));
229named_tuple_into_params!(4: (0 A), (1 B), (2 C), (3 D));
230named_tuple_into_params!(5: (0 A), (1 B), (2 C), (3 D), (4 E));
231named_tuple_into_params!(6: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F));
232named_tuple_into_params!(7: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G));
233named_tuple_into_params!(8: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H));
234named_tuple_into_params!(9: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I));
235named_tuple_into_params!(10: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J));
236named_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));
237named_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));
238named_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));
239named_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));
240named_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));
241named_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));
242
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::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#[cfg(feature = "replication")]
285impl From<Params> for libsql_replication::rpc::proxy::query::Params {
286 fn from(params: Params) -> Self {
287 use libsql_replication::rpc::proxy;
288
289 match params {
290 Params::None => proxy::query::Params::Positional(proxy::Positional::default()),
291 Params::Positional(values) => {
292 let values = values
293 .iter()
294 .map(|v| bincode::serialize(v).unwrap())
295 .map(|data| proxy::Value { data })
296 .collect::<Vec<_>>();
297 proxy::query::Params::Positional(proxy::Positional { values })
298 }
299 Params::Named(values) => {
300 let (names, values) = values
301 .into_iter()
302 .map(|(name, value)| {
303 let data = bincode::serialize(&value).unwrap();
304 let value = proxy::Value { data };
305 (name, value)
306 })
307 .unzip();
308
309 proxy::query::Params::Named(proxy::Named { names, values })
310 }
311 }
312 }
313}
314
315#[macro_export]
317macro_rules! params {
318 () => {
319 ()
320 };
321 ($($value:expr),* $(,)?) => {{
322 use $crate::params::IntoValue;
323 [$($value.into_value()),*]
324
325 }};
326}
327
328#[macro_export]
330macro_rules! named_params {
331 () => {
332 ()
333 };
334 ($($param_name:literal: $value:expr),* $(,)?) => {{
335 use $crate::params::IntoValue;
336 [$(($param_name, $value.into_value())),*]
337 }};
338}
339
340#[cfg(test)]
341mod tests {
342 use crate::Value;
343
344 #[test]
345 fn test_serialize_array() {
346 assert_eq!(
347 params!([0; 16])[0].as_ref().unwrap(),
348 &Value::Blob(vec![0; 16])
349 );
350 }
351}