1use odbc_sys::{Date, Time, Timestamp};
2
3use super::{AnySlice, AnySliceMut, BufferDesc, NullableSlice, NullableSliceMut};
4use crate::{BindParamDesc, Bit};
5
6pub trait Item: Sized + Copy {
37 fn bind_param_desc(nullable: bool) -> BindParamDesc;
39
40 #[deprecated(note = "Use `bind_param_desc` instead")]
54 fn buffer_desc(nullable: bool) -> BufferDesc;
55
56 fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]>;
58 fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<'_, Self>>;
60
61 fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]>;
63
64 fn as_nullable_slice_mut(variant: AnySliceMut<'_>) -> Option<NullableSliceMut<'_, Self>>;
66}
67
68macro_rules! impl_item {
69 ($t:ident, $bind:ident, $plain:ident, $null:ident) => {
70 impl Item for $t {
71 fn bind_param_desc(nullable: bool) -> BindParamDesc {
72 BindParamDesc::$bind(nullable)
73 }
74
75 fn buffer_desc(nullable: bool) -> BufferDesc {
76 BufferDesc::$plain { nullable }
77 }
78
79 fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]> {
80 match variant {
81 AnySlice::$plain(vals) => Some(vals),
82 _ => None,
83 }
84 }
85
86 fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<'_, Self>> {
87 match variant {
88 AnySlice::$null(vals) => Some(vals),
89 _ => None,
90 }
91 }
92
93 fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]> {
94 match variant {
95 AnySliceMut::$plain(vals) => Some(vals),
96 _ => None,
97 }
98 }
99
100 fn as_nullable_slice_mut(
101 variant: AnySliceMut<'_>,
102 ) -> Option<NullableSliceMut<'_, Self>> {
103 match variant {
104 AnySliceMut::$null(vals) => Some(vals),
105 _ => None,
106 }
107 }
108 }
109 };
110}
111
112impl_item!(f64, f64, F64, NullableF64);
113impl_item!(f32, f32, F32, NullableF32);
114impl_item!(u8, u8, U8, NullableU8);
115impl_item!(i8, i8, I8, NullableI8);
116impl_item!(i16, i16, I16, NullableI16);
117impl_item!(i32, i32, I32, NullableI32);
118impl_item!(i64, i64, I64, NullableI64);
119impl_item!(Date, date, Date, NullableDate);
120impl_item!(Bit, bit, Bit, NullableBit);
121
122const DEFAULT_TIME_PRECISION: i16 = 7;
127
128impl Item for Time {
129 fn bind_param_desc(nullable: bool) -> BindParamDesc {
130 BindParamDesc::time(nullable, DEFAULT_TIME_PRECISION)
131 }
132
133 fn buffer_desc(nullable: bool) -> BufferDesc {
134 BufferDesc::Time { nullable }
135 }
136
137 fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]> {
138 if let AnySlice::Time(vals) = variant {
139 Some(vals)
140 } else {
141 None
142 }
143 }
144
145 fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<'_, Self>> {
146 if let AnySlice::NullableTime(vals) = variant {
147 Some(vals)
148 } else {
149 None
150 }
151 }
152
153 fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]> {
154 if let AnySliceMut::Time(vals) = variant {
155 Some(vals)
156 } else {
157 None
158 }
159 }
160
161 fn as_nullable_slice_mut(variant: AnySliceMut<'_>) -> Option<NullableSliceMut<'_, Self>> {
162 if let AnySliceMut::NullableTime(vals) = variant {
163 Some(vals)
164 } else {
165 None
166 }
167 }
168}
169
170impl Item for Timestamp {
171 fn bind_param_desc(nullable: bool) -> BindParamDesc {
172 BindParamDesc::timestamp(nullable, DEFAULT_TIME_PRECISION)
173 }
174
175 fn buffer_desc(nullable: bool) -> BufferDesc {
176 BufferDesc::Timestamp { nullable }
177 }
178
179 fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]> {
180 if let AnySlice::Timestamp(vals) = variant {
181 Some(vals)
182 } else {
183 None
184 }
185 }
186
187 fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<'_, Self>> {
188 if let AnySlice::NullableTimestamp(vals) = variant {
189 Some(vals)
190 } else {
191 None
192 }
193 }
194
195 fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]> {
196 if let AnySliceMut::Timestamp(vals) = variant {
197 Some(vals)
198 } else {
199 None
200 }
201 }
202
203 fn as_nullable_slice_mut(variant: AnySliceMut<'_>) -> Option<NullableSliceMut<'_, Self>> {
204 if let AnySliceMut::NullableTimestamp(vals) = variant {
205 Some(vals)
206 } else {
207 None
208 }
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use crate::{
215 BindParamDesc,
216 sys::{Date, Time, Timestamp},
217 };
218
219 use super::{Bit, Item as _};
220
221 #[test]
222 fn item_to_bind_param_desc() {
223 assert_eq!(BindParamDesc::i32(false), i32::bind_param_desc(false));
224 assert_eq!(BindParamDesc::i32(true), i32::bind_param_desc(true));
225 assert_eq!(BindParamDesc::f64(false), f64::bind_param_desc(false));
226 assert_eq!(BindParamDesc::f32(false), f32::bind_param_desc(false));
227 assert_eq!(BindParamDesc::u8(false), u8::bind_param_desc(false));
228 assert_eq!(BindParamDesc::i8(false), i8::bind_param_desc(false));
229 assert_eq!(BindParamDesc::i16(false), i16::bind_param_desc(false));
230 assert_eq!(BindParamDesc::i64(false), i64::bind_param_desc(false));
231 assert_eq!(BindParamDesc::date(false), Date::bind_param_desc(false));
232 assert_eq!(BindParamDesc::bit(false), Bit::bind_param_desc(false));
233 assert_eq!(BindParamDesc::time(false, 7), Time::bind_param_desc(false));
234 assert_eq!(
235 BindParamDesc::timestamp(false, 7),
236 Timestamp::bind_param_desc(false)
237 );
238 }
239}