vortex_array/arrays/null/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_buffer::ByteBuffer;
5use vortex_dtype::DType;
6use vortex_error::VortexResult;
7use vortex_mask::Mask;
8use vortex_scalar::Scalar;
9
10use crate::serde::ArrayChildren;
11use crate::stats::{ArrayStats, StatsSetRef};
12use crate::vtable::{
13    ArrayVTable, CanonicalVTable, NotSupported, OperationsVTable, SerdeVTable, VTable,
14    ValidityVTable, VisitorVTable,
15};
16use crate::{
17    ArrayBufferVisitor, ArrayChildVisitor, ArrayRef, Canonical, EmptyMetadata, EncodingId,
18    EncodingRef, IntoArray, vtable,
19};
20
21mod compute;
22
23vtable!(Null);
24
25impl VTable for NullVTable {
26    type Array = NullArray;
27    type Encoding = NullEncoding;
28
29    type ArrayVTable = Self;
30    type CanonicalVTable = Self;
31    type OperationsVTable = Self;
32    type ValidityVTable = Self;
33    type VisitorVTable = Self;
34    type ComputeVTable = NotSupported;
35    type EncodeVTable = NotSupported;
36    type SerdeVTable = Self;
37
38    fn id(_encoding: &Self::Encoding) -> EncodingId {
39        EncodingId::new_ref("vortex.null")
40    }
41
42    fn encoding(_array: &Self::Array) -> EncodingRef {
43        EncodingRef::new_ref(NullEncoding.as_ref())
44    }
45}
46
47/// A array where all values are null.
48///
49/// This mirrors the Apache Arrow Null array encoding and provides an efficient representation
50/// for arrays containing only null values. No actual data is stored, only the length.
51///
52/// All operations on null arrays return null values or indicate invalid data.
53///
54/// # Examples
55///
56/// ```
57/// use vortex_array::arrays::NullArray;
58/// use vortex_array::IntoArray;
59///
60/// // Create a null array with 5 elements
61/// let array = NullArray::new(5);
62///
63/// // Slice the array - still contains nulls
64/// let sliced = array.slice(1, 3).unwrap();
65/// assert_eq!(sliced.len(), 2);
66///
67/// // All elements are null
68/// let scalar = array.scalar_at(0).unwrap();
69/// assert!(scalar.is_null());
70/// ```
71#[derive(Clone, Debug)]
72pub struct NullArray {
73    len: usize,
74    stats_set: ArrayStats,
75}
76
77#[derive(Clone, Debug)]
78pub struct NullEncoding;
79
80impl NullArray {
81    pub fn new(len: usize) -> Self {
82        Self {
83            len,
84            stats_set: Default::default(),
85        }
86    }
87}
88
89impl ArrayVTable<NullVTable> for NullVTable {
90    fn len(array: &NullArray) -> usize {
91        array.len
92    }
93
94    fn dtype(_array: &NullArray) -> &DType {
95        &DType::Null
96    }
97
98    fn stats(array: &NullArray) -> StatsSetRef<'_> {
99        array.stats_set.to_ref(array.as_ref())
100    }
101}
102
103impl SerdeVTable<NullVTable> for NullVTable {
104    type Metadata = EmptyMetadata;
105
106    fn metadata(_array: &NullArray) -> VortexResult<Option<Self::Metadata>> {
107        Ok(Some(EmptyMetadata))
108    }
109
110    fn build(
111        _encoding: &NullEncoding,
112        _dtype: &DType,
113        len: usize,
114        _metadata: &Self::Metadata,
115        _buffers: &[ByteBuffer],
116        _children: &dyn ArrayChildren,
117    ) -> VortexResult<NullArray> {
118        Ok(NullArray::new(len))
119    }
120}
121
122impl VisitorVTable<NullVTable> for NullVTable {
123    fn visit_buffers(_array: &NullArray, _visitor: &mut dyn ArrayBufferVisitor) {}
124
125    fn visit_children(_array: &NullArray, _visitor: &mut dyn ArrayChildVisitor) {}
126}
127
128impl CanonicalVTable<NullVTable> for NullVTable {
129    fn canonicalize(array: &NullArray) -> VortexResult<Canonical> {
130        Ok(Canonical::Null(array.clone()))
131    }
132}
133
134impl OperationsVTable<NullVTable> for NullVTable {
135    fn slice(_array: &NullArray, start: usize, stop: usize) -> VortexResult<ArrayRef> {
136        Ok(NullArray::new(stop - start).into_array())
137    }
138
139    fn scalar_at(_array: &NullArray, _index: usize) -> VortexResult<Scalar> {
140        Ok(Scalar::null(DType::Null))
141    }
142}
143
144impl ValidityVTable<NullVTable> for NullVTable {
145    fn is_valid(_array: &NullArray, _index: usize) -> VortexResult<bool> {
146        Ok(false)
147    }
148
149    fn all_valid(array: &NullArray) -> VortexResult<bool> {
150        Ok(array.is_empty())
151    }
152
153    fn all_invalid(array: &NullArray) -> VortexResult<bool> {
154        Ok(!array.is_empty())
155    }
156
157    fn validity_mask(array: &NullArray) -> VortexResult<Mask> {
158        Ok(Mask::AllFalse(array.len))
159    }
160}