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