Skip to main content

arrow_array/array/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5//! The concrete array definitions
6
7mod binary_array;
8
9use crate::types::*;
10use arrow_buffer::{ArrowNativeType, Buffer, NullBuffer, OffsetBuffer, ScalarBuffer};
11use arrow_data::ArrayData;
12use arrow_schema::{DataType, IntervalUnit, TimeUnit};
13use std::any::Any;
14use std::sync::Arc;
15
16pub use binary_array::*;
17
18mod boolean_array;
19pub use boolean_array::*;
20
21mod byte_array;
22pub use byte_array::*;
23
24mod dictionary_array;
25pub use dictionary_array::*;
26
27mod fixed_size_binary_array;
28pub use fixed_size_binary_array::*;
29
30mod fixed_size_list_array;
31pub use fixed_size_list_array::*;
32
33mod list_array;
34pub use list_array::*;
35
36mod map_array;
37pub use map_array::*;
38
39mod null_array;
40pub use null_array::*;
41
42mod primitive_array;
43pub use primitive_array::*;
44
45mod string_array;
46pub use string_array::*;
47
48mod struct_array;
49pub use struct_array::*;
50
51mod union_array;
52pub use union_array::*;
53
54mod run_array;
55
56pub use run_array::*;
57
58mod byte_view_array;
59
60pub use byte_view_array::*;
61
62mod list_view_array;
63
64pub use list_view_array::*;
65
66use crate::iterator::ArrayIter;
67
68/// An array in the [Arrow Columnar Format](https://arrow.apache.org/docs/format/Columnar.html)
69///
70/// # Safety
71///
72/// Implementations of this trait must ensure that all methods implementations comply with
73/// the Arrow specification. No safety guards are placed and failing to comply with it can
74/// translate into panics or undefined behavior. For example, a value computed based on `len`
75/// may be used as a direct index into memory regions without checks.
76///
77/// Note that it is likely impossible to correctly implement the trait for a
78/// third party type, as substantial arrow-rs functionality is based on the
79/// return values of [`Array::data_type`] and third party types cannot extend
80/// the [`DataType`] enum. So any code that attempts casting based on data type
81/// (including internal arrow library code) risks a panic or undefined behavior.
82/// See [this discussion] for more details.
83///
84/// This trait might be sealed in the future. Use at your own risk.
85///
86/// [this discussion]: https://github.com/apache/arrow-rs/pull/9234#pullrequestreview-3708950936
87pub unsafe trait Array: std::fmt::Debug + Send + Sync {
88    /// Returns the array as [`Any`] so that it can be
89    /// downcasted to a specific implementation.
90    ///
91    /// # Example:
92    ///
93    /// ```
94    /// # use std::sync::Arc;
95    /// # use arrow_array::{Int32Array, RecordBatch};
96    /// # use arrow_schema::{Schema, Field, DataType, ArrowError};
97    ///
98    /// let id = Int32Array::from(vec![1, 2, 3, 4, 5]);
99    /// let batch = RecordBatch::try_new(
100    ///     Arc::new(Schema::new(vec![Field::new("id", DataType::Int32, false)])),
101    ///     vec![Arc::new(id)]
102    /// ).unwrap();
103    ///
104    /// let int32array = batch
105    ///     .column(0)
106    ///     .as_any()
107    ///     .downcast_ref::<Int32Array>()
108    ///     .expect("Failed to downcast");
109    /// ```
110    fn as_any(&self) -> &dyn Any;
111
112    /// Returns the underlying data of this array
113    fn to_data(&self) -> ArrayData;
114
115    /// Returns the underlying data of this array
116    ///
117    /// Unlike [`Array::to_data`] this consumes self, allowing it avoid unnecessary clones
118    fn into_data(self) -> ArrayData;
119
120    /// Returns a reference to the [`DataType`] of this array.
121    ///
122    /// # Example:
123    ///
124    /// ```
125    /// use arrow_schema::DataType;
126    /// use arrow_array::{Array, Int32Array};
127    ///
128    /// let array = Int32Array::from(vec![1, 2, 3, 4, 5]);
129    ///
130    /// assert_eq!(*array.data_type(), DataType::Int32);
131    /// ```
132    fn data_type(&self) -> &DataType;
133
134    /// Returns a zero-copy slice of this array with the indicated offset and length.
135    ///
136    /// # Example:
137    ///
138    /// ```
139    /// use arrow_array::{Array, Int32Array};
140    ///
141    /// let array = Int32Array::from(vec![1, 2, 3, 4, 5]);
142    /// // Make slice over the values [2, 3, 4]
143    /// let array_slice = array.slice(1, 3);
144    ///
145    /// assert_eq!(&array_slice, &Int32Array::from(vec![2, 3, 4]));
146    /// ```
147    ///
148    /// # Panics
149    /// Panics if `offset + length > self.len()`
150    fn slice(&self, offset: usize, length: usize) -> ArrayRef;
151
152    /// Returns the length (i.e., number of elements) of this array.
153    ///
154    /// # Example:
155    ///
156    /// ```
157    /// use arrow_array::{Array, Int32Array};
158    ///
159    /// let array = Int32Array::from(vec![1, 2, 3, 4, 5]);
160    ///
161    /// assert_eq!(array.len(), 5);
162    /// ```
163    fn len(&self) -> usize;
164
165    /// Returns whether this array is empty.
166    ///
167    /// # Example:
168    ///
169    /// ```
170    /// use arrow_array::{Array, Int32Array};
171    ///
172    /// let array = Int32Array::from(vec![1, 2, 3, 4, 5]);
173    ///
174    /// assert_eq!(array.is_empty(), false);
175    /// ```
176    fn is_empty(&self) -> bool;
177
178    /// Shrinks the capacity of any exclusively owned buffer as much as possible
179    ///
180    /// Shared or externally allocated buffers will be ignored, and
181    /// any buffer offsets will be preserved.
182    fn shrink_to_fit(&mut self) {}
183
184    /// Returns the offset into the underlying data used by this array(-slice).
185    /// Note that the underlying data can be shared by many arrays.
186    /// This defaults to `0`.
187    ///
188    /// # Example:
189    ///
190    /// ```
191    /// use arrow_array::{Array, BooleanArray};
192    ///
193    /// let array = BooleanArray::from(vec![false, false, true, true]);
194    /// let array_slice = array.slice(1, 3);
195    ///
196    /// assert_eq!(array.offset(), 0);
197    /// assert_eq!(array_slice.offset(), 1);
198    /// ```
199    fn offset(&self) -> usize;
200
201    /// Returns the null buffer of this array if any.
202    ///
203    /// The null buffer contains the "physical" nulls of an array, that is how
204    /// the nulls are represented in the underlying arrow format.
205    ///
206    /// The physical representation is efficient, but is sometimes non intuitive
207    /// for certain array types such as those with nullable child arrays like
208    /// [`DictionaryArray::values`], [`RunArray::values`] or [`UnionArray`], or without a
209    /// null buffer, such as [`NullArray`].
210    ///
211    /// To determine if each element of such an array is "logically" null,
212    /// use the slower [`Array::logical_nulls`] to obtain a computed mask.
213    fn nulls(&self) -> Option<&NullBuffer>;
214
215    /// Returns a potentially computed [`NullBuffer`] that represents the logical
216    /// null values of this array, if any.
217    ///
218    /// Logical nulls represent the values that are null in the array,
219    /// regardless of the underlying physical arrow representation.
220    ///
221    /// For most array types, this is equivalent to the "physical" nulls
222    /// returned by [`Array::nulls`]. It is different for the following cases, because which
223    /// elements are null is not encoded in a single null buffer:
224    ///
225    /// * [`DictionaryArray`] where [`DictionaryArray::values`] contains nulls
226    /// * [`RunArray`] where [`RunArray::values`] contains nulls
227    /// * [`NullArray`] where all indices are nulls
228    /// * [`UnionArray`] where the selected values contains nulls
229    ///
230    /// In these cases a logical [`NullBuffer`] will be computed, encoding the
231    /// logical nullability of these arrays, beyond what is encoded in
232    /// [`Array::nulls`]
233    fn logical_nulls(&self) -> Option<NullBuffer> {
234        self.nulls().cloned()
235    }
236
237    /// Returns whether the element at `index` is null according to [`Array::nulls`]
238    ///
239    /// Note: For performance reasons, this method returns nullability solely as determined by the
240    /// null buffer. This difference can lead to surprising results, for example, [`NullArray::is_null`] always
241    /// returns `false` as the array lacks a null buffer. Similarly [`DictionaryArray`], [`RunArray`] and [`UnionArray`] may
242    /// encode nullability in their children. See [`Self::logical_nulls`] for more information.
243    ///
244    /// # Example:
245    ///
246    /// ```
247    /// use arrow_array::{Array, Int32Array, NullArray};
248    ///
249    /// let array = Int32Array::from(vec![Some(1), None]);
250    /// assert_eq!(array.is_null(0), false);
251    /// assert_eq!(array.is_null(1), true);
252    ///
253    /// // NullArrays do not have a null buffer, and therefore always
254    /// // return false for is_null.
255    /// let array = NullArray::new(1);
256    /// assert_eq!(array.is_null(0), false);
257    /// ```
258    ///
259    /// # Panics
260    ///
261    /// Panics if `index >= self.len()`.
262    ///
263    /// Note: arrays without a null buffer currently return `false` instead of
264    /// panicking, but callers must not rely on this.
265    fn is_null(&self, index: usize) -> bool {
266        self.nulls().is_some_and(|n| n.is_null(index))
267    }
268
269    /// Returns whether the element at `index` is *not* null, the
270    /// opposite of [`Self::is_null`].
271    ///
272    /// # Example:
273    ///
274    /// ```
275    /// use arrow_array::{Array, Int32Array};
276    ///
277    /// let array = Int32Array::from(vec![Some(1), None]);
278    ///
279    /// assert_eq!(array.is_valid(0), true);
280    /// assert_eq!(array.is_valid(1), false);
281    /// ```
282    ///
283    /// # Panics
284    ///
285    /// Panics if `index >= self.len()`.
286    ///
287    /// Note: arrays without a null buffer currently return `true` instead of
288    /// panicking, but callers must not rely on this.
289    fn is_valid(&self, index: usize) -> bool {
290        !self.is_null(index)
291    }
292
293    /// Returns the total number of physical null values in this array.
294    ///
295    /// Note: this method returns the physical null count, i.e. that encoded in [`Array::nulls`],
296    /// see [`Array::logical_nulls`] for logical nullability
297    ///
298    /// # Example:
299    ///
300    /// ```
301    /// use arrow_array::{Array, Int32Array};
302    ///
303    /// // Construct an array with values [1, NULL, NULL]
304    /// let array = Int32Array::from(vec![Some(1), None, None]);
305    ///
306    /// assert_eq!(array.null_count(), 2);
307    /// ```
308    fn null_count(&self) -> usize {
309        self.nulls().map(|n| n.null_count()).unwrap_or_default()
310    }
311
312    /// Returns the total number of logical null values in this array.
313    ///
314    /// Note: this method returns the logical null count, i.e. that encoded in
315    /// [`Array::logical_nulls`]. In general this is equivalent to [`Array::null_count`] but may differ in the
316    /// presence of logical nullability, see [`Array::nulls`] and [`Array::logical_nulls`].
317    ///
318    /// # Example:
319    ///
320    /// ```
321    /// use arrow_array::{Array, Int32Array};
322    ///
323    /// // Construct an array with values [1, NULL, NULL]
324    /// let array = Int32Array::from(vec![Some(1), None, None]);
325    ///
326    /// assert_eq!(array.logical_null_count(), 2);
327    /// ```
328    fn logical_null_count(&self) -> usize {
329        self.logical_nulls()
330            .map(|n| n.null_count())
331            .unwrap_or_default()
332    }
333
334    /// Returns `false` if the array is guaranteed to not contain any logical nulls
335    ///
336    /// This is generally equivalent to `Array::logical_null_count() != 0` unless determining
337    /// the logical nulls is expensive, in which case this method can return true even for an
338    /// array without nulls.
339    ///
340    /// This is also generally equivalent to `Array::null_count() != 0` but may differ in the
341    /// presence of logical nullability, see [`Array::logical_null_count`] and [`Array::null_count`].
342    ///
343    /// Implementations will return `true` unless they can cheaply prove no logical nulls
344    /// are present. For example a [`DictionaryArray`] with nullable values will still return true,
345    /// even if the nulls present in [`DictionaryArray::values`] are not referenced by any key,
346    /// and therefore would not appear in [`Array::logical_nulls`].
347    fn is_nullable(&self) -> bool {
348        self.logical_null_count() != 0
349    }
350
351    /// Returns the total number of bytes of memory pointed to by this array.
352    /// The buffers store bytes in the Arrow memory format, and include the data as well as the validity map.
353    /// Note that this does not always correspond to the exact memory usage of an array,
354    /// since multiple arrays can share the same buffers or slices thereof.
355    fn get_buffer_memory_size(&self) -> usize;
356
357    /// Returns the total number of bytes of memory occupied physically by this array.
358    /// This value will always be greater than returned by `get_buffer_memory_size()` and
359    /// includes the overhead of the data structures that contain the pointers to the various buffers.
360    fn get_array_memory_size(&self) -> usize;
361
362    /// Claim memory used by this array in the provided memory pool.
363    ///
364    /// This recursively claims memory for:
365    /// - All data buffers in this array
366    /// - All child arrays (for nested types like List, Struct, etc.)
367    /// - The null bitmap buffer if present
368    ///
369    /// This method guarantees that the memory pool will only compute occupied memory
370    /// exactly once. For example, if this array is derived from operations like `slice`,
371    /// calling `claim` on it would not change the memory pool's usage if the underlying buffers
372    /// are already counted before.
373    ///
374    /// # Example
375    /// ```
376    /// # use arrow_array::{Int32Array, Array};
377    /// # use arrow_buffer::TrackingMemoryPool;
378    /// # use arrow_buffer::MemoryPool;
379    ///
380    /// let pool = TrackingMemoryPool::default();
381    ///
382    /// let small_array = Int32Array::from(vec![1, 2, 3, 4, 5]);
383    /// let small_array_size = small_array.get_buffer_memory_size();
384    ///
385    /// // Claim the array's memory in the pool
386    /// small_array.claim(&pool);
387    ///
388    /// // Create and claim slices of `small_array`; should not increase memory usage
389    /// let slice1 = small_array.slice(0, 2);
390    /// let slice2 = small_array.slice(2, 2);
391    /// slice1.claim(&pool);
392    /// slice2.claim(&pool);
393    ///
394    /// assert_eq!(pool.used(), small_array_size);
395    ///
396    /// // Create a `large_array` which does not derive from the original `small_array`
397    ///
398    /// let large_array = Int32Array::from((0..1000).collect::<Vec<i32>>());
399    /// let large_array_size = large_array.get_buffer_memory_size();
400    ///
401    /// large_array.claim(&pool);
402    ///
403    /// // Trying to claim more than once is a no-op
404    /// large_array.claim(&pool);
405    /// large_array.claim(&pool);
406    ///
407    /// assert_eq!(pool.used(), small_array_size + large_array_size);
408    ///
409    /// let sum_of_all_sizes = small_array_size + large_array_size + slice1.get_buffer_memory_size() + slice2.get_buffer_memory_size();
410    ///
411    /// // `get_buffer_memory_size` works independently of the memory pool, so a sum of all the
412    /// // arrays in scope will always be >= the memory used reported by the memory pool.
413    /// assert_ne!(pool.used(), sum_of_all_sizes);
414    ///
415    /// // Until the final claim is dropped the buffer size remains accounted for
416    /// drop(small_array);
417    /// drop(slice1);
418    ///
419    /// assert_eq!(pool.used(), small_array_size + large_array_size);
420    ///
421    /// // Dropping this finally releases the buffer that was backing `small_array`
422    /// drop(slice2);
423    ///
424    /// assert_eq!(pool.used(), large_array_size);
425    /// ```
426    #[cfg(feature = "pool")]
427    fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
428        self.to_data().claim(pool)
429    }
430}
431
432/// A reference-counted reference to a generic `Array`
433pub type ArrayRef = Arc<dyn Array>;
434
435/// Ergonomics: Allow use of an ArrayRef as an `&dyn Array`
436unsafe impl Array for ArrayRef {
437    fn as_any(&self) -> &dyn Any {
438        self.as_ref().as_any()
439    }
440
441    fn to_data(&self) -> ArrayData {
442        self.as_ref().to_data()
443    }
444
445    fn into_data(self) -> ArrayData {
446        self.to_data()
447    }
448
449    fn data_type(&self) -> &DataType {
450        self.as_ref().data_type()
451    }
452
453    fn slice(&self, offset: usize, length: usize) -> ArrayRef {
454        self.as_ref().slice(offset, length)
455    }
456
457    fn len(&self) -> usize {
458        self.as_ref().len()
459    }
460
461    fn is_empty(&self) -> bool {
462        self.as_ref().is_empty()
463    }
464
465    /// For shared buffers, this is a no-op.
466    fn shrink_to_fit(&mut self) {
467        if let Some(slf) = Arc::get_mut(self) {
468            slf.shrink_to_fit();
469        } else {
470            // We ignore shared buffers.
471        }
472    }
473
474    fn offset(&self) -> usize {
475        self.as_ref().offset()
476    }
477
478    fn nulls(&self) -> Option<&NullBuffer> {
479        self.as_ref().nulls()
480    }
481
482    fn logical_nulls(&self) -> Option<NullBuffer> {
483        self.as_ref().logical_nulls()
484    }
485
486    fn is_null(&self, index: usize) -> bool {
487        self.as_ref().is_null(index)
488    }
489
490    fn is_valid(&self, index: usize) -> bool {
491        self.as_ref().is_valid(index)
492    }
493
494    fn null_count(&self) -> usize {
495        self.as_ref().null_count()
496    }
497
498    fn logical_null_count(&self) -> usize {
499        self.as_ref().logical_null_count()
500    }
501
502    fn is_nullable(&self) -> bool {
503        self.as_ref().is_nullable()
504    }
505
506    fn get_buffer_memory_size(&self) -> usize {
507        self.as_ref().get_buffer_memory_size()
508    }
509
510    fn get_array_memory_size(&self) -> usize {
511        self.as_ref().get_array_memory_size()
512    }
513
514    #[cfg(feature = "pool")]
515    fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
516        self.as_ref().claim(pool)
517    }
518}
519
520unsafe impl<T: Array> Array for &T {
521    fn as_any(&self) -> &dyn Any {
522        T::as_any(self)
523    }
524
525    fn to_data(&self) -> ArrayData {
526        T::to_data(self)
527    }
528
529    fn into_data(self) -> ArrayData {
530        self.to_data()
531    }
532
533    fn data_type(&self) -> &DataType {
534        T::data_type(self)
535    }
536
537    fn slice(&self, offset: usize, length: usize) -> ArrayRef {
538        T::slice(self, offset, length)
539    }
540
541    fn len(&self) -> usize {
542        T::len(self)
543    }
544
545    fn is_empty(&self) -> bool {
546        T::is_empty(self)
547    }
548
549    fn offset(&self) -> usize {
550        T::offset(self)
551    }
552
553    fn nulls(&self) -> Option<&NullBuffer> {
554        T::nulls(self)
555    }
556
557    fn logical_nulls(&self) -> Option<NullBuffer> {
558        T::logical_nulls(self)
559    }
560
561    fn is_null(&self, index: usize) -> bool {
562        T::is_null(self, index)
563    }
564
565    fn is_valid(&self, index: usize) -> bool {
566        T::is_valid(self, index)
567    }
568
569    fn null_count(&self) -> usize {
570        T::null_count(self)
571    }
572
573    fn logical_null_count(&self) -> usize {
574        T::logical_null_count(self)
575    }
576
577    fn is_nullable(&self) -> bool {
578        T::is_nullable(self)
579    }
580
581    fn get_buffer_memory_size(&self) -> usize {
582        T::get_buffer_memory_size(self)
583    }
584
585    fn get_array_memory_size(&self) -> usize {
586        T::get_array_memory_size(self)
587    }
588
589    #[cfg(feature = "pool")]
590    fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
591        T::claim(self, pool)
592    }
593}
594
595/// A generic trait for accessing the values of an [`Array`]
596///
597/// This trait helps write specialized implementations of algorithms for
598/// different array types. Specialized implementations allow the compiler
599/// to optimize the code for the specific array type, which can lead to
600/// significant performance improvements.
601///
602/// # Example
603/// For example, to write three different implementations of a string length function
604/// for [`StringArray`], [`LargeStringArray`], and [`StringViewArray`], you can write
605///
606/// ```
607/// # use std::sync::Arc;
608/// # use arrow_array::{ArrayAccessor, ArrayRef, ArrowPrimitiveType, OffsetSizeTrait, PrimitiveArray};
609/// # use arrow_buffer::ArrowNativeType;
610/// # use arrow_array::cast::AsArray;
611/// # use arrow_array::iterator::ArrayIter;
612/// # use arrow_array::types::{Int32Type, Int64Type};
613/// # use arrow_schema::{ArrowError, DataType};
614/// /// This function takes a dynamically typed `ArrayRef` and calls
615/// /// calls one of three specialized implementations
616/// fn character_length(arg: ArrayRef) -> Result<ArrayRef, ArrowError> {
617///     match arg.data_type() {
618///         DataType::Utf8 => {
619///             // downcast the ArrayRef to a StringArray and call the specialized implementation
620///             let string_array = arg.as_string::<i32>();
621///             character_length_general::<Int32Type, _>(string_array)
622///         }
623///         DataType::LargeUtf8 => {
624///             character_length_general::<Int64Type, _>(arg.as_string::<i64>())
625///         }
626///         DataType::Utf8View => {
627///             character_length_general::<Int32Type, _>(arg.as_string_view())
628///         }
629///         _ => Err(ArrowError::InvalidArgumentError("Unsupported data type".to_string())),
630///     }
631/// }
632///
633/// /// A generic implementation of the character_length function
634/// /// This function uses the `ArrayAccessor` trait to access the values of the array
635/// /// so the compiler can generated specialized implementations for different array types
636/// ///
637/// /// Returns a new array with the length of each string in the input array
638/// /// * Int32Array for Utf8 and Utf8View arrays (lengths are 32-bit integers)
639/// /// * Int64Array for LargeUtf8 arrays (lengths are 64-bit integers)
640/// ///
641/// /// This is generic on the type of the primitive array (different string arrays have
642/// /// different lengths) and the type of the array accessor (different string arrays
643/// /// have different ways to access the values)
644/// fn character_length_general<'a, T: ArrowPrimitiveType, V: ArrayAccessor<Item = &'a str>>(
645///     array: V,
646/// ) -> Result<ArrayRef, ArrowError>
647/// where
648///     T::Native: OffsetSizeTrait,
649/// {
650///     let iter = ArrayIter::new(array);
651///     // Create a Int32Array / Int64Array with the length of each string
652///     let result = iter
653///         .map(|string| {
654///             string.map(|string: &str| {
655///                 T::Native::from_usize(string.chars().count())
656///                     .expect("should not fail as string.chars will always return integer")
657///             })
658///         })
659///         .collect::<PrimitiveArray<T>>();
660///
661///     /// Return the result as a new ArrayRef (dynamically typed)
662///     Ok(Arc::new(result) as ArrayRef)
663/// }
664/// ```
665///
666/// # Validity
667///
668/// An [`ArrayAccessor`] must always return a well-defined value for an index
669/// that is within the bounds `0..Array::len`, including for null indexes where
670/// [`Array::is_null`] is true.
671///
672/// The value at null indexes is unspecified, and implementations must not rely
673/// on a specific value such as [`Default::default`] being returned, however, it
674/// must not be undefined
675pub trait ArrayAccessor: Array {
676    /// The Arrow type of the element being accessed.
677    type Item: Send + Sync;
678
679    /// Returns the element at index `i`
680    /// # Panics
681    /// Panics if the value is outside the bounds of the array
682    fn value(&self, index: usize) -> Self::Item;
683
684    /// Returns the element at index `i`
685    /// # Safety
686    /// Caller is responsible for ensuring that the index is within the bounds of the array
687    unsafe fn value_unchecked(&self, index: usize) -> Self::Item;
688}
689
690/// A trait for Arrow String Arrays, currently three types are supported:
691/// - `StringArray`
692/// - `LargeStringArray`
693/// - `StringViewArray`
694///
695/// This trait helps to abstract over the different types of string arrays
696/// so that we don't need to duplicate the implementation for each type.
697pub trait StringArrayType<'a>: ArrayAccessor<Item = &'a str> + Sized {
698    /// Returns true if all data within this string array is ASCII
699    fn is_ascii(&self) -> bool;
700
701    /// Constructs a new iterator
702    fn iter(&self) -> ArrayIter<Self>;
703}
704
705impl<'a, O: OffsetSizeTrait> StringArrayType<'a> for &'a GenericStringArray<O> {
706    fn is_ascii(&self) -> bool {
707        GenericStringArray::<O>::is_ascii(self)
708    }
709
710    fn iter(&self) -> ArrayIter<Self> {
711        GenericStringArray::<O>::iter(self)
712    }
713}
714impl<'a> StringArrayType<'a> for &'a StringViewArray {
715    fn is_ascii(&self) -> bool {
716        StringViewArray::is_ascii(self)
717    }
718
719    fn iter(&self) -> ArrayIter<Self> {
720        StringViewArray::iter(self)
721    }
722}
723
724/// A trait for Arrow Binary Arrays, currently four types are supported:
725/// - `BinaryArray`
726/// - `LargeBinaryArray`
727/// - `BinaryViewArray`
728/// - `FixedSizeBinaryArray`
729///
730/// This trait helps to abstract over the different types of binary arrays
731/// so that we don't need to duplicate the implementation for each type.
732pub trait BinaryArrayType<'a>: ArrayAccessor<Item = &'a [u8]> + Sized {
733    /// Constructs a new iterator
734    fn iter(&self) -> ArrayIter<Self>;
735}
736
737impl<'a, O: OffsetSizeTrait> BinaryArrayType<'a> for &'a GenericBinaryArray<O> {
738    fn iter(&self) -> ArrayIter<Self> {
739        GenericBinaryArray::<O>::iter(self)
740    }
741}
742impl<'a> BinaryArrayType<'a> for &'a BinaryViewArray {
743    fn iter(&self) -> ArrayIter<Self> {
744        BinaryViewArray::iter(self)
745    }
746}
747impl<'a> BinaryArrayType<'a> for &'a FixedSizeBinaryArray {
748    fn iter(&self) -> ArrayIter<Self> {
749        FixedSizeBinaryArray::iter(self)
750    }
751}
752
753/// A trait for Arrow list-like arrays, abstracting over
754/// [`GenericListArray`], [`GenericListViewArray`], and [`FixedSizeListArray`].
755///
756/// This trait provides a uniform interface for accessing the child values and
757/// computing the element range for a given index, regardless of the underlying
758/// list layout (offsets, offsets+sizes, or fixed-size).
759pub trait ListLikeArray: Array {
760    /// Returns the child values array.
761    fn values(&self) -> &ArrayRef;
762
763    /// Returns the start and end indices into the values array for the list
764    /// element at `index`.
765    fn element_range(&self, index: usize) -> std::ops::Range<usize>;
766}
767
768impl PartialEq for dyn Array + '_ {
769    fn eq(&self, other: &Self) -> bool {
770        self.to_data().eq(&other.to_data())
771    }
772}
773
774impl<T: Array> PartialEq<T> for dyn Array + '_ {
775    fn eq(&self, other: &T) -> bool {
776        self.to_data().eq(&other.to_data())
777    }
778}
779
780impl PartialEq for NullArray {
781    fn eq(&self, other: &NullArray) -> bool {
782        self.to_data().eq(&other.to_data())
783    }
784}
785
786impl<T: ArrowPrimitiveType> PartialEq for PrimitiveArray<T> {
787    fn eq(&self, other: &PrimitiveArray<T>) -> bool {
788        self.to_data().eq(&other.to_data())
789    }
790}
791
792impl<K: ArrowDictionaryKeyType> PartialEq for DictionaryArray<K> {
793    fn eq(&self, other: &Self) -> bool {
794        self.to_data().eq(&other.to_data())
795    }
796}
797
798impl PartialEq for BooleanArray {
799    fn eq(&self, other: &BooleanArray) -> bool {
800        self.to_data().eq(&other.to_data())
801    }
802}
803
804impl<OffsetSize: OffsetSizeTrait> PartialEq for GenericStringArray<OffsetSize> {
805    fn eq(&self, other: &Self) -> bool {
806        self.to_data().eq(&other.to_data())
807    }
808}
809
810impl<OffsetSize: OffsetSizeTrait> PartialEq for GenericBinaryArray<OffsetSize> {
811    fn eq(&self, other: &Self) -> bool {
812        self.to_data().eq(&other.to_data())
813    }
814}
815
816impl PartialEq for FixedSizeBinaryArray {
817    fn eq(&self, other: &Self) -> bool {
818        self.to_data().eq(&other.to_data())
819    }
820}
821
822impl<OffsetSize: OffsetSizeTrait> PartialEq for GenericListArray<OffsetSize> {
823    fn eq(&self, other: &Self) -> bool {
824        self.to_data().eq(&other.to_data())
825    }
826}
827
828impl<OffsetSize: OffsetSizeTrait> PartialEq for GenericListViewArray<OffsetSize> {
829    fn eq(&self, other: &Self) -> bool {
830        self.to_data().eq(&other.to_data())
831    }
832}
833
834impl PartialEq for MapArray {
835    fn eq(&self, other: &Self) -> bool {
836        self.to_data().eq(&other.to_data())
837    }
838}
839
840impl PartialEq for FixedSizeListArray {
841    fn eq(&self, other: &Self) -> bool {
842        self.to_data().eq(&other.to_data())
843    }
844}
845
846impl PartialEq for StructArray {
847    fn eq(&self, other: &Self) -> bool {
848        self.to_data().eq(&other.to_data())
849    }
850}
851
852impl<T: ByteViewType + ?Sized> PartialEq for GenericByteViewArray<T> {
853    fn eq(&self, other: &Self) -> bool {
854        self.to_data().eq(&other.to_data())
855    }
856}
857
858impl<R: RunEndIndexType> PartialEq for RunArray<R> {
859    fn eq(&self, other: &Self) -> bool {
860        self.to_data().eq(&other.to_data())
861    }
862}
863
864/// Constructs an [`ArrayRef`] from an [`ArrayData`].
865///
866/// # Notes:
867///
868/// It is more efficient to directly construct the concrete array type rather
869/// than using this function as creating an `ArrayData` requires at least one
870/// additional allocation (the Vec of buffers).
871///
872/// # Example:
873/// ```
874/// # use std::sync::Arc;
875/// # use arrow_data::ArrayData;
876/// # use arrow_array::{make_array, ArrayRef, Int32Array};
877/// # use arrow_buffer::{Buffer, ScalarBuffer};
878/// # use arrow_schema::DataType;
879/// // Create an Int32Array with values [1, 2, 3]
880/// let values_buffer = Buffer::from_slice_ref(&[1, 2, 3]);
881/// // ArrayData can be constructed using ArrayDataBuilder
882///  let builder = ArrayData::builder(DataType::Int32)
883///    .len(3)
884///    .add_buffer(values_buffer.clone());
885/// let array_data = builder.build().unwrap();
886/// // Create the ArrayRef from the ArrayData
887/// let array = make_array(array_data);
888///
889/// // It is equivalent to directly constructing the Int32Array
890/// let scalar_buffer = ScalarBuffer::from(values_buffer);
891/// let int32_array: ArrayRef = Arc::new(Int32Array::new(scalar_buffer, None));
892/// assert_eq!(&array, &int32_array);
893/// ```
894pub fn make_array(data: ArrayData) -> ArrayRef {
895    match data.data_type() {
896        DataType::Boolean => Arc::new(BooleanArray::from(data)) as ArrayRef,
897        DataType::Int8 => Arc::new(Int8Array::from(data)) as ArrayRef,
898        DataType::Int16 => Arc::new(Int16Array::from(data)) as ArrayRef,
899        DataType::Int32 => Arc::new(Int32Array::from(data)) as ArrayRef,
900        DataType::Int64 => Arc::new(Int64Array::from(data)) as ArrayRef,
901        DataType::UInt8 => Arc::new(UInt8Array::from(data)) as ArrayRef,
902        DataType::UInt16 => Arc::new(UInt16Array::from(data)) as ArrayRef,
903        DataType::UInt32 => Arc::new(UInt32Array::from(data)) as ArrayRef,
904        DataType::UInt64 => Arc::new(UInt64Array::from(data)) as ArrayRef,
905        DataType::Float16 => Arc::new(Float16Array::from(data)) as ArrayRef,
906        DataType::Float32 => Arc::new(Float32Array::from(data)) as ArrayRef,
907        DataType::Float64 => Arc::new(Float64Array::from(data)) as ArrayRef,
908        DataType::Date32 => Arc::new(Date32Array::from(data)) as ArrayRef,
909        DataType::Date64 => Arc::new(Date64Array::from(data)) as ArrayRef,
910        DataType::Time32(TimeUnit::Second) => Arc::new(Time32SecondArray::from(data)) as ArrayRef,
911        DataType::Time32(TimeUnit::Millisecond) => {
912            Arc::new(Time32MillisecondArray::from(data)) as ArrayRef
913        }
914        DataType::Time64(TimeUnit::Microsecond) => {
915            Arc::new(Time64MicrosecondArray::from(data)) as ArrayRef
916        }
917        DataType::Time64(TimeUnit::Nanosecond) => {
918            Arc::new(Time64NanosecondArray::from(data)) as ArrayRef
919        }
920        DataType::Timestamp(TimeUnit::Second, _) => {
921            Arc::new(TimestampSecondArray::from(data)) as ArrayRef
922        }
923        DataType::Timestamp(TimeUnit::Millisecond, _) => {
924            Arc::new(TimestampMillisecondArray::from(data)) as ArrayRef
925        }
926        DataType::Timestamp(TimeUnit::Microsecond, _) => {
927            Arc::new(TimestampMicrosecondArray::from(data)) as ArrayRef
928        }
929        DataType::Timestamp(TimeUnit::Nanosecond, _) => {
930            Arc::new(TimestampNanosecondArray::from(data)) as ArrayRef
931        }
932        DataType::Interval(IntervalUnit::YearMonth) => {
933            Arc::new(IntervalYearMonthArray::from(data)) as ArrayRef
934        }
935        DataType::Interval(IntervalUnit::DayTime) => {
936            Arc::new(IntervalDayTimeArray::from(data)) as ArrayRef
937        }
938        DataType::Interval(IntervalUnit::MonthDayNano) => {
939            Arc::new(IntervalMonthDayNanoArray::from(data)) as ArrayRef
940        }
941        DataType::Duration(TimeUnit::Second) => {
942            Arc::new(DurationSecondArray::from(data)) as ArrayRef
943        }
944        DataType::Duration(TimeUnit::Millisecond) => {
945            Arc::new(DurationMillisecondArray::from(data)) as ArrayRef
946        }
947        DataType::Duration(TimeUnit::Microsecond) => {
948            Arc::new(DurationMicrosecondArray::from(data)) as ArrayRef
949        }
950        DataType::Duration(TimeUnit::Nanosecond) => {
951            Arc::new(DurationNanosecondArray::from(data)) as ArrayRef
952        }
953        DataType::Binary => Arc::new(BinaryArray::from(data)) as ArrayRef,
954        DataType::LargeBinary => Arc::new(LargeBinaryArray::from(data)) as ArrayRef,
955        DataType::FixedSizeBinary(_) => Arc::new(FixedSizeBinaryArray::from(data)) as ArrayRef,
956        DataType::BinaryView => Arc::new(BinaryViewArray::from(data)) as ArrayRef,
957        DataType::Utf8 => Arc::new(StringArray::from(data)) as ArrayRef,
958        DataType::LargeUtf8 => Arc::new(LargeStringArray::from(data)) as ArrayRef,
959        DataType::Utf8View => Arc::new(StringViewArray::from(data)) as ArrayRef,
960        DataType::List(_) => Arc::new(ListArray::from(data)) as ArrayRef,
961        DataType::LargeList(_) => Arc::new(LargeListArray::from(data)) as ArrayRef,
962        DataType::ListView(_) => Arc::new(ListViewArray::from(data)) as ArrayRef,
963        DataType::LargeListView(_) => Arc::new(LargeListViewArray::from(data)) as ArrayRef,
964        DataType::Struct(_) => Arc::new(StructArray::from(data)) as ArrayRef,
965        DataType::Map(_, _) => Arc::new(MapArray::from(data)) as ArrayRef,
966        DataType::Union(_, _) => Arc::new(UnionArray::from(data)) as ArrayRef,
967        DataType::FixedSizeList(_, _) => Arc::new(FixedSizeListArray::from(data)) as ArrayRef,
968        DataType::Dictionary(key_type, _) => match key_type.as_ref() {
969            DataType::Int8 => Arc::new(DictionaryArray::<Int8Type>::from(data)) as ArrayRef,
970            DataType::Int16 => Arc::new(DictionaryArray::<Int16Type>::from(data)) as ArrayRef,
971            DataType::Int32 => Arc::new(DictionaryArray::<Int32Type>::from(data)) as ArrayRef,
972            DataType::Int64 => Arc::new(DictionaryArray::<Int64Type>::from(data)) as ArrayRef,
973            DataType::UInt8 => Arc::new(DictionaryArray::<UInt8Type>::from(data)) as ArrayRef,
974            DataType::UInt16 => Arc::new(DictionaryArray::<UInt16Type>::from(data)) as ArrayRef,
975            DataType::UInt32 => Arc::new(DictionaryArray::<UInt32Type>::from(data)) as ArrayRef,
976            DataType::UInt64 => Arc::new(DictionaryArray::<UInt64Type>::from(data)) as ArrayRef,
977            dt => unimplemented!("Unexpected dictionary key type {dt}"),
978        },
979        DataType::RunEndEncoded(run_ends_type, _) => match run_ends_type.data_type() {
980            DataType::Int16 => Arc::new(RunArray::<Int16Type>::from(data)) as ArrayRef,
981            DataType::Int32 => Arc::new(RunArray::<Int32Type>::from(data)) as ArrayRef,
982            DataType::Int64 => Arc::new(RunArray::<Int64Type>::from(data)) as ArrayRef,
983            dt => unimplemented!("Unexpected data type for run_ends array {dt}"),
984        },
985        DataType::Null => Arc::new(NullArray::from(data)) as ArrayRef,
986        DataType::Decimal32(_, _) => Arc::new(Decimal32Array::from(data)) as ArrayRef,
987        DataType::Decimal64(_, _) => Arc::new(Decimal64Array::from(data)) as ArrayRef,
988        DataType::Decimal128(_, _) => Arc::new(Decimal128Array::from(data)) as ArrayRef,
989        DataType::Decimal256(_, _) => Arc::new(Decimal256Array::from(data)) as ArrayRef,
990        dt => unimplemented!("Unexpected data type {dt}"),
991    }
992}
993
994/// Creates a new empty array
995///
996/// ```
997/// use std::sync::Arc;
998/// use arrow_schema::DataType;
999/// use arrow_array::{ArrayRef, Int32Array, new_empty_array};
1000///
1001/// let empty_array = new_empty_array(&DataType::Int32);
1002/// let array: ArrayRef = Arc::new(Int32Array::from(vec![] as Vec<i32>));
1003///
1004/// assert_eq!(&array, &empty_array);
1005/// ```
1006pub fn new_empty_array(data_type: &DataType) -> ArrayRef {
1007    let data = ArrayData::new_empty(data_type);
1008    make_array(data)
1009}
1010
1011/// Creates a new array of `data_type` of length `length` filled
1012/// entirely of `NULL` values
1013///
1014/// ```
1015/// use std::sync::Arc;
1016/// use arrow_schema::DataType;
1017/// use arrow_array::{ArrayRef, Int32Array, new_null_array};
1018///
1019/// let null_array = new_null_array(&DataType::Int32, 3);
1020/// let array: ArrayRef = Arc::new(Int32Array::from(vec![None, None, None]));
1021///
1022/// assert_eq!(&array, &null_array);
1023/// ```
1024pub fn new_null_array(data_type: &DataType, length: usize) -> ArrayRef {
1025    make_array(ArrayData::new_null(data_type, length))
1026}
1027
1028/// Helper function that creates an [`OffsetBuffer`] from a buffer and array offset/ length
1029///
1030/// # Safety
1031///
1032/// - buffer must contain valid arrow offsets ( [`OffsetBuffer`] ) for the
1033///   given length and offset.
1034unsafe fn get_offsets_from_buffer<O: ArrowNativeType>(
1035    buffer: Buffer,
1036    offset: usize,
1037    len: usize,
1038) -> OffsetBuffer<O> {
1039    if len == 0 && buffer.is_empty() {
1040        return OffsetBuffer::new_empty();
1041    }
1042
1043    let scalar_buffer = ScalarBuffer::new(buffer, offset, len + 1);
1044    // Safety:
1045    // Arguments were valid
1046    unsafe { OffsetBuffer::new_unchecked(scalar_buffer) }
1047}
1048
1049/// Helper function for printing potentially long arrays.
1050///
1051/// Note this function is deliberately not generic over the array or closure
1052/// type: it is called from `Debug` impls that are instantiated for many
1053/// concrete array types, and using dynamic dispatch here avoids duplicating
1054/// this function's code in each of those instantiations
1055fn print_long_array(
1056    array: &dyn Array,
1057    f: &mut std::fmt::Formatter,
1058    print_item: &mut dyn FnMut(usize, &mut std::fmt::Formatter) -> std::fmt::Result,
1059) -> std::fmt::Result {
1060    let head = std::cmp::min(10, array.len());
1061
1062    for i in 0..head {
1063        if array.is_null(i) {
1064            writeln!(f, "  null,")?;
1065        } else {
1066            write!(f, "  ")?;
1067            print_item(i, f)?;
1068            writeln!(f, ",")?;
1069        }
1070    }
1071    if array.len() > 10 {
1072        if array.len() > 20 {
1073            writeln!(f, "  ...{} elements...,", array.len() - 20)?;
1074        }
1075
1076        let tail = std::cmp::max(head, array.len() - 10);
1077
1078        for i in tail..array.len() {
1079            if array.is_null(i) {
1080                writeln!(f, "  null,")?;
1081            } else {
1082                write!(f, "  ")?;
1083                print_item(i, f)?;
1084                writeln!(f, ",")?;
1085            }
1086        }
1087    }
1088    Ok(())
1089}
1090
1091#[cfg(test)]
1092mod tests {
1093    use super::*;
1094    use crate::cast::{as_union_array, downcast_array};
1095    use crate::downcast_run_array;
1096    use arrow_buffer::MutableBuffer;
1097    use arrow_schema::{Field, Fields, UnionFields, UnionMode};
1098
1099    #[test]
1100    fn test_empty_primitive() {
1101        let array = new_empty_array(&DataType::Int32);
1102        let a = array.as_any().downcast_ref::<Int32Array>().unwrap();
1103        assert_eq!(a.len(), 0);
1104        let expected: &[i32] = &[];
1105        assert_eq!(a.values(), expected);
1106    }
1107
1108    #[test]
1109    fn test_empty_variable_sized() {
1110        let array = new_empty_array(&DataType::Utf8);
1111        let a = array.as_any().downcast_ref::<StringArray>().unwrap();
1112        assert_eq!(a.len(), 0);
1113        assert_eq!(a.value_offsets()[0], 0i32);
1114    }
1115
1116    #[test]
1117    fn test_empty_list_primitive() {
1118        let data_type = DataType::List(Arc::new(Field::new_list_field(DataType::Int32, false)));
1119        let array = new_empty_array(&data_type);
1120        let a = array.as_any().downcast_ref::<ListArray>().unwrap();
1121        assert_eq!(a.len(), 0);
1122        assert_eq!(a.value_offsets()[0], 0i32);
1123    }
1124
1125    #[test]
1126    fn test_null_boolean() {
1127        let array = new_null_array(&DataType::Boolean, 9);
1128        let a = array.as_any().downcast_ref::<BooleanArray>().unwrap();
1129        assert_eq!(a.len(), 9);
1130        for i in 0..9 {
1131            assert!(a.is_null(i));
1132        }
1133    }
1134
1135    #[test]
1136    fn test_null_primitive() {
1137        let array = new_null_array(&DataType::Int32, 9);
1138        let a = array.as_any().downcast_ref::<Int32Array>().unwrap();
1139        assert_eq!(a.len(), 9);
1140        for i in 0..9 {
1141            assert!(a.is_null(i));
1142        }
1143    }
1144
1145    #[test]
1146    fn test_null_struct() {
1147        // It is possible to create a null struct containing a non-nullable child
1148        // see https://github.com/apache/arrow-rs/pull/3244 for details
1149        let struct_type = DataType::Struct(vec![Field::new("data", DataType::Int64, false)].into());
1150        let array = new_null_array(&struct_type, 9);
1151
1152        let a = array.as_any().downcast_ref::<StructArray>().unwrap();
1153        assert_eq!(a.len(), 9);
1154        assert_eq!(a.column(0).len(), 9);
1155        for i in 0..9 {
1156            assert!(a.is_null(i));
1157        }
1158
1159        // Make sure we can slice the resulting array.
1160        a.slice(0, 5);
1161    }
1162
1163    #[test]
1164    fn test_null_variable_sized() {
1165        let array = new_null_array(&DataType::Utf8, 9);
1166        let a = array.as_any().downcast_ref::<StringArray>().unwrap();
1167        assert_eq!(a.len(), 9);
1168        assert_eq!(a.value_offsets()[9], 0i32);
1169        for i in 0..9 {
1170            assert!(a.is_null(i));
1171        }
1172    }
1173
1174    #[test]
1175    fn test_null_list_primitive() {
1176        let data_type = DataType::List(Arc::new(Field::new_list_field(DataType::Int32, true)));
1177        let array = new_null_array(&data_type, 9);
1178        let a = array.as_any().downcast_ref::<ListArray>().unwrap();
1179        assert_eq!(a.len(), 9);
1180        assert_eq!(a.value_offsets()[9], 0i32);
1181        for i in 0..9 {
1182            assert!(a.is_null(i));
1183        }
1184    }
1185
1186    #[test]
1187    fn test_null_map() {
1188        let data_type = DataType::Map(
1189            Arc::new(Field::new(
1190                Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
1191                DataType::Struct(Fields::from(vec![
1192                    Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, DataType::Utf8, false),
1193                    Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Int32, true),
1194                ])),
1195                false,
1196            )),
1197            false,
1198        );
1199        let array = new_null_array(&data_type, 9);
1200        let a = array.as_any().downcast_ref::<MapArray>().unwrap();
1201        assert_eq!(a.len(), 9);
1202        assert_eq!(a.value_offsets()[9], 0i32);
1203        for i in 0..9 {
1204            assert!(a.is_null(i));
1205        }
1206    }
1207
1208    #[test]
1209    fn test_null_dictionary() {
1210        let values =
1211            vec![None, None, None, None, None, None, None, None, None] as Vec<Option<&str>>;
1212
1213        let array: DictionaryArray<Int8Type> = values.into_iter().collect();
1214        let array = Arc::new(array) as ArrayRef;
1215
1216        let null_array = new_null_array(array.data_type(), 9);
1217        assert_eq!(&array, &null_array);
1218        assert_eq!(
1219            array.to_data().buffers()[0].len(),
1220            null_array.to_data().buffers()[0].len()
1221        );
1222    }
1223
1224    #[test]
1225    fn test_null_union() {
1226        for mode in [UnionMode::Sparse, UnionMode::Dense] {
1227            let data_type = DataType::Union(
1228                UnionFields::try_new(
1229                    vec![2, 1],
1230                    vec![
1231                        Field::new("foo", DataType::Int32, true),
1232                        Field::new("bar", DataType::Int64, true),
1233                    ],
1234                )
1235                .unwrap(),
1236                mode,
1237            );
1238            let array = new_null_array(&data_type, 4);
1239
1240            let array = as_union_array(array.as_ref());
1241            assert_eq!(array.len(), 4);
1242            assert_eq!(array.null_count(), 0);
1243            assert_eq!(array.logical_null_count(), 4);
1244
1245            for i in 0..4 {
1246                let a = array.value(i);
1247                assert_eq!(a.len(), 1);
1248                assert_eq!(a.null_count(), 1);
1249                assert_eq!(a.logical_null_count(), 1);
1250                assert!(a.is_null(0))
1251            }
1252
1253            array.to_data().validate_full().unwrap();
1254        }
1255    }
1256
1257    #[test]
1258    fn test_null_runs() {
1259        for r in [DataType::Int16, DataType::Int32, DataType::Int64] {
1260            let data_type = DataType::RunEndEncoded(
1261                Arc::new(Field::new(Field::REE_RUN_ENDS_FIELD_DEFAULT_NAME, r, false)),
1262                Arc::new(Field::new(
1263                    Field::REE_VALUES_FIELD_DEFAULT_NAME,
1264                    DataType::Utf8,
1265                    true,
1266                )),
1267            );
1268
1269            let array = new_null_array(&data_type, 4);
1270            let array = array.as_ref();
1271
1272            downcast_run_array! {
1273                array => {
1274                    assert_eq!(array.len(), 4);
1275                    assert_eq!(array.null_count(), 0);
1276                    assert_eq!(array.logical_null_count(), 4);
1277                    assert_eq!(array.values().len(), 1);
1278                    assert_eq!(array.values().null_count(), 1);
1279                    assert_eq!(array.run_ends().len(), 4);
1280                    assert_eq!(array.run_ends().values(), &[4]);
1281
1282                    let idx = array.get_physical_indices(&[0, 1, 2, 3]).unwrap();
1283                    assert_eq!(idx, &[0,0,0,0]);
1284                }
1285                d => unreachable!("{d}")
1286            }
1287        }
1288    }
1289
1290    #[test]
1291    fn test_null_fixed_size_binary() {
1292        for size in [1, 2, 7] {
1293            let array = new_null_array(&DataType::FixedSizeBinary(size), 6);
1294            let array = array
1295                .as_ref()
1296                .as_any()
1297                .downcast_ref::<FixedSizeBinaryArray>()
1298                .unwrap();
1299
1300            assert_eq!(array.len(), 6);
1301            assert_eq!(array.null_count(), 6);
1302            assert_eq!(array.logical_null_count(), 6);
1303            array.iter().for_each(|x| assert!(x.is_none()));
1304        }
1305    }
1306
1307    #[test]
1308    fn test_memory_size_null() {
1309        let null_arr = NullArray::new(32);
1310
1311        assert_eq!(0, null_arr.get_buffer_memory_size());
1312        assert_eq!(
1313            std::mem::size_of::<usize>(),
1314            null_arr.get_array_memory_size()
1315        );
1316    }
1317
1318    #[test]
1319    fn test_memory_size_primitive() {
1320        let arr = PrimitiveArray::<Int64Type>::from_iter_values(0..128);
1321        let empty = PrimitiveArray::<Int64Type>::from(ArrayData::new_empty(arr.data_type()));
1322
1323        // subtract empty array to avoid magic numbers for the size of additional fields
1324        assert_eq!(
1325            arr.get_array_memory_size() - empty.get_array_memory_size(),
1326            128 * std::mem::size_of::<i64>()
1327        );
1328    }
1329
1330    #[test]
1331    fn test_memory_size_primitive_sliced() {
1332        let arr = PrimitiveArray::<Int64Type>::from_iter_values(0..128);
1333        let slice1 = arr.slice(0, 64);
1334        let slice2 = arr.slice(64, 64);
1335
1336        // both slices report the full buffer memory usage, even though the buffers are shared
1337        assert_eq!(slice1.get_array_memory_size(), arr.get_array_memory_size());
1338        assert_eq!(slice2.get_array_memory_size(), arr.get_array_memory_size());
1339    }
1340
1341    #[test]
1342    fn test_memory_size_primitive_nullable() {
1343        let arr: PrimitiveArray<Int64Type> = (0..128)
1344            .map(|i| if i % 20 == 0 { Some(i) } else { None })
1345            .collect();
1346        let empty_with_bitmap = PrimitiveArray::<Int64Type>::from(
1347            ArrayData::builder(arr.data_type().clone())
1348                .add_buffer(MutableBuffer::new(0).into())
1349                .null_bit_buffer(Some(MutableBuffer::new_null(0).into()))
1350                .build()
1351                .unwrap(),
1352        );
1353
1354        // expected size is the size of the PrimitiveArray struct,
1355        // which includes the optional validity buffer
1356        // plus one buffer on the heap
1357        assert_eq!(
1358            std::mem::size_of::<PrimitiveArray<Int64Type>>(),
1359            empty_with_bitmap.get_array_memory_size()
1360        );
1361
1362        // subtract empty array to avoid magic numbers for the size of additional fields
1363        // the size of the validity bitmap is rounded up to 64 bytes
1364        assert_eq!(
1365            arr.get_array_memory_size() - empty_with_bitmap.get_array_memory_size(),
1366            128 * std::mem::size_of::<i64>() + 64
1367        );
1368    }
1369
1370    #[test]
1371    fn test_memory_size_dictionary() {
1372        let values = PrimitiveArray::<Int64Type>::from_iter_values(0..16);
1373        let keys = PrimitiveArray::<Int16Type>::from_iter_values(
1374            (0..256).map(|i| (i % values.len()) as i16),
1375        );
1376
1377        let dict_data_type = DataType::Dictionary(
1378            Box::new(keys.data_type().clone()),
1379            Box::new(values.data_type().clone()),
1380        );
1381        let dict_data = keys
1382            .into_data()
1383            .into_builder()
1384            .data_type(dict_data_type)
1385            .child_data(vec![values.into_data()])
1386            .build()
1387            .unwrap();
1388
1389        let empty_data = ArrayData::new_empty(&DataType::Dictionary(
1390            Box::new(DataType::Int16),
1391            Box::new(DataType::Int64),
1392        ));
1393
1394        let arr = DictionaryArray::<Int16Type>::from(dict_data);
1395        let empty = DictionaryArray::<Int16Type>::from(empty_data);
1396
1397        let expected_keys_size = 256 * std::mem::size_of::<i16>();
1398        assert_eq!(
1399            arr.keys().get_array_memory_size() - empty.keys().get_array_memory_size(),
1400            expected_keys_size
1401        );
1402
1403        let expected_values_size = 16 * std::mem::size_of::<i64>();
1404        assert_eq!(
1405            arr.values().get_array_memory_size() - empty.values().get_array_memory_size(),
1406            expected_values_size
1407        );
1408
1409        let expected_size = expected_keys_size + expected_values_size;
1410        assert_eq!(
1411            arr.get_array_memory_size() - empty.get_array_memory_size(),
1412            expected_size
1413        );
1414    }
1415
1416    /// Test function that takes an &dyn Array
1417    fn compute_my_thing(arr: &dyn Array) -> bool {
1418        !arr.is_empty()
1419    }
1420
1421    #[test]
1422    fn test_array_ref_as_array() {
1423        let arr: Int32Array = vec![1, 2, 3].into_iter().map(Some).collect();
1424
1425        // works well!
1426        assert!(compute_my_thing(&arr));
1427
1428        // Should also work when wrapped as an ArrayRef
1429        let arr: ArrayRef = Arc::new(arr);
1430        assert!(compute_my_thing(&arr));
1431        assert!(compute_my_thing(arr.as_ref()));
1432    }
1433
1434    #[test]
1435    fn test_downcast_array() {
1436        let array: Int32Array = vec![1, 2, 3].into_iter().map(Some).collect();
1437
1438        let boxed: ArrayRef = Arc::new(array);
1439        let array: Int32Array = downcast_array(&boxed);
1440
1441        let expected: Int32Array = vec![1, 2, 3].into_iter().map(Some).collect();
1442        assert_eq!(array, expected);
1443    }
1444}