Skip to main content

vortex_array/builders/
null.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::any::Any;
5
6use vortex_error::VortexResult;
7use vortex_error::vortex_ensure;
8use vortex_mask::Mask;
9
10use crate::ArrayRef;
11use crate::IntoArray;
12use crate::arrays::NullArray;
13use crate::builders::ArrayBuilder;
14use crate::canonical::Canonical;
15use crate::dtype::DType;
16use crate::scalar::Scalar;
17
18/// The builder for building a [`NullArray`].
19pub struct NullBuilder {
20    length: usize,
21}
22
23impl Default for NullBuilder {
24    fn default() -> Self {
25        Self::new()
26    }
27}
28
29impl NullBuilder {
30    pub fn new() -> Self {
31        Self { length: 0 }
32    }
33}
34
35impl ArrayBuilder for NullBuilder {
36    fn as_any(&self) -> &dyn Any {
37        self
38    }
39
40    fn as_any_mut(&mut self) -> &mut dyn Any {
41        self
42    }
43
44    fn dtype(&self) -> &DType {
45        &DType::Null
46    }
47
48    fn len(&self) -> usize {
49        self.length
50    }
51
52    fn append_zeros(&mut self, n: usize) {
53        self.length += n;
54    }
55
56    unsafe fn append_nulls_unchecked(&mut self, n: usize) {
57        self.length += n;
58    }
59
60    fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
61        vortex_ensure!(
62            scalar.dtype() == self.dtype(),
63            "NullBuilder expected scalar with dtype {}, got {}",
64            self.dtype(),
65            scalar.dtype()
66        );
67
68        self.append_null();
69        Ok(())
70    }
71
72    unsafe fn extend_from_array_unchecked(&mut self, array: &ArrayRef) {
73        self.append_nulls(array.len());
74    }
75
76    fn reserve_exact(&mut self, _additional: usize) {}
77
78    unsafe fn set_validity_unchecked(&mut self, _validity: Mask) {}
79
80    fn finish(&mut self) -> ArrayRef {
81        NullArray::new(self.length).into_array()
82    }
83
84    fn finish_into_canonical(&mut self) -> Canonical {
85        Canonical::Null(NullArray::new(self.length))
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92    use crate::builders::ArrayBuilder;
93    use crate::dtype::DType;
94    use crate::scalar::Scalar;
95
96    #[test]
97    fn test_append_scalar() {
98        let mut builder = NullBuilder::new();
99
100        // Test appending null scalar.
101        let null_scalar = Scalar::null(DType::Null);
102        builder.append_scalar(&null_scalar).unwrap();
103        builder.append_scalar(&null_scalar).unwrap();
104        builder.append_scalar(&null_scalar).unwrap();
105
106        let array = builder.finish();
107        assert_eq!(array.len(), 3);
108
109        // For null arrays, all values are null - nothing to check for actual values.
110        // Just verify the array is indeed a null array with the right length.
111
112        // Test wrong dtype error.
113        let mut builder = NullBuilder::new();
114        let wrong_scalar = Scalar::from(42i32);
115        assert!(builder.append_scalar(&wrong_scalar).is_err());
116    }
117}