From 5a9d08875119479300eca374244d1b72d0333ebd Mon Sep 17 00:00:00 2001 From: Liam Bao Date: Wed, 1 Apr 2026 11:25:17 -0400 Subject: [PATCH 1/2] Support `GenericListViewArray::new_unchecked` and refactor ListView json decoder --- arrow-array/src/array/list_view_array.rs | 28 ++++++++++++++++++++++++ arrow-json/src/reader/list_array.rs | 28 ++++++++++-------------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/arrow-array/src/array/list_view_array.rs b/arrow-array/src/array/list_view_array.rs index 75ff6117eeba..9f8f0b147c08 100644 --- a/arrow-array/src/array/list_view_array.rs +++ b/arrow-array/src/array/list_view_array.rs @@ -223,6 +223,34 @@ impl GenericListViewArray { Self::try_new(field, offsets, sizes, values, nulls).unwrap() } + /// Create a new [`GenericListViewArray`] from the provided parts without validation + /// + /// See [`Self::try_new`] for the checked version of this function, and the + /// documentation of that function for the invariants that must be upheld. + /// + /// # Safety + /// + /// Safe if [`Self::new`] would not panic with the given arguments + pub unsafe fn new_unchecked( + field: FieldRef, + offsets: ScalarBuffer, + sizes: ScalarBuffer, + values: ArrayRef, + nulls: Option, + ) -> Self { + if cfg!(feature = "force_validate") { + return Self::new(field, offsets, sizes, values, nulls); + } + + Self { + data_type: Self::DATA_TYPE_CONSTRUCTOR(field), + nulls, + values, + value_offsets: offsets, + value_sizes: sizes, + } + } + /// Create a new [`GenericListViewArray`] of length `len` where all values are null pub fn new_null(field: FieldRef, len: usize) -> Self { let values = new_empty_array(field.data_type()); diff --git a/arrow-json/src/reader/list_array.rs b/arrow-json/src/reader/list_array.rs index b11124576df2..0ee1b5af1cd9 100644 --- a/arrow-json/src/reader/list_array.rs +++ b/arrow-json/src/reader/list_array.rs @@ -19,10 +19,9 @@ use std::marker::PhantomData; use std::sync::Arc; use arrow_array::builder::BooleanBufferBuilder; -use arrow_array::{ArrayRef, GenericListArray, OffsetSizeTrait, make_array}; +use arrow_array::{ArrayRef, GenericListArray, GenericListViewArray, OffsetSizeTrait}; use arrow_buffer::buffer::NullBuffer; -use arrow_buffer::{Buffer, OffsetBuffer, ScalarBuffer}; -use arrow_data::ArrayDataBuilder; +use arrow_buffer::{OffsetBuffer, ScalarBuffer}; use arrow_schema::{ArrowError, DataType, FieldRef}; use crate::reader::tape::{Tape, TapeElement}; @@ -109,22 +108,17 @@ impl ArrayDecoder for ListLikeArrayDeco sizes.push(offsets[i] - offsets[i - 1]); } offsets.pop(); - let data_type = if O::IS_LARGE { - DataType::LargeListView(self.field.clone()) - } else { - DataType::ListView(self.field.clone()) - }; // SAFETY: offsets and sizes are constructed correctly from the tape - let array_data = unsafe { - ArrayDataBuilder::new(data_type) - .len(pos.len()) - .nulls(nulls) - .child_data(vec![values.to_data()]) - .add_buffer(Buffer::from_vec(offsets)) - .add_buffer(Buffer::from_vec(sizes)) - .build_unchecked() + let array = unsafe { + GenericListViewArray::::new_unchecked( + self.field.clone(), + ScalarBuffer::from(offsets), + ScalarBuffer::from(sizes), + values, + nulls, + ) }; - Ok(make_array(array_data)) + Ok(Arc::new(array)) } else { // SAFETY: offsets are built monotonically starting from 0 let offsets = unsafe { OffsetBuffer::::new_unchecked(ScalarBuffer::from(offsets)) }; From e44308e60eb628807c05c591c5664e3c29ba40f5 Mon Sep 17 00:00:00 2001 From: Liam Bao Date: Tue, 14 Apr 2026 18:39:08 -0400 Subject: [PATCH 2/2] Improve doc --- arrow-array/src/array/list_view_array.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arrow-array/src/array/list_view_array.rs b/arrow-array/src/array/list_view_array.rs index 9f8f0b147c08..a032d8715a90 100644 --- a/arrow-array/src/array/list_view_array.rs +++ b/arrow-array/src/array/list_view_array.rs @@ -230,7 +230,8 @@ impl GenericListViewArray { /// /// # Safety /// - /// Safe if [`Self::new`] would not panic with the given arguments + /// The parts must form a valid [`ListViewArray`] or [`LargeListViewArray`] according + /// to the Arrow spec. pub unsafe fn new_unchecked( field: FieldRef, offsets: ScalarBuffer,