odbc_api/buffers/
dyn_column_buffer.rs1use super::{
2 BinColumn, BinColumnSlice, BufferDesc, ColumnBuffer, ColumnarBuffer, Indicator, NullableSlice,
3 Slice, TextColumn, TextColumnSlice, column_with_indicator::ColumnWithIndicator,
4};
5
6use crate::{
7 Error,
8 fixed_sized::Pod,
9 handles::{CData, CDataMut},
10};
11
12use std::{any::Any, collections::HashSet, ffi::c_void};
13
14pub type ColumnarDynBuffer = ColumnarBuffer<BoxColumnBuffer>;
19
20impl ColumnarDynBuffer {
21 pub fn from_descs(capacity: usize, descs: impl IntoIterator<Item = BufferDesc>) -> Self {
23 let mut column_index = 0;
24 let columns = descs
25 .into_iter()
26 .map(move |desc| {
27 let buffer = desc.column_buffer(capacity);
28 column_index += 1;
29 (column_index, buffer)
30 })
31 .collect();
32 unsafe { ColumnarBuffer::new_unchecked(capacity, columns) }
33 }
34
35 pub fn try_from_descs(
40 capacity: usize,
41 descs: impl IntoIterator<Item = BufferDesc>,
42 ) -> Result<Self, Error> {
43 let mut column_index = 0;
44 let columns = descs
45 .into_iter()
46 .map(move |desc| {
47 let buffer = desc
48 .try_column_buffer(capacity)
49 .map_err(|source| source.add_context(column_index))?;
50 column_index += 1;
51 Ok::<_, Error>((column_index, buffer))
52 })
53 .collect::<Result<_, _>>()?;
54 Ok(unsafe { ColumnarBuffer::new_unchecked(capacity, columns) })
55 }
56
57 pub fn from_descs_and_indices(
62 max_rows: usize,
63 description: impl Iterator<Item = (u16, BufferDesc)>,
64 ) -> Self {
65 let columns: Vec<_> = description
66 .map(|(col_index, buffer_desc)| (col_index, buffer_desc.column_buffer(max_rows)))
67 .collect();
68
69 let mut indices = HashSet::new();
71 if columns
72 .iter()
73 .any(move |&(col_index, _)| !indices.insert(col_index))
74 {
75 panic!("Column indices must be unique.")
76 }
77
78 ColumnarBuffer::new(columns)
79 }
80}
81
82pub type BoxColumnBuffer = Box<dyn AnyColumnBuffer>;
86
87pub trait AnyColumnBuffer: ColumnBuffer + Any + Send {}
96
97impl<T> AnyColumnBuffer for T where T: ColumnBuffer + Any + Send {}
98
99unsafe impl CData for Box<dyn AnyColumnBuffer> {
100 fn cdata_type(&self) -> odbc_sys::CDataType {
101 self.as_ref().cdata_type()
102 }
103
104 fn indicator_ptr(&self) -> *const isize {
105 self.as_ref().indicator_ptr()
106 }
107
108 fn value_ptr(&self) -> *const c_void {
109 self.as_ref().value_ptr()
110 }
111
112 fn buffer_length(&self) -> isize {
113 self.as_ref().buffer_length()
114 }
115}
116
117unsafe impl CDataMut for Box<dyn AnyColumnBuffer> {
118 fn mut_indicator_ptr(&mut self) -> *mut isize {
119 self.as_mut().mut_indicator_ptr()
120 }
121
122 fn mut_value_ptr(&mut self) -> *mut c_void {
123 self.as_mut().mut_value_ptr()
124 }
125}
126
127unsafe impl ColumnBuffer for Box<dyn AnyColumnBuffer> {
128 fn capacity(&self) -> usize {
129 self.as_ref().capacity()
130 }
131
132 fn has_truncated_values(&self, num_rows: usize) -> Option<Indicator> {
133 self.as_ref().has_truncated_values(num_rows)
134 }
135}
136
137unsafe impl Slice for Box<dyn AnyColumnBuffer> {
138 type Slice<'a> = AnyColumnBufferSlice<'a>;
139
140 fn slice(&self, valid_rows: usize) -> AnyColumnBufferSlice<'_> {
141 AnyColumnBufferSlice {
142 buffer: self,
143 valid_rows,
144 }
145 }
146}
147
148#[derive(Clone, Copy)]
151pub struct AnyColumnBufferSlice<'a> {
152 buffer: &'a BoxColumnBuffer,
153 valid_rows: usize,
154}
155
156impl<'a> AnyColumnBufferSlice<'a> {
157 pub fn of<T>(self) -> Option<T::Slice<'a>>
159 where
160 T: Slice + 'static,
161 {
162 let buffer: &dyn Any = self.buffer.as_ref();
163 let buffer = buffer.downcast_ref::<T>()?;
164 Some(T::slice(buffer, self.valid_rows))
165 }
166
167 pub fn as_text(self) -> Option<TextColumnSlice<'a, u8>> {
173 self.of::<TextColumn<u8>>()
174 }
175
176 pub fn as_wide_text(self) -> Option<TextColumnSlice<'a, u16>> {
182 self.of::<TextColumn<u16>>()
183 }
184
185 pub fn as_binary(self) -> Option<BinColumnSlice<'a>> {
190 self.of::<BinColumn>()
191 }
192
193 pub fn as_slice<T>(self) -> Option<&'a [T]>
195 where
196 T: Pod,
197 {
198 self.of::<Vec<T>>()
199 }
200
201 pub fn as_nullable_slice<T>(self) -> Option<NullableSlice<'a, T>>
203 where
204 T: Pod,
205 {
206 self.of::<ColumnWithIndicator<T>>()
207 }
208}
209
210#[cfg(test)]
211mod tests {
212
213 use super::{BufferDesc, ColumnarDynBuffer};
214
215 #[test]
216 #[should_panic(expected = "Column indices must be unique.")]
217 fn assert_unique_column_indices() {
218 let bd = BufferDesc::I32 { nullable: false };
219 ColumnarDynBuffer::from_descs_and_indices(1, [(1, bd), (2, bd), (1, bd)].iter().cloned());
220 }
221}