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