use std::ffi::{c_double, c_int}; use variadics_please::all_tuples_enumerated; use crate::{Result, Statement, ffi}; mod sealed { pub trait Sealed {} } use sealed::Sealed; pub trait Param: Sealed { #[doc(hidden)] fn __bind_in(&self, stmt: &mut Statement<'_>, i: c_int) -> Result<()>; } pub trait Params: Sealed { #[doc(hidden)] fn __bind_in(&self, stmt: &mut Statement<'_>) -> Result<()>; } impl Sealed for c_int {} impl Param for c_int { #[inline] fn __bind_in(&self, stmt: &mut Statement<'_>, i: c_int) -> Result<()> { stmt.bind_i32(i, *self) } } impl Sealed for ffi::sqlite3_int64 {} impl Param for ffi::sqlite3_int64 { #[inline] fn __bind_in(&self, stmt: &mut Statement<'_>, i: c_int) -> Result<()> { stmt.bind_i64(i, *self) } } impl Sealed for c_double {} impl Param for c_double { #[inline] fn __bind_in(&self, stmt: &mut Statement<'_>, i: c_int) -> Result<()> { stmt.bind_double(i, *self) } } impl Sealed for Option {} impl Param for Option { fn __bind_in(&self, stmt: &mut Statement<'_>, i: c_int) -> Result<()> { match self.as_ref() { Some(v) => v.__bind_in(stmt, i), // explicitly binding NULL is required in case a previous call bound a value here None => stmt.bind_null(i), } } } impl Sealed for () {} impl Param for () { #[inline] fn __bind_in(&self, stmt: &mut Statement<'_>, i: c_int) -> Result<()> { stmt.bind_null(i) } } impl Params for () { fn __bind_in(&self, _stmt: &mut Statement<'_>) -> Result<()> { Ok(()) } } macro_rules! impl_params { ($(($i:tt, $T:ident)),*) => { impl<$($T:Param),*> Sealed for ($($T,)*) {} impl<$($T:Param),*> Params for ($($T,)*) { fn __bind_in(&self, stmt: &mut Statement<'_>) -> Result<()> { $(self.$i.__bind_in(stmt, $i + 1)?;)* Ok(()) } } impl<$($T:Param),*> Sealed for ($(($T, c_int),)*) {} impl<$($T:Param),*> Params for ($(($T, c_int),)*) { fn __bind_in(&self, stmt: &mut Statement<'_>) -> Result<()> { $(self.$i.0.__bind_in(stmt, self.$i.1)?;)* Ok(()) } } } } all_tuples_enumerated!(impl_params, 1, 12, T);