odbc_api/
into_parameter.rs

1use widestring::{U16Str, U16String};
2
3use crate::{
4    buffers::Indicator,
5    fixed_sized::Pod,
6    parameter::{InputParameter, VarBinaryBox, VarBinarySlice, VarWCharBox, VarWCharSlice},
7    Nullable,
8};
9
10#[cfg(not(any(feature = "wide", all(not(feature = "narrow"), target_os = "windows"))))]
11use crate::parameter::{VarCharBox, VarCharSlice};
12
13/// An instance can be consumed and to create a parameter which can be bound to a statement during
14/// execution.
15///
16/// Due to specific layout requirements and the necessity to provide pointers to length and
17/// indicator values, as opposed to taking the actual values it is often necessary starting from
18/// idiomatic Rust types, to convert, enrich and marshal them into values which can be bound to
19/// ODBC. This also provides a safe extension point for all kinds of parameters, as only the
20/// implementation of `Parameters` is unsafe.
21pub trait IntoParameter {
22    type Parameter: InputParameter;
23
24    fn into_parameter(self) -> Self::Parameter;
25}
26
27impl<T> IntoParameter for T
28where
29    T: InputParameter,
30{
31    type Parameter = Self;
32
33    fn into_parameter(self) -> Self::Parameter {
34        self
35    }
36}
37
38#[cfg(not(any(feature = "wide", all(not(feature = "narrow"), target_os = "windows"))))]
39impl<'a> IntoParameter for &'a str {
40    type Parameter = VarCharSlice<'a>;
41
42    fn into_parameter(self) -> Self::Parameter {
43        VarCharSlice::new(self.as_bytes())
44    }
45}
46
47#[cfg(any(feature = "wide", all(not(feature = "narrow"), target_os = "windows")))]
48impl IntoParameter for &'_ str {
49    type Parameter = VarWCharBox;
50
51    fn into_parameter(self) -> Self::Parameter {
52        VarWCharBox::from_str_slice(self)
53    }
54}
55
56impl<'a> IntoParameter for Option<&'a str> {
57    type Parameter = <&'a str as IntoParameter>::Parameter;
58
59    fn into_parameter(self) -> Self::Parameter {
60        match self {
61            Some(str) => str.into_parameter(),
62            #[cfg(not(any(
63                feature = "wide",
64                all(not(feature = "narrow"), target_os = "windows")
65            )))]
66            None => VarCharSlice::NULL,
67            #[cfg(any(feature = "wide", all(not(feature = "narrow"), target_os = "windows")))]
68            None => VarWCharBox::null(),
69        }
70    }
71}
72
73#[cfg(not(any(feature = "wide", all(not(feature = "narrow"), target_os = "windows"))))]
74impl IntoParameter for String {
75    type Parameter = VarCharBox;
76
77    fn into_parameter(self) -> Self::Parameter {
78        VarCharBox::from_string(self)
79    }
80}
81
82#[cfg(any(feature = "wide", all(not(feature = "narrow"), target_os = "windows")))]
83impl IntoParameter for String {
84    type Parameter = VarWCharBox;
85
86    fn into_parameter(self) -> Self::Parameter {
87        VarWCharBox::from_str_slice(&self)
88    }
89}
90
91impl IntoParameter for Option<String> {
92    type Parameter = <String as IntoParameter>::Parameter;
93
94    fn into_parameter(self) -> Self::Parameter {
95        match self {
96            Some(str) => str.into_parameter(),
97            #[cfg(not(any(
98                feature = "wide",
99                all(not(feature = "narrow"), target_os = "windows")
100            )))]
101            None => VarCharBox::null(),
102            #[cfg(any(feature = "wide", all(not(feature = "narrow"), target_os = "windows")))]
103            None => VarWCharBox::null(),
104        }
105    }
106}
107
108impl<'a> IntoParameter for &'a [u8] {
109    type Parameter = VarBinarySlice<'a>;
110
111    fn into_parameter(self) -> Self::Parameter {
112        VarBinarySlice::new(self)
113    }
114}
115
116impl<'a> IntoParameter for Option<&'a [u8]> {
117    type Parameter = VarBinarySlice<'a>;
118
119    fn into_parameter(self) -> Self::Parameter {
120        match self {
121            Some(str) => str.into_parameter(),
122            None => VarBinarySlice::NULL,
123        }
124    }
125}
126
127impl IntoParameter for Vec<u8> {
128    type Parameter = VarBinaryBox;
129
130    fn into_parameter(self) -> Self::Parameter {
131        VarBinaryBox::from_vec(self)
132    }
133}
134
135impl IntoParameter for Option<Vec<u8>> {
136    type Parameter = VarBinaryBox;
137
138    fn into_parameter(self) -> Self::Parameter {
139        match self {
140            Some(str) => str.into_parameter(),
141            None => VarBinaryBox::null(),
142        }
143    }
144}
145
146impl<'a> IntoParameter for &'a U16Str {
147    type Parameter = VarWCharSlice<'a>;
148
149    fn into_parameter(self) -> Self::Parameter {
150        let slice = self.as_slice();
151        let length_in_bytes = slice.len() * 2;
152        VarWCharSlice::from_buffer(slice, Indicator::Length(length_in_bytes))
153    }
154}
155
156impl<'a> IntoParameter for Option<&'a U16Str> {
157    type Parameter = VarWCharSlice<'a>;
158
159    fn into_parameter(self) -> Self::Parameter {
160        match self {
161            Some(str) => str.into_parameter(),
162            None => VarWCharSlice::NULL,
163        }
164    }
165}
166
167impl IntoParameter for U16String {
168    type Parameter = VarWCharBox;
169
170    fn into_parameter(self) -> Self::Parameter {
171        VarWCharBox::from_u16_string(self)
172    }
173}
174
175impl IntoParameter for Option<U16String> {
176    type Parameter = VarWCharBox;
177
178    fn into_parameter(self) -> Self::Parameter {
179        match self {
180            Some(str) => str.into_parameter(),
181            None => VarWCharBox::null(),
182        }
183    }
184}
185
186impl<T> IntoParameter for Option<T>
187where
188    T: Pod + InputParameter,
189{
190    type Parameter = Nullable<T>;
191
192    fn into_parameter(self) -> Self::Parameter {
193        match self {
194            Some(value) => Nullable::new(value),
195            None => Nullable::null(),
196        }
197    }
198}