odbc_api/parameter_collection/
tuple.rs

1//! Implement `Parameters` trait for tuples consisting of elements implementing `SingleParameter`
2//! trait.
3
4use super::ParameterCollectionRef;
5use crate::{Error, InOut, Out, OutputParameter, handles::Statement, parameter::InputParameter};
6
7macro_rules! impl_bind_parameters {
8    ($offset:expr, $stmt:ident) => (
9        Ok(())
10    );
11    ($offset:expr, $stmt:ident $head:ident $($tail:ident)*) => (
12        {
13            $head.bind_to($offset+1, $stmt)?;
14            impl_bind_parameters!($offset+1, $stmt $($tail)*)
15        }
16    );
17}
18
19macro_rules! impl_parameters_for_tuple{
20    ($($t:ident)*) => (
21        #[allow(unused_parens)]
22        #[allow(unused_variables)]
23        #[allow(non_snake_case)]
24        unsafe impl<$($t:ParameterTupleElement,)*> ParameterCollectionRef for ($($t,)*)
25        {
26            fn parameter_set_size(&self) -> usize {
27                1
28            }
29
30            unsafe fn bind_parameters_to(&mut self, stmt: &mut impl Statement) -> Result<(), Error> {
31                let ($($t,)*) = self;
32                #[allow(unused_unsafe)]
33                unsafe {
34                impl_bind_parameters!(0, stmt $($t)*)
35                }
36            }
37        }
38    );
39}
40
41// The unit type is used to signal no parameters.
42impl_parameters_for_tuple! {}
43impl_parameters_for_tuple! { A }
44impl_parameters_for_tuple! { A B }
45impl_parameters_for_tuple! { A B C }
46impl_parameters_for_tuple! { A B C D }
47impl_parameters_for_tuple! { A B C D E }
48impl_parameters_for_tuple! { A B C D E F }
49impl_parameters_for_tuple! { A B C D E F G }
50impl_parameters_for_tuple! { A B C D E F G H }
51impl_parameters_for_tuple! { A B C D E F G H I }
52impl_parameters_for_tuple! { A B C D E F G H I J }
53impl_parameters_for_tuple! { A B C D E F G H I J K }
54impl_parameters_for_tuple! { A B C D E F G H I J K L }
55impl_parameters_for_tuple! { A B C D E F G H I J K L M }
56impl_parameters_for_tuple! { A B C D E F G H I J K L M N }
57impl_parameters_for_tuple! { A B C D E F G H I J K L M N O }
58impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P }
59impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q }
60impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R }
61impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S }
62impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T }
63impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U }
64impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V }
65impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W }
66impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X }
67impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X Y }
68impl_parameters_for_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
69
70/// Implementers of this trait can be used as individual parameters of in a tuple of parameter
71/// references. This includes input parameters, output or in/out parameters.
72///
73/// # Safety
74///
75/// Parameters bound to the statement must remain valid for the lifetime of the instance.
76pub unsafe trait ParameterTupleElement {
77    /// Bind the parameter in question to a specific `parameter_number`.
78    ///
79    /// # Safety
80    ///
81    /// Since the parameter is now bound to `stmt` callers must take care that it is ensured that
82    /// the parameter remains valid while it is used. If the parameter is bound as an output
83    /// parameter it must also be ensured that it is exclusively referenced by statement.
84    unsafe fn bind_to(
85        &mut self,
86        parameter_number: u16,
87        stmt: &mut impl Statement,
88    ) -> Result<(), Error>;
89}
90
91/// Bind immutable references as input parameters.
92unsafe impl<T: ?Sized> ParameterTupleElement for &T
93where
94    T: InputParameter,
95{
96    unsafe fn bind_to(
97        &mut self,
98        parameter_number: u16,
99        stmt: &mut impl Statement,
100    ) -> Result<(), Error> {
101        self.assert_completness();
102        unsafe { stmt.bind_input_parameter(parameter_number, *self) }.into_result(stmt)
103    }
104}
105
106/// Bind mutable references as input/output parameter.
107unsafe impl<T> ParameterTupleElement for InOut<'_, T>
108where
109    T: OutputParameter + InputParameter,
110{
111    unsafe fn bind_to(
112        &mut self,
113        parameter_number: u16,
114        stmt: &mut impl Statement,
115    ) -> Result<(), Error> {
116        self.0.assert_completness();
117        unsafe { stmt.bind_parameter(parameter_number, odbc_sys::ParamType::InputOutput, self.0) }
118            .into_result(stmt)
119    }
120}
121
122/// Mutable references wrapped in `Out` are bound as output parameters.
123unsafe impl<T> ParameterTupleElement for Out<'_, T>
124where
125    T: OutputParameter,
126{
127    unsafe fn bind_to(
128        &mut self,
129        parameter_number: u16,
130        stmt: &mut impl Statement,
131    ) -> Result<(), Error> {
132        unsafe { stmt.bind_parameter(parameter_number, odbc_sys::ParamType::Output, self.0) }
133            .into_result(stmt)
134    }
135}