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 vortex_error::VortexResult;
5use vortex_error::vortex_ensure;
6use vortex_error::vortex_panic;
7use vortex_session::VortexSession;
8
9use crate::ArrayRef;
10use crate::ExecutionCtx;
11use crate::ExecutionResult;
12use crate::array::Array;
13use crate::array::ArrayId;
14use crate::array::ArrayParts;
15use crate::array::ArrayView;
16use crate::array::EmptyArrayData;
17use crate::array::OperationsVTable;
18use crate::array::VTable;
19use crate::array::ValidityVTable;
20use crate::arrays::null::compute::rules::PARENT_RULES;
21use crate::buffer::BufferHandle;
22use crate::dtype::DType;
23use crate::scalar::Scalar;
24use crate::serde::ArrayChildren;
25use crate::validity::Validity;
26
27pub(crate) mod compute;
28
29/// A [`Null`]-encoded Vortex array.
30pub type NullArray = Array<Null>;
31
32impl VTable for Null {
33    type ArrayData = EmptyArrayData;
34
35    type OperationsVTable = Self;
36    type ValidityVTable = Self;
37
38    fn id(&self) -> ArrayId {
39        Self::ID
40    }
41
42    fn validate(
43        &self,
44        _data: &EmptyArrayData,
45        dtype: &DType,
46        _len: usize,
47        _slots: &[Option<ArrayRef>],
48    ) -> VortexResult<()> {
49        vortex_ensure!(*dtype == DType::Null, "NullArray dtype must be DType::Null");
50        Ok(())
51    }
52
53    fn nbuffers(_array: ArrayView<'_, Self>) -> usize {
54        0
55    }
56
57    fn buffer(_array: ArrayView<'_, Self>, idx: usize) -> BufferHandle {
58        vortex_panic!("NullArray buffer index {idx} out of bounds")
59    }
60
61    fn buffer_name(_array: ArrayView<'_, Self>, _idx: usize) -> Option<String> {
62        None
63    }
64
65    fn slot_name(_array: ArrayView<'_, Self>, idx: usize) -> String {
66        vortex_panic!("NullArray slot_name index {idx} out of bounds")
67    }
68
69    fn serialize(
70        _array: ArrayView<'_, Self>,
71        _session: &VortexSession,
72    ) -> VortexResult<Option<Vec<u8>>> {
73        Ok(Some(vec![]))
74    }
75
76    fn deserialize(
77        &self,
78        dtype: &DType,
79        len: usize,
80        metadata: &[u8],
81
82        _buffers: &[BufferHandle],
83        _children: &dyn ArrayChildren,
84        _session: &VortexSession,
85    ) -> VortexResult<ArrayParts<Self>> {
86        vortex_ensure!(
87            metadata.is_empty(),
88            "NullArray expects empty metadata, got {} bytes",
89            metadata.len()
90        );
91        Ok(ArrayParts::new(
92            self.clone(),
93            dtype.clone(),
94            len,
95            EmptyArrayData,
96        ))
97    }
98
99    fn reduce_parent(
100        array: ArrayView<'_, Self>,
101        parent: &ArrayRef,
102        child_idx: usize,
103    ) -> VortexResult<Option<ArrayRef>> {
104        PARENT_RULES.evaluate(array, parent, child_idx)
105    }
106
107    fn execute(array: Array<Self>, _ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
108        Ok(ExecutionResult::done(array))
109    }
110}
111
112/// A array where all values are null.
113///
114/// This mirrors the Apache Arrow Null array encoding and provides an efficient representation
115/// for arrays containing only null values. No actual data is stored, only the length.
116///
117/// All operations on null arrays return null values or indicate invalid data.
118///
119/// # Examples
120///
121/// ```
122/// # fn main() -> vortex_error::VortexResult<()> {
123/// use vortex_array::arrays::NullArray;
124/// use vortex_array::IntoArray;
125///
126/// // Create a null array with 5 elements
127/// let array = NullArray::new(5);
128///
129/// // Slice the array - still contains nulls
130/// let sliced = array.slice(1..3)?;
131/// assert_eq!(sliced.len(), 2);
132///
133/// // All elements are null
134/// let scalar = array.scalar_at(0).unwrap();
135/// assert!(scalar.is_null());
136/// # Ok(())
137/// # }
138/// ```
139#[derive(Clone, Debug)]
140pub struct Null;
141
142impl Null {
143    pub const ID: ArrayId = ArrayId::new_ref("vortex.null");
144}
145
146impl Array<Null> {
147    pub fn new(len: usize) -> Self {
148        unsafe {
149            Array::from_parts_unchecked(ArrayParts::new(Null, DType::Null, len, EmptyArrayData))
150        }
151    }
152}
153
154impl OperationsVTable<Null> for Null {
155    fn scalar_at(
156        _array: ArrayView<'_, Null>,
157        _index: usize,
158        _ctx: &mut ExecutionCtx,
159    ) -> VortexResult<Scalar> {
160        Ok(Scalar::null(DType::Null))
161    }
162}
163
164impl ValidityVTable<Null> for Null {
165    fn validity(_array: ArrayView<'_, Null>) -> VortexResult<Validity> {
166        Ok(Validity::AllInvalid)
167    }
168}