Skip to content

Commit d4b293d

Browse files
authored
Avoid a clone when creating ListViewArray from ArrayData (#9193)
# Which issue does this PR close? - Part of #9061 - broken out of #9058 # Rationale for this change Let's make arrow-rs the fastest we can and the fewer allocations the better # What changes are included in this PR? Apply pattern from #9114 # Are these changes tested? Existing tests # Are there any user-facing changes? No
1 parent 556942c commit d4b293d

File tree

1 file changed

+22
-21
lines changed

1 file changed

+22
-21
lines changed

arrow-array/src/array/list_view_array.rs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use arrow_buffer::{NullBuffer, ScalarBuffer};
18+
use arrow_buffer::{Buffer, NullBuffer, ScalarBuffer};
1919
use arrow_data::{ArrayData, ArrayDataBuilder};
2020
use arrow_schema::{ArrowError, DataType, FieldRef};
2121
use std::any::Any;
@@ -576,23 +576,25 @@ impl<OffsetSize: OffsetSizeTrait> From<FixedSizeListArray> for GenericListViewAr
576576

577577
impl<OffsetSize: OffsetSizeTrait> GenericListViewArray<OffsetSize> {
578578
fn try_new_from_array_data(data: ArrayData) -> Result<Self, ArrowError> {
579-
if data.buffers().len() != 2 {
580-
return Err(ArrowError::InvalidArgumentError(format!(
581-
"ListViewArray data should contain two buffers (value offsets & value sizes), had {}",
582-
data.buffers().len()
583-
)));
584-
}
579+
let (data_type, len, nulls, offset, buffers, child_data) = data.into_parts();
585580

586-
if data.child_data().len() != 1 {
587-
return Err(ArrowError::InvalidArgumentError(format!(
588-
"ListViewArray should contain a single child array (values array), had {}",
589-
data.child_data().len()
590-
)));
591-
}
581+
// ArrayData is valid, and verified type above
582+
// buffer[0] is offsets, buffer[1] is sizes
583+
let num_buffers = buffers.len();
584+
let [offsets_buffer, sizes_buffer] : [Buffer; 2] = buffers.try_into().map_err(|_| {
585+
ArrowError::InvalidArgumentError(format!(
586+
"ListViewArray data should contain two buffers (value offsets & value sizes), had {num_buffers}",
587+
))
588+
})?;
592589

593-
let values = data.child_data()[0].clone();
590+
let num_child = child_data.len();
591+
let [values]: [ArrayData; 1] = child_data.try_into().map_err(|_| {
592+
ArrowError::InvalidArgumentError(format!(
593+
"ListViewArray should contain a single child array (values array), had {num_child}",
594+
))
595+
})?;
594596

595-
if let Some(child_data_type) = Self::get_type(data.data_type()) {
597+
if let Some(child_data_type) = Self::get_type(&data_type) {
596598
if values.data_type() != child_data_type {
597599
return Err(ArrowError::InvalidArgumentError(format!(
598600
"{}ListViewArray's child datatype {:?} does not \
@@ -607,18 +609,17 @@ impl<OffsetSize: OffsetSizeTrait> GenericListViewArray<OffsetSize> {
607609
"{}ListViewArray's datatype must be {}ListViewArray(). It is {:?}",
608610
OffsetSize::PREFIX,
609611
OffsetSize::PREFIX,
610-
data.data_type()
612+
data_type
611613
)));
612614
}
613615

614616
let values = make_array(values);
615-
// ArrayData is valid, and verified type above
616-
let value_offsets = ScalarBuffer::new(data.buffers()[0].clone(), data.offset(), data.len());
617-
let value_sizes = ScalarBuffer::new(data.buffers()[1].clone(), data.offset(), data.len());
617+
let value_offsets = ScalarBuffer::new(offsets_buffer, offset, len);
618+
let value_sizes = ScalarBuffer::new(sizes_buffer, offset, len);
618619

619620
Ok(Self {
620-
data_type: data.data_type().clone(),
621-
nulls: data.nulls().cloned(),
621+
data_type,
622+
nulls,
622623
values,
623624
value_offsets,
624625
value_sizes,

0 commit comments

Comments
 (0)