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