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