1use crate::{
2 buffers::{FetchRowMember, Indicator},
3 handles::{CData, CDataMut, DataType, HasDataType},
4 parameter::{CElement, OutputParameter},
5};
6use odbc_sys::{CDataType, Date, Numeric, Time, Timestamp};
7use std::{
8 ffi::c_void,
9 ptr::{null, null_mut},
10};
11
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Ord, PartialOrd)]
18pub struct Bit(pub u8);
19
20impl Bit {
21 pub fn from_bool(boolean: bool) -> Self {
30 if boolean {
31 Bit(1)
32 } else {
33 Bit(0)
34 }
35 }
36
37 pub fn as_bool(self) -> bool {
39 match self.0 {
40 0 => false,
41 1 => true,
42 _ => panic!("Invalid boolean representation in Bit."),
43 }
44 }
45}
46
47pub unsafe trait Pod: Default + Copy + CElement + CDataMut + 'static {
55 const C_DATA_TYPE: CDataType;
57}
58
59macro_rules! impl_pod {
60 ($t:ident, $c_data_type:expr) => {
61 unsafe impl CData for $t {
62 fn cdata_type(&self) -> CDataType {
63 $c_data_type
64 }
65
66 fn indicator_ptr(&self) -> *const isize {
67 null()
69 }
70
71 fn value_ptr(&self) -> *const c_void {
72 self as *const $t as *const c_void
73 }
74
75 fn buffer_length(&self) -> isize {
76 0
77 }
78 }
79
80 unsafe impl CDataMut for $t {
81 fn mut_indicator_ptr(&mut self) -> *mut isize {
83 null_mut()
84 }
85
86 fn mut_value_ptr(&mut self) -> *mut c_void {
88 self as *mut $t as *mut c_void
89 }
90 }
91
92 unsafe impl CElement for $t {
93 fn assert_completness(&self) {}
95 }
96
97 unsafe impl Pod for $t {
98 const C_DATA_TYPE: CDataType = $c_data_type;
99 }
100
101 unsafe impl FetchRowMember for $t {
102 fn indicator(&self) -> Option<Indicator> {
103 None
104 }
105 }
106 };
107}
108
109impl_pod!(f64, CDataType::Double);
110impl_pod!(f32, CDataType::Float);
111impl_pod!(Date, CDataType::TypeDate);
112impl_pod!(Timestamp, CDataType::TypeTimestamp);
113impl_pod!(Time, CDataType::TypeTime);
114impl_pod!(Numeric, CDataType::Numeric);
115impl_pod!(i16, CDataType::SShort);
116impl_pod!(u16, CDataType::UShort);
117impl_pod!(i32, CDataType::SLong);
118impl_pod!(u32, CDataType::ULong);
119impl_pod!(i8, CDataType::STinyInt);
120impl_pod!(u8, CDataType::UTinyInt);
121impl_pod!(Bit, CDataType::Bit);
122impl_pod!(i64, CDataType::SBigInt);
123impl_pod!(u64, CDataType::UBigInt);
124
125macro_rules! impl_input_fixed_sized {
130 ($t:ident, $data_type:expr) => {
131 impl HasDataType for $t {
132 fn data_type(&self) -> DataType {
133 $data_type
134 }
135 }
136
137 unsafe impl OutputParameter for $t {}
138 };
139}
140
141impl_input_fixed_sized!(f64, DataType::Double);
142impl_input_fixed_sized!(f32, DataType::Real);
143impl_input_fixed_sized!(Date, DataType::Date);
144impl_input_fixed_sized!(i16, DataType::SmallInt);
145impl_input_fixed_sized!(i32, DataType::Integer);
146impl_input_fixed_sized!(i8, DataType::TinyInt);
147impl_input_fixed_sized!(Bit, DataType::Bit);
148impl_input_fixed_sized!(i64, DataType::BigInt);
149
150#[cfg(test)]
154mod tests {
155
156 use super::Bit;
157
158 #[test]
160 #[should_panic(expected = "Invalid boolean representation in Bit.")]
161 fn invalid_bit() {
162 let bit = Bit(2);
163 bit.as_bool();
164 }
165}