vortex_array/arrow/compute/to_arrow/
list.rs1use std::sync::Arc;
5
6use arrow_array::{ArrayRef as ArrowArrayRef, GenericListArray, OffsetSizeTrait};
7use arrow_schema::{DataType, Field, FieldRef};
8use vortex_dtype::{DType, IntegerPType};
9use vortex_error::{VortexResult, vortex_bail};
10
11use crate::arrays::{ListArray, ListVTable, list_view_from_list};
12use crate::arrow::IntoArrowArray;
13use crate::arrow::compute::{ToArrowKernel, ToArrowKernelAdapter};
14use crate::compute::cast;
15use crate::{IntoArray, ToCanonical, register_kernel};
16
17impl ToArrowKernel for ListVTable {
18 fn to_arrow(
19 &self,
20 array: &ListArray,
21 arrow_type: Option<&DataType>,
22 ) -> VortexResult<Option<ArrowArrayRef>> {
23 match arrow_type {
24 None => {
25 list_array_to_arrow_list::<i32>(array, None)
28 }
29 Some(DataType::List(field)) => list_array_to_arrow_list::<i32>(array, Some(field)),
30 Some(DataType::LargeList(field)) => list_array_to_arrow_list::<i64>(array, Some(field)),
31 Some(dt @ DataType::ListView(_)) | Some(dt @ DataType::LargeListView(_)) => {
32 let list_view = list_view_from_list(array.clone());
34 Ok(list_view.into_array().into_arrow(dt)?)
35 }
36 _ => vortex_bail!(
37 "Cannot convert `ListArray` to non-list Arrow type: {:?}",
38 arrow_type
39 ),
40 }
41 .map(Some)
42 }
43}
44
45register_kernel!(ToArrowKernelAdapter(ListVTable).lift());
46
47fn list_array_to_arrow_list<O: IntegerPType + OffsetSizeTrait>(
49 array: &ListArray,
50 element: Option<&FieldRef>,
51) -> VortexResult<ArrowArrayRef> {
52 let offsets_dtype = DType::Primitive(O::PTYPE, array.dtype().nullability());
54 let offsets = cast(array.offsets(), &offsets_dtype)
55 .map_err(|err| err.with_context(format!("Failed to cast offsets to {offsets_dtype}")))?
56 .to_primitive();
57
58 let arrow_offsets = offsets.buffer::<O>().into_arrow_offset_buffer();
60 let nulls = array.validity_mask().to_null_buffer();
61
62 let (elements, element_field) = {
64 if let Some(element) = element {
65 (
67 array.elements().clone().into_arrow(element.data_type())?,
68 element.clone(),
69 )
70 } else {
71 let elements = array.elements().clone().into_arrow_preferred()?;
73 let element_field = Arc::new(Field::new_list_field(
74 elements.data_type().clone(),
75 array.elements().dtype().is_nullable(),
76 ));
77 (elements, element_field)
78 }
79 };
80
81 Ok(Arc::new(GenericListArray::new(
82 element_field,
83 arrow_offsets,
84 elements,
85 nulls,
86 )))
87}