polars_arrow/array/primitive/
mod.rs

1use std::ops::Range;
2
3use either::Either;
4
5use super::{Array, Splitable};
6use crate::array::iterator::NonNullValuesIter;
7use crate::bitmap::utils::{BitmapIter, ZipValidity};
8use crate::bitmap::Bitmap;
9use crate::buffer::Buffer;
10use crate::datatypes::*;
11use crate::trusted_len::TrustedLen;
12use crate::types::{days_ms, f16, i256, months_days_ns, NativeType};
13
14mod ffi;
15pub(super) mod fmt;
16mod from_natural;
17pub mod iterator;
18
19mod mutable;
20pub use mutable::*;
21use polars_error::{polars_bail, PolarsResult};
22use polars_utils::index::{Bounded, Indexable, NullCount};
23use polars_utils::slice::SliceAble;
24
25/// A [`PrimitiveArray`] is Arrow's semantically equivalent of an immutable `Vec<Option<T>>` where
26/// T is [`NativeType`] (e.g. [`i32`]). It implements [`Array`].
27///
28/// One way to think about a [`PrimitiveArray`] is `(DataType, Arc<Vec<T>>, Option<Arc<Vec<u8>>>)`
29/// where:
30/// * the first item is the array's logical type
31/// * the second is the immutable values
32/// * the third is the immutable validity (whether a value is null or not as a bitmap).
33///
34/// The size of this struct is `O(1)`, as all data is stored behind an [`std::sync::Arc`].
35/// # Example
36/// ```
37/// use polars_arrow::array::PrimitiveArray;
38/// use polars_arrow::bitmap::Bitmap;
39/// use polars_arrow::buffer::Buffer;
40///
41/// let array = PrimitiveArray::from([Some(1i32), None, Some(10)]);
42/// assert_eq!(array.value(0), 1);
43/// assert_eq!(array.iter().collect::<Vec<_>>(), vec![Some(&1i32), None, Some(&10)]);
44/// assert_eq!(array.values_iter().copied().collect::<Vec<_>>(), vec![1, 0, 10]);
45/// // the underlying representation
46/// assert_eq!(array.values(), &Buffer::from(vec![1i32, 0, 10]));
47/// assert_eq!(array.validity(), Some(&Bitmap::from([true, false, true])));
48///
49/// ```
50#[derive(Clone)]
51pub struct PrimitiveArray<T: NativeType> {
52    dtype: ArrowDataType,
53    values: Buffer<T>,
54    validity: Option<Bitmap>,
55}
56
57pub(super) fn check<T: NativeType>(
58    dtype: &ArrowDataType,
59    values: &[T],
60    validity_len: Option<usize>,
61) -> PolarsResult<()> {
62    if validity_len.is_some_and(|len| len != values.len()) {
63        polars_bail!(ComputeError: "validity mask length must match the number of values")
64    }
65
66    if dtype.to_physical_type() != PhysicalType::Primitive(T::PRIMITIVE) {
67        polars_bail!(ComputeError: "PrimitiveArray can only be initialized with a DataType whose physical type is Primitive")
68    }
69    Ok(())
70}
71
72impl<T: NativeType> PrimitiveArray<T> {
73    /// The canonical method to create a [`PrimitiveArray`] out of its internal components.
74    /// # Implementation
75    /// This function is `O(1)`.
76    ///
77    /// # Errors
78    /// This function errors iff:
79    /// * The validity is not `None` and its length is different from `values`'s length
80    /// * The `dtype`'s [`PhysicalType`] is not equal to [`PhysicalType::Primitive(T::PRIMITIVE)`]
81    pub fn try_new(
82        dtype: ArrowDataType,
83        values: Buffer<T>,
84        validity: Option<Bitmap>,
85    ) -> PolarsResult<Self> {
86        check(&dtype, &values, validity.as_ref().map(|v| v.len()))?;
87        Ok(Self {
88            dtype,
89            values,
90            validity,
91        })
92    }
93
94    /// # Safety
95    /// Doesn't check invariants
96    pub unsafe fn new_unchecked(
97        dtype: ArrowDataType,
98        values: Buffer<T>,
99        validity: Option<Bitmap>,
100    ) -> Self {
101        if cfg!(debug_assertions) {
102            check(&dtype, &values, validity.as_ref().map(|v| v.len())).unwrap();
103        }
104
105        Self {
106            dtype,
107            values,
108            validity,
109        }
110    }
111
112    /// Returns a new [`PrimitiveArray`] with a different logical type.
113    ///
114    /// This function is useful to assign a different [`ArrowDataType`] to the array.
115    /// Used to change the arrays' logical type (see example).
116    /// # Example
117    /// ```
118    /// use polars_arrow::array::Int32Array;
119    /// use polars_arrow::datatypes::ArrowDataType;
120    ///
121    /// let array = Int32Array::from(&[Some(1), None, Some(2)]).to(ArrowDataType::Date32);
122    /// assert_eq!(
123    ///    format!("{:?}", array),
124    ///    "Date32[1970-01-02, None, 1970-01-03]"
125    /// );
126    /// ```
127    /// # Panics
128    /// Panics iff the `dtype`'s [`PhysicalType`] is not equal to [`PhysicalType::Primitive(T::PRIMITIVE)`]
129    #[inline]
130    #[must_use]
131    pub fn to(self, dtype: ArrowDataType) -> Self {
132        check(
133            &dtype,
134            &self.values,
135            self.validity.as_ref().map(|v| v.len()),
136        )
137        .unwrap();
138        Self {
139            dtype,
140            values: self.values,
141            validity: self.validity,
142        }
143    }
144
145    /// Creates a (non-null) [`PrimitiveArray`] from a vector of values.
146    /// This function is `O(1)`.
147    /// # Examples
148    /// ```
149    /// use polars_arrow::array::PrimitiveArray;
150    ///
151    /// let array = PrimitiveArray::from_vec(vec![1, 2, 3]);
152    /// assert_eq!(format!("{:?}", array), "Int32[1, 2, 3]");
153    /// ```
154    pub fn from_vec(values: Vec<T>) -> Self {
155        Self::new(T::PRIMITIVE.into(), values.into(), None)
156    }
157
158    /// Returns an iterator over the values and validity, `Option<&T>`.
159    #[inline]
160    pub fn iter(&self) -> ZipValidity<&T, std::slice::Iter<T>, BitmapIter> {
161        ZipValidity::new_with_validity(self.values().iter(), self.validity())
162    }
163
164    /// Returns an iterator of the values, `&T`, ignoring the arrays' validity.
165    #[inline]
166    pub fn values_iter(&self) -> std::slice::Iter<T> {
167        self.values().iter()
168    }
169
170    /// Returns an iterator of the non-null values `T`.
171    #[inline]
172    pub fn non_null_values_iter(&self) -> NonNullValuesIter<'_, [T]> {
173        NonNullValuesIter::new(self.values(), self.validity())
174    }
175
176    /// Returns the length of this array
177    #[inline]
178    pub fn len(&self) -> usize {
179        self.values.len()
180    }
181
182    /// The values [`Buffer`].
183    /// Values on null slots are undetermined (they can be anything).
184    #[inline]
185    pub fn values(&self) -> &Buffer<T> {
186        &self.values
187    }
188
189    /// Returns the optional validity.
190    #[inline]
191    pub fn validity(&self) -> Option<&Bitmap> {
192        self.validity.as_ref()
193    }
194
195    /// Returns the arrays' [`ArrowDataType`].
196    #[inline]
197    pub fn dtype(&self) -> &ArrowDataType {
198        &self.dtype
199    }
200
201    /// Returns the value at slot `i`.
202    ///
203    /// Equivalent to `self.values()[i]`. The value of a null slot is undetermined (it can be anything).
204    /// # Panic
205    /// This function panics iff `i >= self.len`.
206    #[inline]
207    pub fn value(&self, i: usize) -> T {
208        self.values[i]
209    }
210
211    /// Returns the value at index `i`.
212    /// The value on null slots is undetermined (it can be anything).
213    ///
214    /// # Safety
215    /// Caller must be sure that `i < self.len()`
216    #[inline]
217    pub unsafe fn value_unchecked(&self, i: usize) -> T {
218        *self.values.get_unchecked(i)
219    }
220
221    // /// Returns the element at index `i` or `None` if it is null
222    // /// # Panics
223    // /// iff `i >= self.len()`
224    // #[inline]
225    // pub fn get(&self, i: usize) -> Option<T> {
226    //     if !self.is_null(i) {
227    //         // soundness: Array::is_null panics if i >= self.len
228    //         unsafe { Some(self.value_unchecked(i)) }
229    //     } else {
230    //         None
231    //     }
232    // }
233
234    /// Slices this [`PrimitiveArray`] by an offset and length.
235    /// # Implementation
236    /// This operation is `O(1)`.
237    #[inline]
238    pub fn slice(&mut self, offset: usize, length: usize) {
239        assert!(
240            offset + length <= self.len(),
241            "offset + length may not exceed length of array"
242        );
243        unsafe { self.slice_unchecked(offset, length) }
244    }
245
246    /// Slices this [`PrimitiveArray`] by an offset and length.
247    /// # Implementation
248    /// This operation is `O(1)`.
249    ///
250    /// # Safety
251    /// The caller must ensure that `offset + length <= self.len()`.
252    #[inline]
253    pub unsafe fn slice_unchecked(&mut self, offset: usize, length: usize) {
254        self.validity = self
255            .validity
256            .take()
257            .map(|bitmap| bitmap.sliced_unchecked(offset, length))
258            .filter(|bitmap| bitmap.unset_bits() > 0);
259        self.values.slice_unchecked(offset, length);
260    }
261
262    impl_sliced!();
263    impl_mut_validity!();
264    impl_into_array!();
265
266    /// Returns this [`PrimitiveArray`] with new values.
267    /// # Panics
268    /// This function panics iff `values.len() != self.len()`.
269    #[must_use]
270    pub fn with_values(mut self, values: Buffer<T>) -> Self {
271        self.set_values(values);
272        self
273    }
274
275    /// Update the values of this [`PrimitiveArray`].
276    /// # Panics
277    /// This function panics iff `values.len() != self.len()`.
278    pub fn set_values(&mut self, values: Buffer<T>) {
279        assert_eq!(
280            values.len(),
281            self.len(),
282            "values' length must be equal to this arrays' length"
283        );
284        self.values = values;
285    }
286
287    /// Applies a function `f` to the validity of this array.
288    ///
289    /// This is an API to leverage clone-on-write
290    /// # Panics
291    /// This function panics if the function `f` modifies the length of the [`Bitmap`].
292    pub fn apply_validity<F: FnOnce(Bitmap) -> Bitmap>(&mut self, f: F) {
293        if let Some(validity) = std::mem::take(&mut self.validity) {
294            self.set_validity(Some(f(validity)))
295        }
296    }
297
298    /// Returns an option of a mutable reference to the values of this [`PrimitiveArray`].
299    pub fn get_mut_values(&mut self) -> Option<&mut [T]> {
300        self.values.get_mut_slice()
301    }
302
303    /// Returns its internal representation
304    #[must_use]
305    pub fn into_inner(self) -> (ArrowDataType, Buffer<T>, Option<Bitmap>) {
306        let Self {
307            dtype,
308            values,
309            validity,
310        } = self;
311        (dtype, values, validity)
312    }
313
314    /// Creates a [`PrimitiveArray`] from its internal representation.
315    /// This is the inverted from [`PrimitiveArray::into_inner`]
316    pub fn from_inner(
317        dtype: ArrowDataType,
318        values: Buffer<T>,
319        validity: Option<Bitmap>,
320    ) -> PolarsResult<Self> {
321        check(&dtype, &values, validity.as_ref().map(|v| v.len()))?;
322        Ok(unsafe { Self::from_inner_unchecked(dtype, values, validity) })
323    }
324
325    /// Creates a [`PrimitiveArray`] from its internal representation.
326    /// This is the inverted from [`PrimitiveArray::into_inner`]
327    ///
328    /// # Safety
329    /// Callers must ensure all invariants of this struct are upheld.
330    pub unsafe fn from_inner_unchecked(
331        dtype: ArrowDataType,
332        values: Buffer<T>,
333        validity: Option<Bitmap>,
334    ) -> Self {
335        Self {
336            dtype,
337            values,
338            validity,
339        }
340    }
341
342    /// Try to convert this [`PrimitiveArray`] to a [`MutablePrimitiveArray`] via copy-on-write semantics.
343    ///
344    /// A [`PrimitiveArray`] is backed by a [`Buffer`] and [`Bitmap`] which are essentially `Arc<Vec<_>>`.
345    /// This function returns a [`MutablePrimitiveArray`] (via [`std::sync::Arc::get_mut`]) iff both values
346    /// and validity have not been cloned / are unique references to their underlying vectors.
347    ///
348    /// This function is primarily used to reuse memory regions.
349    #[must_use]
350    pub fn into_mut(self) -> Either<Self, MutablePrimitiveArray<T>> {
351        use Either::*;
352
353        if let Some(bitmap) = self.validity {
354            match bitmap.into_mut() {
355                Left(bitmap) => Left(PrimitiveArray::new(self.dtype, self.values, Some(bitmap))),
356                Right(mutable_bitmap) => match self.values.into_mut() {
357                    Right(values) => Right(
358                        MutablePrimitiveArray::try_new(self.dtype, values, Some(mutable_bitmap))
359                            .unwrap(),
360                    ),
361                    Left(values) => Left(PrimitiveArray::new(
362                        self.dtype,
363                        values,
364                        Some(mutable_bitmap.into()),
365                    )),
366                },
367            }
368        } else {
369            match self.values.into_mut() {
370                Right(values) => {
371                    Right(MutablePrimitiveArray::try_new(self.dtype, values, None).unwrap())
372                },
373                Left(values) => Left(PrimitiveArray::new(self.dtype, values, None)),
374            }
375        }
376    }
377
378    /// Returns a new empty (zero-length) [`PrimitiveArray`].
379    pub fn new_empty(dtype: ArrowDataType) -> Self {
380        Self::new(dtype, Buffer::new(), None)
381    }
382
383    /// Returns a new [`PrimitiveArray`] where all slots are null / `None`.
384    #[inline]
385    pub fn new_null(dtype: ArrowDataType, length: usize) -> Self {
386        Self::new(
387            dtype,
388            vec![T::default(); length].into(),
389            Some(Bitmap::new_zeroed(length)),
390        )
391    }
392
393    /// Creates a (non-null) [`PrimitiveArray`] from an iterator of values.
394    /// # Implementation
395    /// This does not assume that the iterator has a known length.
396    pub fn from_values<I: IntoIterator<Item = T>>(iter: I) -> Self {
397        Self::new(T::PRIMITIVE.into(), Vec::<T>::from_iter(iter).into(), None)
398    }
399
400    /// Creates a (non-null) [`PrimitiveArray`] from a slice of values.
401    /// # Implementation
402    /// This is essentially a memcopy and is thus `O(N)`
403    pub fn from_slice<P: AsRef<[T]>>(slice: P) -> Self {
404        Self::new(
405            T::PRIMITIVE.into(),
406            Vec::<T>::from(slice.as_ref()).into(),
407            None,
408        )
409    }
410
411    /// Creates a (non-null) [`PrimitiveArray`] from a [`TrustedLen`] of values.
412    /// # Implementation
413    /// This does not assume that the iterator has a known length.
414    pub fn from_trusted_len_values_iter<I: TrustedLen<Item = T>>(iter: I) -> Self {
415        MutablePrimitiveArray::<T>::from_trusted_len_values_iter(iter).into()
416    }
417
418    /// Creates a new [`PrimitiveArray`] from an iterator over values
419    ///
420    /// # Safety
421    /// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
422    /// I.e. that `size_hint().1` correctly reports its length.
423    pub unsafe fn from_trusted_len_values_iter_unchecked<I: Iterator<Item = T>>(iter: I) -> Self {
424        MutablePrimitiveArray::<T>::from_trusted_len_values_iter_unchecked(iter).into()
425    }
426
427    /// Creates a [`PrimitiveArray`] from a [`TrustedLen`] of optional values.
428    pub fn from_trusted_len_iter<I: TrustedLen<Item = Option<T>>>(iter: I) -> Self {
429        MutablePrimitiveArray::<T>::from_trusted_len_iter(iter).into()
430    }
431
432    /// Creates a [`PrimitiveArray`] from an iterator of optional values.
433    ///
434    /// # Safety
435    /// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
436    /// I.e. that `size_hint().1` correctly reports its length.
437    pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = Option<T>>>(iter: I) -> Self {
438        MutablePrimitiveArray::<T>::from_trusted_len_iter_unchecked(iter).into()
439    }
440
441    /// Alias for `Self::try_new(..).unwrap()`.
442    /// # Panics
443    /// This function errors iff:
444    /// * The validity is not `None` and its length is different from `values`'s length
445    /// * The `dtype`'s [`PhysicalType`] is not equal to [`PhysicalType::Primitive`].
446    pub fn new(dtype: ArrowDataType, values: Buffer<T>, validity: Option<Bitmap>) -> Self {
447        Self::try_new(dtype, values, validity).unwrap()
448    }
449
450    /// Transmute this PrimitiveArray into another PrimitiveArray.
451    ///
452    /// T and U must have the same size and alignment.
453    pub fn transmute<U: NativeType>(self) -> PrimitiveArray<U> {
454        let PrimitiveArray {
455            values, validity, ..
456        } = self;
457
458        // SAFETY: this is fine, we checked size and alignment, and NativeType
459        // is always Pod.
460        assert_eq!(size_of::<T>(), size_of::<U>());
461        assert_eq!(align_of::<T>(), align_of::<U>());
462        let new_values = unsafe { std::mem::transmute::<Buffer<T>, Buffer<U>>(values) };
463        PrimitiveArray::new(U::PRIMITIVE.into(), new_values, validity)
464    }
465
466    /// Fills this entire array with the given value, leaving the validity mask intact.
467    ///
468    /// Reuses the memory of the PrimitiveArray if possible.
469    pub fn fill_with(mut self, value: T) -> Self {
470        if let Some(values) = self.get_mut_values() {
471            for x in values.iter_mut() {
472                *x = value;
473            }
474            self
475        } else {
476            let values = vec![value; self.len()];
477            Self::new(T::PRIMITIVE.into(), values.into(), self.validity)
478        }
479    }
480}
481
482impl<T: NativeType> Array for PrimitiveArray<T> {
483    impl_common_array!();
484
485    fn validity(&self) -> Option<&Bitmap> {
486        self.validity.as_ref()
487    }
488
489    #[inline]
490    fn with_validity(&self, validity: Option<Bitmap>) -> Box<dyn Array> {
491        Box::new(self.clone().with_validity(validity))
492    }
493}
494
495impl<T: NativeType> Splitable for PrimitiveArray<T> {
496    #[inline(always)]
497    fn check_bound(&self, offset: usize) -> bool {
498        offset <= self.len()
499    }
500
501    unsafe fn _split_at_unchecked(&self, offset: usize) -> (Self, Self) {
502        let (lhs_values, rhs_values) = unsafe { self.values.split_at_unchecked(offset) };
503        let (lhs_validity, rhs_validity) = unsafe { self.validity.split_at_unchecked(offset) };
504
505        (
506            Self {
507                dtype: self.dtype.clone(),
508                values: lhs_values,
509                validity: lhs_validity,
510            },
511            Self {
512                dtype: self.dtype.clone(),
513                values: rhs_values,
514                validity: rhs_validity,
515            },
516        )
517    }
518}
519
520impl<T: NativeType> SliceAble for PrimitiveArray<T> {
521    unsafe fn slice_unchecked(&self, range: Range<usize>) -> Self {
522        self.clone().sliced_unchecked(range.start, range.len())
523    }
524
525    fn slice(&self, range: Range<usize>) -> Self {
526        self.clone().sliced(range.start, range.len())
527    }
528}
529
530impl<T: NativeType> Indexable for PrimitiveArray<T> {
531    type Item = Option<T>;
532
533    fn get(&self, i: usize) -> Self::Item {
534        if !self.is_null(i) {
535            // soundness: Array::is_null panics if i >= self.len
536            unsafe { Some(self.value_unchecked(i)) }
537        } else {
538            None
539        }
540    }
541
542    unsafe fn get_unchecked(&self, i: usize) -> Self::Item {
543        if !self.is_null_unchecked(i) {
544            Some(self.value_unchecked(i))
545        } else {
546            None
547        }
548    }
549}
550
551/// A type definition [`PrimitiveArray`] for `i8`
552pub type Int8Array = PrimitiveArray<i8>;
553/// A type definition [`PrimitiveArray`] for `i16`
554pub type Int16Array = PrimitiveArray<i16>;
555/// A type definition [`PrimitiveArray`] for `i32`
556pub type Int32Array = PrimitiveArray<i32>;
557/// A type definition [`PrimitiveArray`] for `i64`
558pub type Int64Array = PrimitiveArray<i64>;
559/// A type definition [`PrimitiveArray`] for `i128`
560pub type Int128Array = PrimitiveArray<i128>;
561/// A type definition [`PrimitiveArray`] for `i256`
562pub type Int256Array = PrimitiveArray<i256>;
563/// A type definition [`PrimitiveArray`] for [`days_ms`]
564pub type DaysMsArray = PrimitiveArray<days_ms>;
565/// A type definition [`PrimitiveArray`] for [`months_days_ns`]
566pub type MonthsDaysNsArray = PrimitiveArray<months_days_ns>;
567/// A type definition [`PrimitiveArray`] for `f16`
568pub type Float16Array = PrimitiveArray<f16>;
569/// A type definition [`PrimitiveArray`] for `f32`
570pub type Float32Array = PrimitiveArray<f32>;
571/// A type definition [`PrimitiveArray`] for `f64`
572pub type Float64Array = PrimitiveArray<f64>;
573/// A type definition [`PrimitiveArray`] for `u8`
574pub type UInt8Array = PrimitiveArray<u8>;
575/// A type definition [`PrimitiveArray`] for `u16`
576pub type UInt16Array = PrimitiveArray<u16>;
577/// A type definition [`PrimitiveArray`] for `u32`
578pub type UInt32Array = PrimitiveArray<u32>;
579/// A type definition [`PrimitiveArray`] for `u64`
580pub type UInt64Array = PrimitiveArray<u64>;
581
582/// A type definition [`MutablePrimitiveArray`] for `i8`
583pub type Int8Vec = MutablePrimitiveArray<i8>;
584/// A type definition [`MutablePrimitiveArray`] for `i16`
585pub type Int16Vec = MutablePrimitiveArray<i16>;
586/// A type definition [`MutablePrimitiveArray`] for `i32`
587pub type Int32Vec = MutablePrimitiveArray<i32>;
588/// A type definition [`MutablePrimitiveArray`] for `i64`
589pub type Int64Vec = MutablePrimitiveArray<i64>;
590/// A type definition [`MutablePrimitiveArray`] for `i128`
591pub type Int128Vec = MutablePrimitiveArray<i128>;
592/// A type definition [`MutablePrimitiveArray`] for `i256`
593pub type Int256Vec = MutablePrimitiveArray<i256>;
594/// A type definition [`MutablePrimitiveArray`] for [`days_ms`]
595pub type DaysMsVec = MutablePrimitiveArray<days_ms>;
596/// A type definition [`MutablePrimitiveArray`] for [`months_days_ns`]
597pub type MonthsDaysNsVec = MutablePrimitiveArray<months_days_ns>;
598/// A type definition [`MutablePrimitiveArray`] for `f16`
599pub type Float16Vec = MutablePrimitiveArray<f16>;
600/// A type definition [`MutablePrimitiveArray`] for `f32`
601pub type Float32Vec = MutablePrimitiveArray<f32>;
602/// A type definition [`MutablePrimitiveArray`] for `f64`
603pub type Float64Vec = MutablePrimitiveArray<f64>;
604/// A type definition [`MutablePrimitiveArray`] for `u8`
605pub type UInt8Vec = MutablePrimitiveArray<u8>;
606/// A type definition [`MutablePrimitiveArray`] for `u16`
607pub type UInt16Vec = MutablePrimitiveArray<u16>;
608/// A type definition [`MutablePrimitiveArray`] for `u32`
609pub type UInt32Vec = MutablePrimitiveArray<u32>;
610/// A type definition [`MutablePrimitiveArray`] for `u64`
611pub type UInt64Vec = MutablePrimitiveArray<u64>;
612
613impl<T: NativeType> Default for PrimitiveArray<T> {
614    fn default() -> Self {
615        PrimitiveArray::new(T::PRIMITIVE.into(), Default::default(), None)
616    }
617}
618
619impl<T: NativeType> Bounded for PrimitiveArray<T> {
620    fn len(&self) -> usize {
621        self.values.len()
622    }
623}
624
625impl<T: NativeType> NullCount for PrimitiveArray<T> {
626    fn null_count(&self) -> usize {
627        <Self as Array>::null_count(self)
628    }
629}