Skip to main content

odbc_api/buffers/
any_buffer.rs

1use std::{collections::HashSet, ffi::c_void};
2
3use odbc_sys::{CDataType, Date, Numeric, Time, Timestamp};
4
5use crate::{
6    Bit, Error,
7    buffers::columnar::Resize,
8    columnar_bulk_inserter::BoundInputSlice,
9    error::TooLargeBufferSize,
10    handles::{CData, CDataMut, StatementRef},
11};
12
13use super::{
14    BinColumn, BinColumnView, BufferDesc, CharColumn, ColumnarBuffer, Indicator, Item,
15    NullableSlice, NullableSliceMut, TextColumn, TextColumnView, WCharColumn,
16    bin_column::BinColumnSliceMut,
17    column_with_indicator::{
18        OptBitColumn, OptDateColumn, OptF32Column, OptF64Column, OptI8Column, OptI16Column,
19        OptI32Column, OptI64Column, OptTimeColumn, OptTimestampColumn, OptU8Column,
20    },
21    columnar::ColumnBuffer,
22    text_column::TextColumnSliceMut,
23};
24
25/// Buffer holding a single column of either a result set or parameter
26#[derive(Debug)]
27pub enum AnyBuffer {
28    /// A buffer for holding both nullable and required binary data.
29    Binary(BinColumn),
30    /// A buffer for holding both nullable and required text data. Uses the system encoding for
31    /// character data.
32    Text(CharColumn),
33    /// A buffer for holding both nullable and required text data. Uses UTF-16 encoding
34    WText(WCharColumn),
35    Date(Vec<Date>),
36    Time(Vec<Time>),
37    Timestamp(Vec<Timestamp>),
38    F64(Vec<f64>),
39    F32(Vec<f32>),
40    I8(Vec<i8>),
41    I16(Vec<i16>),
42    I32(Vec<i32>),
43    I64(Vec<i64>),
44    U8(Vec<u8>),
45    Bit(Vec<Bit>),
46    Numeric(Vec<Numeric>),
47    NullableDate(OptDateColumn),
48    NullableTime(OptTimeColumn),
49    NullableTimestamp(OptTimestampColumn),
50    NullableF64(OptF64Column),
51    NullableF32(OptF32Column),
52    NullableI8(OptI8Column),
53    NullableI16(OptI16Column),
54    NullableI32(OptI32Column),
55    NullableI64(OptI64Column),
56    NullableU8(OptU8Column),
57    NullableBit(OptBitColumn),
58}
59
60impl AnyBuffer {
61    /// Map buffer description to actual buffer.
62    pub fn try_from_desc(max_rows: usize, desc: BufferDesc) -> Result<Self, TooLargeBufferSize> {
63        let fallible_allocations = true;
64        Self::impl_from_desc(max_rows, desc, fallible_allocations)
65    }
66
67    /// Map buffer description to actual buffer.
68    pub fn from_desc(max_rows: usize, desc: BufferDesc) -> Self {
69        let fallible_allocations = false;
70        Self::impl_from_desc(max_rows, desc, fallible_allocations).unwrap()
71    }
72
73    /// Map buffer description to actual buffer.
74    fn impl_from_desc(
75        max_rows: usize,
76        desc: BufferDesc,
77        fallible_allocations: bool,
78    ) -> Result<Self, TooLargeBufferSize> {
79        let buffer = match desc {
80            BufferDesc::Binary { max_bytes } => {
81                if fallible_allocations {
82                    AnyBuffer::Binary(BinColumn::try_new(max_rows, max_bytes)?)
83                } else {
84                    AnyBuffer::Binary(BinColumn::new(max_rows, max_bytes))
85                }
86            }
87            BufferDesc::Text { max_str_len } => {
88                if fallible_allocations {
89                    AnyBuffer::Text(TextColumn::try_new(max_rows, max_str_len)?)
90                } else {
91                    AnyBuffer::Text(TextColumn::new(max_rows, max_str_len))
92                }
93            }
94            BufferDesc::WText { max_str_len } => {
95                if fallible_allocations {
96                    AnyBuffer::WText(TextColumn::try_new(max_rows, max_str_len)?)
97                } else {
98                    AnyBuffer::WText(TextColumn::new(max_rows, max_str_len))
99                }
100            }
101            BufferDesc::Date { nullable: false } => {
102                AnyBuffer::Date(vec![Date::default(); max_rows])
103            }
104            BufferDesc::Time { nullable: false } => {
105                AnyBuffer::Time(vec![Time::default(); max_rows])
106            }
107            BufferDesc::Timestamp { nullable: false } => {
108                AnyBuffer::Timestamp(vec![Timestamp::default(); max_rows])
109            }
110            BufferDesc::F64 { nullable: false } => AnyBuffer::F64(vec![f64::default(); max_rows]),
111            BufferDesc::F32 { nullable: false } => AnyBuffer::F32(vec![f32::default(); max_rows]),
112            BufferDesc::I8 { nullable: false } => AnyBuffer::I8(vec![i8::default(); max_rows]),
113            BufferDesc::I16 { nullable: false } => AnyBuffer::I16(vec![i16::default(); max_rows]),
114            BufferDesc::I32 { nullable: false } => AnyBuffer::I32(vec![i32::default(); max_rows]),
115            BufferDesc::I64 { nullable: false } => AnyBuffer::I64(vec![i64::default(); max_rows]),
116            BufferDesc::U8 { nullable: false } => AnyBuffer::U8(vec![u8::default(); max_rows]),
117            BufferDesc::Bit { nullable: false } => AnyBuffer::Bit(vec![Bit::default(); max_rows]),
118            BufferDesc::Numeric => AnyBuffer::Numeric(vec![Numeric::default(); max_rows]),
119            BufferDesc::Date { nullable: true } => {
120                AnyBuffer::NullableDate(OptDateColumn::new(max_rows))
121            }
122            BufferDesc::Time { nullable: true } => {
123                AnyBuffer::NullableTime(OptTimeColumn::new(max_rows))
124            }
125            BufferDesc::Timestamp { nullable: true } => {
126                AnyBuffer::NullableTimestamp(OptTimestampColumn::new(max_rows))
127            }
128            BufferDesc::F64 { nullable: true } => {
129                AnyBuffer::NullableF64(OptF64Column::new(max_rows))
130            }
131            BufferDesc::F32 { nullable: true } => {
132                AnyBuffer::NullableF32(OptF32Column::new(max_rows))
133            }
134            BufferDesc::I8 { nullable: true } => AnyBuffer::NullableI8(OptI8Column::new(max_rows)),
135            BufferDesc::I16 { nullable: true } => {
136                AnyBuffer::NullableI16(OptI16Column::new(max_rows))
137            }
138            BufferDesc::I32 { nullable: true } => {
139                AnyBuffer::NullableI32(OptI32Column::new(max_rows))
140            }
141            BufferDesc::I64 { nullable: true } => {
142                AnyBuffer::NullableI64(OptI64Column::new(max_rows))
143            }
144            BufferDesc::U8 { nullable: true } => AnyBuffer::NullableU8(OptU8Column::new(max_rows)),
145            BufferDesc::Bit { nullable: true } => {
146                AnyBuffer::NullableBit(OptBitColumn::new(max_rows))
147            }
148        };
149        Ok(buffer)
150    }
151
152    fn inner(&self) -> &dyn CData {
153        match self {
154            AnyBuffer::Binary(col) => col,
155            AnyBuffer::Text(col) => col,
156            AnyBuffer::WText(col) => col,
157            AnyBuffer::F64(col) => col,
158            AnyBuffer::F32(col) => col,
159            AnyBuffer::Date(col) => col,
160            AnyBuffer::Time(col) => col,
161            AnyBuffer::Timestamp(col) => col,
162            AnyBuffer::I8(col) => col,
163            AnyBuffer::I16(col) => col,
164            AnyBuffer::I32(col) => col,
165            AnyBuffer::I64(col) => col,
166            AnyBuffer::Bit(col) => col,
167            AnyBuffer::U8(col) => col,
168            AnyBuffer::Numeric(col) => col,
169            AnyBuffer::NullableF64(col) => col,
170            AnyBuffer::NullableF32(col) => col,
171            AnyBuffer::NullableDate(col) => col,
172            AnyBuffer::NullableTime(col) => col,
173            AnyBuffer::NullableTimestamp(col) => col,
174            AnyBuffer::NullableI8(col) => col,
175            AnyBuffer::NullableI16(col) => col,
176            AnyBuffer::NullableI32(col) => col,
177            AnyBuffer::NullableI64(col) => col,
178            AnyBuffer::NullableBit(col) => col,
179            AnyBuffer::NullableU8(col) => col,
180        }
181    }
182
183    fn inner_mut(&mut self) -> &mut dyn AnyBufferVariantMut {
184        match self {
185            AnyBuffer::Binary(col) => col,
186            AnyBuffer::Text(col) => col,
187            AnyBuffer::WText(col) => col,
188            AnyBuffer::F64(col) => col,
189            AnyBuffer::F32(col) => col,
190            AnyBuffer::Date(col) => col,
191            AnyBuffer::Time(col) => col,
192            AnyBuffer::Timestamp(col) => col,
193            AnyBuffer::I8(col) => col,
194            AnyBuffer::I16(col) => col,
195            AnyBuffer::I32(col) => col,
196            AnyBuffer::I64(col) => col,
197            AnyBuffer::Bit(col) => col,
198            AnyBuffer::U8(col) => col,
199            AnyBuffer::Numeric(col) => col,
200            AnyBuffer::NullableF64(col) => col,
201            AnyBuffer::NullableF32(col) => col,
202            AnyBuffer::NullableDate(col) => col,
203            AnyBuffer::NullableTime(col) => col,
204            AnyBuffer::NullableTimestamp(col) => col,
205            AnyBuffer::NullableI8(col) => col,
206            AnyBuffer::NullableI16(col) => col,
207            AnyBuffer::NullableI32(col) => col,
208            AnyBuffer::NullableI64(col) => col,
209            AnyBuffer::NullableBit(col) => col,
210            AnyBuffer::NullableU8(col) => col,
211        }
212    }
213}
214
215/// A trait implemented by all variants of [`AnyBuffer`]. This allows us to reduce the number of
216/// match statements for methods mutating [`AnyBuffer`], as we only need to implement
217/// [`AnyBuffer::inner_mut`].
218trait AnyBufferVariantMut: CDataMut + Resize {}
219
220impl<T> AnyBufferVariantMut for T where T: CDataMut + Resize {}
221
222unsafe impl CData for AnyBuffer {
223    fn cdata_type(&self) -> CDataType {
224        self.inner().cdata_type()
225    }
226
227    fn indicator_ptr(&self) -> *const isize {
228        self.inner().indicator_ptr()
229    }
230
231    fn value_ptr(&self) -> *const c_void {
232        self.inner().value_ptr()
233    }
234
235    fn buffer_length(&self) -> isize {
236        self.inner().buffer_length()
237    }
238}
239
240unsafe impl CDataMut for AnyBuffer {
241    fn mut_indicator_ptr(&mut self) -> *mut isize {
242        self.inner_mut().mut_indicator_ptr()
243    }
244
245    fn mut_value_ptr(&mut self) -> *mut c_void {
246        self.inner_mut().mut_value_ptr()
247    }
248}
249
250/// Flexible columnar buffer implementation. Bind this to a cursor to fetch values in bulk, or pass
251/// this as a parameter to a statement, to submit many parameters at once.
252pub type ColumnarAnyBuffer = ColumnarBuffer<AnyBuffer>;
253
254impl ColumnarAnyBuffer {
255    /// Allocates a [`ColumnarBuffer`] fitting the buffer descriptions.
256    pub fn from_descs(capacity: usize, descs: impl IntoIterator<Item = BufferDesc>) -> Self {
257        let mut column_index = 0;
258        let columns = descs
259            .into_iter()
260            .map(move |desc| {
261                let buffer = AnyBuffer::from_desc(capacity, desc);
262                column_index += 1;
263                (column_index, buffer)
264            })
265            .collect();
266        unsafe { ColumnarBuffer::new_unchecked(capacity, columns) }
267    }
268
269    /// Allocates a [`ColumnarBuffer`] fitting the buffer descriptions. If not enough memory is
270    /// available to allocate the buffers this function fails with
271    /// [`Error::TooLargeColumnBufferSize`]. This function is slower than [`Self::from_descs`]
272    /// which would just panic if not enough memory is available for allocation.
273    pub fn try_from_descs(
274        capacity: usize,
275        descs: impl IntoIterator<Item = BufferDesc>,
276    ) -> Result<Self, Error> {
277        let mut column_index = 0;
278        let columns = descs
279            .into_iter()
280            .map(move |desc| {
281                let buffer = AnyBuffer::try_from_desc(capacity, desc)
282                    .map_err(|source| source.add_context(column_index))?;
283                column_index += 1;
284                Ok::<_, Error>((column_index, buffer))
285            })
286            .collect::<Result<_, _>>()?;
287        Ok(unsafe { ColumnarBuffer::new_unchecked(capacity, columns) })
288    }
289
290    /// Allows you to pass the buffer descriptions together with a one based column index referring
291    /// the column, the buffer is supposed to bind to. This allows you also to ignore columns in a
292    /// result set, by not binding them at all. There is no restriction on the order of column
293    /// indices passed, but the function will panic, if the indices are not unique.
294    pub fn from_descs_and_indices(
295        max_rows: usize,
296        description: impl Iterator<Item = (u16, BufferDesc)>,
297    ) -> ColumnarBuffer<AnyBuffer> {
298        let columns: Vec<_> = description
299            .map(|(col_index, buffer_desc)| {
300                (col_index, AnyBuffer::from_desc(max_rows, buffer_desc))
301            })
302            .collect();
303
304        // Assert uniqueness of indices
305        let mut indices = HashSet::new();
306        if columns
307            .iter()
308            .any(move |&(col_index, _)| !indices.insert(col_index))
309        {
310            panic!("Column indices must be unique.")
311        }
312
313        ColumnarBuffer::new(columns)
314    }
315}
316
317/// A borrowed view on the valid rows in a column of a [`crate::buffers::ColumnarBuffer`].
318///
319/// For columns of fixed size types, which are guaranteed to not contain null, a direct access to
320/// the slice is offered. Buffers over nullable columns can be accessed via an iterator over
321/// options.
322#[derive(Debug, Clone, Copy)]
323pub enum AnySlice<'a> {
324    /// Nullable character data in the system encoding.
325    Text(TextColumnView<'a, u8>),
326    /// Nullable character data encoded in UTF-16.
327    WText(TextColumnView<'a, u16>),
328    Binary(BinColumnView<'a>),
329    Date(&'a [Date]),
330    Time(&'a [Time]),
331    Timestamp(&'a [Timestamp]),
332    F64(&'a [f64]),
333    F32(&'a [f32]),
334    I8(&'a [i8]),
335    I16(&'a [i16]),
336    I32(&'a [i32]),
337    I64(&'a [i64]),
338    U8(&'a [u8]),
339    Bit(&'a [Bit]),
340    Numeric(&'a [Numeric]),
341    NullableDate(NullableSlice<'a, Date>),
342    NullableTime(NullableSlice<'a, Time>),
343    NullableTimestamp(NullableSlice<'a, Timestamp>),
344    NullableF64(NullableSlice<'a, f64>),
345    NullableF32(NullableSlice<'a, f32>),
346    NullableI8(NullableSlice<'a, i8>),
347    NullableI16(NullableSlice<'a, i16>),
348    NullableI32(NullableSlice<'a, i32>),
349    NullableI64(NullableSlice<'a, i64>),
350    NullableU8(NullableSlice<'a, u8>),
351    NullableBit(NullableSlice<'a, Bit>),
352    NullableNumeric(NullableSlice<'a, Numeric>),
353}
354
355impl<'a> AnySlice<'a> {
356    /// This method is useful if you expect the variant to be [`AnySlice::Text`]. It allows you to
357    /// unwrap the inner column view without explictly matching it.
358    pub fn as_text_view(self) -> Option<TextColumnView<'a, u8>> {
359        if let Self::Text(view) = self {
360            Some(view)
361        } else {
362            None
363        }
364    }
365
366    /// This method is useful if you expect the variant to be [`AnySlice::WText`]. It allows you to
367    /// unwrap the inner column view without explictly matching it.
368    pub fn as_w_text_view(self) -> Option<TextColumnView<'a, u16>> {
369        if let Self::WText(view) = self {
370            Some(view)
371        } else {
372            None
373        }
374    }
375
376    /// This method is useful if you expect the variant to be [`AnySlice::Binary`]. It allows you to
377    /// unwrap the inner column view without explictly matching it.
378    pub fn as_bin_view(self) -> Option<BinColumnView<'a>> {
379        if let Self::Binary(view) = self {
380            Some(view)
381        } else {
382            None
383        }
384    }
385
386    /// Extract the array type from an [`AnySlice`].
387    pub fn as_slice<I: Item>(self) -> Option<&'a [I]> {
388        I::as_slice(self)
389    }
390
391    /// Extract the typed nullable buffer from an [`AnySlice`].
392    pub fn as_nullable_slice<I: Item>(self) -> Option<NullableSlice<'a, I>> {
393        I::as_nullable_slice(self)
394    }
395}
396
397unsafe impl<'a> BoundInputSlice<'a> for AnyBuffer {
398    type SliceMut = AnySliceMut<'a>;
399
400    unsafe fn as_view_mut(
401        &'a mut self,
402        parameter_index: u16,
403        stmt: StatementRef<'a>,
404    ) -> Self::SliceMut {
405        let num_rows = self.capacity();
406        unsafe {
407            match self {
408                AnyBuffer::Binary(column) => {
409                    AnySliceMut::Binary(column.as_view_mut(parameter_index, stmt))
410                }
411                AnyBuffer::Text(column) => {
412                    AnySliceMut::Text(column.as_view_mut(parameter_index, stmt))
413                }
414                AnyBuffer::WText(column) => {
415                    AnySliceMut::WText(column.as_view_mut(parameter_index, stmt))
416                }
417                AnyBuffer::Date(column) => AnySliceMut::Date(column),
418                AnyBuffer::Time(column) => AnySliceMut::Time(column),
419                AnyBuffer::Timestamp(column) => AnySliceMut::Timestamp(column),
420                AnyBuffer::F64(column) => AnySliceMut::F64(column),
421                AnyBuffer::F32(column) => AnySliceMut::F32(column),
422                AnyBuffer::I8(column) => AnySliceMut::I8(column),
423                AnyBuffer::I16(column) => AnySliceMut::I16(column),
424                AnyBuffer::I32(column) => AnySliceMut::I32(column),
425                AnyBuffer::I64(column) => AnySliceMut::I64(column),
426                AnyBuffer::U8(column) => AnySliceMut::U8(column),
427                AnyBuffer::Bit(column) => AnySliceMut::Bit(column),
428                AnyBuffer::Numeric(column) => AnySliceMut::Numeric(column),
429                AnyBuffer::NullableDate(column) => {
430                    AnySliceMut::NullableDate(column.writer_n(num_rows))
431                }
432                AnyBuffer::NullableTime(column) => {
433                    AnySliceMut::NullableTime(column.writer_n(num_rows))
434                }
435                AnyBuffer::NullableTimestamp(column) => {
436                    AnySliceMut::NullableTimestamp(column.writer_n(num_rows))
437                }
438                AnyBuffer::NullableF64(column) => {
439                    AnySliceMut::NullableF64(column.writer_n(num_rows))
440                }
441                AnyBuffer::NullableF32(column) => {
442                    AnySliceMut::NullableF32(column.writer_n(num_rows))
443                }
444                AnyBuffer::NullableI8(column) => AnySliceMut::NullableI8(column.writer_n(num_rows)),
445                AnyBuffer::NullableI16(column) => {
446                    AnySliceMut::NullableI16(column.writer_n(num_rows))
447                }
448                AnyBuffer::NullableI32(column) => {
449                    AnySliceMut::NullableI32(column.writer_n(num_rows))
450                }
451                AnyBuffer::NullableI64(column) => {
452                    AnySliceMut::NullableI64(column.writer_n(num_rows))
453                }
454                AnyBuffer::NullableU8(column) => AnySliceMut::NullableU8(column.writer_n(num_rows)),
455                AnyBuffer::NullableBit(column) => {
456                    AnySliceMut::NullableBit(column.writer_n(num_rows))
457                }
458            }
459        }
460    }
461}
462
463/// A mutable slice of an input buffer, with runtime type information. Edit values in this slice in
464/// order to send parameters in bulk to a database.
465pub enum AnySliceMut<'a> {
466    Text(TextColumnSliceMut<'a, u8>),
467    /// Nullable character data encoded in UTF-16.
468    WText(TextColumnSliceMut<'a, u16>),
469    Binary(BinColumnSliceMut<'a>),
470    Date(&'a mut [Date]),
471    Time(&'a mut [Time]),
472    Timestamp(&'a mut [Timestamp]),
473    F64(&'a mut [f64]),
474    F32(&'a mut [f32]),
475    I8(&'a mut [i8]),
476    I16(&'a mut [i16]),
477    I32(&'a mut [i32]),
478    I64(&'a mut [i64]),
479    U8(&'a mut [u8]),
480    Bit(&'a mut [Bit]),
481    Numeric(&'a mut [Numeric]),
482    NullableDate(NullableSliceMut<'a, Date>),
483    NullableTime(NullableSliceMut<'a, Time>),
484    NullableTimestamp(NullableSliceMut<'a, Timestamp>),
485    NullableF64(NullableSliceMut<'a, f64>),
486    NullableF32(NullableSliceMut<'a, f32>),
487    NullableI8(NullableSliceMut<'a, i8>),
488    NullableI16(NullableSliceMut<'a, i16>),
489    NullableI32(NullableSliceMut<'a, i32>),
490    NullableI64(NullableSliceMut<'a, i64>),
491    NullableU8(NullableSliceMut<'a, u8>),
492    NullableBit(NullableSliceMut<'a, Bit>),
493}
494
495impl<'a> AnySliceMut<'a> {
496    /// This method is useful if you expect the variant to be [`AnySliceMut::Binary`]. It allows you
497    /// to unwrap the inner column view without explictly matching it.
498    pub fn as_bin_view(self) -> Option<BinColumnSliceMut<'a>> {
499        if let Self::Binary(view) = self {
500            Some(view)
501        } else {
502            None
503        }
504    }
505
506    /// This method is useful if you expect the variant to be [`AnySliceMut::Text`]. It allows you
507    /// to unwrap the inner column view without explictly matching it.
508    pub fn as_text_view(self) -> Option<TextColumnSliceMut<'a, u8>> {
509        if let Self::Text(view) = self {
510            Some(view)
511        } else {
512            None
513        }
514    }
515
516    /// This method is useful if you expect the variant to be [`AnySliceMut::WText`]. It allows you
517    /// to unwrap the inner column view without explictly matching it.
518    pub fn as_w_text_view(self) -> Option<TextColumnSliceMut<'a, u16>> {
519        if let Self::WText(view) = self {
520            Some(view)
521        } else {
522            None
523        }
524    }
525
526    /// Extract the array type from an [`AnySliceMut`].
527    pub fn as_slice<I: Item>(self) -> Option<&'a mut [I]> {
528        I::as_slice_mut(self)
529    }
530
531    /// Extract the typed nullable buffer from an [`AnySliceMut`].
532    pub fn as_nullable_slice<I: Item>(self) -> Option<NullableSliceMut<'a, I>> {
533        I::as_nullable_slice_mut(self)
534    }
535}
536
537unsafe impl ColumnBuffer for AnyBuffer {
538    type View<'a> = AnySlice<'a>;
539
540    fn capacity(&self) -> usize {
541        match self {
542            AnyBuffer::Binary(col) => col.capacity(),
543            AnyBuffer::Text(col) => col.capacity(),
544            AnyBuffer::WText(col) => col.capacity(),
545            AnyBuffer::Date(col) => col.capacity(),
546            AnyBuffer::Time(col) => col.capacity(),
547            AnyBuffer::Timestamp(col) => col.capacity(),
548            AnyBuffer::F64(col) => col.capacity(),
549            AnyBuffer::F32(col) => col.capacity(),
550            AnyBuffer::I8(col) => col.capacity(),
551            AnyBuffer::I16(col) => col.capacity(),
552            AnyBuffer::I32(col) => col.capacity(),
553            AnyBuffer::I64(col) => col.capacity(),
554            AnyBuffer::U8(col) => col.capacity(),
555            AnyBuffer::Bit(col) => col.capacity(),
556            AnyBuffer::Numeric(col) => col.capacity(),
557            AnyBuffer::NullableDate(col) => col.capacity(),
558            AnyBuffer::NullableTime(col) => col.capacity(),
559            AnyBuffer::NullableTimestamp(col) => col.capacity(),
560            AnyBuffer::NullableF64(col) => col.capacity(),
561            AnyBuffer::NullableF32(col) => col.capacity(),
562            AnyBuffer::NullableI8(col) => col.capacity(),
563            AnyBuffer::NullableI16(col) => col.capacity(),
564            AnyBuffer::NullableI32(col) => col.capacity(),
565            AnyBuffer::NullableI64(col) => col.capacity(),
566            AnyBuffer::NullableU8(col) => col.capacity(),
567            AnyBuffer::NullableBit(col) => col.capacity(),
568        }
569    }
570
571    fn view(&self, valid_rows: usize) -> AnySlice<'_> {
572        match self {
573            AnyBuffer::Binary(col) => AnySlice::Binary(col.view(valid_rows)),
574            AnyBuffer::Text(col) => AnySlice::Text(col.view(valid_rows)),
575            AnyBuffer::WText(col) => AnySlice::WText(col.view(valid_rows)),
576            AnyBuffer::Date(col) => AnySlice::Date(&col[0..valid_rows]),
577            AnyBuffer::Time(col) => AnySlice::Time(&col[0..valid_rows]),
578            AnyBuffer::Timestamp(col) => AnySlice::Timestamp(&col[0..valid_rows]),
579            AnyBuffer::F64(col) => AnySlice::F64(&col[0..valid_rows]),
580            AnyBuffer::F32(col) => AnySlice::F32(&col[0..valid_rows]),
581            AnyBuffer::I8(col) => AnySlice::I8(&col[0..valid_rows]),
582            AnyBuffer::I16(col) => AnySlice::I16(&col[0..valid_rows]),
583            AnyBuffer::I32(col) => AnySlice::I32(&col[0..valid_rows]),
584            AnyBuffer::I64(col) => AnySlice::I64(&col[0..valid_rows]),
585            AnyBuffer::U8(col) => AnySlice::U8(&col[0..valid_rows]),
586            AnyBuffer::Bit(col) => AnySlice::Bit(&col[0..valid_rows]),
587            AnyBuffer::Numeric(col) => AnySlice::Numeric(&col[0..valid_rows]),
588            AnyBuffer::NullableDate(col) => AnySlice::NullableDate(col.iter(valid_rows)),
589            AnyBuffer::NullableTime(col) => AnySlice::NullableTime(col.iter(valid_rows)),
590            AnyBuffer::NullableTimestamp(col) => AnySlice::NullableTimestamp(col.iter(valid_rows)),
591            AnyBuffer::NullableF64(col) => AnySlice::NullableF64(col.iter(valid_rows)),
592            AnyBuffer::NullableF32(col) => AnySlice::NullableF32(col.iter(valid_rows)),
593            AnyBuffer::NullableI8(col) => AnySlice::NullableI8(col.iter(valid_rows)),
594            AnyBuffer::NullableI16(col) => AnySlice::NullableI16(col.iter(valid_rows)),
595            AnyBuffer::NullableI32(col) => AnySlice::NullableI32(col.iter(valid_rows)),
596            AnyBuffer::NullableI64(col) => AnySlice::NullableI64(col.iter(valid_rows)),
597            AnyBuffer::NullableU8(col) => AnySlice::NullableU8(col.iter(valid_rows)),
598            AnyBuffer::NullableBit(col) => AnySlice::NullableBit(col.iter(valid_rows)),
599        }
600    }
601
602    fn has_truncated_values(&self, num_rows: usize) -> Option<Indicator> {
603        match self {
604            AnyBuffer::Binary(col) => col.has_truncated_values(num_rows),
605            AnyBuffer::Text(col) => col.has_truncated_values(num_rows),
606            AnyBuffer::WText(col) => col.has_truncated_values(num_rows),
607            _ => None,
608        }
609    }
610}
611
612impl Resize for AnyBuffer {
613    fn resize(&mut self, new_capacity: usize) {
614        self.inner_mut().resize(new_capacity);
615    }
616}
617
618#[cfg(test)]
619mod tests {
620    use crate::buffers::{AnySlice, AnySliceMut, ColumnBuffer, Resize};
621
622    use super::AnyBuffer;
623
624    #[test]
625    fn any_buffer_is_resize() {
626        // Given an `AnyBuffer` with a capacity of 2 and values [1, 2]
627        let mut buffer = AnyBuffer::I32(vec![1, 2]);
628
629        // When we resize it to a capacity of 4
630        buffer.resize(4);
631
632        // Then the buffer should still have the same values in the first two positions and the
633        // remaining positions should be filled with default values (0 for i32)
634        assert_eq!(buffer.view(4).as_slice(), Some([1i32, 2, 0, 0].as_slice()));
635        // And the capacity should be 4
636        assert_eq!(buffer.capacity(), 4);
637    }
638
639    #[test]
640    fn slice_should_only_contain_part_of_the_buffer() {
641        let buffer = AnyBuffer::I32(vec![1, 2, 3]);
642
643        let view = buffer.view(2);
644
645        assert_eq!(Some([1, 2].as_slice()), view.as_slice::<i32>());
646    }
647
648    #[test]
649    fn slice_should_be_none_if_types_mismatch() {
650        let buffer = [1, 2, 3];
651        let view = AnySlice::I32(&buffer);
652        assert_eq!(None, view.as_slice::<i16>());
653    }
654
655    #[test]
656    fn slice_mut_should_be_none_if_types_mismatch() {
657        let mut buffer = [1, 2, 3];
658        let view = AnySliceMut::I32(&mut buffer);
659        assert_eq!(None, view.as_slice::<i16>());
660    }
661
662    #[test]
663    fn nullable_slice_should_be_none_if_buffer_is_non_nullable() {
664        let buffer = [1, 2, 3];
665        let view = AnySlice::I32(&buffer);
666        assert!(view.as_nullable_slice::<i32>().is_none());
667    }
668
669    #[test]
670    fn nullable_slice_mut_should_be_none_if_buffer_is_non_nullable() {
671        let mut buffer = [1, 2, 3];
672        let view = AnySliceMut::I32(&mut buffer);
673        assert!(view.as_nullable_slice::<i32>().is_none());
674    }
675}