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