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