vortex_array/arrays/null/
mod.rs

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