Skip to content

Commit 556942c

Browse files
authored
Avoid a clone when creating ListArray from ArrayData (#9194)
# 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 a92c8a9 commit 556942c

File tree

1 file changed

+14
-12
lines changed

1 file changed

+14
-12
lines changed

arrow-array/src/array/list_array.rs

Lines changed: 14 additions & 12 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 crate::array::{get_offsets, make_array, print_long_array};
18+
use crate::array::{get_offsets_from_buffer, make_array, print_long_array};
1919
use crate::builder::{GenericListBuilder, PrimitiveBuilder};
2020
use crate::{
2121
Array, ArrayAccessor, ArrayRef, ArrowPrimitiveType, FixedSizeListArray,
@@ -479,23 +479,26 @@ impl<OffsetSize: OffsetSizeTrait> From<FixedSizeListArray> for GenericListArray<
479479

480480
impl<OffsetSize: OffsetSizeTrait> GenericListArray<OffsetSize> {
481481
fn try_new_from_array_data(data: ArrayData) -> Result<Self, ArrowError> {
482-
if data.buffers().len() != 1 {
482+
let (data_type, len, nulls, offset, mut buffers, mut child_data) = data.into_parts();
483+
484+
if buffers.len() != 1 {
483485
return Err(ArrowError::InvalidArgumentError(format!(
484486
"ListArray data should contain a single buffer only (value offsets), had {}",
485-
data.buffers().len()
487+
buffers.len()
486488
)));
487489
}
490+
let buffer = buffers.pop().expect("checked above");
488491

489-
if data.child_data().len() != 1 {
492+
if child_data.len() != 1 {
490493
return Err(ArrowError::InvalidArgumentError(format!(
491494
"ListArray should contain a single child array (values array), had {}",
492-
data.child_data().len()
495+
child_data.len()
493496
)));
494497
}
495498

496-
let values = data.child_data()[0].clone();
499+
let values = child_data.pop().expect("checked above");
497500

498-
if let Some(child_data_type) = Self::get_type(data.data_type()) {
501+
if let Some(child_data_type) = Self::get_type(&data_type) {
499502
if values.data_type() != child_data_type {
500503
return Err(ArrowError::InvalidArgumentError(format!(
501504
"[Large]ListArray's child datatype {:?} does not \
@@ -506,19 +509,18 @@ impl<OffsetSize: OffsetSizeTrait> GenericListArray<OffsetSize> {
506509
}
507510
} else {
508511
return Err(ArrowError::InvalidArgumentError(format!(
509-
"[Large]ListArray's datatype must be [Large]ListArray(). It is {:?}",
510-
data.data_type()
512+
"[Large]ListArray's datatype must be [Large]ListArray(). It is {data_type:?}",
511513
)));
512514
}
513515

514516
let values = make_array(values);
515517
// SAFETY:
516518
// ArrayData is valid, and verified type above
517-
let value_offsets = unsafe { get_offsets(&data) };
519+
let value_offsets = unsafe { get_offsets_from_buffer(buffer, offset, len) };
518520

519521
Ok(Self {
520-
data_type: data.data_type().clone(),
521-
nulls: data.nulls().cloned(),
522+
data_type,
523+
nulls,
522524
values,
523525
value_offsets,
524526
})

0 commit comments

Comments
 (0)