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::ListArrayExt;
31use crate::arrays::listview::ListViewArrayExt;
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::assert_arrays_eq;
521 use crate::builders::ArrayBuilder;
522 use crate::builders::listview::PrimitiveArray;
523 use crate::dtype::DType;
524 use crate::dtype::Nullability::NonNullable;
525 use crate::dtype::Nullability::Nullable;
526 use crate::dtype::PType::I32;
527 use crate::scalar::Scalar;
528 use crate::validity::Validity;
529
530 #[test]
531 fn test_empty() {
532 let mut builder =
533 ListViewBuilder::<u32, u32>::with_capacity(Arc::new(I32.into()), NonNullable, 0, 0);
534
535 let listview = builder.finish();
536 assert_eq!(listview.len(), 0);
537 }
538
539 #[test]
540 fn test_basic_append_and_nulls() {
541 let mut ctx = array_session().create_execution_ctx();
542 let dtype: Arc<DType> = Arc::new(I32.into());
543 let mut builder =
544 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
545
546 builder
548 .append_value(
549 Scalar::list(
550 Arc::clone(&dtype),
551 vec![1i32.into(), 2i32.into(), 3i32.into()],
552 NonNullable,
553 )
554 .as_list(),
555 )
556 .unwrap();
557
558 builder
560 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
561 .unwrap();
562
563 builder.append_null();
565
566 builder
568 .append_value(
569 Scalar::list(dtype, vec![4i32.into(), 5i32.into()], NonNullable).as_list(),
570 )
571 .unwrap();
572
573 let listview = builder.finish_into_listview();
574 assert_eq!(listview.len(), 4);
575
576 assert_arrays_eq!(
578 listview.list_elements_at(0).unwrap(),
579 PrimitiveArray::from_iter([1i32, 2, 3]),
580 &mut ctx
581 );
582
583 assert_eq!(listview.list_elements_at(1).unwrap().len(), 0);
585
586 assert!(
588 !listview
589 .validity()
590 .vortex_expect("listview validity should be derivable")
591 .execute_is_valid(2, &mut ctx)
592 .unwrap()
593 );
594
595 assert_arrays_eq!(
597 listview.list_elements_at(3).unwrap(),
598 PrimitiveArray::from_iter([4i32, 5]),
599 &mut ctx
600 );
601 }
602
603 #[test]
604 fn test_different_offset_size_types() {
605 let mut ctx = array_session().create_execution_ctx();
606 let dtype: Arc<DType> = Arc::new(I32.into());
608 let mut builder =
609 ListViewBuilder::<u32, u8>::with_capacity(Arc::clone(&dtype), NonNullable, 0, 0);
610
611 builder
612 .append_value(
613 Scalar::list(
614 Arc::clone(&dtype),
615 vec![1i32.into(), 2i32.into()],
616 NonNullable,
617 )
618 .as_list(),
619 )
620 .unwrap();
621
622 builder
623 .append_value(
624 Scalar::list(
625 dtype,
626 vec![3i32.into(), 4i32.into(), 5i32.into()],
627 NonNullable,
628 )
629 .as_list(),
630 )
631 .unwrap();
632
633 let listview = builder.finish_into_listview();
634 assert_eq!(listview.len(), 2);
635
636 assert_arrays_eq!(
638 listview.list_elements_at(0).unwrap(),
639 PrimitiveArray::from_iter([1i32, 2]),
640 &mut ctx
641 );
642
643 assert_arrays_eq!(
645 listview.list_elements_at(1).unwrap(),
646 PrimitiveArray::from_iter([3i32, 4, 5]),
647 &mut ctx
648 );
649
650 let dtype2: Arc<DType> = Arc::new(I32.into());
652 let mut builder2 =
653 ListViewBuilder::<u64, u16>::with_capacity(Arc::clone(&dtype2), NonNullable, 0, 0);
654
655 for i in 0..5 {
656 builder2
657 .append_value(
658 Scalar::list(Arc::clone(&dtype2), vec![(i * 10).into()], NonNullable).as_list(),
659 )
660 .unwrap();
661 }
662
663 let listview2 = builder2.finish_into_listview();
664 assert_eq!(listview2.len(), 5);
665
666 for i in 0..5i32 {
668 assert_arrays_eq!(
669 listview2.list_elements_at(i as usize).unwrap(),
670 PrimitiveArray::from_iter([i * 10]),
671 &mut ctx
672 );
673 }
674 }
675
676 #[test]
677 fn test_builder_trait_methods() {
678 let mut ctx = array_session().create_execution_ctx();
679 let dtype: Arc<DType> = Arc::new(I32.into());
680 let mut builder =
681 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
682
683 builder.append_zeros(2);
685 assert_eq!(builder.len(), 2);
686
687 unsafe {
689 builder.append_nulls_unchecked(2);
690 }
691 assert_eq!(builder.len(), 4);
692
693 let list_scalar = Scalar::list(dtype, vec![10i32.into(), 20i32.into()], Nullable);
695 builder.append_scalar(&list_scalar).unwrap();
696 assert_eq!(builder.len(), 5);
697
698 let listview = builder.finish_into_listview();
699 assert_eq!(listview.len(), 5);
700
701 assert_eq!(listview.list_elements_at(0).unwrap().len(), 0);
703 assert_eq!(listview.list_elements_at(1).unwrap().len(), 0);
704
705 assert!(
707 !listview
708 .validity()
709 .vortex_expect("listview validity should be derivable")
710 .execute_is_valid(2, &mut ctx)
711 .unwrap()
712 );
713 assert!(
714 !listview
715 .validity()
716 .vortex_expect("listview validity should be derivable")
717 .execute_is_valid(3, &mut ctx)
718 .unwrap()
719 );
720
721 assert_arrays_eq!(
723 listview.list_elements_at(4).unwrap(),
724 PrimitiveArray::from_iter([10i32, 20]),
725 &mut ctx
726 );
727 }
728
729 #[test]
730 fn test_extend_from_array() {
731 let mut ctx = array_session().create_execution_ctx();
732 let dtype: Arc<DType> = Arc::new(I32.into());
733
734 let source = ListArray::from_iter_opt_slow::<u32, _, Vec<i32>>(
736 [Some(vec![1, 2, 3]), None, Some(vec![4, 5])],
737 Arc::new(I32.into()),
738 )
739 .unwrap();
740
741 let mut builder =
742 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
743
744 builder
746 .append_value(Scalar::list(dtype, vec![0i32.into()], NonNullable).as_list())
747 .unwrap();
748
749 let source = source
751 .into_array()
752 .execute::<ListViewArray>(&mut ctx)
753 .unwrap();
754 builder
755 .append_listview_array(source.as_view(), &mut ctx)
756 .unwrap();
757
758 let empty_source = ListArray::from_iter_opt_slow::<u32, _, Vec<i32>>(
760 std::iter::empty::<Option<Vec<i32>>>(),
761 Arc::new(I32.into()),
762 )
763 .unwrap();
764 let empty_source = empty_source
765 .into_array()
766 .execute::<ListViewArray>(&mut ctx)
767 .unwrap();
768 builder
769 .append_listview_array(empty_source.as_view(), &mut ctx)
770 .unwrap();
771
772 let listview = builder.finish_into_listview();
773 assert_eq!(listview.len(), 4);
774
775 assert_arrays_eq!(
778 listview.list_elements_at(0).unwrap(),
779 PrimitiveArray::from_iter([0i32]),
780 &mut ctx
781 );
782
783 assert_arrays_eq!(
785 listview.list_elements_at(1).unwrap(),
786 PrimitiveArray::from_iter([1i32, 2, 3]),
787 &mut ctx
788 );
789
790 assert!(
792 !listview
793 .validity()
794 .vortex_expect("listview validity should be derivable")
795 .execute_is_valid(2, &mut ctx)
796 .unwrap()
797 );
798
799 assert_arrays_eq!(
801 listview.list_elements_at(3).unwrap(),
802 PrimitiveArray::from_iter([4i32, 5]),
803 &mut ctx
804 );
805 }
806
807 #[test]
808 fn test_append_list_array_grows_builder() -> VortexResult<()> {
809 let mut ctx = array_session().create_execution_ctx();
810 let dtype: Arc<DType> = Arc::new(I32.into());
811
812 let lists: Vec<Option<Vec<i32>>> =
815 (0..100).map(|i| (i % 10 != 0).then(|| vec![i])).collect();
816 let source = ListArray::from_iter_opt_slow::<u32, _, _>(lists.clone(), Arc::clone(&dtype))?;
817
818 let mut builder =
819 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
820 builder.append_list_array(source.as_view(), &mut ctx)?;
821 builder.append_list_array(source.as_view(), &mut ctx)?;
823
824 let listview = builder.finish_into_listview();
825 assert!(listview.is_zero_copy_to_list());
826
827 let expected = ListArray::from_iter_opt_slow::<u32, _, _>(
828 lists.iter().cloned().chain(lists.iter().cloned()),
829 dtype,
830 )?;
831 assert_arrays_eq!(listview, expected, &mut ctx);
832
833 Ok(())
834 }
835
836 #[test]
837 fn test_extend_from_array_overlapping_listview() {
838 let mut ctx = array_session().create_execution_ctx();
839 let dtype: Arc<DType> = Arc::new(I32.into());
840
841 let source = unsafe {
846 ListViewArray::new_unchecked(
847 buffer![10i32, 20, 30].into_array(),
848 buffer![0u32, 1, 0].into_array(),
849 buffer![2u8, 2, 1].into_array(),
850 Validity::from_iter([true, false, true]),
851 )
852 };
853 assert!(!source.is_zero_copy_to_list());
854
855 let mut builder =
856 ListViewBuilder::<u32, u8>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
857 builder
858 .append_listview_array(source.as_view(), &mut ctx)
859 .unwrap();
860
861 let listview = builder.finish_into_listview();
862 assert_eq!(listview.len(), 3);
863 assert!(listview.is_zero_copy_to_list());
864
865 assert_arrays_eq!(
866 listview.list_elements_at(0).unwrap(),
867 PrimitiveArray::from_iter([10i32, 20]),
868 &mut ctx
869 );
870 assert!(
871 !listview
872 .validity()
873 .vortex_expect("listview validity should be derivable")
874 .execute_is_valid(1, &mut ctx)
875 .unwrap()
876 );
877 assert_eq!(listview.list_elements_at(1).unwrap().len(), 0);
878 assert_arrays_eq!(
879 listview.list_elements_at(2).unwrap(),
880 PrimitiveArray::from_iter([10i32]),
881 &mut ctx
882 );
883 }
884
885 #[test]
886 fn test_error_append_null_to_non_nullable() {
887 let dtype: Arc<DType> = Arc::new(I32.into());
888 let mut builder =
889 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), NonNullable, 0, 0);
890
891 let null_scalar = Scalar::null(DType::List(dtype, Nullable));
893 let null_list = null_scalar.as_list();
894
895 let result = builder.append_value(null_list);
897 assert!(result.is_err());
898 assert!(
899 result
900 .unwrap_err()
901 .to_string()
902 .contains("null value to non-nullable")
903 );
904 }
905
906 #[test]
907 fn test_append_array_as_list() {
908 let dtype: Arc<DType> = Arc::new(I32.into());
909 let mut ctx = array_session().create_execution_ctx();
910 let mut builder =
911 ListViewBuilder::<u32, u32>::with_capacity(Arc::clone(&dtype), NonNullable, 20, 10);
912
913 let arr1 = buffer![1i32, 2, 3].into_array();
915 builder.append_array_as_list(&arr1, &mut ctx).unwrap();
916
917 builder
919 .append_value(
920 Scalar::list(
921 Arc::clone(&dtype),
922 vec![10i32.into(), 11i32.into()],
923 NonNullable,
924 )
925 .as_list(),
926 )
927 .unwrap();
928
929 let arr2 = buffer![4i32, 5].into_array();
931 builder.append_array_as_list(&arr2, &mut ctx).unwrap();
932
933 let arr3 = buffer![0i32; 0].into_array();
935 builder.append_array_as_list(&arr3, &mut ctx).unwrap();
936
937 builder
939 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
940 .unwrap();
941
942 let listview = builder.finish_into_listview();
943 assert_eq!(listview.len(), 5);
944
945 assert_arrays_eq!(
947 listview.elements(),
948 PrimitiveArray::from_iter([1i32, 2, 3, 10, 11, 4, 5]),
949 &mut ctx
950 );
951
952 assert_arrays_eq!(
954 listview.offsets(),
955 PrimitiveArray::from_iter([0u32, 3, 5, 7, 7]),
956 &mut ctx
957 );
958
959 assert_arrays_eq!(
961 listview.sizes(),
962 PrimitiveArray::from_iter([3u32, 2, 2, 0, 0]),
963 &mut ctx
964 );
965
966 let mut builder = ListViewBuilder::<u32, u32>::with_capacity(dtype, NonNullable, 20, 10);
968 let wrong_dtype_arr = buffer![1i64, 2, 3].into_array();
969 assert!(
970 builder
971 .append_array_as_list(&wrong_dtype_arr, &mut ctx)
972 .is_err()
973 );
974 }
975}