Skip to main content

vortex_array/arrays/null/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::hash::Hash;
5
6use vortex_dtype::DType;
7use vortex_error::VortexResult;
8use vortex_error::vortex_ensure;
9use vortex_session::VortexSession;
10
11use crate::ArrayBufferVisitor;
12use crate::ArrayChildVisitor;
13use crate::ArrayRef;
14use crate::EmptyMetadata;
15use crate::ExecutionCtx;
16use crate::Precision;
17use crate::arrays::null::compute::rules::PARENT_RULES;
18use crate::buffer::BufferHandle;
19use crate::scalar::Scalar;
20use crate::serde::ArrayChildren;
21use crate::stats::ArrayStats;
22use crate::stats::StatsSetRef;
23use crate::validity::Validity;
24use crate::vtable;
25use crate::vtable::ArrayId;
26use crate::vtable::BaseArrayVTable;
27use crate::vtable::OperationsVTable;
28use crate::vtable::VTable;
29use crate::vtable::ValidityVTable;
30use crate::vtable::VisitorVTable;
31
32pub(crate) mod compute;
33
34vtable!(Null);
35
36impl VTable for NullVTable {
37    type Array = NullArray;
38
39    type Metadata = EmptyMetadata;
40
41    type ArrayVTable = Self;
42    type OperationsVTable = Self;
43    type ValidityVTable = Self;
44    type VisitorVTable = Self;
45
46    fn id(_array: &Self::Array) -> ArrayId {
47        Self::ID
48    }
49
50    fn metadata(_array: &NullArray) -> VortexResult<Self::Metadata> {
51        Ok(EmptyMetadata)
52    }
53
54    fn serialize(_metadata: Self::Metadata) -> VortexResult<Option<Vec<u8>>> {
55        Ok(Some(vec![]))
56    }
57
58    fn deserialize(
59        _bytes: &[u8],
60        _dtype: &DType,
61        _len: usize,
62        _buffers: &[BufferHandle],
63        _session: &VortexSession,
64    ) -> VortexResult<Self::Metadata> {
65        Ok(EmptyMetadata)
66    }
67
68    fn build(
69        _dtype: &DType,
70        len: usize,
71        _metadata: &Self::Metadata,
72        _buffers: &[BufferHandle],
73        _children: &dyn ArrayChildren,
74    ) -> VortexResult<NullArray> {
75        Ok(NullArray::new(len))
76    }
77
78    fn with_children(_array: &mut Self::Array, children: Vec<ArrayRef>) -> VortexResult<()> {
79        vortex_ensure!(
80            children.is_empty(),
81            "NullArray has no children, got {}",
82            children.len()
83        );
84        Ok(())
85    }
86
87    fn reduce_parent(
88        array: &Self::Array,
89        parent: &ArrayRef,
90        child_idx: usize,
91    ) -> VortexResult<Option<ArrayRef>> {
92        PARENT_RULES.evaluate(array, parent, child_idx)
93    }
94
95    fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult<ArrayRef> {
96        Ok(array.to_array())
97    }
98}
99
100/// A array where all values are null.
101///
102/// This mirrors the Apache Arrow Null array encoding and provides an efficient representation
103/// for arrays containing only null values. No actual data is stored, only the length.
104///
105/// All operations on null arrays return null values or indicate invalid data.
106///
107/// # Examples
108///
109/// ```
110/// # fn main() -> vortex_error::VortexResult<()> {
111/// use vortex_array::arrays::NullArray;
112/// use vortex_array::IntoArray;
113///
114/// // Create a null array with 5 elements
115/// let array = NullArray::new(5);
116///
117/// // Slice the array - still contains nulls
118/// let sliced = array.slice(1..3)?;
119/// assert_eq!(sliced.len(), 2);
120///
121/// // All elements are null
122/// let scalar = array.scalar_at(0).unwrap();
123/// assert!(scalar.is_null());
124/// # Ok(())
125/// # }
126/// ```
127#[derive(Clone, Debug)]
128pub struct NullArray {
129    len: usize,
130    stats_set: ArrayStats,
131}
132
133#[derive(Debug)]
134pub struct NullVTable;
135
136impl NullVTable {
137    pub const ID: ArrayId = ArrayId::new_ref("vortex.null");
138}
139
140impl NullArray {
141    pub fn new(len: usize) -> Self {
142        Self {
143            len,
144            stats_set: Default::default(),
145        }
146    }
147}
148
149impl BaseArrayVTable<NullVTable> for NullVTable {
150    fn len(array: &NullArray) -> usize {
151        array.len
152    }
153
154    fn dtype(_array: &NullArray) -> &DType {
155        &DType::Null
156    }
157
158    fn stats(array: &NullArray) -> StatsSetRef<'_> {
159        array.stats_set.to_ref(array.as_ref())
160    }
161
162    fn array_hash<H: std::hash::Hasher>(array: &NullArray, state: &mut H, _precision: Precision) {
163        array.len.hash(state);
164    }
165
166    fn array_eq(array: &NullArray, other: &NullArray, _precision: Precision) -> bool {
167        array.len == other.len
168    }
169}
170
171impl VisitorVTable<NullVTable> for NullVTable {
172    fn visit_buffers(_array: &NullArray, _visitor: &mut dyn ArrayBufferVisitor) {}
173
174    fn visit_children(_array: &NullArray, _visitor: &mut dyn ArrayChildVisitor) {}
175
176    fn nchildren(_array: &NullArray) -> usize {
177        0
178    }
179
180    fn nth_child(_array: &NullArray, _idx: usize) -> Option<ArrayRef> {
181        None
182    }
183}
184
185impl OperationsVTable<NullVTable> for NullVTable {
186    fn scalar_at(_array: &NullArray, _index: usize) -> VortexResult<Scalar> {
187        Ok(Scalar::null(DType::Null))
188    }
189}
190
191impl ValidityVTable<NullVTable> for NullVTable {
192    fn validity(_array: &NullArray) -> VortexResult<Validity> {
193        Ok(Validity::AllInvalid)
194    }
195}