odbc_api/buffers/
any_buffer.rs

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