vortex_array/array/
implementation.rs

1use std::any::Any;
2use std::fmt::Debug;
3use std::sync::Arc;
4
5use vortex_dtype::DType;
6use vortex_error::{VortexResult, vortex_bail};
7use vortex_mask::Mask;
8
9use crate::array::canonical::ArrayCanonicalImpl;
10use crate::array::validity::ArrayValidityImpl;
11use crate::array::visitor::ArrayVisitorImpl;
12use crate::builders::ArrayBuilder;
13use crate::compute::{ComputeFn, Filter, KernelRef};
14use crate::stats::{Precision, Stat, StatsSetRef};
15use crate::vtable::VTableRef;
16use crate::{
17    Array, ArrayComputeImpl, ArrayRef, ArrayStatisticsImpl, ArrayVariantsImpl, ArrayVisitor,
18    Canonical, Encoding, EncodingId,
19};
20
21/// A trait used to encapsulate common implementation behaviour for a Vortex [`Array`].
22pub trait ArrayImpl:
23    'static
24    + Send
25    + Sync
26    + Debug
27    + Clone
28    + ArrayCanonicalImpl
29    + ArrayComputeImpl
30    + ArrayStatisticsImpl
31    + ArrayValidityImpl
32    + ArrayVariantsImpl
33    + ArrayVisitorImpl<<Self::Encoding as Encoding>::Metadata>
34{
35    type Encoding: Encoding;
36
37    fn _len(&self) -> usize;
38    fn _dtype(&self) -> &DType;
39    fn _vtable(&self) -> VTableRef;
40
41    /// Replace the children of this array with the given arrays.
42    ///
43    /// ## Pre-conditions
44    ///
45    /// - The number of given children matches the current number of children of the array.
46    fn _with_children(&self, children: &[ArrayRef]) -> VortexResult<Self>;
47}
48
49impl<A: ArrayImpl + 'static> Array for A {
50    fn as_any(&self) -> &dyn Any {
51        self
52    }
53
54    fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
55        self
56    }
57
58    fn to_array(&self) -> ArrayRef {
59        Arc::new(self.clone())
60    }
61
62    fn into_array(self) -> ArrayRef
63    where
64        Self: Sized,
65    {
66        Arc::new(self)
67    }
68
69    fn len(&self) -> usize {
70        ArrayImpl::_len(self)
71    }
72
73    fn dtype(&self) -> &DType {
74        ArrayImpl::_dtype(self)
75    }
76
77    fn encoding(&self) -> EncodingId {
78        self.vtable().id()
79    }
80
81    fn vtable(&self) -> VTableRef {
82        ArrayImpl::_vtable(self)
83    }
84
85    fn find_kernel(&self, compute_fn: &dyn ComputeFn) -> Option<KernelRef> {
86        let any = compute_fn.as_any();
87
88        // Check each of the known compute functions.
89
90        if any.is::<Filter>() {
91            if let Some(f) = <Self as ArrayComputeImpl>::FILTER {
92                return Some(f);
93            }
94        }
95
96        // Otherwise, fallback to a manual lookup
97        self._find_kernel(compute_fn)
98    }
99
100    /// Returns whether the item at `index` is valid.
101    fn is_valid(&self, index: usize) -> VortexResult<bool> {
102        if index >= self.len() {
103            vortex_bail!("Index out of bounds: {} >= {}", index, self.len());
104        }
105        ArrayValidityImpl::_is_valid(self, index)
106    }
107
108    /// Returns whether the item at `index` is invalid.
109    fn is_invalid(&self, index: usize) -> VortexResult<bool> {
110        self.is_valid(index).map(|valid| !valid)
111    }
112
113    /// Returns whether all items in the array are valid.
114    ///
115    /// This is usually cheaper than computing a precise `valid_count`.
116    fn all_valid(&self) -> VortexResult<bool> {
117        ArrayValidityImpl::_all_valid(self)
118    }
119
120    /// Returns whether the array is all invalid.
121    ///
122    /// This is usually cheaper than computing a precise `invalid_count`.
123    fn all_invalid(&self) -> VortexResult<bool> {
124        ArrayValidityImpl::_all_invalid(self)
125    }
126
127    /// Returns the number of valid elements in the array.
128    fn valid_count(&self) -> VortexResult<usize> {
129        if let Some(Precision::Exact(invalid_count)) =
130            self.statistics().get_as::<usize>(Stat::NullCount)
131        {
132            return Ok(self.len() - invalid_count);
133        }
134
135        let count = ArrayValidityImpl::_valid_count(self)?;
136        assert!(count <= self.len(), "Valid count exceeds array length");
137
138        self.statistics()
139            .set(Stat::NullCount, Precision::exact(self.len() - count));
140
141        Ok(count)
142    }
143
144    /// Returns the number of invalid elements in the array.
145    fn invalid_count(&self) -> VortexResult<usize> {
146        if let Some(Precision::Exact(invalid_count)) =
147            self.statistics().get_as::<usize>(Stat::NullCount)
148        {
149            return Ok(invalid_count);
150        }
151
152        let count = ArrayValidityImpl::_invalid_count(self)?;
153        assert!(count <= self.len(), "Invalid count exceeds array length");
154
155        self.statistics()
156            .set(Stat::NullCount, Precision::exact(count));
157
158        Ok(count)
159    }
160
161    /// Returns the canonical validity mask for the array.
162    fn validity_mask(&self) -> VortexResult<Mask> {
163        let mask = ArrayValidityImpl::_validity_mask(self)?;
164        assert_eq!(mask.len(), self.len(), "Validity mask length mismatch");
165        Ok(mask)
166    }
167
168    /// Returns the canonical representation of the array.
169    fn to_canonical(&self) -> VortexResult<Canonical> {
170        let canonical = ArrayCanonicalImpl::_to_canonical(self)?;
171        assert_eq!(
172            canonical.as_ref().len(),
173            self.len(),
174            "Canonical length mismatch"
175        );
176        assert_eq!(
177            canonical.as_ref().dtype(),
178            self.dtype(),
179            "Canonical dtype mismatch"
180        );
181        canonical.as_ref().statistics().inherit(self.statistics());
182        Ok(canonical)
183    }
184
185    /// Writes the array into the canonical builder.
186    ///
187    /// The [`DType`] of the builder must match that of the array.
188    fn append_to_builder(&self, builder: &mut dyn ArrayBuilder) -> VortexResult<()> {
189        if builder.dtype() != self.dtype() {
190            vortex_bail!(
191                "Builder dtype mismatch: expected {}, got {}",
192                self.dtype(),
193                builder.dtype(),
194            );
195        }
196        let len = builder.len();
197
198        ArrayCanonicalImpl::_append_to_builder(self, builder)?;
199        assert_eq!(
200            len + self.len(),
201            builder.len(),
202            "Builder length mismatch after writing array for encoding {}",
203            self.encoding(),
204        );
205        Ok(())
206    }
207
208    fn statistics(&self) -> StatsSetRef<'_> {
209        self._stats_ref()
210    }
211
212    fn with_children(&self, children: &[ArrayRef]) -> VortexResult<ArrayRef> {
213        if self.nchildren() != children.len() {
214            vortex_bail!("Child count mismatch");
215        }
216
217        for (s, o) in self.children().iter().zip(children.iter()) {
218            assert_eq!(s.len(), o.len());
219        }
220
221        Ok(self._with_children(children)?.into_array())
222    }
223}