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 { Bit(1) } else { Bit(0) }
31 }
32
33 pub fn as_bool(self) -> bool {
35 match self.0 {
36 0 => false,
37 1 => true,
38 _ => panic!("Invalid boolean representation in Bit."),
39 }
40 }
41}
42
43pub unsafe trait Pod: Default + Copy + CElement + CDataMut + 'static {
51 const C_DATA_TYPE: CDataType;
53}
54
55macro_rules! impl_pod {
56 ($t:ident, $c_data_type:expr) => {
57 unsafe impl CData for $t {
58 fn cdata_type(&self) -> CDataType {
59 $c_data_type
60 }
61
62 fn indicator_ptr(&self) -> *const isize {
63 null()
65 }
66
67 fn value_ptr(&self) -> *const c_void {
68 self as *const $t as *const c_void
69 }
70
71 fn buffer_length(&self) -> isize {
72 0
73 }
74 }
75
76 unsafe impl CDataMut for $t {
77 fn mut_indicator_ptr(&mut self) -> *mut isize {
79 null_mut()
80 }
81
82 fn mut_value_ptr(&mut self) -> *mut c_void {
84 self as *mut $t as *mut c_void
85 }
86 }
87
88 unsafe impl CElement for $t {
89 fn assert_completness(&self) {}
91 }
92
93 unsafe impl Pod for $t {
94 const C_DATA_TYPE: CDataType = $c_data_type;
95 }
96
97 unsafe impl FetchRowMember for $t {
98 fn indicator(&self) -> Option<Indicator> {
99 None
100 }
101 }
102 };
103}
104
105impl_pod!(f64, CDataType::Double);
106impl_pod!(f32, CDataType::Float);
107impl_pod!(Date, CDataType::TypeDate);
108impl_pod!(Timestamp, CDataType::TypeTimestamp);
109impl_pod!(Time, CDataType::TypeTime);
110impl_pod!(Numeric, CDataType::Numeric);
111impl_pod!(i16, CDataType::SShort);
112impl_pod!(u16, CDataType::UShort);
113impl_pod!(i32, CDataType::SLong);
114impl_pod!(u32, CDataType::ULong);
115impl_pod!(i8, CDataType::STinyInt);
116impl_pod!(u8, CDataType::UTinyInt);
117impl_pod!(Bit, CDataType::Bit);
118impl_pod!(i64, CDataType::SBigInt);
119impl_pod!(u64, CDataType::UBigInt);
120
121macro_rules! impl_input_fixed_sized {
126 ($t:ident, $data_type:expr) => {
127 impl HasDataType for $t {
128 fn data_type(&self) -> DataType {
129 $data_type
130 }
131 }
132
133 unsafe impl OutputParameter for $t {}
134 };
135}
136
137impl_input_fixed_sized!(f64, DataType::Double);
138impl_input_fixed_sized!(f32, DataType::Real);
139impl_input_fixed_sized!(Date, DataType::Date);
140impl_input_fixed_sized!(i16, DataType::SmallInt);
141impl_input_fixed_sized!(i32, DataType::Integer);
142impl_input_fixed_sized!(i8, DataType::TinyInt);
143impl_input_fixed_sized!(Bit, DataType::Bit);
144impl_input_fixed_sized!(i64, DataType::BigInt);
145
146#[cfg(test)]
150mod tests {
151
152 use super::Bit;
153
154 #[test]
156 #[should_panic(expected = "Invalid boolean representation in Bit.")]
157 fn invalid_bit() {
158 let bit = Bit(2);
159 bit.as_bool();
160 }
161}