vortex_array/vtable/
validity.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_error::VortexResult;
5use vortex_mask::Mask;
6
7use crate::Array;
8use crate::validity::Validity;
9use crate::vtable::VTable;
10
11// TODO(aduffy): these methods should be infallible.
12pub trait ValidityVTable<V: VTable> {
13    fn is_valid(array: &V::Array, index: usize) -> VortexResult<bool>;
14
15    fn all_valid(array: &V::Array) -> VortexResult<bool>;
16
17    fn all_invalid(array: &V::Array) -> VortexResult<bool>;
18
19    /// Returns the number of valid elements in the array.
20    ///
21    /// ## Post-conditions
22    /// - The count is less than or equal to the length of the array.
23    fn valid_count(array: &V::Array) -> VortexResult<usize> {
24        Ok(Self::validity_mask(array)?.true_count())
25    }
26
27    /// Returns the number of invalid elements in the array.
28    ///
29    /// ## Post-conditions
30    /// - The count is less than or equal to the length of the array.
31    fn invalid_count(array: &V::Array) -> VortexResult<usize> {
32        Ok(Self::validity_mask(array)?.false_count())
33    }
34
35    fn validity_mask(array: &V::Array) -> VortexResult<Mask>;
36}
37
38/// An implementation of the [`ValidityVTable`] for arrays that hold validity as a child array.
39pub struct ValidityVTableFromValidityHelper;
40
41/// Expose validity held as a child array.
42pub trait ValidityHelper {
43    fn validity(&self) -> &Validity;
44}
45
46impl<V: VTable> ValidityVTable<V> for ValidityVTableFromValidityHelper
47where
48    V::Array: ValidityHelper,
49{
50    fn is_valid(array: &V::Array, index: usize) -> VortexResult<bool> {
51        array.validity().is_valid(index)
52    }
53
54    fn all_valid(array: &V::Array) -> VortexResult<bool> {
55        array.validity().all_valid()
56    }
57
58    fn all_invalid(array: &V::Array) -> VortexResult<bool> {
59        array.validity().all_invalid()
60    }
61
62    fn validity_mask(array: &V::Array) -> VortexResult<Mask> {
63        array.validity().to_mask(array.len())
64    }
65}
66
67/// An implementation of the [`ValidityVTable`] for arrays that hold an unsliced validity
68/// and a slice into it.
69pub struct ValidityVTableFromValiditySliceHelper;
70
71pub trait ValiditySliceHelper {
72    fn unsliced_validity_and_slice(&self) -> (&Validity, usize, usize);
73
74    fn sliced_validity(&self) -> Validity {
75        let (unsliced_validity, start, stop) = self.unsliced_validity_and_slice();
76        unsliced_validity.slice(start, stop)
77    }
78}
79
80impl<V: VTable> ValidityVTable<V> for ValidityVTableFromValiditySliceHelper
81where
82    V::Array: ValiditySliceHelper,
83{
84    fn is_valid(array: &V::Array, index: usize) -> VortexResult<bool> {
85        let (unsliced_validity, start, _) = array.unsliced_validity_and_slice();
86        unsliced_validity.is_valid(start + index)
87    }
88
89    fn all_valid(array: &V::Array) -> VortexResult<bool> {
90        array.sliced_validity().all_valid()
91    }
92
93    fn all_invalid(array: &V::Array) -> VortexResult<bool> {
94        array.sliced_validity().all_invalid()
95    }
96
97    fn validity_mask(array: &V::Array) -> VortexResult<Mask> {
98        array.sliced_validity().to_mask(array.len())
99    }
100}
101
102/// An implementation of the [`ValidityVTable`] for arrays that delegate validity entirely
103/// to a child array.
104pub struct ValidityVTableFromChild;
105
106pub trait ValidityChild<V: VTable> {
107    fn validity_child(array: &V::Array) -> &dyn Array;
108}
109
110impl<V: VTable> ValidityVTable<V> for ValidityVTableFromChild
111where
112    V: ValidityChild<V>,
113{
114    fn is_valid(array: &V::Array, index: usize) -> VortexResult<bool> {
115        V::validity_child(array).is_valid(index)
116    }
117
118    fn all_valid(array: &V::Array) -> VortexResult<bool> {
119        V::validity_child(array).all_valid()
120    }
121
122    fn all_invalid(array: &V::Array) -> VortexResult<bool> {
123        V::validity_child(array).all_invalid()
124    }
125
126    fn validity_mask(array: &V::Array) -> VortexResult<Mask> {
127        V::validity_child(array).validity_mask()
128    }
129}