Skip to main content

vortex_array/arrow/
convert.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::sync::Arc;
5
6use arrow_array::AnyDictionaryArray;
7use arrow_array::Array as ArrowArray;
8use arrow_array::ArrowPrimitiveType;
9use arrow_array::BooleanArray as ArrowBooleanArray;
10use arrow_array::DictionaryArray;
11use arrow_array::FixedSizeListArray as ArrowFixedSizeListArray;
12use arrow_array::GenericByteArray;
13use arrow_array::GenericByteViewArray;
14use arrow_array::GenericListArray;
15use arrow_array::GenericListViewArray;
16use arrow_array::NullArray as ArrowNullArray;
17use arrow_array::OffsetSizeTrait;
18use arrow_array::PrimitiveArray as ArrowPrimitiveArray;
19use arrow_array::RecordBatch;
20use arrow_array::StructArray as ArrowStructArray;
21use arrow_array::cast::AsArray;
22use arrow_array::cast::as_null_array;
23use arrow_array::make_array;
24use arrow_array::types::ArrowDictionaryKeyType;
25use arrow_array::types::ByteArrayType;
26use arrow_array::types::ByteViewType;
27use arrow_array::types::Date32Type;
28use arrow_array::types::Date64Type;
29use arrow_array::types::Decimal32Type;
30use arrow_array::types::Decimal64Type;
31use arrow_array::types::Decimal128Type;
32use arrow_array::types::Decimal256Type;
33use arrow_array::types::Float16Type;
34use arrow_array::types::Float32Type;
35use arrow_array::types::Float64Type;
36use arrow_array::types::Int8Type;
37use arrow_array::types::Int16Type;
38use arrow_array::types::Int32Type;
39use arrow_array::types::Int64Type;
40use arrow_array::types::Time32MillisecondType;
41use arrow_array::types::Time32SecondType;
42use arrow_array::types::Time64MicrosecondType;
43use arrow_array::types::Time64NanosecondType;
44use arrow_array::types::TimestampMicrosecondType;
45use arrow_array::types::TimestampMillisecondType;
46use arrow_array::types::TimestampNanosecondType;
47use arrow_array::types::TimestampSecondType;
48use arrow_array::types::UInt8Type;
49use arrow_array::types::UInt16Type;
50use arrow_array::types::UInt32Type;
51use arrow_array::types::UInt64Type;
52use arrow_buffer::ArrowNativeType;
53use arrow_buffer::BooleanBuffer;
54use arrow_buffer::Buffer as ArrowBuffer;
55use arrow_buffer::ScalarBuffer;
56use arrow_buffer::buffer::NullBuffer;
57use arrow_buffer::buffer::OffsetBuffer;
58use arrow_schema::DataType;
59use arrow_schema::TimeUnit as ArrowTimeUnit;
60use itertools::Itertools;
61use vortex_buffer::Alignment;
62use vortex_buffer::BitBuffer;
63use vortex_buffer::Buffer;
64use vortex_buffer::ByteBuffer;
65use vortex_error::VortexExpect as _;
66use vortex_error::VortexResult;
67use vortex_error::vortex_bail;
68use vortex_error::vortex_panic;
69
70use crate::ArrayRef;
71use crate::IntoArray;
72use crate::arrays::BoolArray;
73use crate::arrays::DecimalArray;
74use crate::arrays::DictArray;
75use crate::arrays::FixedSizeListArray;
76use crate::arrays::ListArray;
77use crate::arrays::ListViewArray;
78use crate::arrays::NullArray;
79use crate::arrays::PrimitiveArray;
80use crate::arrays::StructArray;
81use crate::arrays::TemporalArray;
82use crate::arrays::VarBinArray;
83use crate::arrays::VarBinViewArray;
84use crate::arrow::FromArrowArray;
85use crate::dtype::DType;
86use crate::dtype::DecimalDType;
87use crate::dtype::IntegerPType;
88use crate::dtype::NativePType;
89use crate::dtype::PType;
90use crate::dtype::i256;
91use crate::extension::datetime::TimeUnit;
92use crate::validity::Validity;
93
94impl IntoArray for ArrowBuffer {
95    fn into_array(self) -> ArrayRef {
96        PrimitiveArray::from_byte_buffer(
97            ByteBuffer::from_arrow_buffer(self, Alignment::of::<u8>()),
98            PType::U8,
99            Validity::NonNullable,
100        )
101        .into_array()
102    }
103}
104
105impl IntoArray for BooleanBuffer {
106    fn into_array(self) -> ArrayRef {
107        BoolArray::new(self.into(), Validity::NonNullable).into_array()
108    }
109}
110
111impl<T> IntoArray for ScalarBuffer<T>
112where
113    T: ArrowNativeType + NativePType,
114{
115    fn into_array(self) -> ArrayRef {
116        PrimitiveArray::new(
117            Buffer::<T>::from_arrow_scalar_buffer(self),
118            Validity::NonNullable,
119        )
120        .into_array()
121    }
122}
123
124impl<O> IntoArray for OffsetBuffer<O>
125where
126    O: IntegerPType + OffsetSizeTrait,
127{
128    fn into_array(self) -> ArrayRef {
129        let primitive = PrimitiveArray::new(
130            Buffer::from_arrow_scalar_buffer(self.into_inner()),
131            Validity::NonNullable,
132        );
133
134        primitive.into_array()
135    }
136}
137
138macro_rules! impl_from_arrow_primitive {
139    ($T:path) => {
140        impl FromArrowArray<&ArrowPrimitiveArray<$T>> for ArrayRef {
141            fn from_arrow(value: &ArrowPrimitiveArray<$T>, nullable: bool) -> VortexResult<Self> {
142                let buffer = Buffer::from_arrow_scalar_buffer(value.values().clone());
143                let validity = nulls(value.nulls(), nullable);
144                Ok(PrimitiveArray::new(buffer, validity).into_array())
145            }
146        }
147    };
148}
149
150impl_from_arrow_primitive!(Int8Type);
151impl_from_arrow_primitive!(Int16Type);
152impl_from_arrow_primitive!(Int32Type);
153impl_from_arrow_primitive!(Int64Type);
154impl_from_arrow_primitive!(UInt8Type);
155impl_from_arrow_primitive!(UInt16Type);
156impl_from_arrow_primitive!(UInt32Type);
157impl_from_arrow_primitive!(UInt64Type);
158impl_from_arrow_primitive!(Float16Type);
159impl_from_arrow_primitive!(Float32Type);
160impl_from_arrow_primitive!(Float64Type);
161
162impl FromArrowArray<&ArrowPrimitiveArray<Decimal32Type>> for ArrayRef {
163    fn from_arrow(
164        array: &ArrowPrimitiveArray<Decimal32Type>,
165        nullable: bool,
166    ) -> VortexResult<Self> {
167        let decimal_type = DecimalDType::new(array.precision(), array.scale());
168        let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
169        let validity = nulls(array.nulls(), nullable);
170        Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
171    }
172}
173
174impl FromArrowArray<&ArrowPrimitiveArray<Decimal64Type>> for ArrayRef {
175    fn from_arrow(
176        array: &ArrowPrimitiveArray<Decimal64Type>,
177        nullable: bool,
178    ) -> VortexResult<Self> {
179        let decimal_type = DecimalDType::new(array.precision(), array.scale());
180        let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
181        let validity = nulls(array.nulls(), nullable);
182        Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
183    }
184}
185
186impl FromArrowArray<&ArrowPrimitiveArray<Decimal128Type>> for ArrayRef {
187    fn from_arrow(
188        array: &ArrowPrimitiveArray<Decimal128Type>,
189        nullable: bool,
190    ) -> VortexResult<Self> {
191        let decimal_type = DecimalDType::new(array.precision(), array.scale());
192        let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
193        let validity = nulls(array.nulls(), nullable);
194        Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
195    }
196}
197
198impl FromArrowArray<&ArrowPrimitiveArray<Decimal256Type>> for ArrayRef {
199    fn from_arrow(
200        array: &ArrowPrimitiveArray<Decimal256Type>,
201        nullable: bool,
202    ) -> VortexResult<Self> {
203        let decimal_type = DecimalDType::new(array.precision(), array.scale());
204        let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
205        // SAFETY: Our i256 implementation has the same bit-pattern representation of the
206        //  arrow_buffer::i256 type. It is safe to treat values held inside the buffer as values
207        //  of either type.
208        let buffer =
209            unsafe { std::mem::transmute::<Buffer<arrow_buffer::i256>, Buffer<i256>>(buffer) };
210        let validity = nulls(array.nulls(), nullable);
211        Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
212    }
213}
214
215macro_rules! impl_from_arrow_temporal {
216    ($T:path) => {
217        impl FromArrowArray<&ArrowPrimitiveArray<$T>> for ArrayRef {
218            fn from_arrow(
219                value: &ArrowPrimitiveArray<$T>,
220                nullable: bool,
221            ) -> vortex_error::VortexResult<Self> {
222                Ok(temporal_array(value, nullable))
223            }
224        }
225    };
226}
227
228// timestamp
229impl_from_arrow_temporal!(TimestampSecondType);
230impl_from_arrow_temporal!(TimestampMillisecondType);
231impl_from_arrow_temporal!(TimestampMicrosecondType);
232impl_from_arrow_temporal!(TimestampNanosecondType);
233
234// time
235impl_from_arrow_temporal!(Time32SecondType);
236impl_from_arrow_temporal!(Time32MillisecondType);
237impl_from_arrow_temporal!(Time64MicrosecondType);
238impl_from_arrow_temporal!(Time64NanosecondType);
239
240// date
241impl_from_arrow_temporal!(Date32Type);
242impl_from_arrow_temporal!(Date64Type);
243
244fn temporal_array<T: ArrowPrimitiveType>(value: &ArrowPrimitiveArray<T>, nullable: bool) -> ArrayRef
245where
246    T::Native: NativePType,
247{
248    let arr = PrimitiveArray::new(
249        Buffer::from_arrow_scalar_buffer(value.values().clone()),
250        nulls(value.nulls(), nullable),
251    )
252    .into_array();
253
254    match value.data_type() {
255        DataType::Timestamp(time_unit, tz) => {
256            TemporalArray::new_timestamp(arr, time_unit.into(), tz.clone()).into()
257        }
258        DataType::Time32(time_unit) => TemporalArray::new_time(arr, time_unit.into()).into(),
259        DataType::Time64(time_unit) => TemporalArray::new_time(arr, time_unit.into()).into(),
260        DataType::Date32 => TemporalArray::new_date(arr, TimeUnit::Days).into(),
261        DataType::Date64 => TemporalArray::new_date(arr, TimeUnit::Milliseconds).into(),
262        DataType::Duration(_) => unimplemented!(),
263        DataType::Interval(_) => unimplemented!(),
264        _ => vortex_panic!("Invalid temporal type: {}", value.data_type()),
265    }
266}
267
268impl<T: ByteArrayType> FromArrowArray<&GenericByteArray<T>> for ArrayRef
269where
270    <T as ByteArrayType>::Offset: IntegerPType,
271{
272    fn from_arrow(value: &GenericByteArray<T>, nullable: bool) -> VortexResult<Self> {
273        let dtype = match T::DATA_TYPE {
274            DataType::Binary | DataType::LargeBinary => DType::Binary(nullable.into()),
275            DataType::Utf8 | DataType::LargeUtf8 => DType::Utf8(nullable.into()),
276            dt => vortex_panic!("Invalid data type for ByteArray: {dt}"),
277        };
278        // SAFETY: Arrow arrays are already validated (valid UTF-8, valid offsets, correct validity).
279        Ok(unsafe {
280            VarBinArray::new_unchecked(
281                value.offsets().clone().into_array(),
282                ByteBuffer::from_arrow_buffer(value.values().clone(), Alignment::of::<u8>()),
283                dtype,
284                nulls(value.nulls(), nullable),
285            )
286        }
287        .into_array())
288    }
289}
290
291impl<T: ByteViewType> FromArrowArray<&GenericByteViewArray<T>> for ArrayRef {
292    fn from_arrow(value: &GenericByteViewArray<T>, nullable: bool) -> VortexResult<Self> {
293        let dtype = match T::DATA_TYPE {
294            DataType::BinaryView => DType::Binary(nullable.into()),
295            DataType::Utf8View => DType::Utf8(nullable.into()),
296            dt => vortex_panic!("Invalid data type for ByteViewArray: {dt}"),
297        };
298
299        let views_buffer = Buffer::from_byte_buffer(
300            Buffer::from_arrow_scalar_buffer(value.views().clone()).into_byte_buffer(),
301        );
302
303        // SAFETY: arrow-rs ByteViewArray already checks the same invariants, we inherit those
304        //  guarantees by zero-copy constructing from one.
305        Ok(unsafe {
306            VarBinViewArray::new_unchecked(
307                views_buffer,
308                Arc::from(
309                    value
310                        .data_buffers()
311                        .iter()
312                        .map(|b| ByteBuffer::from_arrow_buffer(b.clone(), Alignment::of::<u8>()))
313                        .collect::<Vec<_>>(),
314                ),
315                dtype,
316                nulls(value.nulls(), nullable),
317            )
318            .into_array()
319        })
320    }
321}
322
323impl FromArrowArray<&ArrowBooleanArray> for ArrayRef {
324    fn from_arrow(value: &ArrowBooleanArray, nullable: bool) -> VortexResult<Self> {
325        Ok(BoolArray::new(
326            value.values().clone().into(),
327            nulls(value.nulls(), nullable),
328        )
329        .into_array())
330    }
331}
332
333/// Strip out the nulls from this array and return a new array without nulls.
334fn remove_nulls(data: arrow_data::ArrayData) -> arrow_data::ArrayData {
335    if data.null_count() == 0 {
336        // No nulls to remove, return the array as is
337        return data;
338    }
339
340    let children = match data.data_type() {
341        DataType::Struct(fields) => Some(
342            fields
343                .iter()
344                .zip(data.child_data().iter())
345                .map(|(field, child_data)| {
346                    if field.is_nullable() {
347                        child_data.clone()
348                    } else {
349                        remove_nulls(child_data.clone())
350                    }
351                })
352                .collect_vec(),
353        ),
354        DataType::List(f)
355        | DataType::LargeList(f)
356        | DataType::ListView(f)
357        | DataType::LargeListView(f)
358        | DataType::FixedSizeList(f, _)
359            if !f.is_nullable() =>
360        {
361            // All list types only have one child
362            assert_eq!(
363                data.child_data().len(),
364                1,
365                "List types should have one child"
366            );
367            Some(vec![remove_nulls(data.child_data()[0].clone())])
368        }
369        _ => None,
370    };
371
372    let mut builder = data.into_builder().nulls(None);
373    if let Some(children) = children {
374        builder = builder.child_data(children);
375    }
376    builder
377        .build()
378        .vortex_expect("reconstructing array without nulls")
379}
380
381impl FromArrowArray<&ArrowStructArray> for ArrayRef {
382    fn from_arrow(value: &ArrowStructArray, nullable: bool) -> VortexResult<Self> {
383        Ok(StructArray::try_new(
384            value.column_names().iter().copied().collect(),
385            value
386                .columns()
387                .iter()
388                .zip(value.fields())
389                .map(|(c, field)| {
390                    // Arrow pushes down nulls, even into non-nullable fields. So we strip them
391                    // out here because Vortex is a little more strict.
392                    if c.null_count() > 0 && !field.is_nullable() {
393                        let stripped = make_array(remove_nulls(c.into_data()));
394                        Self::from_arrow(stripped.as_ref(), false)
395                    } else {
396                        Self::from_arrow(c.as_ref(), field.is_nullable())
397                    }
398                })
399                .collect::<VortexResult<Vec<_>>>()?,
400            value.len(),
401            nulls(value.nulls(), nullable),
402        )?
403        .into_array())
404    }
405}
406
407impl<O: IntegerPType + OffsetSizeTrait> FromArrowArray<&GenericListArray<O>> for ArrayRef {
408    fn from_arrow(value: &GenericListArray<O>, nullable: bool) -> VortexResult<Self> {
409        // Extract the validity of the underlying element array.
410        let elements_are_nullable = match value.data_type() {
411            DataType::List(field) => field.is_nullable(),
412            DataType::LargeList(field) => field.is_nullable(),
413            dt => vortex_panic!("Invalid data type for ListArray: {dt}"),
414        };
415
416        let elements = Self::from_arrow(value.values().as_ref(), elements_are_nullable)?;
417
418        // `offsets` are always non-nullable.
419        let offsets = value.offsets().clone().into_array();
420        let nulls = nulls(value.nulls(), nullable);
421
422        Ok(ListArray::try_new(elements, offsets, nulls)?.into_array())
423    }
424}
425
426impl<O: OffsetSizeTrait + NativePType> FromArrowArray<&GenericListViewArray<O>> for ArrayRef {
427    fn from_arrow(array: &GenericListViewArray<O>, nullable: bool) -> VortexResult<Self> {
428        // Extract the validity of the underlying element array.
429        let elements_are_nullable = match array.data_type() {
430            DataType::ListView(field) => field.is_nullable(),
431            DataType::LargeListView(field) => field.is_nullable(),
432            dt => vortex_panic!("Invalid data type for ListViewArray: {dt}"),
433        };
434
435        let elements = Self::from_arrow(array.values().as_ref(), elements_are_nullable)?;
436
437        // `offsets` and `sizes` are always non-nullable.
438        let offsets = array.offsets().clone().into_array();
439        let sizes = array.sizes().clone().into_array();
440        let nulls = nulls(array.nulls(), nullable);
441
442        Ok(ListViewArray::try_new(elements, offsets, sizes, nulls)?.into_array())
443    }
444}
445
446impl FromArrowArray<&ArrowFixedSizeListArray> for ArrayRef {
447    fn from_arrow(array: &ArrowFixedSizeListArray, nullable: bool) -> VortexResult<Self> {
448        let DataType::FixedSizeList(field, list_size) = array.data_type() else {
449            vortex_panic!("Invalid data type for ListArray: {}", array.data_type());
450        };
451
452        Ok(FixedSizeListArray::try_new(
453            Self::from_arrow(array.values().as_ref(), field.is_nullable())?,
454            *list_size as u32,
455            nulls(array.nulls(), nullable),
456            array.len(),
457        )?
458        .into_array())
459    }
460}
461
462impl FromArrowArray<&ArrowNullArray> for ArrayRef {
463    fn from_arrow(value: &ArrowNullArray, nullable: bool) -> VortexResult<Self> {
464        assert!(nullable);
465        Ok(NullArray::new(value.len()).into_array())
466    }
467}
468
469impl<K: ArrowDictionaryKeyType> FromArrowArray<&DictionaryArray<K>> for DictArray {
470    fn from_arrow(array: &DictionaryArray<K>, nullable: bool) -> VortexResult<Self> {
471        let keys = AnyDictionaryArray::keys(array);
472        let keys = ArrayRef::from_arrow(keys, keys.is_nullable())?;
473        let values = ArrayRef::from_arrow(array.values().as_ref(), nullable)?;
474        // SAFETY: we assume that Arrow has checked the invariants on construction.
475        Ok(unsafe { DictArray::new_unchecked(keys, values) })
476    }
477}
478
479fn nulls(nulls: Option<&NullBuffer>, nullable: bool) -> Validity {
480    if nullable {
481        nulls
482            .map(|nulls| {
483                if nulls.null_count() == nulls.len() {
484                    Validity::AllInvalid
485                } else {
486                    Validity::from(BitBuffer::from(nulls.inner().clone()))
487                }
488            })
489            .unwrap_or_else(|| Validity::AllValid)
490    } else {
491        assert!(nulls.map(|x| x.null_count() == 0).unwrap_or(true));
492        Validity::NonNullable
493    }
494}
495
496impl FromArrowArray<&dyn ArrowArray> for ArrayRef {
497    fn from_arrow(array: &dyn ArrowArray, nullable: bool) -> VortexResult<Self> {
498        match array.data_type() {
499            DataType::Boolean => Self::from_arrow(array.as_boolean(), nullable),
500            DataType::UInt8 => Self::from_arrow(array.as_primitive::<UInt8Type>(), nullable),
501            DataType::UInt16 => Self::from_arrow(array.as_primitive::<UInt16Type>(), nullable),
502            DataType::UInt32 => Self::from_arrow(array.as_primitive::<UInt32Type>(), nullable),
503            DataType::UInt64 => Self::from_arrow(array.as_primitive::<UInt64Type>(), nullable),
504            DataType::Int8 => Self::from_arrow(array.as_primitive::<Int8Type>(), nullable),
505            DataType::Int16 => Self::from_arrow(array.as_primitive::<Int16Type>(), nullable),
506            DataType::Int32 => Self::from_arrow(array.as_primitive::<Int32Type>(), nullable),
507            DataType::Int64 => Self::from_arrow(array.as_primitive::<Int64Type>(), nullable),
508            DataType::Float16 => Self::from_arrow(array.as_primitive::<Float16Type>(), nullable),
509            DataType::Float32 => Self::from_arrow(array.as_primitive::<Float32Type>(), nullable),
510            DataType::Float64 => Self::from_arrow(array.as_primitive::<Float64Type>(), nullable),
511            DataType::Utf8 => Self::from_arrow(array.as_string::<i32>(), nullable),
512            DataType::LargeUtf8 => Self::from_arrow(array.as_string::<i64>(), nullable),
513            DataType::Binary => Self::from_arrow(array.as_binary::<i32>(), nullable),
514            DataType::LargeBinary => Self::from_arrow(array.as_binary::<i64>(), nullable),
515            DataType::BinaryView => Self::from_arrow(array.as_binary_view(), nullable),
516            DataType::Utf8View => Self::from_arrow(array.as_string_view(), nullable),
517            DataType::Struct(_) => Self::from_arrow(array.as_struct(), nullable),
518            DataType::List(_) => Self::from_arrow(array.as_list::<i32>(), nullable),
519            DataType::LargeList(_) => Self::from_arrow(array.as_list::<i64>(), nullable),
520            DataType::ListView(_) => Self::from_arrow(array.as_list_view::<i32>(), nullable),
521            DataType::LargeListView(_) => Self::from_arrow(array.as_list_view::<i64>(), nullable),
522            DataType::FixedSizeList(..) => Self::from_arrow(array.as_fixed_size_list(), nullable),
523            DataType::Null => Self::from_arrow(as_null_array(array), nullable),
524            DataType::Timestamp(u, _) => match u {
525                ArrowTimeUnit::Second => {
526                    Self::from_arrow(array.as_primitive::<TimestampSecondType>(), nullable)
527                }
528                ArrowTimeUnit::Millisecond => {
529                    Self::from_arrow(array.as_primitive::<TimestampMillisecondType>(), nullable)
530                }
531                ArrowTimeUnit::Microsecond => {
532                    Self::from_arrow(array.as_primitive::<TimestampMicrosecondType>(), nullable)
533                }
534                ArrowTimeUnit::Nanosecond => {
535                    Self::from_arrow(array.as_primitive::<TimestampNanosecondType>(), nullable)
536                }
537            },
538            DataType::Date32 => Self::from_arrow(array.as_primitive::<Date32Type>(), nullable),
539            DataType::Date64 => Self::from_arrow(array.as_primitive::<Date64Type>(), nullable),
540            DataType::Time32(u) => match u {
541                ArrowTimeUnit::Second => {
542                    Self::from_arrow(array.as_primitive::<Time32SecondType>(), nullable)
543                }
544                ArrowTimeUnit::Millisecond => {
545                    Self::from_arrow(array.as_primitive::<Time32MillisecondType>(), nullable)
546                }
547                ArrowTimeUnit::Microsecond | ArrowTimeUnit::Nanosecond => unreachable!(),
548            },
549            DataType::Time64(u) => match u {
550                ArrowTimeUnit::Microsecond => {
551                    Self::from_arrow(array.as_primitive::<Time64MicrosecondType>(), nullable)
552                }
553                ArrowTimeUnit::Nanosecond => {
554                    Self::from_arrow(array.as_primitive::<Time64NanosecondType>(), nullable)
555                }
556                ArrowTimeUnit::Second | ArrowTimeUnit::Millisecond => unreachable!(),
557            },
558            DataType::Decimal32(..) => {
559                Self::from_arrow(array.as_primitive::<Decimal32Type>(), nullable)
560            }
561            DataType::Decimal64(..) => {
562                Self::from_arrow(array.as_primitive::<Decimal64Type>(), nullable)
563            }
564            DataType::Decimal128(..) => {
565                Self::from_arrow(array.as_primitive::<Decimal128Type>(), nullable)
566            }
567            DataType::Decimal256(..) => {
568                Self::from_arrow(array.as_primitive::<Decimal256Type>(), nullable)
569            }
570            DataType::Dictionary(key_type, _) => match key_type.as_ref() {
571                DataType::Int8 => Ok(DictArray::from_arrow(
572                    array.as_dictionary::<Int8Type>(),
573                    nullable,
574                )?
575                .into_array()),
576                DataType::Int16 => Ok(DictArray::from_arrow(
577                    array.as_dictionary::<Int16Type>(),
578                    nullable,
579                )?
580                .into_array()),
581                DataType::Int32 => Ok(DictArray::from_arrow(
582                    array.as_dictionary::<Int32Type>(),
583                    nullable,
584                )?
585                .into_array()),
586                DataType::Int64 => Ok(DictArray::from_arrow(
587                    array.as_dictionary::<Int64Type>(),
588                    nullable,
589                )?
590                .into_array()),
591                DataType::UInt8 => Ok(DictArray::from_arrow(
592                    array.as_dictionary::<UInt8Type>(),
593                    nullable,
594                )?
595                .into_array()),
596                DataType::UInt16 => Ok(DictArray::from_arrow(
597                    array.as_dictionary::<UInt16Type>(),
598                    nullable,
599                )?
600                .into_array()),
601                DataType::UInt32 => Ok(DictArray::from_arrow(
602                    array.as_dictionary::<UInt32Type>(),
603                    nullable,
604                )?
605                .into_array()),
606                DataType::UInt64 => Ok(DictArray::from_arrow(
607                    array.as_dictionary::<UInt64Type>(),
608                    nullable,
609                )?
610                .into_array()),
611                key_dt => vortex_bail!("Unsupported dictionary key type: {key_dt}"),
612            },
613            dt => vortex_bail!("Array encoding not implemented for Arrow data type {dt}"),
614        }
615    }
616}
617
618impl FromArrowArray<RecordBatch> for ArrayRef {
619    fn from_arrow(array: RecordBatch, nullable: bool) -> VortexResult<Self> {
620        ArrayRef::from_arrow(&arrow_array::StructArray::from(array), nullable)
621    }
622}
623
624impl FromArrowArray<&RecordBatch> for ArrayRef {
625    fn from_arrow(array: &RecordBatch, nullable: bool) -> VortexResult<Self> {
626        Self::from_arrow(array.clone(), nullable)
627    }
628}
629
630#[cfg(test)]
631mod tests {
632    use std::sync::Arc;
633
634    use arrow_array::Array as ArrowArray;
635    use arrow_array::BinaryArray;
636    use arrow_array::BooleanArray;
637    use arrow_array::Date32Array;
638    use arrow_array::Date64Array;
639    use arrow_array::FixedSizeListArray as ArrowFixedSizeListArray;
640    use arrow_array::Float32Array;
641    use arrow_array::Float64Array;
642    use arrow_array::GenericListViewArray;
643    use arrow_array::Int8Array;
644    use arrow_array::Int16Array;
645    use arrow_array::Int32Array;
646    use arrow_array::Int64Array;
647    use arrow_array::LargeBinaryArray;
648    use arrow_array::LargeStringArray;
649    use arrow_array::NullArray;
650    use arrow_array::RecordBatch;
651    use arrow_array::StringArray;
652    use arrow_array::StructArray;
653    use arrow_array::Time32MillisecondArray;
654    use arrow_array::Time32SecondArray;
655    use arrow_array::Time64MicrosecondArray;
656    use arrow_array::Time64NanosecondArray;
657    use arrow_array::TimestampMicrosecondArray;
658    use arrow_array::TimestampMillisecondArray;
659    use arrow_array::TimestampNanosecondArray;
660    use arrow_array::TimestampSecondArray;
661    use arrow_array::UInt8Array;
662    use arrow_array::UInt16Array;
663    use arrow_array::UInt32Array;
664    use arrow_array::UInt64Array;
665    use arrow_array::builder::BinaryViewBuilder;
666    use arrow_array::builder::Decimal128Builder;
667    use arrow_array::builder::Decimal256Builder;
668    use arrow_array::builder::Int32Builder;
669    use arrow_array::builder::LargeListBuilder;
670    use arrow_array::builder::ListBuilder;
671    use arrow_array::builder::StringViewBuilder;
672    use arrow_array::new_null_array;
673    use arrow_array::types::ArrowPrimitiveType;
674    use arrow_array::types::Float16Type;
675    use arrow_buffer::BooleanBuffer;
676    use arrow_buffer::Buffer as ArrowBuffer;
677    use arrow_buffer::OffsetBuffer;
678    use arrow_buffer::ScalarBuffer;
679    use arrow_schema::DataType;
680    use arrow_schema::Field;
681    use arrow_schema::Fields;
682    use arrow_schema::Schema;
683
684    use crate::ArrayRef;
685    use crate::IntoArray;
686    use crate::arrays::Decimal;
687    use crate::arrays::FixedSizeList;
688    use crate::arrays::List;
689    use crate::arrays::ListView;
690    use crate::arrays::Primitive;
691    use crate::arrays::Struct;
692    use crate::arrays::VarBin;
693    use crate::arrays::VarBinView;
694    use crate::arrays::fixed_size_list::FixedSizeListArrayExt;
695    use crate::arrays::list::ListArrayExt;
696    use crate::arrays::listview::ListViewArrayExt;
697    use crate::arrays::struct_::StructArrayExt;
698    use crate::arrow::FromArrowArray as _;
699    use crate::arrow::convert::TemporalArray;
700    use crate::dtype::DType;
701    use crate::dtype::Nullability;
702    use crate::dtype::PType;
703    use crate::extension::datetime::TimeUnit;
704    use crate::extension::datetime::Timestamp;
705
706    // Test primitive array conversions
707    #[test]
708    fn test_int8_array_conversion() {
709        let arrow_array = Int8Array::from(vec![Some(1), None, Some(3), Some(4)]);
710        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
711
712        let arrow_array_non_null = Int8Array::from(vec![1, 2, 3, 4]);
713        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
714
715        assert_eq!(vortex_array.len(), 4);
716        assert_eq!(vortex_array_non_null.len(), 4);
717
718        // Verify metadata - should be PrimitiveArray with I8 ptype
719        let primitive_array = vortex_array.as_::<Primitive>();
720        assert_eq!(primitive_array.ptype(), PType::I8);
721
722        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
723        assert_eq!(primitive_array_non_null.ptype(), PType::I8);
724    }
725
726    #[test]
727    fn test_int16_array_conversion() {
728        let arrow_array = Int16Array::from(vec![Some(100), None, Some(300), Some(400)]);
729        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
730
731        let arrow_array_non_null = Int16Array::from(vec![100, 200, 300, 400]);
732        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
733
734        assert_eq!(vortex_array.len(), 4);
735        assert_eq!(vortex_array_non_null.len(), 4);
736
737        // Verify metadata - should be PrimitiveArray with I16 ptype
738        let primitive_array = vortex_array.as_::<Primitive>();
739        assert_eq!(primitive_array.ptype(), PType::I16);
740
741        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
742        assert_eq!(primitive_array_non_null.ptype(), PType::I16);
743    }
744
745    #[test]
746    fn test_int32_array_conversion() {
747        let arrow_array = Int32Array::from(vec![Some(1000), None, Some(3000), Some(4000)]);
748        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
749
750        let arrow_array_non_null = Int32Array::from(vec![1000, 2000, 3000, 4000]);
751        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
752
753        assert_eq!(vortex_array.len(), 4);
754        assert_eq!(vortex_array_non_null.len(), 4);
755
756        // Verify metadata - should be PrimitiveArray with I32 ptype
757        let primitive_array = vortex_array.as_::<Primitive>();
758        assert_eq!(primitive_array.ptype(), PType::I32);
759
760        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
761        assert_eq!(primitive_array_non_null.ptype(), PType::I32);
762    }
763
764    #[test]
765    fn test_int64_array_conversion() {
766        let arrow_array = Int64Array::from(vec![Some(10000), None, Some(30000), Some(40000)]);
767        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
768
769        let arrow_array_non_null = Int64Array::from(vec![10000_i64, 20000, 30000, 40000]);
770        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
771
772        assert_eq!(vortex_array.len(), 4);
773        assert_eq!(vortex_array_non_null.len(), 4);
774
775        // Verify metadata - should be PrimitiveArray with I64 ptype
776        let primitive_array = vortex_array.as_::<Primitive>();
777        assert_eq!(primitive_array.ptype(), PType::I64);
778
779        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
780        assert_eq!(primitive_array_non_null.ptype(), PType::I64);
781    }
782
783    #[test]
784    fn test_uint8_array_conversion() {
785        let arrow_array = UInt8Array::from(vec![Some(1), None, Some(3), Some(4)]);
786        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
787
788        let arrow_array_non_null = UInt8Array::from(vec![1_u8, 2, 3, 4]);
789        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
790
791        assert_eq!(vortex_array.len(), 4);
792        assert_eq!(vortex_array_non_null.len(), 4);
793
794        // Verify metadata - should be PrimitiveArray with U8 ptype
795        let primitive_array = vortex_array.as_::<Primitive>();
796        assert_eq!(primitive_array.ptype(), PType::U8);
797
798        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
799        assert_eq!(primitive_array_non_null.ptype(), PType::U8);
800    }
801
802    #[test]
803    fn test_uint16_array_conversion() {
804        let arrow_array = UInt16Array::from(vec![Some(100), None, Some(300), Some(400)]);
805        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
806
807        let arrow_array_non_null = UInt16Array::from(vec![100_u16, 200, 300, 400]);
808        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
809
810        assert_eq!(vortex_array.len(), 4);
811        assert_eq!(vortex_array_non_null.len(), 4);
812
813        // Verify metadata - should be PrimitiveArray with U16 ptype
814        let primitive_array = vortex_array.as_::<Primitive>();
815        assert_eq!(primitive_array.ptype(), PType::U16);
816
817        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
818        assert_eq!(primitive_array_non_null.ptype(), PType::U16);
819    }
820
821    #[test]
822    fn test_uint32_array_conversion() {
823        let arrow_array = UInt32Array::from(vec![Some(1000), None, Some(3000), Some(4000)]);
824        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
825
826        let arrow_array_non_null = UInt32Array::from(vec![1000_u32, 2000, 3000, 4000]);
827        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
828
829        assert_eq!(vortex_array.len(), 4);
830        assert_eq!(vortex_array_non_null.len(), 4);
831
832        // Verify metadata - should be PrimitiveArray with U32 ptype
833        let primitive_array = vortex_array.as_::<Primitive>();
834        assert_eq!(primitive_array.ptype(), PType::U32);
835
836        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
837        assert_eq!(primitive_array_non_null.ptype(), PType::U32);
838    }
839
840    #[test]
841    fn test_uint64_array_conversion() {
842        let arrow_array = UInt64Array::from(vec![Some(10000), None, Some(30000), Some(40000)]);
843        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
844
845        let arrow_array_non_null = UInt64Array::from(vec![10000_u64, 20000, 30000, 40000]);
846        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
847
848        assert_eq!(vortex_array.len(), 4);
849        assert_eq!(vortex_array_non_null.len(), 4);
850
851        // Verify metadata - should be PrimitiveArray with U64 ptype
852        let primitive_array = vortex_array.as_::<Primitive>();
853        assert_eq!(primitive_array.ptype(), PType::U64);
854
855        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
856        assert_eq!(primitive_array_non_null.ptype(), PType::U64);
857    }
858
859    #[test]
860    fn test_float16_array_conversion() {
861        let values = vec![
862            Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5)),
863            None,
864            Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(3.5)),
865        ];
866        let arrow_array = arrow_array::PrimitiveArray::<Float16Type>::from(values);
867        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
868
869        let non_null_values = vec![
870            <Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5),
871            <Float16Type as ArrowPrimitiveType>::Native::from_f32(2.5),
872        ];
873        let arrow_array_non_null =
874            arrow_array::PrimitiveArray::<Float16Type>::from(non_null_values);
875        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
876
877        assert_eq!(vortex_array.len(), 3);
878        assert_eq!(vortex_array_non_null.len(), 2);
879
880        // Verify metadata - should be PrimitiveArray with F16 ptype
881        let primitive_array = vortex_array.as_::<Primitive>();
882        assert_eq!(primitive_array.ptype(), PType::F16);
883
884        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
885        assert_eq!(primitive_array_non_null.ptype(), PType::F16);
886    }
887
888    #[test]
889    fn test_float32_array_conversion() {
890        let arrow_array = Float32Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)]);
891        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
892
893        let arrow_array_non_null = Float32Array::from(vec![1.5_f32, 2.5, 3.5, 4.5]);
894        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
895
896        assert_eq!(vortex_array.len(), 4);
897        assert_eq!(vortex_array_non_null.len(), 4);
898
899        // Verify metadata - should be PrimitiveArray with F32 ptype
900        let primitive_array = vortex_array.as_::<Primitive>();
901        assert_eq!(primitive_array.ptype(), PType::F32);
902
903        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
904        assert_eq!(primitive_array_non_null.ptype(), PType::F32);
905    }
906
907    #[test]
908    fn test_float64_array_conversion() {
909        let arrow_array = Float64Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)]);
910        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
911
912        let arrow_array_non_null = Float64Array::from(vec![1.5_f64, 2.5, 3.5, 4.5]);
913        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
914
915        assert_eq!(vortex_array.len(), 4);
916        assert_eq!(vortex_array_non_null.len(), 4);
917
918        // Verify metadata - should be PrimitiveArray with F64 ptype
919        let primitive_array = vortex_array.as_::<Primitive>();
920        assert_eq!(primitive_array.ptype(), PType::F64);
921
922        let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
923        assert_eq!(primitive_array_non_null.ptype(), PType::F64);
924    }
925
926    // Test decimal array conversions
927    #[test]
928    fn test_decimal128_array_conversion() {
929        let mut builder = Decimal128Builder::with_capacity(4);
930        builder.append_value(12345);
931        builder.append_null();
932        builder.append_value(67890);
933        builder.append_value(11111);
934        let decimal_array = builder.finish().with_precision_and_scale(10, 2).unwrap();
935
936        let vortex_array = ArrayRef::from_arrow(&decimal_array, true).unwrap();
937        assert_eq!(vortex_array.len(), 4);
938
939        let mut builder_non_null = Decimal128Builder::with_capacity(3);
940        builder_non_null.append_value(12345);
941        builder_non_null.append_value(67890);
942        builder_non_null.append_value(11111);
943        let decimal_array_non_null = builder_non_null
944            .finish()
945            .with_precision_and_scale(10, 2)
946            .unwrap();
947
948        let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false).unwrap();
949        assert_eq!(vortex_array_non_null.len(), 3);
950
951        // Verify metadata - should be DecimalArray with correct precision and scale
952        let decimal_vortex_array = vortex_array.as_::<Decimal>();
953        assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 10);
954        assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 2);
955
956        let decimal_vortex_array_non_null = vortex_array_non_null.as_::<Decimal>();
957        assert_eq!(
958            decimal_vortex_array_non_null.decimal_dtype().precision(),
959            10
960        );
961        assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 2);
962    }
963
964    #[test]
965    fn test_decimal256_array_conversion() {
966        let mut builder = Decimal256Builder::with_capacity(4);
967        builder.append_value(arrow_buffer::i256::from_i128(12345));
968        builder.append_null();
969        builder.append_value(arrow_buffer::i256::from_i128(67890));
970        builder.append_value(arrow_buffer::i256::from_i128(11111));
971        let decimal_array = builder.finish().with_precision_and_scale(38, 10).unwrap();
972
973        let vortex_array = ArrayRef::from_arrow(&decimal_array, true).unwrap();
974        assert_eq!(vortex_array.len(), 4);
975
976        let mut builder_non_null = Decimal256Builder::with_capacity(3);
977        builder_non_null.append_value(arrow_buffer::i256::from_i128(12345));
978        builder_non_null.append_value(arrow_buffer::i256::from_i128(67890));
979        builder_non_null.append_value(arrow_buffer::i256::from_i128(11111));
980        let decimal_array_non_null = builder_non_null
981            .finish()
982            .with_precision_and_scale(38, 10)
983            .unwrap();
984
985        let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false).unwrap();
986        assert_eq!(vortex_array_non_null.len(), 3);
987
988        // Verify metadata - should be DecimalArray with correct precision and scale
989        let decimal_vortex_array = vortex_array.as_::<Decimal>();
990        assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 38);
991        assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 10);
992
993        let decimal_vortex_array_non_null = vortex_array_non_null.as_::<Decimal>();
994        assert_eq!(
995            decimal_vortex_array_non_null.decimal_dtype().precision(),
996            38
997        );
998        assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 10);
999    }
1000
1001    // Test temporal array conversions
1002    #[test]
1003    fn test_timestamp_second_array_conversion() {
1004        let arrow_array =
1005            TimestampSecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1006        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1007
1008        let arrow_array_non_null = TimestampSecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1009        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1010
1011        assert_eq!(vortex_array.len(), 4);
1012        assert_eq!(vortex_array_non_null.len(), 4);
1013
1014        // Verify metadata - should be TemporalArray with Second time unit
1015        let temporal_array = TemporalArray::try_from(vortex_array).unwrap();
1016        assert_eq!(
1017            temporal_array.temporal_metadata().time_unit(),
1018            TimeUnit::Seconds
1019        );
1020
1021        let temporal_array_non_null = TemporalArray::try_from(vortex_array_non_null).unwrap();
1022        assert_eq!(
1023            temporal_array_non_null.temporal_metadata().time_unit(),
1024            TimeUnit::Seconds
1025        );
1026    }
1027
1028    #[test]
1029    fn test_timestamp_millisecond_array_conversion() {
1030        let arrow_array =
1031            TimestampMillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1032        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1033
1034        let arrow_array_non_null =
1035            TimestampMillisecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1036        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1037
1038        assert_eq!(vortex_array.len(), 4);
1039        assert_eq!(vortex_array_non_null.len(), 4);
1040    }
1041
1042    #[test]
1043    fn test_timestamp_microsecond_array_conversion() {
1044        let arrow_array =
1045            TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1046        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1047
1048        let arrow_array_non_null =
1049            TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1050        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1051
1052        assert_eq!(vortex_array.len(), 4);
1053        assert_eq!(vortex_array_non_null.len(), 4);
1054    }
1055
1056    #[test]
1057    fn test_timestamp_timezone_microsecond_array_conversion() {
1058        let arrow_array =
1059            TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])
1060                .with_timezone("UTC");
1061        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1062
1063        let arrow_array_non_null =
1064            TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]).with_timezone("UTC");
1065        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1066
1067        assert_eq!(vortex_array.len(), 4);
1068        assert_eq!(
1069            vortex_array.dtype(),
1070            &DType::Extension(
1071                Timestamp::new_with_tz(
1072                    TimeUnit::Microseconds,
1073                    Some("UTC".into()),
1074                    Nullability::Nullable
1075                )
1076                .erased()
1077            ),
1078        );
1079        assert_eq!(vortex_array_non_null.len(), 4);
1080        assert_eq!(
1081            vortex_array_non_null.dtype(),
1082            &DType::Extension(
1083                Timestamp::new_with_tz(
1084                    TimeUnit::Microseconds,
1085                    Some("UTC".into()),
1086                    Nullability::NonNullable
1087                )
1088                .erased()
1089            )
1090        );
1091    }
1092
1093    #[test]
1094    fn test_timestamp_nanosecond_array_conversion() {
1095        let arrow_array =
1096            TimestampNanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1097        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1098
1099        let arrow_array_non_null = TimestampNanosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1100        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1101
1102        assert_eq!(vortex_array.len(), 4);
1103        assert_eq!(vortex_array_non_null.len(), 4);
1104    }
1105
1106    #[test]
1107    fn test_time32_second_array_conversion() {
1108        let arrow_array = Time32SecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1109        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1110
1111        let arrow_array_non_null = Time32SecondArray::from(vec![1000_i32, 2000, 3000, 4000]);
1112        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1113
1114        assert_eq!(vortex_array.len(), 4);
1115        assert_eq!(vortex_array_non_null.len(), 4);
1116
1117        // Verify metadata - should be TemporalArray with Second time unit
1118        let temporal_array = TemporalArray::try_from(vortex_array).unwrap();
1119        assert_eq!(
1120            temporal_array.temporal_metadata().time_unit(),
1121            TimeUnit::Seconds
1122        );
1123
1124        let temporal_array_non_null = TemporalArray::try_from(vortex_array_non_null).unwrap();
1125        assert_eq!(
1126            temporal_array_non_null.temporal_metadata().time_unit(),
1127            TimeUnit::Seconds
1128        );
1129    }
1130
1131    #[test]
1132    fn test_time32_millisecond_array_conversion() {
1133        let arrow_array =
1134            Time32MillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1135        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1136
1137        let arrow_array_non_null = Time32MillisecondArray::from(vec![1000_i32, 2000, 3000, 4000]);
1138        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1139
1140        assert_eq!(vortex_array.len(), 4);
1141        assert_eq!(vortex_array_non_null.len(), 4);
1142    }
1143
1144    #[test]
1145    fn test_time64_microsecond_array_conversion() {
1146        let arrow_array =
1147            Time64MicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1148        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1149
1150        let arrow_array_non_null = Time64MicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1151        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1152
1153        assert_eq!(vortex_array.len(), 4);
1154        assert_eq!(vortex_array_non_null.len(), 4);
1155    }
1156
1157    #[test]
1158    fn test_time64_nanosecond_array_conversion() {
1159        let arrow_array =
1160            Time64NanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1161        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1162
1163        let arrow_array_non_null = Time64NanosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1164        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1165
1166        assert_eq!(vortex_array.len(), 4);
1167        assert_eq!(vortex_array_non_null.len(), 4);
1168    }
1169
1170    #[test]
1171    fn test_date32_array_conversion() {
1172        let arrow_array = Date32Array::from(vec![Some(18000), None, Some(18002), Some(18003)]);
1173        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1174
1175        let arrow_array_non_null = Date32Array::from(vec![18000_i32, 18001, 18002, 18003]);
1176        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1177
1178        assert_eq!(vortex_array.len(), 4);
1179        assert_eq!(vortex_array_non_null.len(), 4);
1180    }
1181
1182    #[test]
1183    fn test_date64_array_conversion() {
1184        let arrow_array = Date64Array::from(vec![
1185            Some(1555200000000),
1186            None,
1187            Some(1555286400000),
1188            Some(1555372800000),
1189        ]);
1190        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1191
1192        let arrow_array_non_null = Date64Array::from(vec![
1193            1555200000000_i64,
1194            1555213600000,
1195            1555286400000,
1196            1555372800000,
1197        ]);
1198        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1199
1200        assert_eq!(vortex_array.len(), 4);
1201        assert_eq!(vortex_array_non_null.len(), 4);
1202    }
1203
1204    // Test string/binary array conversions
1205    #[test]
1206    fn test_utf8_array_conversion() {
1207        let arrow_array = StringArray::from(vec![Some("hello"), None, Some("world"), Some("test")]);
1208        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1209
1210        let arrow_array_non_null = StringArray::from(vec!["hello", "world", "test", "vortex"]);
1211        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1212
1213        assert_eq!(vortex_array.len(), 4);
1214        assert_eq!(vortex_array_non_null.len(), 4);
1215
1216        // Verify metadata - should be VarBinArray with Utf8 dtype
1217        let varbin_array = vortex_array.as_::<VarBin>();
1218        assert_eq!(varbin_array.dtype(), &DType::Utf8(true.into()));
1219
1220        let varbin_array_non_null = vortex_array_non_null.as_::<VarBin>();
1221        assert_eq!(varbin_array_non_null.dtype(), &DType::Utf8(false.into()));
1222    }
1223
1224    #[test]
1225    fn test_large_utf8_array_conversion() {
1226        let arrow_array =
1227            LargeStringArray::from(vec![Some("hello"), None, Some("world"), Some("test")]);
1228        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1229
1230        let arrow_array_non_null = LargeStringArray::from(vec!["hello", "world", "test", "vortex"]);
1231        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1232
1233        assert_eq!(vortex_array.len(), 4);
1234        assert_eq!(vortex_array_non_null.len(), 4);
1235    }
1236
1237    #[test]
1238    fn test_binary_array_conversion() {
1239        let arrow_array = BinaryArray::from(vec![
1240            Some("hello".as_bytes()),
1241            None,
1242            Some("world".as_bytes()),
1243            Some("test".as_bytes()),
1244        ]);
1245        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1246
1247        let arrow_array_non_null = BinaryArray::from(vec![
1248            "hello".as_bytes(),
1249            "world".as_bytes(),
1250            "test".as_bytes(),
1251            "vortex".as_bytes(),
1252        ]);
1253        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1254
1255        assert_eq!(vortex_array.len(), 4);
1256        assert_eq!(vortex_array_non_null.len(), 4);
1257    }
1258
1259    #[test]
1260    fn test_large_binary_array_conversion() {
1261        let arrow_array = LargeBinaryArray::from(vec![
1262            Some("hello".as_bytes()),
1263            None,
1264            Some("world".as_bytes()),
1265            Some("test".as_bytes()),
1266        ]);
1267        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1268
1269        let arrow_array_non_null = LargeBinaryArray::from(vec![
1270            "hello".as_bytes(),
1271            "world".as_bytes(),
1272            "test".as_bytes(),
1273            "vortex".as_bytes(),
1274        ]);
1275        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1276
1277        assert_eq!(vortex_array.len(), 4);
1278        assert_eq!(vortex_array_non_null.len(), 4);
1279    }
1280
1281    #[test]
1282    fn test_utf8_view_array_conversion() {
1283        let mut builder = StringViewBuilder::new();
1284        builder.append_value("hello");
1285        builder.append_null();
1286        builder.append_value("world");
1287        builder.append_value("test");
1288        let arrow_array = builder.finish();
1289        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1290
1291        let mut builder_non_null = StringViewBuilder::new();
1292        builder_non_null.append_value("hello");
1293        builder_non_null.append_value("world");
1294        builder_non_null.append_value("test");
1295        builder_non_null.append_value("vortex");
1296        let arrow_array_non_null = builder_non_null.finish();
1297        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1298
1299        assert_eq!(vortex_array.len(), 4);
1300        assert_eq!(vortex_array_non_null.len(), 4);
1301
1302        // Verify metadata - should be VarBinViewArray with correct buffer count and dtype
1303        let varbin_view_array = vortex_array.as_::<VarBinView>();
1304        assert_eq!(
1305            varbin_view_array.data_buffers().len(),
1306            arrow_array.data_buffers().len()
1307        );
1308        assert_eq!(varbin_view_array.dtype(), &DType::Utf8(true.into()));
1309
1310        let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinView>();
1311        assert_eq!(
1312            varbin_view_array_non_null.data_buffers().len(),
1313            arrow_array_non_null.data_buffers().len()
1314        );
1315        assert_eq!(
1316            varbin_view_array_non_null.dtype(),
1317            &DType::Utf8(false.into())
1318        );
1319    }
1320
1321    #[test]
1322    fn test_binary_view_array_conversion() {
1323        let mut builder = BinaryViewBuilder::new();
1324        builder.append_value(b"hello");
1325        builder.append_null();
1326        builder.append_value(b"world");
1327        builder.append_value(b"test");
1328        let arrow_array = builder.finish();
1329        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1330
1331        let mut builder_non_null = BinaryViewBuilder::new();
1332        builder_non_null.append_value(b"hello");
1333        builder_non_null.append_value(b"world");
1334        builder_non_null.append_value(b"test");
1335        builder_non_null.append_value(b"vortex");
1336        let arrow_array_non_null = builder_non_null.finish();
1337        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1338
1339        assert_eq!(vortex_array.len(), 4);
1340        assert_eq!(vortex_array_non_null.len(), 4);
1341
1342        // Verify metadata - should be VarBinViewArray with correct buffer count and dtype
1343        let varbin_view_array = vortex_array.as_::<VarBinView>();
1344        assert_eq!(
1345            varbin_view_array.data_buffers().len(),
1346            arrow_array.data_buffers().len()
1347        );
1348        assert_eq!(varbin_view_array.dtype(), &DType::Binary(true.into()));
1349
1350        let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinView>();
1351        assert_eq!(
1352            varbin_view_array_non_null.data_buffers().len(),
1353            arrow_array_non_null.data_buffers().len()
1354        );
1355        assert_eq!(
1356            varbin_view_array_non_null.dtype(),
1357            &DType::Binary(false.into())
1358        );
1359    }
1360
1361    // Test boolean array conversions
1362    #[test]
1363    fn test_boolean_array_conversion() {
1364        let arrow_array = BooleanArray::from(vec![Some(true), None, Some(false), Some(true)]);
1365        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1366
1367        let arrow_array_non_null = BooleanArray::from(vec![true, false, true, false]);
1368        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1369
1370        assert_eq!(vortex_array.len(), 4);
1371        assert_eq!(vortex_array_non_null.len(), 4);
1372    }
1373
1374    // Test struct array conversions
1375    #[test]
1376    fn test_struct_array_conversion() {
1377        let fields = vec![
1378            Field::new("field1", DataType::Int32, true),
1379            Field::new("field2", DataType::Utf8, false),
1380        ];
1381        let schema = Fields::from(fields);
1382
1383        let field1_data = Int32Array::from(vec![Some(1), None, Some(3)]);
1384        let field2_data = StringArray::from(vec!["a", "b", "c"]);
1385
1386        let arrow_array = StructArray::new(
1387            schema.clone(),
1388            vec![Arc::new(field1_data), Arc::new(field2_data)],
1389            None,
1390        );
1391
1392        let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1393        assert_eq!(vortex_array.len(), 3);
1394
1395        // Verify metadata - should be StructArray with correct field names
1396        let struct_vortex_array = vortex_array.as_::<Struct>();
1397        assert_eq!(struct_vortex_array.names().len(), 2);
1398        assert_eq!(struct_vortex_array.names()[0], "field1");
1399        assert_eq!(struct_vortex_array.names()[1], "field2");
1400
1401        // Test nullable struct
1402        let nullable_array = StructArray::new(
1403            schema,
1404            vec![
1405                Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])),
1406                Arc::new(StringArray::from(vec!["a", "b", "c"])),
1407            ],
1408            Some(arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![
1409                true, false, true,
1410            ]))),
1411        );
1412
1413        let vortex_nullable_array = ArrayRef::from_arrow(&nullable_array, true).unwrap();
1414        assert_eq!(vortex_nullable_array.len(), 3);
1415
1416        // Verify metadata for nullable struct
1417        let struct_vortex_nullable_array = vortex_nullable_array.as_::<Struct>();
1418        assert_eq!(struct_vortex_nullable_array.names().len(), 2);
1419        assert_eq!(struct_vortex_nullable_array.names()[0], "field1");
1420        assert_eq!(struct_vortex_nullable_array.names()[1], "field2");
1421    }
1422
1423    // Test list array conversions
1424    #[test]
1425    fn test_list_array_conversion() {
1426        let mut builder = ListBuilder::new(Int32Builder::new());
1427        builder.append_value([Some(1), None, Some(3)]);
1428        builder.append_null();
1429        builder.append_value([Some(4), Some(5)]);
1430        let arrow_array = builder.finish();
1431
1432        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1433        assert_eq!(vortex_array.len(), 3);
1434
1435        // Verify metadata - should be ListArray with correct offsets
1436        let list_vortex_array = vortex_array.as_::<List>();
1437        let offsets_array = list_vortex_array.offsets().as_::<Primitive>();
1438        assert_eq!(offsets_array.len(), 4); // n+1 offsets for n lists
1439        assert_eq!(offsets_array.ptype(), PType::I32);
1440
1441        // Test non-nullable list
1442        let mut builder_non_null = ListBuilder::new(Int32Builder::new());
1443        builder_non_null.append_value([Some(1), None, Some(3)]);
1444        builder_non_null.append_value([Some(4), Some(5)]);
1445        let arrow_array_non_null = builder_non_null.finish();
1446
1447        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1448        assert_eq!(vortex_array_non_null.len(), 2);
1449
1450        // Verify metadata for non-nullable list
1451        let list_vortex_array_non_null = vortex_array_non_null.as_::<List>();
1452        let offsets_array_non_null = list_vortex_array_non_null.offsets().as_::<Primitive>();
1453        assert_eq!(offsets_array_non_null.len(), 3); // n+1 offsets for n lists
1454        assert_eq!(offsets_array_non_null.ptype(), PType::I32);
1455    }
1456
1457    #[test]
1458    fn test_large_list_array_conversion() {
1459        let mut builder = LargeListBuilder::new(Int32Builder::new());
1460        builder.append_value([Some(1), None, Some(3)]);
1461        builder.append_null();
1462        builder.append_value([Some(4), Some(5)]);
1463        let arrow_array = builder.finish();
1464
1465        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1466        assert_eq!(vortex_array.len(), 3);
1467
1468        // Verify metadata - should be ListArray with correct offsets (I64 for large lists)
1469        let list_vortex_array = vortex_array.as_::<List>();
1470        let offsets_array = list_vortex_array.offsets().as_::<Primitive>();
1471        assert_eq!(offsets_array.len(), 4); // n+1 offsets for n lists
1472        assert_eq!(offsets_array.ptype(), PType::I64); // Large lists use I64 offsets
1473
1474        // Test non-nullable large list
1475        let mut builder_non_null = LargeListBuilder::new(Int32Builder::new());
1476        builder_non_null.append_value([Some(1), None, Some(3)]);
1477        builder_non_null.append_value([Some(4), Some(5)]);
1478        let arrow_array_non_null = builder_non_null.finish();
1479
1480        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1481        assert_eq!(vortex_array_non_null.len(), 2);
1482
1483        // Verify metadata for non-nullable large list
1484        let list_vortex_array_non_null = vortex_array_non_null.as_::<List>();
1485        let offsets_array_non_null = list_vortex_array_non_null.offsets().as_::<Primitive>();
1486        assert_eq!(offsets_array_non_null.len(), 3); // n+1 offsets for n lists
1487        assert_eq!(offsets_array_non_null.ptype(), PType::I64); // Large lists use I64 offsets
1488    }
1489
1490    #[test]
1491    fn test_fixed_size_list_array_conversion() {
1492        // Create elements for the fixed-size lists
1493        let values = Int32Array::from(vec![
1494            Some(1),
1495            Some(2),
1496            Some(3), // First list
1497            Some(4),
1498            None,
1499            Some(6), // Second list (with null element)
1500            Some(7),
1501            Some(8),
1502            Some(9), // Third list
1503            Some(10),
1504            Some(11),
1505            Some(12), // Fourth list
1506        ]);
1507
1508        // Create a FixedSizeListArray with list_size=3
1509        let field = Arc::new(Field::new("item", DataType::Int32, true));
1510        let arrow_array =
1511            ArrowFixedSizeListArray::try_new(Arc::clone(&field), 3, Arc::new(values), None)
1512                .unwrap();
1513        let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1514
1515        assert_eq!(vortex_array.len(), 4);
1516
1517        // Verify metadata - should be FixedSizeListArray with correct list size
1518        let fsl_vortex_array = vortex_array.as_::<FixedSizeList>();
1519        assert_eq!(fsl_vortex_array.list_size(), 3);
1520        assert_eq!(fsl_vortex_array.elements().len(), 12); // 4 lists * 3 elements
1521
1522        // Test nullable fixed-size list
1523        let values_nullable = Int32Array::from(vec![
1524            Some(1),
1525            Some(2),
1526            Some(3), // First list
1527            Some(4),
1528            None,
1529            Some(6), // Second list (will be null)
1530            Some(7),
1531            Some(8),
1532            Some(9), // Third list
1533        ]);
1534
1535        // Create nulls buffer - second list is null
1536        let null_buffer =
1537            arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![true, false, true]));
1538
1539        let arrow_array_nullable = ArrowFixedSizeListArray::try_new(
1540            field,
1541            3,
1542            Arc::new(values_nullable),
1543            Some(null_buffer),
1544        )
1545        .unwrap();
1546        let vortex_array_nullable = ArrayRef::from_arrow(&arrow_array_nullable, true).unwrap();
1547
1548        assert_eq!(vortex_array_nullable.len(), 3);
1549
1550        // Verify metadata for nullable array
1551        let fsl_vortex_array_nullable = vortex_array_nullable.as_::<FixedSizeList>();
1552        assert_eq!(fsl_vortex_array_nullable.list_size(), 3);
1553        assert_eq!(fsl_vortex_array_nullable.elements().len(), 9); // 3 lists * 3 elements
1554    }
1555
1556    #[test]
1557    fn test_list_view_array_conversion() {
1558        // Create values array for the lists
1559        let values = Int32Array::from(vec![
1560            Some(1),
1561            Some(2),
1562            Some(3), // First list [1, 2, 3]
1563            Some(4),
1564            Some(5), // Second list [4, 5]
1565            Some(6), // Third list [6]
1566            Some(7),
1567            Some(8),
1568            Some(9),
1569            Some(10), // Fourth list [7, 8, 9, 10]
1570        ]);
1571
1572        // Create offsets and sizes for ListView
1573        let offsets = ScalarBuffer::from(vec![0i32, 3, 5, 6]);
1574        let sizes = ScalarBuffer::from(vec![3i32, 2, 1, 4]);
1575
1576        let field = Arc::new(Field::new("item", DataType::Int32, true));
1577        let arrow_array = GenericListViewArray::try_new(
1578            Arc::clone(&field),
1579            offsets.clone(),
1580            sizes.clone(),
1581            Arc::new(values.clone()),
1582            None,
1583        )
1584        .unwrap();
1585
1586        let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1587        assert_eq!(vortex_array.len(), 4);
1588
1589        // Verify metadata - should be ListViewArray with correct offsets and sizes
1590        let list_view_vortex_array = vortex_array.as_::<ListView>();
1591        let offsets_array = list_view_vortex_array.offsets().as_::<Primitive>();
1592        let sizes_array = list_view_vortex_array.sizes().as_::<Primitive>();
1593
1594        assert_eq!(offsets_array.len(), 4);
1595        assert_eq!(offsets_array.ptype(), PType::I32);
1596        assert_eq!(sizes_array.len(), 4);
1597        assert_eq!(sizes_array.ptype(), PType::I32);
1598
1599        // Test nullable ListView
1600        let null_buffer =
1601            arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![true, false, true, true]));
1602
1603        let arrow_array_nullable = GenericListViewArray::try_new(
1604            Arc::clone(&field),
1605            offsets,
1606            sizes,
1607            Arc::new(values.clone()),
1608            Some(null_buffer),
1609        )
1610        .unwrap();
1611
1612        let vortex_array_nullable = ArrayRef::from_arrow(&arrow_array_nullable, true).unwrap();
1613        assert_eq!(vortex_array_nullable.len(), 4);
1614
1615        // Test LargeListView (i64 offsets and sizes)
1616        let large_offsets = ScalarBuffer::from(vec![0i64, 3, 5, 6]);
1617        let large_sizes = ScalarBuffer::from(vec![3i64, 2, 1, 4]);
1618
1619        let large_arrow_array = GenericListViewArray::try_new(
1620            field,
1621            large_offsets,
1622            large_sizes,
1623            Arc::new(values),
1624            None,
1625        )
1626        .unwrap();
1627
1628        let large_vortex_array = ArrayRef::from_arrow(&large_arrow_array, false).unwrap();
1629        assert_eq!(large_vortex_array.len(), 4);
1630
1631        // Verify metadata for large ListView
1632        let large_list_view_vortex_array = large_vortex_array.as_::<ListView>();
1633        let large_offsets_array = large_list_view_vortex_array.offsets().as_::<Primitive>();
1634        let large_sizes_array = large_list_view_vortex_array.sizes().as_::<Primitive>();
1635
1636        assert_eq!(large_offsets_array.len(), 4);
1637        assert_eq!(large_offsets_array.ptype(), PType::I64); // Large ListView uses I64 offsets
1638        assert_eq!(large_sizes_array.len(), 4);
1639        assert_eq!(large_sizes_array.ptype(), PType::I64); // Large ListView uses I64 sizes
1640    }
1641
1642    // Test null array conversions
1643    #[test]
1644    fn test_null_array_conversion() {
1645        let arrow_array = NullArray::new(5);
1646        let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1647        assert_eq!(vortex_array.len(), 5);
1648    }
1649
1650    // Test buffer conversions
1651    #[test]
1652    fn test_arrow_buffer_conversion() {
1653        let data = vec![1u8, 2, 3, 4, 5];
1654        let arrow_buffer = ArrowBuffer::from_vec(data);
1655        let vortex_array = arrow_buffer.into_array();
1656        assert_eq!(vortex_array.len(), 5);
1657    }
1658
1659    #[test]
1660    fn test_boolean_buffer_conversion() {
1661        let data = vec![true, false, true, false, true];
1662        let boolean_buffer = BooleanBuffer::from(data);
1663        let vortex_array = boolean_buffer.into_array();
1664        assert_eq!(vortex_array.len(), 5);
1665    }
1666
1667    #[test]
1668    fn test_scalar_buffer_conversion() {
1669        let data = vec![1i32, 2, 3, 4, 5];
1670        let scalar_buffer = ScalarBuffer::from(data);
1671        let vortex_array = scalar_buffer.into_array();
1672        assert_eq!(vortex_array.len(), 5);
1673    }
1674
1675    #[test]
1676    fn test_offset_buffer_conversion() {
1677        let data = vec![0i32, 2, 5, 8, 10];
1678        let offset_buffer = OffsetBuffer::new(ScalarBuffer::from(data));
1679        let vortex_array = offset_buffer.into_array();
1680        assert_eq!(vortex_array.len(), 5);
1681    }
1682
1683    // Test RecordBatch conversions
1684    #[test]
1685    fn test_record_batch_conversion() {
1686        let schema = Arc::new(Schema::new(vec![
1687            Field::new("field1", DataType::Int32, false),
1688            Field::new("field2", DataType::Utf8, false),
1689        ]));
1690
1691        let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1692        let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1693
1694        let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1695
1696        let vortex_array = ArrayRef::from_arrow(record_batch, false).unwrap();
1697        assert_eq!(vortex_array.len(), 4);
1698
1699        // Test with reference
1700        let schema = Arc::new(Schema::new(vec![
1701            Field::new("field1", DataType::Int32, false),
1702            Field::new("field2", DataType::Utf8, false),
1703        ]));
1704
1705        let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1706        let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1707
1708        let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1709
1710        let vortex_array = ArrayRef::from_arrow(&record_batch, false).unwrap();
1711        assert_eq!(vortex_array.len(), 4);
1712    }
1713
1714    // Test dynamic dispatch conversion
1715    #[test]
1716    fn test_dyn_array_conversion() {
1717        let int_array = Int32Array::from(vec![1, 2, 3, 4]);
1718        let dyn_array: &dyn ArrowArray = &int_array;
1719        let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1720        assert_eq!(vortex_array.len(), 4);
1721
1722        let string_array = StringArray::from(vec!["a", "b", "c"]);
1723        let dyn_array: &dyn ArrowArray = &string_array;
1724        let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1725        assert_eq!(vortex_array.len(), 3);
1726
1727        let bool_array = BooleanArray::from(vec![true, false, true]);
1728        let dyn_array: &dyn ArrowArray = &bool_array;
1729        let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1730        assert_eq!(vortex_array.len(), 3);
1731    }
1732
1733    // Existing tests
1734    #[test]
1735    pub fn nullable_may_contain_non_nullable() {
1736        let null_struct_array_with_non_nullable_field = new_null_array(
1737            &DataType::Struct(Fields::from(vec![Field::new(
1738                "non_nullable_inner",
1739                DataType::Int32,
1740                false,
1741            )])),
1742            1,
1743        );
1744        ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).unwrap();
1745    }
1746
1747    #[test]
1748    pub fn nullable_may_contain_deeply_nested_non_nullable() {
1749        let null_struct_array_with_non_nullable_field = new_null_array(
1750            &DataType::Struct(Fields::from(vec![Field::new(
1751                "non_nullable_inner",
1752                DataType::Struct(Fields::from(vec![Field::new(
1753                    "non_nullable_deeper_inner",
1754                    DataType::Int32,
1755                    false,
1756                )])),
1757                false,
1758            )])),
1759            1,
1760        );
1761        ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).unwrap();
1762    }
1763
1764    #[test]
1765    #[should_panic]
1766    pub fn cannot_handle_nullable_struct_containing_non_nullable_dictionary() {
1767        let null_struct_array_with_non_nullable_field = new_null_array(
1768            &DataType::Struct(Fields::from(vec![Field::new(
1769                "non_nullable_deeper_inner",
1770                DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1771                false,
1772            )])),
1773            1,
1774        );
1775
1776        ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).unwrap();
1777    }
1778}