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