vortex_array/vtable/
validity.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_error::vortex_panic;
5use vortex_mask::Mask;
6
7use crate::validity::Validity;
8use crate::vtable::{NotSupported, VTable};
9use crate::{Array, ArrayRef};
10
11pub trait ValidityVTable<V: VTable> {
12    fn is_valid(array: &V::Array, index: usize) -> bool;
13
14    fn all_valid(array: &V::Array) -> bool;
15
16    fn all_invalid(array: &V::Array) -> bool;
17
18    /// Returns the number of valid elements in the array.
19    ///
20    /// ## Post-conditions
21    /// - The count is less than or equal to the length of the array.
22    fn valid_count(array: &V::Array) -> usize {
23        Self::validity_mask(array).true_count()
24    }
25
26    /// Returns the number of invalid elements in the array.
27    ///
28    /// ## Post-conditions
29    /// - The count is less than or equal to the length of the array.
30    fn invalid_count(array: &V::Array) -> usize {
31        Self::validity_mask(array).false_count()
32    }
33
34    fn validity_mask(array: &V::Array) -> Mask;
35}
36
37impl<V: VTable> ValidityVTable<V> for NotSupported {
38    fn is_valid(array: &V::Array, _index: usize) -> bool {
39        vortex_panic!(
40            "Legacy is_valid is not supported for {} arrays",
41            array.encoding_id()
42        )
43    }
44
45    fn all_valid(array: &V::Array) -> bool {
46        vortex_panic!(
47            "Legacy all_valid is not supported for {} arrays",
48            array.encoding_id()
49        )
50    }
51
52    fn all_invalid(array: &V::Array) -> bool {
53        vortex_panic!(
54            "Legacy all_invalid is not supported for {} arrays",
55            array.encoding_id()
56        )
57    }
58
59    fn validity_mask(array: &V::Array) -> Mask {
60        vortex_panic!(
61            "Legacy validity_mask is not supported for {} arrays",
62            array.encoding_id()
63        )
64    }
65}
66
67/// An implementation of the [`ValidityVTable`] for arrays that hold validity as a child array.
68pub struct ValidityVTableFromValidityHelper;
69
70/// Expose validity held as a child array.
71pub trait ValidityHelper {
72    fn validity(&self) -> &Validity;
73}
74
75impl<V: VTable> ValidityVTable<V> for ValidityVTableFromValidityHelper
76where
77    V::Array: ValidityHelper,
78{
79    fn is_valid(array: &V::Array, index: usize) -> bool {
80        array.validity().is_valid(index)
81    }
82
83    fn all_valid(array: &V::Array) -> bool {
84        array.validity().all_valid(array.len())
85    }
86
87    fn all_invalid(array: &V::Array) -> bool {
88        array.validity().all_invalid(array.len())
89    }
90
91    fn validity_mask(array: &V::Array) -> Mask {
92        array.validity().to_mask(array.len())
93    }
94}
95
96/// An implementation of the [`ValidityVTable`] for arrays that hold an unsliced validity
97/// and a slice into it.
98pub struct ValidityVTableFromValiditySliceHelper;
99
100pub trait ValiditySliceHelper {
101    fn unsliced_validity_and_slice(&self) -> (&Validity, usize, usize);
102
103    fn sliced_validity(&self) -> Validity {
104        let (unsliced_validity, start, stop) = self.unsliced_validity_and_slice();
105        unsliced_validity.slice(start..stop)
106    }
107}
108
109impl<V: VTable> ValidityVTable<V> for ValidityVTableFromValiditySliceHelper
110where
111    V::Array: ValiditySliceHelper,
112{
113    fn is_valid(array: &V::Array, index: usize) -> bool {
114        let (unsliced_validity, start, _) = array.unsliced_validity_and_slice();
115        unsliced_validity.is_valid(start + index)
116    }
117
118    fn all_valid(array: &V::Array) -> bool {
119        array.sliced_validity().all_valid(array.len())
120    }
121
122    fn all_invalid(array: &V::Array) -> bool {
123        array.sliced_validity().all_invalid(array.len())
124    }
125
126    fn validity_mask(array: &V::Array) -> Mask {
127        array.sliced_validity().to_mask(array.len())
128    }
129}
130
131/// An implementation of the [`ValidityVTable`] for arrays that delegate validity entirely
132/// to a child array.
133pub struct ValidityVTableFromChild;
134
135pub trait ValidityChild<V: VTable> {
136    fn validity_child(array: &V::Array) -> &dyn Array;
137}
138
139impl<V: VTable> ValidityVTable<V> for ValidityVTableFromChild
140where
141    V: ValidityChild<V>,
142{
143    fn is_valid(array: &V::Array, index: usize) -> bool {
144        V::validity_child(array).is_valid(index)
145    }
146
147    fn all_valid(array: &V::Array) -> bool {
148        V::validity_child(array).all_valid()
149    }
150
151    fn all_invalid(array: &V::Array) -> bool {
152        V::validity_child(array).all_invalid()
153    }
154
155    fn validity_mask(array: &V::Array) -> Mask {
156        V::validity_child(array).validity_mask()
157    }
158}
159
160/// An implementation of the [`ValidityVTable`] for arrays that hold an unsliced validity
161/// and a slice into it.
162pub struct ValidityVTableFromChildSliceHelper;
163
164pub trait ValidityChildSliceHelper {
165    fn unsliced_child_and_slice(&self) -> (&ArrayRef, usize, usize);
166
167    fn sliced_child_array(&self) -> ArrayRef {
168        let (unsliced_validity, start, stop) = self.unsliced_child_and_slice();
169        unsliced_validity.slice(start..stop)
170    }
171}
172
173impl<V: VTable> ValidityVTable<V> for ValidityVTableFromChildSliceHelper
174where
175    V::Array: ValidityChildSliceHelper,
176{
177    fn is_valid(array: &V::Array, index: usize) -> bool {
178        let (unsliced_validity, start, _) = array.unsliced_child_and_slice();
179        unsliced_validity.is_valid(start + index)
180    }
181
182    fn all_valid(array: &V::Array) -> bool {
183        array.sliced_child_array().all_valid()
184    }
185
186    fn all_invalid(array: &V::Array) -> bool {
187        array.sliced_child_array().all_invalid()
188    }
189
190    fn validity_mask(array: &V::Array) -> Mask {
191        array.sliced_child_array().validity_mask()
192    }
193}