1use std::any::Any;
5use std::sync::Arc;
6
7use num_traits::AsPrimitive;
8use vortex_buffer::BufferAllocatorRef;
9use vortex_error::VortexExpect;
10use vortex_error::VortexResult;
11use vortex_error::vortex_bail;
12use vortex_error::vortex_ensure;
13use vortex_error::vortex_panic;
14
15use crate::ArrayRef;
16use crate::Canonical;
17use crate::ExecutionCtx;
18use crate::IntoArray;
19use crate::array::ArrayView;
20use crate::arrays::List;
21use crate::arrays::ListArray;
22use crate::arrays::ListView;
23use crate::arrays::ListViewArray;
24use crate::arrays::PrimitiveArray;
25use crate::arrays::list::ListArraySlotsExt;
26use crate::arrays::listview::ListViewArraySlotsExt;
27use crate::arrays::listview::ListViewRebuildMode;
28use crate::builders::ArrayBuilder;
29use crate::builders::ChildBuilder;
30use crate::builders::DEFAULT_BUILDER_CAPACITY;
31use crate::builders::PrimitiveBuilder;
32use crate::builders::ValidityBuilder;
33use crate::dtype::DType;
34use crate::dtype::IntegerPType;
35use crate::dtype::Nullability;
36use crate::dtype::Nullability::NonNullable;
37use crate::dtype::OffsetBuilderPType;
38use crate::match_each_integer_ptype;
39use crate::scalar::ListScalar;
40use crate::scalar::Scalar;
41
42pub struct ListBuilder<O: OffsetBuilderPType> {
45 dtype: DType,
47
48 elements_builder: ChildBuilder,
50
51 offsets_builder: PrimitiveBuilder<O>,
53
54 nulls: ValidityBuilder,
56}
57
58impl<O: OffsetBuilderPType> ListBuilder<O> {
59 #[deprecated(note = "use `new_in` with an explicit allocator")]
61 pub fn new(value_dtype: Arc<DType>, nullability: Nullability) -> Self {
62 Self::new_in(value_dtype, nullability, BufferAllocatorRef::static_ref())
63 }
64
65 pub fn new_in(
67 value_dtype: Arc<DType>,
68 nullability: Nullability,
69 allocator: &BufferAllocatorRef,
70 ) -> Self {
71 Self::with_capacity_in(
72 value_dtype,
73 nullability,
74 DEFAULT_BUILDER_CAPACITY * 2,
77 DEFAULT_BUILDER_CAPACITY,
78 allocator,
79 )
80 }
81
82 #[deprecated(note = "use `with_capacity_in` with an explicit allocator")]
90 pub fn with_capacity(
91 value_dtype: Arc<DType>,
92 nullability: Nullability,
93 elements_capacity: usize,
94 capacity: usize,
95 ) -> Self {
96 Self::with_capacity_in(
97 value_dtype,
98 nullability,
99 elements_capacity,
100 capacity,
101 BufferAllocatorRef::static_ref(),
102 )
103 }
104
105 pub fn with_capacity_in(
107 value_dtype: Arc<DType>,
108 nullability: Nullability,
109 elements_capacity: usize,
110 capacity: usize,
111 allocator: &BufferAllocatorRef,
112 ) -> Self {
113 let elements_builder =
114 ChildBuilder::with_capacity(value_dtype.as_ref(), elements_capacity, allocator);
115 let mut offsets_builder =
116 PrimitiveBuilder::<O>::with_capacity_in(NonNullable, capacity + 1, allocator);
117
118 offsets_builder.append_zero();
120
121 Self {
122 elements_builder,
123 offsets_builder,
124 nulls: ValidityBuilder::new(capacity, allocator),
125 dtype: DType::List(value_dtype, nullability),
126 }
127 }
128
129 pub fn append_array_as_list(
136 &mut self,
137 array: &ArrayRef,
138 ctx: &mut ExecutionCtx,
139 ) -> VortexResult<()> {
140 vortex_ensure!(
141 array.dtype() == self.element_dtype(),
142 "Array dtype {:?} does not match list element dtype {:?}",
143 array.dtype(),
144 self.element_dtype()
145 );
146
147 self.elements_builder.append_array(array, ctx)?;
148 self.nulls.append_non_null();
149 self.offsets_builder.append_value(
150 O::from_usize(self.elements_builder.len())
151 .vortex_expect("Failed to convert from usize to O"),
152 );
153
154 Ok(())
155 }
156
157 pub fn append_value(&mut self, value: ListScalar) -> VortexResult<()> {
159 match value.elements() {
160 None => {
161 if self.dtype.nullability() == NonNullable {
162 vortex_bail!("Cannot append null value to non-nullable list");
163 }
164 self.append_null();
165 }
166 Some(elements) => {
167 for scalar in elements {
168 self.elements_builder.append_scalar(&scalar)?;
171 }
172
173 self.nulls.append_non_null();
174 self.offsets_builder.append_value(
175 O::from_usize(self.elements_builder.len())
176 .vortex_expect("Failed to convert from usize to O"),
177 );
178 }
179 }
180
181 Ok(())
182 }
183
184 pub fn finish_into_list(&mut self) -> ListArray {
186 assert_eq!(
187 self.offsets_builder.len(),
188 self.nulls.len() + 1,
189 "offsets length must be one more than nulls length."
190 );
191
192 ListArray::try_new(
193 self.elements_builder.finish(),
194 self.offsets_builder.finish(),
195 self.nulls.finish_with_nullability(self.dtype.nullability()),
196 )
197 .vortex_expect("Buffer, offsets, and validity must have same length.")
198 }
199
200 pub fn element_dtype(&self) -> &DType {
203 let DType::List(element_dtype, _) = &self.dtype else {
204 vortex_panic!("`ListBuilder` has an incorrect dtype: {}", self.dtype);
205 };
206
207 element_dtype
208 }
209
210 pub fn append_list_array(
217 &mut self,
218 array: ArrayView<'_, List>,
219 ctx: &mut ExecutionCtx,
220 ) -> VortexResult<()> {
221 if array.is_empty() {
222 return Ok(());
223 }
224
225 self.nulls.append_validity(array.validity()?, array.len());
226
227 let num_lists = array.len();
228 let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
229 match_each_integer_ptype!(offsets.ptype(), |OffsetType| {
230 let offsets = offsets.as_slice::<OffsetType>();
231 let first: usize = offsets[0].as_();
232 let last: usize = offsets[num_lists].as_();
233
234 let elements_base = self.elements_builder.len();
237 if last > first {
238 self.elements_builder
239 .append_array(&array.elements().slice(first..last)?, ctx)?;
240 }
241
242 self.offsets_builder.reserve_exact(num_lists);
243 let mut offsets_range = self.offsets_builder.uninit_range(num_lists);
244 for i in 0..num_lists {
245 let end: usize = offsets[i + 1].as_();
246 offsets_range.set_value(
247 i,
248 O::from_usize(end - first + elements_base)
249 .vortex_expect("Failed to convert offset"),
250 );
251 }
252 unsafe { offsets_range.finish() };
255 });
256 Ok(())
257 }
258
259 pub fn append_listview_array(
267 &mut self,
268 array: ArrayView<'_, ListView>,
269 ctx: &mut ExecutionCtx,
270 ) -> VortexResult<()> {
271 if array.is_empty() {
272 return Ok(());
273 }
274
275 self.nulls.append_validity(array.validity()?, array.len());
276
277 let array = array
281 .into_owned()
282 .rebuild(ListViewRebuildMode::MakeZeroCopyToList, ctx)?;
283 debug_assert!(array.is_zero_copy_to_list());
284
285 let elements = array.elements();
287 let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
288 let sizes = array.sizes().clone().execute::<PrimitiveArray>(ctx)?;
289
290 match_each_integer_ptype!(offsets.ptype(), |OffsetType| {
291 match_each_integer_ptype!(sizes.ptype(), |SizeType| {
292 extend_from_listview(
293 self,
294 elements,
295 offsets.as_slice::<OffsetType>(),
296 sizes.as_slice::<SizeType>(),
297 ctx,
298 )?
299 })
300 });
301 Ok(())
302 }
303}
304
305fn extend_from_listview<O, OffsetType, SizeType>(
313 builder: &mut ListBuilder<O>,
314 new_elements: &ArrayRef,
315 new_offsets: &[OffsetType],
316 new_sizes: &[SizeType],
317 ctx: &mut ExecutionCtx,
318) -> VortexResult<()>
319where
320 O: OffsetBuilderPType,
321 OffsetType: IntegerPType,
322 SizeType: IntegerPType,
323{
324 let num_lists = new_offsets.len();
325 debug_assert_eq!(num_lists, new_sizes.len());
326
327 let first: usize = new_offsets[0].as_();
330 let last: usize = new_offsets[num_lists - 1].as_() + new_sizes[num_lists - 1].as_();
331
332 let elements_base = builder.elements_builder.len();
333 if last > first {
334 builder
335 .elements_builder
336 .append_array(&new_elements.slice(first..last)?, ctx)?;
337 }
338
339 builder.offsets_builder.reserve_exact(num_lists);
340 let mut offsets_range = builder.offsets_builder.uninit_range(num_lists);
341 for i in 0..num_lists {
342 let end: usize = new_offsets[i].as_() + new_sizes[i].as_();
343 offsets_range.set_value(
344 i,
345 O::from_usize(end - first + elements_base).vortex_expect("Failed to convert offset"),
346 );
347 }
348
349 unsafe { offsets_range.finish() };
352 Ok(())
353}
354
355impl<O: OffsetBuilderPType> ArrayBuilder for ListBuilder<O> {
356 fn as_any(&self) -> &dyn Any {
357 self
358 }
359
360 fn as_any_mut(&mut self) -> &mut dyn Any {
361 self
362 }
363
364 fn dtype(&self) -> &DType {
365 &self.dtype
366 }
367
368 fn len(&self) -> usize {
369 self.nulls.len()
370 }
371
372 fn append_zeros(&mut self, n: usize) {
373 let curr_len = self.elements_builder.len();
374 for _ in 0..n {
375 self.offsets_builder.append_value(
376 O::from_usize(curr_len).vortex_expect("Failed to convert from usize to <O>"),
377 )
378 }
379 self.nulls.append_n_non_nulls(n);
380 }
381
382 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
383 let curr_len = self.elements_builder.len();
384 for _ in 0..n {
385 self.offsets_builder.append_value(
388 O::from_usize(curr_len).vortex_expect("Failed to convert from usize to <O>"),
389 )
390 }
391 self.nulls.append_n_nulls(n);
392 }
393
394 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
395 vortex_ensure!(
396 scalar.dtype() == self.dtype(),
397 "ListBuilder expected scalar with dtype {}, got {}",
398 self.dtype(),
399 scalar.dtype()
400 );
401
402 self.append_value(scalar.as_list())
403 }
404
405 fn reserve_exact(&mut self, additional: usize) {
406 self.elements_builder.reserve_exact(additional);
407 self.offsets_builder.reserve_exact(additional);
408 self.nulls.reserve_exact(additional);
409 }
410
411 fn finish(&mut self) -> ArrayRef {
412 self.finish_into_list().into_array()
413 }
414
415 fn finish_into_canonical(&mut self, ctx: &mut ExecutionCtx) -> Canonical {
416 let listview = self
417 .finish()
418 .execute::<ListViewArray>(ctx)
419 .vortex_expect("list builder should canonicalize to listview");
420 Canonical::List(listview)
421 }
422}
423
424#[cfg(test)]
425mod tests {
426 use std::sync::Arc;
427
428 use Nullability::NonNullable;
429 use Nullability::Nullable;
430 use vortex_buffer::BufferAllocatorRef;
431 use vortex_buffer::buffer;
432 use vortex_error::VortexExpect;
433 use vortex_error::VortexResult;
434
435 use crate::IntoArray;
436 use crate::array_session;
437 use crate::arrays::ChunkedArray;
438 use crate::arrays::ListViewArray;
439 use crate::arrays::PrimitiveArray;
440 use crate::arrays::list::ListArraySlotsExt;
441 use crate::arrays::listview::ListViewArrayExt;
442 use crate::arrays::listview::ListViewArraySlotsExt;
443 use crate::assert_arrays_eq;
444 use crate::builders::ArrayBuilder;
445 use crate::builders::ListViewBuilder;
446 use crate::builders::builder_with_capacity_in;
447 use crate::builders::list::ListArray;
448 use crate::builders::list::ListBuilder;
449 use crate::dtype::DType;
450 use crate::dtype::Nullability;
451 use crate::dtype::OffsetBuilderPType;
452 use crate::dtype::PType::I32;
453 use crate::executor::VortexSessionExecute;
454 use crate::scalar::Scalar;
455 use crate::validity::Validity;
456
457 #[test]
458 fn test_empty() {
459 let mut builder = ListBuilder::<u32>::with_capacity_in(
460 Arc::new(I32.into()),
461 NonNullable,
462 0,
463 0,
464 BufferAllocatorRef::static_ref(),
465 );
466
467 let list = builder.finish();
468 assert_eq!(list.len(), 0);
469 }
470
471 #[test]
472 fn test_values() {
473 let dtype: Arc<DType> = Arc::new(I32.into());
474 let mut builder = ListBuilder::<u32>::with_capacity_in(
475 Arc::clone(&dtype),
476 NonNullable,
477 0,
478 0,
479 BufferAllocatorRef::static_ref(),
480 );
481
482 builder
483 .append_value(
484 Scalar::list(
485 Arc::clone(&dtype),
486 vec![1i32.into(), 2i32.into(), 3i32.into()],
487 NonNullable,
488 )
489 .as_list(),
490 )
491 .unwrap();
492
493 builder
494 .append_value(
495 Scalar::list(
496 dtype,
497 vec![4i32.into(), 5i32.into(), 6i32.into()],
498 NonNullable,
499 )
500 .as_list(),
501 )
502 .unwrap();
503
504 let list = builder.finish();
505 assert_eq!(list.len(), 2);
506
507 let mut ctx = array_session().create_execution_ctx();
508 let list_array = list.execute::<ListViewArray>(&mut ctx).unwrap();
509
510 assert_eq!(list_array.list_elements_at(0).unwrap().len(), 3);
511 assert_eq!(list_array.list_elements_at(1).unwrap().len(), 3);
512 }
513
514 #[test]
515 fn test_append_empty_list() {
516 let dtype: Arc<DType> = Arc::new(I32.into());
517 let mut builder = ListBuilder::<u32>::with_capacity_in(
518 Arc::clone(&dtype),
519 NonNullable,
520 0,
521 0,
522 BufferAllocatorRef::static_ref(),
523 );
524
525 assert!(
526 builder
527 .append_value(Scalar::list_empty(dtype, NonNullable).as_list())
528 .is_ok()
529 )
530 }
531
532 #[test]
533 fn test_nullable_values() {
534 let dtype: Arc<DType> = Arc::new(I32.into());
535 let mut builder = ListBuilder::<u32>::with_capacity_in(
536 Arc::clone(&dtype),
537 Nullable,
538 0,
539 0,
540 BufferAllocatorRef::static_ref(),
541 );
542
543 builder
544 .append_value(
545 Scalar::list(
546 Arc::clone(&dtype),
547 vec![1i32.into(), 2i32.into(), 3i32.into()],
548 NonNullable,
549 )
550 .as_list(),
551 )
552 .unwrap();
553
554 builder
555 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
556 .unwrap();
557
558 builder
559 .append_value(
560 Scalar::list(
561 dtype,
562 vec![4i32.into(), 5i32.into(), 6i32.into()],
563 NonNullable,
564 )
565 .as_list(),
566 )
567 .unwrap();
568
569 let list = builder.finish();
570 assert_eq!(list.len(), 3);
571
572 let mut ctx = array_session().create_execution_ctx();
573 let list_array = list.execute::<ListViewArray>(&mut ctx).unwrap();
574
575 assert_eq!(list_array.list_elements_at(0).unwrap().len(), 3);
576 assert_eq!(list_array.list_elements_at(1).unwrap().len(), 0);
577 assert_eq!(list_array.list_elements_at(2).unwrap().len(), 3);
578 }
579
580 fn test_extend_builder_gen<O: OffsetBuilderPType>() {
581 let list = ListArray::from_iter_opt_slow::<O, _, _>(
582 [Some(vec![0, 1, 2]), None, Some(vec![4, 5])],
583 Arc::new(I32.into()),
584 )
585 .unwrap()
586 .into_array();
587 assert_eq!(list.len(), 3);
588
589 let mut ctx = array_session().create_execution_ctx();
590
591 let mut builder = ListBuilder::<O>::with_capacity_in(
592 Arc::new(I32.into()),
593 Nullable,
594 18,
595 9,
596 BufferAllocatorRef::static_ref(),
597 );
598 list.append_to_builder(&mut builder, &mut ctx).unwrap();
599 list.append_to_builder(&mut builder, &mut ctx).unwrap();
600 list.slice(0..0)
601 .unwrap()
602 .append_to_builder(&mut builder, &mut ctx)
603 .unwrap();
604 list.slice(1..3)
605 .unwrap()
606 .append_to_builder(&mut builder, &mut ctx)
607 .unwrap();
608
609 let expected = ListArray::from_iter_opt_slow::<O, _, _>(
610 [
611 Some(vec![0, 1, 2]),
612 None,
613 Some(vec![4, 5]),
614 Some(vec![0, 1, 2]),
615 None,
616 Some(vec![4, 5]),
617 None,
618 Some(vec![4, 5]),
619 ],
620 Arc::new(DType::Primitive(I32, NonNullable)),
621 )
622 .unwrap()
623 .into_array()
624 .execute::<ListViewArray>(&mut ctx)
625 .unwrap();
626
627 let actual = builder.finish_into_canonical(&mut ctx).into_listview();
628
629 assert_arrays_eq!(actual.elements(), expected.elements(), &mut ctx);
630
631 assert_arrays_eq!(actual.offsets(), expected.offsets(), &mut ctx);
632
633 assert!(
634 actual
635 .validity()
636 .vortex_expect("list validity should be derivable")
637 .mask_eq(
638 &expected
639 .validity()
640 .vortex_expect("list validity should be derivable"),
641 actual.len(),
642 &mut ctx,
643 )
644 .unwrap(),
645 );
646 }
647
648 #[test]
653 fn test_append_to_builder_any_list_builder() -> VortexResult<()> {
654 let mut ctx = array_session().create_execution_ctx();
655
656 let list = ListArray::from_iter_opt_slow::<u64, _, _>(
657 [Some(vec![0, 1, 2]), None, Some(vec![4, 5])],
658 Arc::new(I32.into()),
659 )?
660 .into_array();
661 let listview = list
662 .clone()
663 .execute::<ListViewArray>(&mut ctx)?
664 .into_array();
665 let elem_dtype = || Arc::new(I32.into());
666
667 let mut listview_builder =
670 builder_with_capacity_in(list.dtype(), list.len(), BufferAllocatorRef::static_ref());
671 list.append_to_builder(listview_builder.as_mut(), &mut ctx)?;
672 assert_arrays_eq!(listview_builder.finish(), list, &mut ctx);
673
674 let mut lv_u64_u32 = ListViewBuilder::<u64, u32>::with_capacity_in(
677 elem_dtype(),
678 Nullable,
679 8,
680 4,
681 BufferAllocatorRef::static_ref(),
682 );
683 list.append_to_builder(&mut lv_u64_u32, &mut ctx)?;
684 assert_arrays_eq!(lv_u64_u32.finish(), list, &mut ctx);
685
686 let mut lv_i64_i32 = ListViewBuilder::<i64, i32>::with_capacity_in(
687 elem_dtype(),
688 Nullable,
689 8,
690 4,
691 BufferAllocatorRef::static_ref(),
692 );
693 list.append_to_builder(&mut lv_i64_i32, &mut ctx)?;
694 assert_arrays_eq!(lv_i64_i32.finish(), list, &mut ctx);
695
696 let mut lv_u32_u32 = ListViewBuilder::<u32, u32>::with_capacity_in(
697 elem_dtype(),
698 Nullable,
699 8,
700 4,
701 BufferAllocatorRef::static_ref(),
702 );
703 listview.append_to_builder(&mut lv_u32_u32, &mut ctx)?;
704 assert_arrays_eq!(lv_u32_u32.finish(), list, &mut ctx);
705
706 let mut list_builder = ListBuilder::<u32>::with_capacity_in(
709 elem_dtype(),
710 Nullable,
711 8,
712 4,
713 BufferAllocatorRef::static_ref(),
714 );
715 list.append_to_builder(&mut list_builder, &mut ctx)?;
716 assert_arrays_eq!(list_builder.finish(), list, &mut ctx);
717
718 let mut list_builder_i32 = ListBuilder::<i32>::with_capacity_in(
719 elem_dtype(),
720 Nullable,
721 8,
722 4,
723 BufferAllocatorRef::static_ref(),
724 );
725 listview.append_to_builder(&mut list_builder_i32, &mut ctx)?;
726 assert_arrays_eq!(list_builder_i32.finish(), list, &mut ctx);
727
728 Ok(())
729 }
730
731 #[test]
732 fn test_append_list_arrays_grow_builder() -> VortexResult<()> {
733 let mut ctx = array_session().create_execution_ctx();
734 let dtype: Arc<DType> = Arc::new(I32.into());
735
736 let lists: Vec<Option<Vec<i32>>> =
739 (0..100).map(|i| (i % 10 != 0).then(|| vec![i])).collect();
740 let source = ListArray::from_iter_opt_slow::<u32, _, _>(lists.clone(), Arc::clone(&dtype))?;
741 let expected = ListArray::from_iter_opt_slow::<u32, _, _>(
742 lists.iter().cloned().chain(lists.iter().cloned()),
743 Arc::clone(&dtype),
744 )?;
745
746 let mut builder = ListBuilder::<u32>::with_capacity_in(
748 Arc::clone(&dtype),
749 Nullable,
750 0,
751 0,
752 BufferAllocatorRef::static_ref(),
753 );
754 builder.append_list_array(source.as_view(), &mut ctx)?;
755 builder.append_list_array(source.as_view(), &mut ctx)?;
756 assert_arrays_eq!(builder.finish(), expected, &mut ctx);
757
758 let source_listview = source.into_array().execute::<ListViewArray>(&mut ctx)?;
759 let mut builder = ListBuilder::<u32>::with_capacity_in(
760 dtype,
761 Nullable,
762 0,
763 0,
764 BufferAllocatorRef::static_ref(),
765 );
766 builder.append_listview_array(source_listview.as_view(), &mut ctx)?;
767 builder.append_listview_array(source_listview.as_view(), &mut ctx)?;
768 assert_arrays_eq!(builder.finish(), expected, &mut ctx);
769
770 Ok(())
771 }
772
773 #[test]
777 fn test_append_listview_array_flattens_overlaps_and_skips_leading_elements() -> VortexResult<()>
778 {
779 let mut ctx = array_session().create_execution_ctx();
780 let dtype: Arc<DType> = Arc::new(I32.into());
781
782 let overlapping = unsafe {
787 ListViewArray::new_unchecked(
788 buffer![10i32, 20, 30].into_array(),
789 buffer![0u32, 1, 0].into_array(),
790 buffer![2u8, 2, 1].into_array(),
791 Validity::from_iter([true, false, true]),
792 )
793 };
794 assert!(!overlapping.is_zero_copy_to_list());
795
796 let sliced = unsafe {
798 ListViewArray::new_unchecked(
799 buffer![40i32, 50, 60, 70].into_array(),
800 buffer![0u32, 2].into_array(),
801 buffer![2u32, 2].into_array(),
802 Validity::AllValid,
803 )
804 .with_zero_copy_to_list(true)
805 }
806 .into_array()
807 .slice(1..2)?
808 .execute::<ListViewArray>(&mut ctx)?;
809
810 let mut builder = ListBuilder::<u32>::with_capacity_in(
811 dtype,
812 Nullable,
813 0,
814 0,
815 BufferAllocatorRef::static_ref(),
816 );
817 builder.append_listview_array(overlapping.as_view(), &mut ctx)?;
818 builder.append_listview_array(sliced.as_view(), &mut ctx)?;
819
820 let list = builder.finish_into_list();
821 assert_arrays_eq!(
822 list.elements(),
823 PrimitiveArray::from_iter([10i32, 20, 10, 60, 70]),
824 &mut ctx
825 );
826 assert_arrays_eq!(
827 list.offsets(),
828 PrimitiveArray::from_iter([0u32, 2, 2, 3, 5]),
829 &mut ctx
830 );
831
832 Ok(())
833 }
834
835 #[test]
836 fn test_extend_builder() {
837 test_extend_builder_gen::<i32>();
838 test_extend_builder_gen::<i64>();
839
840 test_extend_builder_gen::<u32>();
841 test_extend_builder_gen::<u64>();
842 }
843
844 #[test]
845 pub fn test_array_with_gap() {
846 let one_trailing_unused_element = ListArray::try_new(
847 buffer![1, 2, 3, 4].into_array(),
848 buffer![0, 3].into_array(),
849 Validity::NonNullable,
850 )
851 .unwrap();
852
853 let second_array = ListArray::try_new(
854 buffer![5, 6].into_array(),
855 buffer![0, 2].into_array(),
856 Validity::NonNullable,
857 )
858 .unwrap();
859
860 let chunked_list = ChunkedArray::try_new(
861 vec![
862 one_trailing_unused_element.clone().into_array(),
863 second_array.clone().into_array(),
864 ],
865 DType::List(Arc::new(DType::Primitive(I32, NonNullable)), NonNullable),
866 );
867
868 let mut ctx = array_session().create_execution_ctx();
869 let canon_values = chunked_list
870 .unwrap()
871 .as_array()
872 .clone()
873 .execute::<ListViewArray>(&mut ctx)
874 .unwrap();
875
876 assert_eq!(
877 one_trailing_unused_element
878 .execute_scalar(0, &mut array_session().create_execution_ctx())
879 .unwrap(),
880 canon_values
881 .execute_scalar(0, &mut array_session().create_execution_ctx())
882 .unwrap()
883 );
884 assert_eq!(
885 second_array
886 .execute_scalar(0, &mut array_session().create_execution_ctx())
887 .unwrap(),
888 canon_values
889 .execute_scalar(1, &mut array_session().create_execution_ctx())
890 .unwrap()
891 );
892 }
893
894 #[test]
895 fn test_append_scalar() {
896 let dtype: Arc<DType> = Arc::new(I32.into());
897 let mut builder = ListBuilder::<u64>::with_capacity_in(
898 Arc::clone(&dtype),
899 Nullable,
900 20,
901 10,
902 BufferAllocatorRef::static_ref(),
903 );
904
905 let list_scalar1 =
907 Scalar::list(Arc::clone(&dtype), vec![1i32.into(), 2i32.into()], Nullable);
908 builder.append_scalar(&list_scalar1).unwrap();
909
910 let list_scalar2 = Scalar::list(
912 Arc::clone(&dtype),
913 vec![3i32.into(), 4i32.into(), 5i32.into()],
914 Nullable,
915 );
916 builder.append_scalar(&list_scalar2).unwrap();
917
918 let null_scalar = Scalar::null(DType::List(Arc::clone(&dtype), Nullable));
920 builder.append_scalar(&null_scalar).unwrap();
921
922 let array = builder.finish_into_list();
923 assert_eq!(array.len(), 3);
924
925 let mut ctx = array_session().create_execution_ctx();
926
927 let scalar0 = array.execute_scalar(0, &mut ctx).unwrap();
930 let list0 = scalar0.as_list();
931 assert_eq!(list0.len(), 2);
932 if let Some(list0_items) = list0.elements() {
933 assert_eq!(list0_items[0].as_primitive().typed_value::<i32>(), Some(1));
934 assert_eq!(list0_items[1].as_primitive().typed_value::<i32>(), Some(2));
935 }
936
937 let scalar1 = array.execute_scalar(1, &mut ctx).unwrap();
938 let list1 = scalar1.as_list();
939 assert_eq!(list1.len(), 3);
940 if let Some(list1_items) = list1.elements() {
941 assert_eq!(list1_items[0].as_primitive().typed_value::<i32>(), Some(3));
942 assert_eq!(list1_items[1].as_primitive().typed_value::<i32>(), Some(4));
943 assert_eq!(list1_items[2].as_primitive().typed_value::<i32>(), Some(5));
944 }
945
946 let scalar2 = array.execute_scalar(2, &mut ctx).unwrap();
947 let list2 = scalar2.as_list();
948 assert!(list2.is_null()); assert!(
952 array
953 .validity()
954 .vortex_expect("list validity should be derivable")
955 .execute_is_valid(0, &mut ctx)
956 .unwrap()
957 );
958 assert!(
959 array
960 .validity()
961 .vortex_expect("list validity should be derivable")
962 .execute_is_valid(1, &mut ctx)
963 .unwrap()
964 );
965 assert!(
966 !array
967 .validity()
968 .vortex_expect("list validity should be derivable")
969 .execute_is_valid(2, &mut ctx)
970 .unwrap()
971 );
972
973 let mut builder = ListBuilder::<u64>::with_capacity_in(
975 dtype,
976 NonNullable,
977 20,
978 10,
979 BufferAllocatorRef::static_ref(),
980 );
981 let wrong_scalar = Scalar::from(42i32);
982 assert!(builder.append_scalar(&wrong_scalar).is_err());
983 }
984
985 #[test]
986 fn test_append_array_as_list() {
987 let dtype: Arc<DType> = Arc::new(I32.into());
988 let mut ctx = array_session().create_execution_ctx();
989 let mut builder = ListBuilder::<u32>::with_capacity_in(
990 Arc::clone(&dtype),
991 NonNullable,
992 20,
993 10,
994 BufferAllocatorRef::static_ref(),
995 );
996
997 let arr1 = buffer![1i32, 2, 3].into_array();
999 builder.append_array_as_list(&arr1, &mut ctx).unwrap();
1000
1001 builder
1003 .append_value(
1004 Scalar::list(
1005 Arc::clone(&dtype),
1006 vec![10i32.into(), 11i32.into()],
1007 NonNullable,
1008 )
1009 .as_list(),
1010 )
1011 .unwrap();
1012
1013 let arr2 = buffer![4i32, 5].into_array();
1015 builder.append_array_as_list(&arr2, &mut ctx).unwrap();
1016
1017 let arr3 = buffer![0i32; 0].into_array();
1019 builder.append_array_as_list(&arr3, &mut ctx).unwrap();
1020
1021 builder
1023 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
1024 .unwrap();
1025
1026 let list = builder.finish_into_list();
1027 assert_eq!(list.len(), 5);
1028
1029 assert_arrays_eq!(
1031 list.elements(),
1032 PrimitiveArray::from_iter([1i32, 2, 3, 10, 11, 4, 5]),
1033 &mut ctx
1034 );
1035
1036 assert_arrays_eq!(
1038 list.offsets(),
1039 PrimitiveArray::from_iter([0u32, 3, 5, 7, 7, 7]),
1040 &mut ctx
1041 );
1042
1043 let mut builder = ListBuilder::<u32>::with_capacity_in(
1045 dtype,
1046 NonNullable,
1047 20,
1048 10,
1049 BufferAllocatorRef::static_ref(),
1050 );
1051 let wrong_dtype_arr = buffer![1i64, 2, 3].into_array();
1052 assert!(
1053 builder
1054 .append_array_as_list(&wrong_dtype_arr, &mut ctx)
1055 .is_err()
1056 );
1057 }
1058}