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 fn buffer_desc(nullable: bool) -> BufferDesc;
54
55 fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]>;
57 fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<'_, Self>>;
59
60 fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]>;
62
63 fn as_nullable_slice_mut(variant: AnySliceMut<'_>) -> Option<NullableSliceMut<'_, Self>>;
65}
66
67macro_rules! impl_item {
68 ($t:ident, $bind:ident, $plain:ident, $null:ident) => {
69 impl Item for $t {
70 fn bind_param_desc(nullable: bool) -> BindParamDesc {
71 BindParamDesc::$bind(nullable)
72 }
73
74 fn buffer_desc(nullable: bool) -> BufferDesc {
75 BufferDesc::$plain { nullable }
76 }
77
78 fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]> {
79 match variant {
80 AnySlice::$plain(vals) => Some(vals),
81 _ => None,
82 }
83 }
84
85 fn as_nullable_slice(variant: AnySlice<'_>) -> Option<NullableSlice<'_, Self>> {
86 match variant {
87 AnySlice::$null(vals) => Some(vals),
88 _ => None,
89 }
90 }
91
92 fn as_slice_mut(variant: AnySliceMut<'_>) -> Option<&'_ mut [Self]> {
93 match variant {
94 AnySliceMut::$plain(vals) => Some(vals),
95 _ => None,
96 }
97 }
98
99 fn as_nullable_slice_mut(
100 variant: AnySliceMut<'_>,
101 ) -> Option<NullableSliceMut<'_, Self>> {
102 match variant {
103 AnySliceMut::$null(vals) => Some(vals),
104 _ => None,
105 }
106 }
107 }
108 };
109}
110
111impl_item!(f64, f64, F64, NullableF64);
112impl_item!(f32, f32, F32, NullableF32);
113impl_item!(u8, u8, U8, NullableU8);
114impl_item!(i8, i8, I8, NullableI8);
115impl_item!(i16, i16, I16, NullableI16);
116impl_item!(i32, i32, I32, NullableI32);
117impl_item!(i64, i64, I64, NullableI64);
118impl_item!(Date, date, Date, NullableDate);
119impl_item!(Time, time, Time, NullableTime);
120impl_item!(Bit, bit, Bit, NullableBit);
121
122const DEFAULT_TIME_PRECISION: i16 = 7;
127
128impl Item for Timestamp {
129 fn bind_param_desc(nullable: bool) -> BindParamDesc {
130 BindParamDesc::timestamp(nullable, DEFAULT_TIME_PRECISION)
131 }
132
133 fn buffer_desc(nullable: bool) -> BufferDesc {
134 BufferDesc::Timestamp { nullable }
135 }
136
137 fn as_slice(variant: AnySlice<'_>) -> Option<&[Self]> {
138 if let AnySlice::Timestamp(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::NullableTimestamp(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::Timestamp(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::NullableTimestamp(vals) = variant {
163 Some(vals)
164 } else {
165 None
166 }
167 }
168}
169
170#[cfg(test)]
171mod tests {
172 use crate::{
173 BindParamDesc,
174 buffers::item::DEFAULT_TIME_PRECISION,
175 sys::{Date, Time, Timestamp},
176 };
177
178 use super::{Bit, Item as _};
179
180 #[test]
181 fn item_to_bind_param_desc() {
182 assert_eq!(BindParamDesc::i32(false), i32::bind_param_desc(false));
183 assert_eq!(BindParamDesc::i32(true), i32::bind_param_desc(true));
184 assert_eq!(BindParamDesc::f64(false), f64::bind_param_desc(false));
185 assert_eq!(BindParamDesc::f32(false), f32::bind_param_desc(false));
186 assert_eq!(BindParamDesc::u8(false), u8::bind_param_desc(false));
187 assert_eq!(BindParamDesc::i8(false), i8::bind_param_desc(false));
188 assert_eq!(BindParamDesc::i16(false), i16::bind_param_desc(false));
189 assert_eq!(BindParamDesc::i64(false), i64::bind_param_desc(false));
190 assert_eq!(BindParamDesc::date(false), Date::bind_param_desc(false));
191 assert_eq!(BindParamDesc::bit(false), Bit::bind_param_desc(false));
192 assert_eq!(BindParamDesc::time(false), Time::bind_param_desc(false));
193 assert_eq!(
194 BindParamDesc::timestamp(false, DEFAULT_TIME_PRECISION),
195 Timestamp::bind_param_desc(false)
196 );
197 }
198}