1use std::ffi::c_void;
2
3use odbc_sys::NULL_DATA;
4
5use crate::{
6 buffers::{FetchRowMember, Indicator},
7 fixed_sized::Pod,
8 handles::{CData, CDataMut, HasDataType},
9 parameter::CElement,
10 OutputParameter,
11};
12
13#[derive(Clone, Copy)]
16pub struct Nullable<T> {
17 indicator: isize,
18 value: T,
19}
20
21impl<T> Nullable<T> {
22 pub fn new(value: T) -> Self {
23 Self {
24 indicator: 0,
25 value,
26 }
27 }
28
29 pub fn null() -> Self
30 where
31 T: Default,
32 {
33 Self {
34 indicator: NULL_DATA,
35 value: Default::default(),
36 }
37 }
38
39 pub fn as_opt(&self) -> Option<&T> {
40 if self.indicator == NULL_DATA {
41 None
42 } else {
43 Some(&self.value)
44 }
45 }
46
47 pub fn into_opt(self) -> Option<T> {
48 if self.indicator == NULL_DATA {
49 None
50 } else {
51 Some(self.value)
52 }
53 }
54}
55
56impl<T> Default for Nullable<T>
57where
58 T: Default,
59{
60 fn default() -> Self {
61 Self::null()
62 }
63}
64
65unsafe impl<T> CData for Nullable<T>
66where
67 T: Pod,
68{
69 fn cdata_type(&self) -> odbc_sys::CDataType {
70 self.value.cdata_type()
71 }
72
73 fn indicator_ptr(&self) -> *const isize {
74 &self.indicator as *const isize
75 }
76
77 fn value_ptr(&self) -> *const c_void {
78 self.value.value_ptr()
79 }
80
81 fn buffer_length(&self) -> isize {
82 0
83 }
84}
85
86impl<T> HasDataType for Nullable<T>
87where
88 T: Pod + HasDataType,
89{
90 fn data_type(&self) -> crate::DataType {
91 self.value.data_type()
92 }
93}
94
95unsafe impl<T> CElement for Nullable<T>
96where
97 T: Pod,
98{
99 fn assert_completness(&self) {}
101}
102
103unsafe impl<T> CDataMut for Nullable<T>
104where
105 T: Pod,
106{
107 fn mut_indicator_ptr(&mut self) -> *mut isize {
108 &mut self.indicator as *mut isize
109 }
110
111 fn mut_value_ptr(&mut self) -> *mut c_void {
112 &mut self.value as *mut T as *mut c_void
113 }
114}
115
116unsafe impl<T> OutputParameter for Nullable<T> where T: Pod + HasDataType {}
117
118unsafe impl<T> FetchRowMember for Nullable<T>
119where
120 T: Pod,
121{
122 fn indicator(&self) -> Option<crate::buffers::Indicator> {
123 Some(Indicator::from_isize(self.indicator))
124 }
125}