1use super::{ArrayData, ArrayDataBuilder, ByteView, data::new_buffers};
24use crate::bit_mask::set_bits;
25use arrow_buffer::buffer::{BooleanBuffer, NullBuffer};
26use arrow_buffer::{ArrowNativeType, Buffer, IntervalMonthDayNano, MutableBuffer, bit_util, i256};
27use arrow_schema::{ArrowError, DataType, IntervalUnit, UnionMode};
28use half::f16;
29use num_integer::Integer;
30use std::mem;
31
32mod boolean;
33mod fixed_binary;
34mod fixed_size_list;
35mod list;
36mod list_view;
37mod null;
38mod primitive;
39mod run;
40mod structure;
41mod union;
42mod utils;
43mod variable_size;
44
45type ExtendNullBits<'a> = Box<dyn Fn(&mut _MutableArrayData, usize, usize) + 'a>;
46type Extend<'a> =
49 Box<dyn Fn(&mut _MutableArrayData, usize, usize, usize) -> Result<(), ArrowError> + 'a>;
50
51type ExtendNulls = Box<dyn Fn(&mut _MutableArrayData, usize) -> Result<(), ArrowError>>;
52
53#[derive(Debug)]
56struct _MutableArrayData<'a> {
57 pub data_type: DataType,
58 pub null_count: usize,
59
60 pub len: usize,
61 pub null_buffer: Option<MutableBuffer>,
62
63 pub buffer1: MutableBuffer,
66 pub buffer2: MutableBuffer,
67 pub child_data: Vec<MutableArrayData<'a>>,
68}
69
70impl _MutableArrayData<'_> {
71 fn null_buffer(&mut self) -> &mut MutableBuffer {
72 self.null_buffer
73 .as_mut()
74 .expect("MutableArrayData not nullable")
75 }
76}
77
78fn build_extend_null_bits(array: &ArrayData, use_nulls: bool) -> ExtendNullBits<'_> {
79 if let Some(nulls) = array.nulls() {
80 let bytes = nulls.validity();
81 Box::new(move |mutable, start, len| {
82 let mutable_len = mutable.len;
83 let out = mutable.null_buffer();
84 utils::resize_for_bits(out, mutable_len + len);
85 mutable.null_count += set_bits(
86 out.as_slice_mut(),
87 bytes,
88 mutable_len,
89 nulls.offset() + start,
90 len,
91 );
92 })
93 } else if use_nulls {
94 Box::new(|mutable, _, len| {
95 let mutable_len = mutable.len;
96 let out = mutable.null_buffer();
97 utils::resize_for_bits(out, mutable_len + len);
98 let write_data = out.as_slice_mut();
99 (0..len).for_each(|i| {
100 bit_util::set_bit(write_data, mutable_len + i);
101 });
102 })
103 } else {
104 Box::new(|_, _, _| {})
105 }
106}
107
108pub struct MutableArrayData<'a> {
137 arrays: Vec<&'a ArrayData>,
142
143 data: _MutableArrayData<'a>,
150
151 dictionary: Option<ArrayData>,
156
157 variadic_data_buffers: Vec<Buffer>,
163
164 extend_values: Vec<Extend<'a>>,
169
170 extend_null_bits: Vec<ExtendNullBits<'a>>,
175
176 extend_nulls: ExtendNulls,
180}
181
182impl std::fmt::Debug for MutableArrayData<'_> {
183 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
184 f.debug_struct("MutableArrayData")
186 .field("data", &self.data)
187 .finish()
188 }
189}
190
191fn build_extend_dictionary(array: &ArrayData, offset: usize, max: usize) -> Option<Extend<'_>> {
195 macro_rules! validate_and_build {
196 ($dt: ty) => {{
197 let _: $dt = max.saturating_sub(1).try_into().ok()?;
201 let offset: $dt = offset.try_into().ok()?;
202 Some(primitive::build_extend_with_offset(array, offset))
203 }};
204 }
205 match array.data_type() {
206 DataType::Dictionary(child_data_type, _) => match child_data_type.as_ref() {
207 DataType::UInt8 => validate_and_build!(u8),
208 DataType::UInt16 => validate_and_build!(u16),
209 DataType::UInt32 => validate_and_build!(u32),
210 DataType::UInt64 => validate_and_build!(u64),
211 DataType::Int8 => validate_and_build!(i8),
212 DataType::Int16 => validate_and_build!(i16),
213 DataType::Int32 => validate_and_build!(i32),
214 DataType::Int64 => validate_and_build!(i64),
215 _ => unreachable!(),
216 },
217 _ => None,
218 }
219}
220
221fn build_extend_view(array: &ArrayData, buffer_offset: u32) -> Extend<'_> {
223 let views = array.buffer::<u128>(0);
224 Box::new(
225 move |mutable: &mut _MutableArrayData, _, start: usize, len: usize| {
226 mutable
227 .buffer1
228 .extend(views[start..start + len].iter().map(|v| {
229 let len = *v as u32;
230 if len <= 12 {
231 return *v; }
233 let mut view = ByteView::from(*v);
234 view.buffer_index += buffer_offset;
235 view.into()
236 }));
237 Ok(())
238 },
239 )
240}
241
242fn build_extend(array: &ArrayData) -> Extend<'_> {
243 match array.data_type() {
244 DataType::Null => null::build_extend(array),
245 DataType::Boolean => boolean::build_extend(array),
246 DataType::UInt8 => primitive::build_extend::<u8>(array),
247 DataType::UInt16 => primitive::build_extend::<u16>(array),
248 DataType::UInt32 => primitive::build_extend::<u32>(array),
249 DataType::UInt64 => primitive::build_extend::<u64>(array),
250 DataType::Int8 => primitive::build_extend::<i8>(array),
251 DataType::Int16 => primitive::build_extend::<i16>(array),
252 DataType::Int32 => primitive::build_extend::<i32>(array),
253 DataType::Int64 => primitive::build_extend::<i64>(array),
254 DataType::Float32 => primitive::build_extend::<f32>(array),
255 DataType::Float64 => primitive::build_extend::<f64>(array),
256 DataType::Date32 | DataType::Time32(_) | DataType::Interval(IntervalUnit::YearMonth) => {
257 primitive::build_extend::<i32>(array)
258 }
259 DataType::Date64
260 | DataType::Time64(_)
261 | DataType::Timestamp(_, _)
262 | DataType::Duration(_)
263 | DataType::Interval(IntervalUnit::DayTime) => primitive::build_extend::<i64>(array),
264 DataType::Interval(IntervalUnit::MonthDayNano) => {
265 primitive::build_extend::<IntervalMonthDayNano>(array)
266 }
267 DataType::Decimal32(_, _) => primitive::build_extend::<i32>(array),
268 DataType::Decimal64(_, _) => primitive::build_extend::<i64>(array),
269 DataType::Decimal128(_, _) => primitive::build_extend::<i128>(array),
270 DataType::Decimal256(_, _) => primitive::build_extend::<i256>(array),
271 DataType::Utf8 | DataType::Binary => variable_size::build_extend::<i32>(array),
272 DataType::LargeUtf8 | DataType::LargeBinary => variable_size::build_extend::<i64>(array),
273 DataType::BinaryView | DataType::Utf8View => unreachable!("should use build_extend_view"),
274 DataType::Map(_, _) | DataType::List(_) => list::build_extend::<i32>(array),
275 DataType::LargeList(_) => list::build_extend::<i64>(array),
276 DataType::ListView(_) => list_view::build_extend::<i32>(array),
277 DataType::LargeListView(_) => list_view::build_extend::<i64>(array),
278 DataType::Dictionary(_, _) => unreachable!("should use build_extend_dictionary"),
279 DataType::Struct(_) => structure::build_extend(array),
280 DataType::FixedSizeBinary(_) => fixed_binary::build_extend(array),
281 DataType::Float16 => primitive::build_extend::<f16>(array),
282 DataType::FixedSizeList(_, _) => fixed_size_list::build_extend(array),
283 DataType::Union(_, mode) => match mode {
284 UnionMode::Sparse => union::build_extend_sparse(array),
285 UnionMode::Dense => union::build_extend_dense(array),
286 },
287 DataType::RunEndEncoded(_, _) => run::build_extend(array),
288 }
289}
290
291fn build_extend_nulls(data_type: &DataType) -> ExtendNulls {
292 Box::new(match data_type {
293 DataType::Null => null::extend_nulls,
294 DataType::Boolean => boolean::extend_nulls,
295 DataType::UInt8 => primitive::extend_nulls::<u8>,
296 DataType::UInt16 => primitive::extend_nulls::<u16>,
297 DataType::UInt32 => primitive::extend_nulls::<u32>,
298 DataType::UInt64 => primitive::extend_nulls::<u64>,
299 DataType::Int8 => primitive::extend_nulls::<i8>,
300 DataType::Int16 => primitive::extend_nulls::<i16>,
301 DataType::Int32 => primitive::extend_nulls::<i32>,
302 DataType::Int64 => primitive::extend_nulls::<i64>,
303 DataType::Float32 => primitive::extend_nulls::<f32>,
304 DataType::Float64 => primitive::extend_nulls::<f64>,
305 DataType::Date32 | DataType::Time32(_) | DataType::Interval(IntervalUnit::YearMonth) => {
306 primitive::extend_nulls::<i32>
307 }
308 DataType::Date64
309 | DataType::Time64(_)
310 | DataType::Timestamp(_, _)
311 | DataType::Duration(_)
312 | DataType::Interval(IntervalUnit::DayTime) => primitive::extend_nulls::<i64>,
313 DataType::Interval(IntervalUnit::MonthDayNano) => {
314 primitive::extend_nulls::<IntervalMonthDayNano>
315 }
316 DataType::Decimal32(_, _) => primitive::extend_nulls::<i32>,
317 DataType::Decimal64(_, _) => primitive::extend_nulls::<i64>,
318 DataType::Decimal128(_, _) => primitive::extend_nulls::<i128>,
319 DataType::Decimal256(_, _) => primitive::extend_nulls::<i256>,
320 DataType::Utf8 | DataType::Binary => variable_size::extend_nulls::<i32>,
321 DataType::LargeUtf8 | DataType::LargeBinary => variable_size::extend_nulls::<i64>,
322 DataType::BinaryView | DataType::Utf8View => primitive::extend_nulls::<u128>,
323 DataType::Map(_, _) | DataType::List(_) => list::extend_nulls::<i32>,
324 DataType::LargeList(_) => list::extend_nulls::<i64>,
325 DataType::ListView(_) => list_view::extend_nulls::<i32>,
326 DataType::LargeListView(_) => list_view::extend_nulls::<i64>,
327 DataType::Dictionary(child_data_type, _) => match child_data_type.as_ref() {
328 DataType::UInt8 => primitive::extend_nulls::<u8>,
329 DataType::UInt16 => primitive::extend_nulls::<u16>,
330 DataType::UInt32 => primitive::extend_nulls::<u32>,
331 DataType::UInt64 => primitive::extend_nulls::<u64>,
332 DataType::Int8 => primitive::extend_nulls::<i8>,
333 DataType::Int16 => primitive::extend_nulls::<i16>,
334 DataType::Int32 => primitive::extend_nulls::<i32>,
335 DataType::Int64 => primitive::extend_nulls::<i64>,
336 _ => unreachable!(),
337 },
338 DataType::Struct(_) => structure::extend_nulls,
339 DataType::FixedSizeBinary(_) => fixed_binary::extend_nulls,
340 DataType::Float16 => primitive::extend_nulls::<f16>,
341 DataType::FixedSizeList(_, _) => fixed_size_list::extend_nulls,
342 DataType::Union(_, mode) => match mode {
343 UnionMode::Sparse => union::extend_nulls_sparse,
344 UnionMode::Dense => union::extend_nulls_dense,
345 },
346 DataType::RunEndEncoded(_, _) => run::extend_nulls,
347 })
348}
349
350fn preallocate_offset_and_binary_buffer<Offset: ArrowNativeType + Integer>(
351 capacity: usize,
352 binary_size: usize,
353) -> [MutableBuffer; 2] {
354 let mut buffer = MutableBuffer::new((1 + capacity) * mem::size_of::<Offset>());
356 buffer.push(Offset::zero());
358
359 [
360 buffer,
361 MutableBuffer::new(binary_size * mem::size_of::<u8>()),
362 ]
363}
364
365#[derive(Debug, Clone)]
367pub enum Capacities {
368 Binary(usize, Option<usize>),
374 List(usize, Option<Box<Capacities>>),
383 Struct(usize, Option<Vec<Capacities>>),
389 Dictionary(usize, Option<Box<Capacities>>),
395 Array(usize),
397}
398
399impl<'a> MutableArrayData<'a> {
400 pub fn new(arrays: Vec<&'a ArrayData>, use_nulls: bool, capacity: usize) -> Self {
412 Self::with_capacities(arrays, use_nulls, Capacities::Array(capacity))
413 }
414
415 pub fn try_new(
422 arrays: Vec<&'a ArrayData>,
423 use_nulls: bool,
424 capacity: usize,
425 ) -> Result<Self, ArrowError> {
426 Self::try_with_capacities(arrays, use_nulls, Capacities::Array(capacity))
427 }
428
429 pub fn with_capacities(
442 arrays: Vec<&'a ArrayData>,
443 use_nulls: bool,
444 capacities: Capacities,
445 ) -> Self {
446 Self::try_with_capacities(arrays, use_nulls, capacities)
447 .expect("MutableArrayData::new is infallible")
448 }
449
450 pub fn try_with_capacities(
457 arrays: Vec<&'a ArrayData>,
458 use_nulls: bool,
459 capacities: Capacities,
460 ) -> Result<Self, ArrowError> {
461 let data_type = arrays[0].data_type();
462
463 for a in arrays.iter().skip(1) {
464 assert_eq!(
465 data_type,
466 a.data_type(),
467 "Arrays with inconsistent types passed to MutableArrayData"
468 )
469 }
470
471 let use_nulls = use_nulls | arrays.iter().any(|array| array.null_count() > 0);
474
475 let mut array_capacity;
476
477 let [buffer1, buffer2] = match (data_type, &capacities) {
478 (
479 DataType::LargeUtf8 | DataType::LargeBinary,
480 Capacities::Binary(capacity, Some(value_cap)),
481 ) => {
482 array_capacity = *capacity;
483 preallocate_offset_and_binary_buffer::<i64>(*capacity, *value_cap)
484 }
485 (DataType::Utf8 | DataType::Binary, Capacities::Binary(capacity, Some(value_cap))) => {
486 array_capacity = *capacity;
487 preallocate_offset_and_binary_buffer::<i32>(*capacity, *value_cap)
488 }
489 (_, Capacities::Array(capacity)) => {
490 array_capacity = *capacity;
491 new_buffers(data_type, *capacity)
492 }
493 (
494 DataType::List(_)
495 | DataType::LargeList(_)
496 | DataType::ListView(_)
497 | DataType::LargeListView(_)
498 | DataType::FixedSizeList(_, _)
499 | DataType::Map(_, _),
500 Capacities::List(capacity, _),
501 ) => {
502 array_capacity = *capacity;
503 new_buffers(data_type, *capacity)
504 }
505 (DataType::Struct(_), Capacities::Struct(capacity, _)) => {
506 array_capacity = *capacity;
507 new_buffers(data_type, *capacity)
508 }
509 _ => panic!("Capacities: {capacities:?} not yet supported"),
510 };
511
512 let child_data = match &data_type {
513 DataType::Decimal32(_, _)
514 | DataType::Decimal64(_, _)
515 | DataType::Decimal128(_, _)
516 | DataType::Decimal256(_, _)
517 | DataType::Null
518 | DataType::Boolean
519 | DataType::UInt8
520 | DataType::UInt16
521 | DataType::UInt32
522 | DataType::UInt64
523 | DataType::Int8
524 | DataType::Int16
525 | DataType::Int32
526 | DataType::Int64
527 | DataType::Float16
528 | DataType::Float32
529 | DataType::Float64
530 | DataType::Date32
531 | DataType::Date64
532 | DataType::Time32(_)
533 | DataType::Time64(_)
534 | DataType::Duration(_)
535 | DataType::Timestamp(_, _)
536 | DataType::Utf8
537 | DataType::Binary
538 | DataType::LargeUtf8
539 | DataType::LargeBinary
540 | DataType::BinaryView
541 | DataType::Utf8View
542 | DataType::Interval(_)
543 | DataType::FixedSizeBinary(_) => vec![],
544 DataType::Map(_, _)
545 | DataType::List(_)
546 | DataType::LargeList(_)
547 | DataType::ListView(_)
548 | DataType::LargeListView(_) => {
549 let children = arrays
550 .iter()
551 .map(|array| &array.child_data()[0])
552 .collect::<Vec<_>>();
553
554 let capacities =
555 if let Capacities::List(capacity, ref child_capacities) = capacities {
556 child_capacities
557 .clone()
558 .map(|c| *c)
559 .unwrap_or(Capacities::Array(capacity))
560 } else {
561 Capacities::Array(array_capacity)
562 };
563
564 vec![MutableArrayData::try_with_capacities(
565 children, use_nulls, capacities,
566 )?]
567 }
568 DataType::Dictionary(_, _) => vec![],
570 DataType::Struct(fields) => match capacities {
571 Capacities::Struct(capacity, Some(ref child_capacities)) => {
572 array_capacity = capacity;
573 (0..fields.len())
574 .zip(child_capacities)
575 .map(|(i, child_cap)| {
576 let child_arrays = arrays
577 .iter()
578 .map(|array| &array.child_data()[i])
579 .collect::<Vec<_>>();
580 MutableArrayData::try_with_capacities(
581 child_arrays,
582 use_nulls,
583 child_cap.clone(),
584 )
585 })
586 .collect::<Result<Vec<_>, _>>()?
587 }
588 Capacities::Struct(capacity, None) => {
589 array_capacity = capacity;
590 (0..fields.len())
591 .map(|i| {
592 let child_arrays = arrays
593 .iter()
594 .map(|array| &array.child_data()[i])
595 .collect::<Vec<_>>();
596 MutableArrayData::try_new(child_arrays, use_nulls, capacity)
597 })
598 .collect::<Result<Vec<_>, _>>()?
599 }
600 _ => (0..fields.len())
601 .map(|i| {
602 let child_arrays = arrays
603 .iter()
604 .map(|array| &array.child_data()[i])
605 .collect::<Vec<_>>();
606 MutableArrayData::try_new(child_arrays, use_nulls, array_capacity)
607 })
608 .collect::<Result<Vec<_>, _>>()?,
609 },
610 DataType::RunEndEncoded(_, _) => {
611 let run_ends_child = arrays
612 .iter()
613 .map(|array| &array.child_data()[0])
614 .collect::<Vec<_>>();
615 let value_child = arrays
616 .iter()
617 .map(|array| &array.child_data()[1])
618 .collect::<Vec<_>>();
619 vec![
620 MutableArrayData::try_new(run_ends_child, false, array_capacity)?,
621 MutableArrayData::try_new(value_child, use_nulls, array_capacity)?,
622 ]
623 }
624 DataType::FixedSizeList(_, size) => {
625 let children = arrays
626 .iter()
627 .map(|array| &array.child_data()[0])
628 .collect::<Vec<_>>();
629 let capacities =
630 if let Capacities::List(capacity, ref child_capacities) = capacities {
631 child_capacities
632 .clone()
633 .map(|c| *c)
634 .unwrap_or(Capacities::Array(capacity * *size as usize))
635 } else {
636 Capacities::Array(array_capacity * *size as usize)
637 };
638 vec![MutableArrayData::try_with_capacities(
639 children, use_nulls, capacities,
640 )?]
641 }
642 DataType::Union(fields, _) => (0..fields.len())
643 .map(|i| {
644 let child_arrays = arrays
645 .iter()
646 .map(|array| &array.child_data()[i])
647 .collect::<Vec<_>>();
648 MutableArrayData::try_new(child_arrays, use_nulls, array_capacity)
649 })
650 .collect::<Result<Vec<_>, _>>()?,
651 };
652
653 let (dictionary, dict_concat) = match &data_type {
655 DataType::Dictionary(_, _) => {
656 let dict_concat = !arrays
658 .windows(2)
659 .all(|a| a[0].child_data()[0].ptr_eq(&a[1].child_data()[0]));
660
661 match dict_concat {
662 false => (Some(arrays[0].child_data()[0].clone()), false),
663 true => {
664 if let Capacities::Dictionary(_, _) = capacities {
665 panic!("dictionary capacity not yet supported")
666 }
667 let dictionaries: Vec<_> =
668 arrays.iter().map(|array| &array.child_data()[0]).collect();
669 let lengths: Vec<_> = dictionaries
670 .iter()
671 .map(|dictionary| dictionary.len())
672 .collect();
673 let capacity = lengths.iter().sum();
674
675 let mut mutable = MutableArrayData::new(dictionaries, false, capacity);
676
677 for (i, len) in lengths.iter().enumerate() {
678 mutable.try_extend(i, 0, *len).expect(
679 "extend failed while building dictionary; \
680 this is a bug in MutableArrayData",
681 )
682 }
683
684 (Some(mutable.freeze()), true)
685 }
686 }
687 }
688 _ => (None, false),
689 };
690
691 let variadic_data_buffers = match &data_type {
692 DataType::BinaryView | DataType::Utf8View => arrays
693 .iter()
694 .flat_map(|x| x.buffers().iter().skip(1))
695 .map(Buffer::clone)
696 .collect(),
697 _ => vec![],
698 };
699
700 let extend_nulls = build_extend_nulls(data_type);
701
702 let extend_null_bits = arrays
703 .iter()
704 .map(|array| build_extend_null_bits(array, use_nulls))
705 .collect();
706
707 let null_buffer = use_nulls.then(|| {
708 let null_bytes = bit_util::ceil(array_capacity, 8);
709 MutableBuffer::from_len_zeroed(null_bytes)
710 });
711
712 let extend_values = match &data_type {
713 DataType::Dictionary(_, _) => {
714 let mut next_offset = 0;
715 let extend_values: Result<Vec<_>, _> = arrays
716 .iter()
717 .map(|array| {
718 let offset = next_offset;
719 let dict_len = array.child_data()[0].len();
720
721 if dict_concat {
722 next_offset += dict_len;
723 }
724
725 build_extend_dictionary(array, offset, offset + dict_len)
726 .ok_or(ArrowError::DictionaryKeyOverflowError)
727 })
728 .collect();
729
730 extend_values?
731 }
732 DataType::BinaryView | DataType::Utf8View => {
733 let mut next_offset = 0u32;
734 arrays
735 .iter()
736 .map(|arr| {
737 let num_data_buffers = (arr.buffers().len() - 1) as u32;
738 let offset = next_offset;
739 next_offset = next_offset
740 .checked_add(num_data_buffers)
741 .expect("view buffer index overflow");
742 build_extend_view(arr, offset)
743 })
744 .collect()
745 }
746 _ => arrays.iter().map(|array| build_extend(array)).collect(),
747 };
748
749 let data = _MutableArrayData {
750 data_type: data_type.clone(),
751 len: 0,
752 null_count: 0,
753 null_buffer,
754 buffer1,
755 buffer2,
756 child_data,
757 };
758 Ok(Self {
759 arrays,
760 data,
761 dictionary,
762 variadic_data_buffers,
763 extend_values,
764 extend_null_bits,
765 extend_nulls,
766 })
767 }
768
769 pub fn try_extend(&mut self, index: usize, start: usize, end: usize) -> Result<(), ArrowError> {
783 let Some(array_len) = self.arrays.get(index).map(|array| array.len()) else {
784 return Err(ArrowError::InvalidArgumentError(format!(
785 "Source array index {index} is out of bounds: there are {} source arrays",
786 self.arrays.len()
787 )));
788 };
789 if end < start || array_len < end {
790 return Err(ArrowError::InvalidArgumentError(format!(
791 "Invalid range {start}..{end} for source array {index} of length {array_len}"
792 )));
793 }
794
795 let len = end - start;
796 (self.extend_null_bits[index])(&mut self.data, start, len);
797 let buf1_len = self.data.buffer1.len();
800 let buf2_len = self.data.buffer2.len();
801 if let Err(e) = (self.extend_values[index])(&mut self.data, index, start, len) {
802 self.data.buffer1.truncate(buf1_len);
805 self.data.buffer2.truncate(buf2_len);
806 return Err(e);
807 }
808 self.data.len += len;
809 Ok(())
810 }
811
812 #[deprecated(
820 since = "59.0.0",
821 note = "Use `try_extend` which returns an error on overflow instead of panicking"
822 )]
823 pub fn extend(&mut self, index: usize, start: usize, end: usize) {
824 self.try_extend(index, start, end).expect("extend failed")
825 }
826
827 pub fn try_extend_nulls(&mut self, len: usize) -> Result<(), ArrowError> {
838 if self.data.null_buffer.is_none() {
839 return Err(ArrowError::InvalidArgumentError(
840 "MutableArrayData cannot be extended with nulls: it was created with `use_nulls` \
841 set to false and no source array is nullable"
842 .to_owned(),
843 ));
844 }
845
846 self.data.len += len;
847 let bit_len = bit_util::ceil(self.data.len, 8);
848 let nulls = self.data.null_buffer();
849 nulls
850 .try_resize(bit_len, 0)
851 .map_err(|e| ArrowError::MemoryError(e.to_string()))?;
852 self.data.null_count += len;
853 (self.extend_nulls)(&mut self.data, len)?;
854 Ok(())
855 }
856
857 #[deprecated(
864 since = "59.0.0",
865 note = "Use `try_extend_nulls` which returns an error on overflow instead of panicking"
866 )]
867 pub fn extend_nulls(&mut self, len: usize) {
868 self.try_extend_nulls(len).expect("extend_nulls failed")
869 }
870
871 #[inline]
873 pub fn len(&self) -> usize {
874 self.data.len
875 }
876
877 #[inline]
879 pub fn is_empty(&self) -> bool {
880 self.data.len == 0
881 }
882
883 #[inline]
885 pub fn null_count(&self) -> usize {
886 self.data.null_count
887 }
888
889 pub fn freeze(self) -> ArrayData {
891 unsafe { self.into_builder().build_unchecked() }
892 }
893
894 pub fn into_builder(self) -> ArrayDataBuilder {
898 let data = self.data;
899
900 let buffers = match data.data_type {
901 DataType::Null
902 | DataType::Struct(_)
903 | DataType::FixedSizeList(_, _)
904 | DataType::RunEndEncoded(_, _) => {
905 vec![]
906 }
907 DataType::BinaryView | DataType::Utf8View => {
908 let mut b = self.variadic_data_buffers;
909 b.insert(0, data.buffer1.into());
910 b
911 }
912 DataType::Utf8
913 | DataType::Binary
914 | DataType::LargeUtf8
915 | DataType::LargeBinary
916 | DataType::ListView(_)
917 | DataType::LargeListView(_) => {
918 vec![data.buffer1.into(), data.buffer2.into()]
919 }
920 DataType::Union(_, mode) => {
921 match mode {
922 UnionMode::Sparse => vec![data.buffer1.into()],
924 UnionMode::Dense => vec![data.buffer1.into(), data.buffer2.into()],
925 }
926 }
927 _ => vec![data.buffer1.into()],
928 };
929
930 let child_data = match data.data_type {
931 DataType::Dictionary(_, _) => vec![self.dictionary.unwrap()],
932 _ => data.child_data.into_iter().map(|x| x.freeze()).collect(),
933 };
934
935 let nulls = match data.data_type {
936 DataType::RunEndEncoded(_, _) | DataType::Null | DataType::Union(_, _) => None,
938 _ => data
939 .null_buffer
940 .map(|nulls| {
941 let bools = BooleanBuffer::new(nulls.into(), 0, data.len);
942 unsafe { NullBuffer::new_unchecked(bools, data.null_count) }
943 })
944 .filter(|n| n.null_count() > 0),
945 };
946
947 ArrayDataBuilder::new(data.data_type)
948 .offset(0)
949 .len(data.len)
950 .nulls(nulls)
951 .buffers(buffers)
952 .child_data(child_data)
953 }
954}
955
956#[cfg(test)]
959mod test {
960 use super::*;
961 use arrow_schema::Field;
962 use std::sync::Arc;
963
964 fn int64_array_data(values: Vec<i64>) -> ArrayData {
965 let len = values.len();
966 ArrayData::try_new(
967 DataType::Int64,
968 len,
969 None,
970 0,
971 vec![arrow_buffer::Buffer::from_slice_ref(&values)],
972 vec![],
973 )
974 .unwrap()
975 }
976
977 #[test]
978 fn test_try_extend_invalid_index_and_range() {
979 let array = int64_array_data(vec![1, 2, 3]);
980 let mut mutable = MutableArrayData::new(vec![&array], false, 3);
981
982 let err = mutable.try_extend(1, 0, 1).unwrap_err();
983 assert_eq!(
984 err.to_string(),
985 "Invalid argument error: Source array index 1 is out of bounds: there are 1 source arrays"
986 );
987
988 let err = mutable.try_extend(0, 0, 4).unwrap_err();
989 assert_eq!(
990 err.to_string(),
991 "Invalid argument error: Invalid range 0..4 for source array 0 of length 3"
992 );
993
994 let err = mutable.try_extend(0, 2, 1).unwrap_err();
996 assert_eq!(
997 err.to_string(),
998 "Invalid argument error: Invalid range 2..1 for source array 0 of length 3"
999 );
1000
1001 mutable.try_extend(0, 3, 3).unwrap();
1003 mutable.try_extend(0, 0, 3).unwrap();
1004 assert_eq!(mutable.len(), 3);
1005 }
1006
1007 #[test]
1008 fn test_try_extend_nulls_without_null_buffer() {
1009 let array = int64_array_data(vec![1, 2, 3]);
1010 let mut mutable = MutableArrayData::new(vec![&array], false, 3);
1011 let err = mutable.try_extend_nulls(1).unwrap_err();
1012 assert!(
1013 err.to_string().contains("cannot be extended with nulls"),
1014 "unexpected error: {err}"
1015 );
1016
1017 let mut mutable = MutableArrayData::new(vec![&array], true, 3);
1018 mutable.try_extend_nulls(1).unwrap();
1019 assert_eq!(mutable.len(), 1);
1020 }
1021
1022 #[test]
1023 fn test_list_append_with_capacities() {
1024 let array = ArrayData::new_empty(&DataType::List(Arc::new(Field::new(
1025 "element",
1026 DataType::Int64,
1027 false,
1028 ))));
1029
1030 let mutable = MutableArrayData::with_capacities(
1031 vec![&array],
1032 false,
1033 Capacities::List(6, Some(Box::new(Capacities::Array(17)))),
1034 );
1035
1036 assert_eq!(mutable.data.buffer1.capacity(), 64);
1038 assert_eq!(mutable.data.child_data[0].data.buffer1.capacity(), 192);
1039 }
1040
1041 #[test]
1042 fn test_map_append_with_capacities() {
1043 let entries = Arc::new(Field::new(
1044 "entries",
1045 DataType::Struct(
1046 vec![
1047 Field::new("keys", DataType::Int64, false),
1048 Field::new("values", DataType::Int64, true),
1049 ]
1050 .into(),
1051 ),
1052 false,
1053 ));
1054 let array = ArrayData::new_empty(&DataType::Map(entries, false));
1055
1056 let mutable = MutableArrayData::with_capacities(
1057 vec![&array],
1058 false,
1059 Capacities::List(
1060 6,
1061 Some(Box::new(Capacities::Struct(
1062 17,
1063 Some(vec![Capacities::Array(17), Capacities::Array(17)]),
1064 ))),
1065 ),
1066 );
1067
1068 assert_eq!(mutable.data.buffer1.capacity(), 64);
1071
1072 let entries = &mutable.data.child_data[0];
1074 assert_eq!(entries.data.buffer1.capacity(), 0);
1075
1076 assert_eq!(entries.data.child_data[0].data.buffer1.capacity(), 192);
1078 assert_eq!(entries.data.child_data[1].data.buffer1.capacity(), 192);
1079 }
1080}