use crate::{
fixed_sized::{Bit, FixedSizedCType},
handles::{CData, CDataMut},
};
use odbc_sys::{Date, Numeric, Time, Timestamp, NULL_DATA};
use std::{
convert::TryInto,
ffi::c_void,
mem::size_of,
ptr::{null, null_mut},
};
pub type OptF64Column = OptFixedSizedColumn<f64>;
pub type OptF32Column = OptFixedSizedColumn<f32>;
pub type OptDateColumn = OptFixedSizedColumn<Date>;
pub type OptTimestampColumn = OptFixedSizedColumn<Timestamp>;
pub type OptTimeColumn = OptFixedSizedColumn<Time>;
pub type OptI32Column = OptFixedSizedColumn<i32>;
pub type OptI64Column = OptFixedSizedColumn<i64>;
pub type OptNumericColumn = OptFixedSizedColumn<Numeric>;
pub type OptU8Column = OptFixedSizedColumn<u8>;
pub type OptI8Column = OptFixedSizedColumn<i8>;
pub type OptBitColumn = OptFixedSizedColumn<Bit>;
pub struct OptFixedSizedColumn<T> {
values: Vec<T>,
indicators: Vec<isize>,
}
impl<T> OptFixedSizedColumn<T>
where
T: Default + Clone,
{
pub fn new(batch_size: usize) -> Self {
Self {
values: vec![T::default(); batch_size],
indicators: vec![NULL_DATA; batch_size],
}
}
pub unsafe fn value_at(&self, row_index: usize) -> Option<&T> {
if self.indicators[row_index] == NULL_DATA {
None
} else {
Some(&self.values[row_index])
}
}
pub fn values(&self) -> &[T] {
&self.values
}
pub fn indicators(&self) -> &[isize] {
&self.indicators
}
}
unsafe impl<T> CData for OptFixedSizedColumn<T>
where
T: FixedSizedCType,
{
fn cdata_type(&self) -> odbc_sys::CDataType {
T::C_DATA_TYPE
}
fn indicator_ptr(&self) -> *const isize {
self.indicators.as_ptr() as *const isize
}
fn value_ptr(&self) -> *const c_void {
self.values.as_ptr() as *const c_void
}
fn buffer_length(&self) -> isize {
size_of::<T>().try_into().unwrap()
}
}
unsafe impl<T> CDataMut for OptFixedSizedColumn<T>
where
T: FixedSizedCType,
{
fn mut_indicator_ptr(&mut self) -> *mut isize {
self.indicators.as_mut_ptr() as *mut isize
}
fn mut_value_ptr(&mut self) -> *mut c_void {
self.values.as_mut_ptr() as *mut c_void
}
}
unsafe impl<T> CData for Vec<T>
where
T: FixedSizedCType,
{
fn cdata_type(&self) -> odbc_sys::CDataType {
T::C_DATA_TYPE
}
fn indicator_ptr(&self) -> *const isize {
null()
}
fn value_ptr(&self) -> *const c_void {
self.as_ptr() as *const c_void
}
fn buffer_length(&self) -> isize {
size_of::<T>().try_into().unwrap()
}
}
unsafe impl<T> CDataMut for Vec<T>
where
T: FixedSizedCType,
{
fn mut_indicator_ptr(&mut self) -> *mut isize {
null_mut()
}
fn mut_value_ptr(&mut self) -> *mut c_void {
self.as_mut_ptr() as *mut c_void
}
}