1use std::sync::Arc;
14
15use vortex_error::VortexExpect;
16use vortex_error::VortexResult;
17use vortex_error::vortex_ensure;
18use vortex_error::vortex_panic;
19use vortex_mask::Mask;
20
21use crate::ArrayRef;
22use crate::Canonical;
23use crate::ExecutionCtx;
24use crate::array::ArrayView;
25use crate::array::IntoArray;
26use crate::arrays::List;
27use crate::arrays::ListView;
28use crate::arrays::ListViewArray;
29use crate::arrays::PrimitiveArray;
30use crate::arrays::list::ListArraySlotsExt;
31use crate::arrays::listview::ListViewArraySlotsExt;
32use crate::arrays::listview::ListViewRebuildMode;
33use crate::builders::ArrayBuilder;
34use crate::builders::DEFAULT_BUILDER_CAPACITY;
35use crate::builders::PrimitiveBuilder;
36use crate::builders::UninitRange;
37use crate::builders::builder_with_capacity;
38use crate::builders::lazy_null_builder::LazyBitBufferBuilder;
39use crate::builtins::ArrayBuiltins;
40use crate::dtype::DType;
41use crate::dtype::IntegerPType;
42use crate::dtype::Nullability;
43use crate::match_each_integer_ptype;
44use crate::scalar::ListScalar;
45use crate::scalar::Scalar;
46
47pub struct ListViewBuilder<O: IntegerPType, S: IntegerPType> {
57 dtype: DType,
59
60 elements_builder: Box<dyn ArrayBuilder>,
62
63 offsets_builder: PrimitiveBuilder<O>,
65
66 sizes_builder: PrimitiveBuilder<S>,
68
69 nulls: LazyBitBufferBuilder,
71}
72
73impl<O: IntegerPType, S: IntegerPType> ListViewBuilder<O, S> {
74 pub fn new(element_dtype: Arc<DType>, nullability: Nullability) -> Self {
76 Self::with_capacity(
77 element_dtype,
78 nullability,
79 DEFAULT_BUILDER_CAPACITY * 2,
82 DEFAULT_BUILDER_CAPACITY,
83 )
84 }
85
86 pub fn with_capacity(
94 element_dtype: Arc<DType>,
95 nullability: Nullability,
96 elements_capacity: usize,
97 capacity: usize,
98 ) -> Self {
99 let elements_builder = builder_with_capacity(&element_dtype, elements_capacity);
100
101 let offsets_builder =
102 PrimitiveBuilder::<O>::with_capacity(Nullability::NonNullable, capacity);
103 let sizes_builder =
104 PrimitiveBuilder::<S>::with_capacity(Nullability::NonNullable, capacity);
105
106 let nulls = LazyBitBufferBuilder::new(capacity);
107
108 Self {
109 dtype: DType::List(element_dtype, nullability),
110 elements_builder,
111 offsets_builder,
112 sizes_builder,
113 nulls,
114 }
115 }
116
117 pub fn append_array_as_list(
124 &mut self,
125 array: &ArrayRef,
126 ctx: &mut ExecutionCtx,
127 ) -> VortexResult<()> {
128 vortex_ensure!(
129 array.dtype() == self.element_dtype(),
130 "Array dtype {:?} does not match list element dtype {:?}",
131 array.dtype(),
132 self.element_dtype()
133 );
134
135 let curr_offset = self.elements_builder.len();
136 let num_elements = array.len();
137
138 assert!(
141 ((curr_offset + num_elements) as u64) < O::max_value_as_u64(),
142 "appending this list would cause an offset overflow"
143 );
144
145 self.elements_builder.reserve_exact(num_elements);
146 array.append_to_builder(self.elements_builder.as_mut(), ctx)?;
147 self.nulls.append_non_null();
148
149 self.offsets_builder.append_value(
150 O::from_usize(curr_offset).vortex_expect("Failed to convert from usize to `O`"),
151 );
152 self.sizes_builder.append_value(
153 S::from_usize(num_elements).vortex_expect("Failed to convert from usize to `S`"),
154 );
155
156 Ok(())
157 }
158
159 pub fn append_value(&mut self, value: ListScalar) -> VortexResult<()> {
164 let Some(elements) = value.elements() else {
165 vortex_ensure!(
167 self.dtype.is_nullable(),
168 "Cannot append null value to non-nullable list builder"
169 );
170 self.append_null();
171 return Ok(());
172 };
173
174 let curr_offset = self.elements_builder.len();
175 let num_elements = elements.len();
176
177 assert!(
180 ((curr_offset + num_elements) as u64) < O::max_value_as_u64(),
181 "appending this list would cause an offset overflow"
182 );
183
184 for scalar in elements {
185 self.elements_builder.append_scalar(&scalar)?;
186 }
187 self.nulls.append_non_null();
188
189 self.offsets_builder.append_value(
190 O::from_usize(curr_offset).vortex_expect("Failed to convert from usize to `O`"),
191 );
192 self.sizes_builder.append_value(
193 S::from_usize(num_elements).vortex_expect("Failed to convert from usize to `S`"),
194 );
195
196 Ok(())
197 }
198
199 pub fn finish_into_listview(&mut self) -> ListViewArray {
201 debug_assert_eq!(self.offsets_builder.len(), self.sizes_builder.len());
202 debug_assert_eq!(self.offsets_builder.len(), self.nulls.len());
203
204 let elements = self.elements_builder.finish();
205 let offsets = self.offsets_builder.finish();
206 let sizes = self.sizes_builder.finish();
207 let validity = self.nulls.finish_with_nullability(self.dtype.nullability());
208
209 unsafe {
220 ListViewArray::new_unchecked(elements, offsets, sizes, validity)
221 .with_zero_copy_to_list(true)
222 }
223 }
224
225 pub fn element_dtype(&self) -> &DType {
228 let DType::List(element_dtype, ..) = &self.dtype else {
229 vortex_panic!("`ListViewBuilder` has an incorrect dtype: {}", self.dtype);
230 };
231
232 element_dtype
233 }
234}
235
236impl<O: IntegerPType, S: IntegerPType> ArrayBuilder for ListViewBuilder<O, S> {
237 fn as_any(&self) -> &dyn std::any::Any {
238 self
239 }
240
241 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
242 self
243 }
244
245 fn dtype(&self) -> &DType {
246 &self.dtype
247 }
248
249 fn len(&self) -> usize {
250 self.offsets_builder.len()
251 }
252
253 fn append_zeros(&mut self, n: usize) {
254 debug_assert_eq!(self.offsets_builder.len(), self.sizes_builder.len());
255 debug_assert_eq!(self.offsets_builder.len(), self.nulls.len());
256
257 let curr_offset = self.elements_builder.len();
259
260 for _ in 0..n {
263 self.offsets_builder.append_value(
264 O::from_usize(curr_offset).vortex_expect("Failed to convert from usize to `O`"),
265 );
266 self.sizes_builder.append_value(S::zero());
267 }
268
269 self.nulls.append_n_non_nulls(n);
270 }
271
272 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
273 debug_assert_eq!(self.offsets_builder.len(), self.sizes_builder.len());
274 debug_assert_eq!(self.offsets_builder.len(), self.nulls.len());
275
276 let curr_offset = self.elements_builder.len();
278
279 for _ in 0..n {
281 self.offsets_builder.append_value(
282 O::from_usize(curr_offset).vortex_expect("Failed to convert from usize to `O`"),
283 );
284 self.sizes_builder.append_value(S::zero());
285 }
286
287 self.nulls.append_n_nulls(n);
289 }
290
291 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
292 vortex_ensure!(
293 scalar.dtype() == self.dtype(),
294 "ListViewBuilder expected scalar with dtype {}, got {}",
295 self.dtype(),
296 scalar.dtype()
297 );
298
299 let list_scalar = scalar.as_list();
300 self.append_value(list_scalar)
301 }
302
303 fn reserve_exact(&mut self, capacity: usize) {
304 self.elements_builder.reserve_exact(capacity * 2);
305 self.offsets_builder.reserve_exact(capacity);
306 self.sizes_builder.reserve_exact(capacity);
307 self.nulls.reserve_exact(capacity);
308 }
309
310 unsafe fn set_validity_unchecked(&mut self, validity: Mask) {
311 self.nulls = LazyBitBufferBuilder::from_validity_mask(validity);
312 }
313
314 fn finish(&mut self) -> ArrayRef {
315 self.finish_into_listview().into_array()
316 }
317
318 fn finish_into_canonical(&mut self, _ctx: &mut ExecutionCtx) -> Canonical {
319 Canonical::List(self.finish_into_listview())
320 }
321
322 fn append_list_array(
323 &mut self,
324 array: ArrayView<'_, List>,
325 ctx: &mut ExecutionCtx,
326 ) -> VortexResult<()> {
327 if array.is_empty() {
328 return Ok(());
329 }
330
331 self.nulls
332 .append_validity_mask(&array.validity()?.execute_mask(array.len(), ctx)?);
333
334 let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
335 match_each_integer_ptype!(offsets.ptype(), |OffsetType| {
336 extend_from_list(
337 self,
338 array.elements(),
339 offsets.as_slice::<OffsetType>(),
340 ctx,
341 )?
342 });
343 Ok(())
344 }
345
346 fn append_listview_array(
347 &mut self,
348 array: ArrayView<'_, ListView>,
349 ctx: &mut ExecutionCtx,
350 ) -> VortexResult<()> {
351 if array.is_empty() {
352 return Ok(());
353 }
354
355 let listview = array
358 .into_owned()
359 .rebuild(ListViewRebuildMode::MakeExact, ctx)?;
360 debug_assert!(listview.is_zero_copy_to_list());
361
362 self.nulls
363 .append_validity_mask(&array.validity()?.execute_mask(array.len(), ctx)?);
364
365 let old_elements_len = self.elements_builder.len();
367 self.elements_builder
368 .reserve_exact(listview.elements().len());
369 listview
370 .elements()
371 .append_to_builder(self.elements_builder.as_mut(), ctx)?;
372 let new_elements_len = self.elements_builder.len();
373
374 let extend_length = listview.len();
376 self.sizes_builder.reserve_exact(extend_length);
377 self.offsets_builder.reserve_exact(extend_length);
378
379 let cast_sizes = listview
381 .sizes()
382 .clone()
383 .cast(self.sizes_builder.dtype().clone())?;
384 cast_sizes.append_to_builder(&mut self.sizes_builder, ctx)?;
385
386 let uninit_range = self.offsets_builder.uninit_range(extend_length);
389
390 let new_offsets = listview.offsets().clone().execute::<PrimitiveArray>(ctx)?;
392
393 match_each_integer_ptype!(new_offsets.ptype(), |A| {
394 adjust_and_extend_offsets::<O, A>(
395 uninit_range,
396 new_offsets,
397 old_elements_len,
398 new_elements_len,
399 );
400 });
401 Ok(())
402 }
403}
404
405fn extend_from_list<O, S, OffsetType>(
411 builder: &mut ListViewBuilder<O, S>,
412 elements: &ArrayRef,
413 offsets: &[OffsetType],
414 ctx: &mut ExecutionCtx,
415) -> VortexResult<()>
416where
417 O: IntegerPType,
418 S: IntegerPType,
419 OffsetType: IntegerPType,
420{
421 let num_lists = offsets.len() - 1;
422 let first: usize = offsets[0].as_();
423 let last: usize = offsets[num_lists].as_();
424
425 let elements_base = builder.elements_builder.len();
426
427 assert!(
430 ((elements_base + (last - first)) as u64) < O::max_value_as_u64(),
431 "appending this list would cause an offset overflow"
432 );
433
434 if last > first {
435 builder.elements_builder.reserve_exact(last - first);
436 elements
437 .slice(first..last)?
438 .append_to_builder(builder.elements_builder.as_mut(), ctx)?;
439 }
440
441 builder.offsets_builder.reserve_exact(num_lists);
442 builder.sizes_builder.reserve_exact(num_lists);
443 let mut offsets_range = builder.offsets_builder.uninit_range(num_lists);
444 let mut sizes_range = builder.sizes_builder.uninit_range(num_lists);
445 for i in 0..num_lists {
446 let start: usize = offsets[i].as_();
447 let end: usize = offsets[i + 1].as_();
448 offsets_range.set_value(
449 i,
450 O::from_usize(start - first + elements_base)
451 .vortex_expect("Failed to convert from usize to `O`"),
452 );
453 sizes_range.set_value(
454 i,
455 S::from_usize(end - start).vortex_expect("Failed to convert from usize to `S`"),
456 );
457 }
458 unsafe { offsets_range.finish() };
461 unsafe { sizes_range.finish() };
462 Ok(())
463}
464
465fn adjust_and_extend_offsets<O: IntegerPType, A: IntegerPType>(
468 mut uninit_range: UninitRange<O>,
469 new_offsets: PrimitiveArray,
470 old_elements_len: usize,
471 new_elements_len: usize,
472) {
473 let new_offsets_slice = new_offsets.as_slice::<A>();
474 let old_elements_len = O::from_usize(old_elements_len)
475 .vortex_expect("the old elements length did not fit into the offset type (impossible)");
476 let new_elements_len = O::from_usize(new_elements_len)
477 .vortex_expect("the current elements length did not fit into the offset type (impossible)");
478
479 for i in 0..uninit_range.len() {
480 let new_offset = O::from_usize(
481 new_offsets_slice[i]
482 .to_usize()
483 .vortex_expect("Offsets must always fit in usize"),
484 )
485 .vortex_expect("New offset somehow did not fit into the builder's offset type");
486
487 let adjusted_new_offset = new_offset + old_elements_len;
490 assert!(
491 adjusted_new_offset <= new_elements_len,
492 "[{i}/{}]: {new_offset} + {old_elements_len} \
493 = {adjusted_new_offset} <= {new_elements_len} failed",
494 uninit_range.len()
495 );
496
497 uninit_range.set_value(i, adjusted_new_offset);
498 }
499
500 unsafe { uninit_range.finish() };
503}
504
505#[cfg(test)]
506mod tests {
507 use std::sync::Arc;
508
509 use vortex_buffer::buffer;
510 use vortex_error::VortexExpect;
511 use vortex_error::VortexResult;
512
513 use super::ListViewBuilder;
514 use crate::IntoArray;
515 use crate::VortexSessionExecute;
516 use crate::array_session;
517 use crate::arrays::ListArray;
518 use crate::arrays::ListViewArray;
519 use crate::arrays::listview::ListViewArrayExt;
520 use crate::arrays::listview::ListViewArraySlotsExt;
521 use crate::assert_arrays_eq;
522 use crate::builders::ArrayBuilder;
523 use crate::builders::listview::PrimitiveArray;
524 use crate::dtype::DType;
525 use crate::dtype::Nullability::NonNullable;
526 use crate::dtype::Nullability::Nullable;
527 use crate::dtype::PType::I32;
528 use crate::scalar::Scalar;
529 use crate::validity::Validity;
530
531 #[test]
532 fn test_empty() {
533 let mut builder =
534 ListViewBuilder::<u32, u32>::with_capacity(Arc::new(I32.into()), NonNullable, 0, 0);
535
536 let listview = builder.finish();
537 assert_eq!(listview.len(), 0);
538 }
539
540 #[test]
541 fn test_basic_append_and_nulls() {
542 let mut ctx = array_session().create_execution_ctx();
543 let dtype: Arc<DType> = Arc::new(I32.into());
544 let mut builder =
545 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
546
547 builder
549 .append_value(
550 Scalar::list(
551 Arc::clone(&dtype),
552 vec![1i32.into(), 2i32.into(), 3i32.into()],
553 NonNullable,
554 )
555 .as_list(),
556 )
557 .unwrap();
558
559 builder
561 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
562 .unwrap();
563
564 builder.append_null();
566
567 builder
569 .append_value(
570 Scalar::list(dtype, vec![4i32.into(), 5i32.into()], NonNullable).as_list(),
571 )
572 .unwrap();
573
574 let listview = builder.finish_into_listview();
575 assert_eq!(listview.len(), 4);
576
577 assert_arrays_eq!(
579 listview.list_elements_at(0).unwrap(),
580 PrimitiveArray::from_iter([1i32, 2, 3]),
581 &mut ctx
582 );
583
584 assert_eq!(listview.list_elements_at(1).unwrap().len(), 0);
586
587 assert!(
589 !listview
590 .validity()
591 .vortex_expect("listview validity should be derivable")
592 .execute_is_valid(2, &mut ctx)
593 .unwrap()
594 );
595
596 assert_arrays_eq!(
598 listview.list_elements_at(3).unwrap(),
599 PrimitiveArray::from_iter([4i32, 5]),
600 &mut ctx
601 );
602 }
603
604 #[test]
605 fn test_different_offset_size_types() {
606 let mut ctx = array_session().create_execution_ctx();
607 let dtype: Arc<DType> = Arc::new(I32.into());
609 let mut builder =
610 ListViewBuilder::<u32, u8>::with_capacity(Arc::clone(&dtype), NonNullable, 0, 0);
611
612 builder
613 .append_value(
614 Scalar::list(
615 Arc::clone(&dtype),
616 vec![1i32.into(), 2i32.into()],
617 NonNullable,
618 )
619 .as_list(),
620 )
621 .unwrap();
622
623 builder
624 .append_value(
625 Scalar::list(
626 dtype,
627 vec![3i32.into(), 4i32.into(), 5i32.into()],
628 NonNullable,
629 )
630 .as_list(),
631 )
632 .unwrap();
633
634 let listview = builder.finish_into_listview();
635 assert_eq!(listview.len(), 2);
636
637 assert_arrays_eq!(
639 listview.list_elements_at(0).unwrap(),
640 PrimitiveArray::from_iter([1i32, 2]),
641 &mut ctx
642 );
643
644 assert_arrays_eq!(
646 listview.list_elements_at(1).unwrap(),
647 PrimitiveArray::from_iter([3i32, 4, 5]),
648 &mut ctx
649 );
650
651 let dtype2: Arc<DType> = Arc::new(I32.into());
653 let mut builder2 =
654 ListViewBuilder::<u64, u16>::with_capacity(Arc::clone(&dtype2), NonNullable, 0, 0);
655
656 for i in 0..5 {
657 builder2
658 .append_value(
659 Scalar::list(Arc::clone(&dtype2), vec![(i * 10).into()], NonNullable).as_list(),
660 )
661 .unwrap();
662 }
663
664 let listview2 = builder2.finish_into_listview();
665 assert_eq!(listview2.len(), 5);
666
667 for i in 0..5i32 {
669 assert_arrays_eq!(
670 listview2.list_elements_at(i as usize).unwrap(),
671 PrimitiveArray::from_iter([i * 10]),
672 &mut ctx
673 );
674 }
675 }
676
677 #[test]
678 fn test_builder_trait_methods() {
679 let mut ctx = array_session().create_execution_ctx();
680 let dtype: Arc<DType> = Arc::new(I32.into());
681 let mut builder =
682 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
683
684 builder.append_zeros(2);
686 assert_eq!(builder.len(), 2);
687
688 unsafe {
690 builder.append_nulls_unchecked(2);
691 }
692 assert_eq!(builder.len(), 4);
693
694 let list_scalar = Scalar::list(dtype, vec![10i32.into(), 20i32.into()], Nullable);
696 builder.append_scalar(&list_scalar).unwrap();
697 assert_eq!(builder.len(), 5);
698
699 let listview = builder.finish_into_listview();
700 assert_eq!(listview.len(), 5);
701
702 assert_eq!(listview.list_elements_at(0).unwrap().len(), 0);
704 assert_eq!(listview.list_elements_at(1).unwrap().len(), 0);
705
706 assert!(
708 !listview
709 .validity()
710 .vortex_expect("listview validity should be derivable")
711 .execute_is_valid(2, &mut ctx)
712 .unwrap()
713 );
714 assert!(
715 !listview
716 .validity()
717 .vortex_expect("listview validity should be derivable")
718 .execute_is_valid(3, &mut ctx)
719 .unwrap()
720 );
721
722 assert_arrays_eq!(
724 listview.list_elements_at(4).unwrap(),
725 PrimitiveArray::from_iter([10i32, 20]),
726 &mut ctx
727 );
728 }
729
730 #[test]
731 fn test_extend_from_array() {
732 let mut ctx = array_session().create_execution_ctx();
733 let dtype: Arc<DType> = Arc::new(I32.into());
734
735 let source = ListArray::from_iter_opt_slow::<u32, _, Vec<i32>>(
737 [Some(vec![1, 2, 3]), None, Some(vec![4, 5])],
738 Arc::new(I32.into()),
739 )
740 .unwrap();
741
742 let mut builder =
743 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
744
745 builder
747 .append_value(Scalar::list(dtype, vec![0i32.into()], NonNullable).as_list())
748 .unwrap();
749
750 let source = source
752 .into_array()
753 .execute::<ListViewArray>(&mut ctx)
754 .unwrap();
755 builder
756 .append_listview_array(source.as_view(), &mut ctx)
757 .unwrap();
758
759 let empty_source = ListArray::from_iter_opt_slow::<u32, _, Vec<i32>>(
761 std::iter::empty::<Option<Vec<i32>>>(),
762 Arc::new(I32.into()),
763 )
764 .unwrap();
765 let empty_source = empty_source
766 .into_array()
767 .execute::<ListViewArray>(&mut ctx)
768 .unwrap();
769 builder
770 .append_listview_array(empty_source.as_view(), &mut ctx)
771 .unwrap();
772
773 let listview = builder.finish_into_listview();
774 assert_eq!(listview.len(), 4);
775
776 assert_arrays_eq!(
779 listview.list_elements_at(0).unwrap(),
780 PrimitiveArray::from_iter([0i32]),
781 &mut ctx
782 );
783
784 assert_arrays_eq!(
786 listview.list_elements_at(1).unwrap(),
787 PrimitiveArray::from_iter([1i32, 2, 3]),
788 &mut ctx
789 );
790
791 assert!(
793 !listview
794 .validity()
795 .vortex_expect("listview validity should be derivable")
796 .execute_is_valid(2, &mut ctx)
797 .unwrap()
798 );
799
800 assert_arrays_eq!(
802 listview.list_elements_at(3).unwrap(),
803 PrimitiveArray::from_iter([4i32, 5]),
804 &mut ctx
805 );
806 }
807
808 #[test]
809 fn test_append_list_array_grows_builder() -> VortexResult<()> {
810 let mut ctx = array_session().create_execution_ctx();
811 let dtype: Arc<DType> = Arc::new(I32.into());
812
813 let lists: Vec<Option<Vec<i32>>> =
816 (0..100).map(|i| (i % 10 != 0).then(|| vec![i])).collect();
817 let source = ListArray::from_iter_opt_slow::<u32, _, _>(lists.clone(), Arc::clone(&dtype))?;
818
819 let mut builder =
820 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
821 builder.append_list_array(source.as_view(), &mut ctx)?;
822 builder.append_list_array(source.as_view(), &mut ctx)?;
824
825 let listview = builder.finish_into_listview();
826 assert!(listview.is_zero_copy_to_list());
827
828 let expected = ListArray::from_iter_opt_slow::<u32, _, _>(
829 lists.iter().cloned().chain(lists.iter().cloned()),
830 dtype,
831 )?;
832 assert_arrays_eq!(listview, expected, &mut ctx);
833
834 Ok(())
835 }
836
837 #[test]
838 fn test_extend_from_array_overlapping_listview() {
839 let mut ctx = array_session().create_execution_ctx();
840 let dtype: Arc<DType> = Arc::new(I32.into());
841
842 let source = unsafe {
847 ListViewArray::new_unchecked(
848 buffer![10i32, 20, 30].into_array(),
849 buffer![0u32, 1, 0].into_array(),
850 buffer![2u8, 2, 1].into_array(),
851 Validity::from_iter([true, false, true]),
852 )
853 };
854 assert!(!source.is_zero_copy_to_list());
855
856 let mut builder =
857 ListViewBuilder::<u32, u8>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
858 builder
859 .append_listview_array(source.as_view(), &mut ctx)
860 .unwrap();
861
862 let listview = builder.finish_into_listview();
863 assert_eq!(listview.len(), 3);
864 assert!(listview.is_zero_copy_to_list());
865
866 assert_arrays_eq!(
867 listview.list_elements_at(0).unwrap(),
868 PrimitiveArray::from_iter([10i32, 20]),
869 &mut ctx
870 );
871 assert!(
872 !listview
873 .validity()
874 .vortex_expect("listview validity should be derivable")
875 .execute_is_valid(1, &mut ctx)
876 .unwrap()
877 );
878 assert_eq!(listview.list_elements_at(1).unwrap().len(), 0);
879 assert_arrays_eq!(
880 listview.list_elements_at(2).unwrap(),
881 PrimitiveArray::from_iter([10i32]),
882 &mut ctx
883 );
884 }
885
886 #[test]
887 fn test_error_append_null_to_non_nullable() {
888 let dtype: Arc<DType> = Arc::new(I32.into());
889 let mut builder =
890 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), NonNullable, 0, 0);
891
892 let null_scalar = Scalar::null(DType::List(dtype, Nullable));
894 let null_list = null_scalar.as_list();
895
896 let result = builder.append_value(null_list);
898 assert!(result.is_err());
899 assert!(
900 result
901 .unwrap_err()
902 .to_string()
903 .contains("null value to non-nullable")
904 );
905 }
906
907 #[test]
908 fn test_append_array_as_list() {
909 let dtype: Arc<DType> = Arc::new(I32.into());
910 let mut ctx = array_session().create_execution_ctx();
911 let mut builder =
912 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), NonNullable, 20, 10);
913
914 let arr1 = buffer![1i32, 2, 3].into_array();
916 builder.append_array_as_list(&arr1, &mut ctx).unwrap();
917
918 builder
920 .append_value(
921 Scalar::list(
922 Arc::clone(&dtype),
923 vec![10i32.into(), 11i32.into()],
924 NonNullable,
925 )
926 .as_list(),
927 )
928 .unwrap();
929
930 let arr2 = buffer![4i32, 5].into_array();
932 builder.append_array_as_list(&arr2, &mut ctx).unwrap();
933
934 let arr3 = buffer![0i32; 0].into_array();
936 builder.append_array_as_list(&arr3, &mut ctx).unwrap();
937
938 builder
940 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
941 .unwrap();
942
943 let listview = builder.finish_into_listview();
944 assert_eq!(listview.len(), 5);
945
946 assert_arrays_eq!(
948 listview.elements(),
949 PrimitiveArray::from_iter([1i32, 2, 3, 10, 11, 4, 5]),
950 &mut ctx
951 );
952
953 assert_arrays_eq!(
955 listview.offsets(),
956 PrimitiveArray::from_iter([0u32, 3, 5, 7, 7]),
957 &mut ctx
958 );
959
960 assert_arrays_eq!(
962 listview.sizes(),
963 PrimitiveArray::from_iter([3u32, 2, 2, 0, 0]),
964 &mut ctx
965 );
966
967 let mut builder = ListViewBuilder::<u32, u32>::with_capacity(dtype, NonNullable, 20, 10);
969 let wrong_dtype_arr = buffer![1i64, 2, 3].into_array();
970 assert!(
971 builder
972 .append_array_as_list(&wrong_dtype_arr, &mut ctx)
973 .is_err()
974 );
975 }
976}