1use std::any::Any;
5use std::sync::Arc;
6
7use num_traits::AsPrimitive;
8use vortex_error::VortexExpect;
9use vortex_error::VortexResult;
10use vortex_error::vortex_bail;
11use vortex_error::vortex_ensure;
12use vortex_error::vortex_panic;
13use vortex_mask::Mask;
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::builders::ArrayBuilder;
28use crate::builders::DEFAULT_BUILDER_CAPACITY;
29use crate::builders::LazyBitBufferBuilder;
30use crate::builders::PrimitiveBuilder;
31use crate::builders::builder_with_capacity;
32use crate::dtype::DType;
33use crate::dtype::IntegerPType;
34use crate::dtype::Nullability;
35use crate::dtype::Nullability::NonNullable;
36use crate::dtype::OffsetBuilderPType;
37use crate::match_each_integer_ptype;
38use crate::scalar::ListScalar;
39use crate::scalar::Scalar;
40
41pub struct ListBuilder<O: OffsetBuilderPType> {
44 dtype: DType,
46
47 elements_builder: Box<dyn ArrayBuilder>,
49
50 offsets_builder: PrimitiveBuilder<O>,
52
53 nulls: LazyBitBufferBuilder,
55}
56
57impl<O: OffsetBuilderPType> ListBuilder<O> {
58 pub fn new(value_dtype: Arc<DType>, nullability: Nullability) -> Self {
60 Self::with_capacity(
61 value_dtype,
62 nullability,
63 DEFAULT_BUILDER_CAPACITY * 2,
66 DEFAULT_BUILDER_CAPACITY,
67 )
68 }
69
70 pub fn with_capacity(
78 value_dtype: Arc<DType>,
79 nullability: Nullability,
80 elements_capacity: usize,
81 capacity: usize,
82 ) -> Self {
83 let elements_builder = builder_with_capacity(value_dtype.as_ref(), elements_capacity);
84 let mut offsets_builder = PrimitiveBuilder::<O>::with_capacity(NonNullable, capacity + 1);
85
86 offsets_builder.append_zero();
88
89 Self {
90 elements_builder,
91 offsets_builder,
92 nulls: LazyBitBufferBuilder::new(capacity),
93 dtype: DType::List(value_dtype, nullability),
94 }
95 }
96
97 pub fn append_array_as_list(
104 &mut self,
105 array: &ArrayRef,
106 ctx: &mut ExecutionCtx,
107 ) -> VortexResult<()> {
108 vortex_ensure!(
109 array.dtype() == self.element_dtype(),
110 "Array dtype {:?} does not match list element dtype {:?}",
111 array.dtype(),
112 self.element_dtype()
113 );
114
115 self.elements_builder.reserve_exact(array.len());
116 array.append_to_builder(self.elements_builder.as_mut(), ctx)?;
117 self.nulls.append_non_null();
118 self.offsets_builder.append_value(
119 O::from_usize(self.elements_builder.len())
120 .vortex_expect("Failed to convert from usize to O"),
121 );
122
123 Ok(())
124 }
125
126 pub fn append_value(&mut self, value: ListScalar) -> VortexResult<()> {
128 match value.elements() {
129 None => {
130 if self.dtype.nullability() == NonNullable {
131 vortex_bail!("Cannot append null value to non-nullable list");
132 }
133 self.append_null();
134 }
135 Some(elements) => {
136 for scalar in elements {
137 self.elements_builder.append_scalar(&scalar)?;
140 }
141
142 self.nulls.append_non_null();
143 self.offsets_builder.append_value(
144 O::from_usize(self.elements_builder.len())
145 .vortex_expect("Failed to convert from usize to O"),
146 );
147 }
148 }
149
150 Ok(())
151 }
152
153 pub fn finish_into_list(&mut self) -> ListArray {
155 assert_eq!(
156 self.offsets_builder.len(),
157 self.nulls.len() + 1,
158 "offsets length must be one more than nulls length."
159 );
160
161 ListArray::try_new(
162 self.elements_builder.finish(),
163 self.offsets_builder.finish(),
164 self.nulls.finish_with_nullability(self.dtype.nullability()),
165 )
166 .vortex_expect("Buffer, offsets, and validity must have same length.")
167 }
168
169 pub fn element_dtype(&self) -> &DType {
172 let DType::List(element_dtype, _) = &self.dtype else {
173 vortex_panic!("`ListBuilder` has an incorrect dtype: {}", self.dtype);
174 };
175
176 element_dtype
177 }
178
179 pub fn append_list_array(
186 &mut self,
187 array: ArrayView<'_, List>,
188 ctx: &mut ExecutionCtx,
189 ) -> VortexResult<()> {
190 if array.is_empty() {
191 return Ok(());
192 }
193
194 self.nulls
195 .append_validity_mask(&array.validity()?.execute_mask(array.len(), ctx)?);
196
197 let num_lists = array.len();
198 let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
199 match_each_integer_ptype!(offsets.ptype(), |OffsetType| {
200 let offsets = offsets.as_slice::<OffsetType>();
201 let first: usize = offsets[0].as_();
202 let last: usize = offsets[num_lists].as_();
203
204 let elements_base = self.elements_builder.len();
207 if last > first {
208 self.elements_builder.reserve_exact(last - first);
209 array
210 .elements()
211 .slice(first..last)?
212 .append_to_builder(self.elements_builder.as_mut(), ctx)?;
213 }
214
215 self.offsets_builder.reserve_exact(num_lists);
216 let mut offsets_range = self.offsets_builder.uninit_range(num_lists);
217 for i in 0..num_lists {
218 let end: usize = offsets[i + 1].as_();
219 offsets_range.set_value(
220 i,
221 O::from_usize(end - first + elements_base)
222 .vortex_expect("Failed to convert offset"),
223 );
224 }
225 unsafe { offsets_range.finish() };
228 });
229 Ok(())
230 }
231
232 pub fn append_listview_array(
237 &mut self,
238 array: ArrayView<'_, ListView>,
239 ctx: &mut ExecutionCtx,
240 ) -> VortexResult<()> {
241 if array.is_empty() {
242 return Ok(());
243 }
244
245 self.nulls
246 .append_validity_mask(&array.validity()?.execute_mask(array.len(), ctx)?);
247
248 let elements = array.elements();
250 let offsets = array.offsets().clone().execute::<PrimitiveArray>(ctx)?;
251 let sizes = array.sizes().clone().execute::<PrimitiveArray>(ctx)?;
252
253 match_each_integer_ptype!(offsets.ptype(), |OffsetType| {
254 match_each_integer_ptype!(sizes.ptype(), |SizeType| {
255 extend_from_listview(
256 self,
257 elements,
258 offsets.as_slice::<OffsetType>(),
259 sizes.as_slice::<SizeType>(),
260 ctx,
261 )?
262 })
263 });
264 Ok(())
265 }
266}
267
268fn extend_from_listview<O, OffsetType, SizeType>(
271 builder: &mut ListBuilder<O>,
272 new_elements: &ArrayRef,
273 new_offsets: &[OffsetType],
274 new_sizes: &[SizeType],
275 ctx: &mut ExecutionCtx,
276) -> VortexResult<()>
277where
278 O: OffsetBuilderPType,
279 OffsetType: IntegerPType,
280 SizeType: IntegerPType,
281{
282 let num_lists = new_offsets.len();
283 debug_assert_eq!(num_lists, new_sizes.len());
284
285 let total_elements: usize = new_sizes.iter().map(|size| size.as_()).sum();
286 builder.elements_builder.reserve_exact(total_elements);
287
288 let mut curr_offset = builder.elements_builder.len();
289 builder.offsets_builder.reserve_exact(num_lists);
290 let mut offsets_range = builder.offsets_builder.uninit_range(num_lists);
291
292 for i in 0..new_offsets.len() {
295 let offset: usize = new_offsets[i].as_();
296 let size: usize = new_sizes[i].as_();
297
298 if size > 0 {
299 let list_elements = new_elements
300 .slice(offset..offset + size)
301 .vortex_expect("list builder slice");
302 list_elements.append_to_builder(builder.elements_builder.as_mut(), ctx)?;
303 curr_offset += size;
304 }
305
306 let new_offset = O::from_usize(curr_offset).vortex_expect("Failed to convert offset");
307
308 offsets_range.set_value(i, new_offset);
309 }
310
311 unsafe { offsets_range.finish() };
314 Ok(())
315}
316
317impl<O: OffsetBuilderPType> ArrayBuilder for ListBuilder<O> {
318 fn as_any(&self) -> &dyn Any {
319 self
320 }
321
322 fn as_any_mut(&mut self) -> &mut dyn Any {
323 self
324 }
325
326 fn dtype(&self) -> &DType {
327 &self.dtype
328 }
329
330 fn len(&self) -> usize {
331 self.nulls.len()
332 }
333
334 fn append_zeros(&mut self, n: usize) {
335 let curr_len = self.elements_builder.len();
336 for _ in 0..n {
337 self.offsets_builder.append_value(
338 O::from_usize(curr_len).vortex_expect("Failed to convert from usize to <O>"),
339 )
340 }
341 self.nulls.append_n_non_nulls(n);
342 }
343
344 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
345 let curr_len = self.elements_builder.len();
346 for _ in 0..n {
347 self.offsets_builder.append_value(
350 O::from_usize(curr_len).vortex_expect("Failed to convert from usize to <O>"),
351 )
352 }
353 self.nulls.append_n_nulls(n);
354 }
355
356 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
357 vortex_ensure!(
358 scalar.dtype() == self.dtype(),
359 "ListBuilder expected scalar with dtype {}, got {}",
360 self.dtype(),
361 scalar.dtype()
362 );
363
364 self.append_value(scalar.as_list())
365 }
366
367 fn reserve_exact(&mut self, additional: usize) {
368 self.elements_builder.reserve_exact(additional);
369 self.offsets_builder.reserve_exact(additional);
370 self.nulls.reserve_exact(additional);
371 }
372
373 unsafe fn set_validity_unchecked(&mut self, validity: Mask) {
374 self.nulls = LazyBitBufferBuilder::from_validity_mask(validity);
375 }
376
377 fn finish(&mut self) -> ArrayRef {
378 self.finish_into_list().into_array()
379 }
380
381 fn finish_into_canonical(&mut self, ctx: &mut ExecutionCtx) -> Canonical {
382 let listview = self
383 .finish()
384 .execute::<ListViewArray>(ctx)
385 .vortex_expect("list builder should canonicalize to listview");
386 Canonical::List(listview)
387 }
388}
389
390#[cfg(test)]
391mod tests {
392 use std::sync::Arc;
393
394 use Nullability::NonNullable;
395 use Nullability::Nullable;
396 use vortex_buffer::buffer;
397 use vortex_error::VortexExpect;
398 use vortex_error::VortexResult;
399
400 use crate::IntoArray;
401 use crate::array_session;
402 use crate::arrays::ChunkedArray;
403 use crate::arrays::ListViewArray;
404 use crate::arrays::PrimitiveArray;
405 use crate::arrays::list::ListArraySlotsExt;
406 use crate::arrays::listview::ListViewArrayExt;
407 use crate::arrays::listview::ListViewArraySlotsExt;
408 use crate::assert_arrays_eq;
409 use crate::builders::ArrayBuilder;
410 use crate::builders::ListViewBuilder;
411 use crate::builders::builder_with_capacity;
412 use crate::builders::list::ListArray;
413 use crate::builders::list::ListBuilder;
414 use crate::dtype::DType;
415 use crate::dtype::Nullability;
416 use crate::dtype::OffsetBuilderPType;
417 use crate::dtype::PType::I32;
418 use crate::executor::VortexSessionExecute;
419 use crate::scalar::Scalar;
420 use crate::validity::Validity;
421
422 #[test]
423 fn test_empty() {
424 let mut builder =
425 ListBuilder::<u32>::with_capacity(Arc::new(I32.into()), NonNullable, 0, 0);
426
427 let list = builder.finish();
428 assert_eq!(list.len(), 0);
429 }
430
431 #[test]
432 fn test_values() {
433 let dtype: Arc<DType> = Arc::new(I32.into());
434 let mut builder = ListBuilder::<u32>::with_capacity(Arc::clone(&dtype), NonNullable, 0, 0);
435
436 builder
437 .append_value(
438 Scalar::list(
439 Arc::clone(&dtype),
440 vec![1i32.into(), 2i32.into(), 3i32.into()],
441 NonNullable,
442 )
443 .as_list(),
444 )
445 .unwrap();
446
447 builder
448 .append_value(
449 Scalar::list(
450 dtype,
451 vec![4i32.into(), 5i32.into(), 6i32.into()],
452 NonNullable,
453 )
454 .as_list(),
455 )
456 .unwrap();
457
458 let list = builder.finish();
459 assert_eq!(list.len(), 2);
460
461 let mut ctx = array_session().create_execution_ctx();
462 let list_array = list.execute::<ListViewArray>(&mut ctx).unwrap();
463
464 assert_eq!(list_array.list_elements_at(0).unwrap().len(), 3);
465 assert_eq!(list_array.list_elements_at(1).unwrap().len(), 3);
466 }
467
468 #[test]
469 fn test_append_empty_list() {
470 let dtype: Arc<DType> = Arc::new(I32.into());
471 let mut builder = ListBuilder::<u32>::with_capacity(Arc::clone(&dtype), NonNullable, 0, 0);
472
473 assert!(
474 builder
475 .append_value(Scalar::list_empty(dtype, NonNullable).as_list())
476 .is_ok()
477 )
478 }
479
480 #[test]
481 fn test_nullable_values() {
482 let dtype: Arc<DType> = Arc::new(I32.into());
483 let mut builder = ListBuilder::<u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
484
485 builder
486 .append_value(
487 Scalar::list(
488 Arc::clone(&dtype),
489 vec![1i32.into(), 2i32.into(), 3i32.into()],
490 NonNullable,
491 )
492 .as_list(),
493 )
494 .unwrap();
495
496 builder
497 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
498 .unwrap();
499
500 builder
501 .append_value(
502 Scalar::list(
503 dtype,
504 vec![4i32.into(), 5i32.into(), 6i32.into()],
505 NonNullable,
506 )
507 .as_list(),
508 )
509 .unwrap();
510
511 let list = builder.finish();
512 assert_eq!(list.len(), 3);
513
514 let mut ctx = array_session().create_execution_ctx();
515 let list_array = list.execute::<ListViewArray>(&mut ctx).unwrap();
516
517 assert_eq!(list_array.list_elements_at(0).unwrap().len(), 3);
518 assert_eq!(list_array.list_elements_at(1).unwrap().len(), 0);
519 assert_eq!(list_array.list_elements_at(2).unwrap().len(), 3);
520 }
521
522 fn test_extend_builder_gen<O: OffsetBuilderPType>() {
523 let list = ListArray::from_iter_opt_slow::<O, _, _>(
524 [Some(vec![0, 1, 2]), None, Some(vec![4, 5])],
525 Arc::new(I32.into()),
526 )
527 .unwrap()
528 .into_array();
529 assert_eq!(list.len(), 3);
530
531 let mut ctx = array_session().create_execution_ctx();
532
533 let mut builder = ListBuilder::<O>::with_capacity(Arc::new(I32.into()), Nullable, 18, 9);
534 list.append_to_builder(&mut builder, &mut ctx).unwrap();
535 list.append_to_builder(&mut builder, &mut ctx).unwrap();
536 list.slice(0..0)
537 .unwrap()
538 .append_to_builder(&mut builder, &mut ctx)
539 .unwrap();
540 list.slice(1..3)
541 .unwrap()
542 .append_to_builder(&mut builder, &mut ctx)
543 .unwrap();
544
545 let expected = ListArray::from_iter_opt_slow::<O, _, _>(
546 [
547 Some(vec![0, 1, 2]),
548 None,
549 Some(vec![4, 5]),
550 Some(vec![0, 1, 2]),
551 None,
552 Some(vec![4, 5]),
553 None,
554 Some(vec![4, 5]),
555 ],
556 Arc::new(DType::Primitive(I32, NonNullable)),
557 )
558 .unwrap()
559 .into_array()
560 .execute::<ListViewArray>(&mut ctx)
561 .unwrap();
562
563 let actual = builder.finish_into_canonical(&mut ctx).into_listview();
564
565 assert_arrays_eq!(actual.elements(), expected.elements(), &mut ctx);
566
567 assert_arrays_eq!(actual.offsets(), expected.offsets(), &mut ctx);
568
569 assert!(
570 actual
571 .validity()
572 .vortex_expect("list validity should be derivable")
573 .mask_eq(
574 &expected
575 .validity()
576 .vortex_expect("list validity should be derivable"),
577 actual.len(),
578 &mut ctx,
579 )
580 .unwrap(),
581 );
582 }
583
584 #[test]
589 fn test_append_to_builder_any_list_builder() -> VortexResult<()> {
590 let mut ctx = array_session().create_execution_ctx();
591
592 let list = ListArray::from_iter_opt_slow::<u64, _, _>(
593 [Some(vec![0, 1, 2]), None, Some(vec![4, 5])],
594 Arc::new(I32.into()),
595 )?
596 .into_array();
597 let listview = list
598 .clone()
599 .execute::<ListViewArray>(&mut ctx)?
600 .into_array();
601 let elem_dtype = || Arc::new(I32.into());
602
603 let mut listview_builder = builder_with_capacity(list.dtype(), list.len());
606 list.append_to_builder(listview_builder.as_mut(), &mut ctx)?;
607 assert_arrays_eq!(listview_builder.finish(), list, &mut ctx);
608
609 let mut lv_u64_u32 =
612 ListViewBuilder::<u64, u32>::with_capacity(elem_dtype(), Nullable, 8, 4);
613 list.append_to_builder(&mut lv_u64_u32, &mut ctx)?;
614 assert_arrays_eq!(lv_u64_u32.finish(), list, &mut ctx);
615
616 let mut lv_i64_i32 =
617 ListViewBuilder::<i64, i32>::with_capacity(elem_dtype(), Nullable, 8, 4);
618 list.append_to_builder(&mut lv_i64_i32, &mut ctx)?;
619 assert_arrays_eq!(lv_i64_i32.finish(), list, &mut ctx);
620
621 let mut lv_u32_u32 =
622 ListViewBuilder::<u32, u32>::with_capacity(elem_dtype(), Nullable, 8, 4);
623 listview.append_to_builder(&mut lv_u32_u32, &mut ctx)?;
624 assert_arrays_eq!(lv_u32_u32.finish(), list, &mut ctx);
625
626 let mut list_builder = ListBuilder::<u32>::with_capacity(elem_dtype(), Nullable, 8, 4);
629 list.append_to_builder(&mut list_builder, &mut ctx)?;
630 assert_arrays_eq!(list_builder.finish(), list, &mut ctx);
631
632 let mut list_builder_i32 = ListBuilder::<i32>::with_capacity(elem_dtype(), Nullable, 8, 4);
633 listview.append_to_builder(&mut list_builder_i32, &mut ctx)?;
634 assert_arrays_eq!(list_builder_i32.finish(), list, &mut ctx);
635
636 Ok(())
637 }
638
639 #[test]
640 fn test_append_list_arrays_grow_builder() -> VortexResult<()> {
641 let mut ctx = array_session().create_execution_ctx();
642 let dtype: Arc<DType> = Arc::new(I32.into());
643
644 let lists: Vec<Option<Vec<i32>>> =
647 (0..100).map(|i| (i % 10 != 0).then(|| vec![i])).collect();
648 let source = ListArray::from_iter_opt_slow::<u32, _, _>(lists.clone(), Arc::clone(&dtype))?;
649 let expected = ListArray::from_iter_opt_slow::<u32, _, _>(
650 lists.iter().cloned().chain(lists.iter().cloned()),
651 Arc::clone(&dtype),
652 )?;
653
654 let mut builder = ListBuilder::<u32>::with_capacity(Arc::clone(&dtype), Nullable, 0, 0);
656 builder.append_list_array(source.as_view(), &mut ctx)?;
657 builder.append_list_array(source.as_view(), &mut ctx)?;
658 assert_arrays_eq!(builder.finish(), expected, &mut ctx);
659
660 let source_listview = source.into_array().execute::<ListViewArray>(&mut ctx)?;
661 let mut builder = ListBuilder::<u32>::with_capacity(dtype, Nullable, 0, 0);
662 builder.append_listview_array(source_listview.as_view(), &mut ctx)?;
663 builder.append_listview_array(source_listview.as_view(), &mut ctx)?;
664 assert_arrays_eq!(builder.finish(), expected, &mut ctx);
665
666 Ok(())
667 }
668
669 #[test]
670 fn test_extend_builder() {
671 test_extend_builder_gen::<i32>();
672 test_extend_builder_gen::<i64>();
673
674 test_extend_builder_gen::<u32>();
675 test_extend_builder_gen::<u64>();
676 }
677
678 #[test]
679 pub fn test_array_with_gap() {
680 let one_trailing_unused_element = ListArray::try_new(
681 buffer![1, 2, 3, 4].into_array(),
682 buffer![0, 3].into_array(),
683 Validity::NonNullable,
684 )
685 .unwrap();
686
687 let second_array = ListArray::try_new(
688 buffer![5, 6].into_array(),
689 buffer![0, 2].into_array(),
690 Validity::NonNullable,
691 )
692 .unwrap();
693
694 let chunked_list = ChunkedArray::try_new(
695 vec![
696 one_trailing_unused_element.clone().into_array(),
697 second_array.clone().into_array(),
698 ],
699 DType::List(Arc::new(DType::Primitive(I32, NonNullable)), NonNullable),
700 );
701
702 let mut ctx = array_session().create_execution_ctx();
703 let canon_values = chunked_list
704 .unwrap()
705 .as_array()
706 .clone()
707 .execute::<ListViewArray>(&mut ctx)
708 .unwrap();
709
710 assert_eq!(
711 one_trailing_unused_element
712 .execute_scalar(0, &mut array_session().create_execution_ctx())
713 .unwrap(),
714 canon_values
715 .execute_scalar(0, &mut array_session().create_execution_ctx())
716 .unwrap()
717 );
718 assert_eq!(
719 second_array
720 .execute_scalar(0, &mut array_session().create_execution_ctx())
721 .unwrap(),
722 canon_values
723 .execute_scalar(1, &mut array_session().create_execution_ctx())
724 .unwrap()
725 );
726 }
727
728 #[test]
729 fn test_append_scalar() {
730 let dtype: Arc<DType> = Arc::new(I32.into());
731 let mut builder = ListBuilder::<u64>::with_capacity(Arc::clone(&dtype), Nullable, 20, 10);
732
733 let list_scalar1 =
735 Scalar::list(Arc::clone(&dtype), vec![1i32.into(), 2i32.into()], Nullable);
736 builder.append_scalar(&list_scalar1).unwrap();
737
738 let list_scalar2 = Scalar::list(
740 Arc::clone(&dtype),
741 vec![3i32.into(), 4i32.into(), 5i32.into()],
742 Nullable,
743 );
744 builder.append_scalar(&list_scalar2).unwrap();
745
746 let null_scalar = Scalar::null(DType::List(Arc::clone(&dtype), Nullable));
748 builder.append_scalar(&null_scalar).unwrap();
749
750 let array = builder.finish_into_list();
751 assert_eq!(array.len(), 3);
752
753 let mut ctx = array_session().create_execution_ctx();
754
755 let scalar0 = array.execute_scalar(0, &mut ctx).unwrap();
758 let list0 = scalar0.as_list();
759 assert_eq!(list0.len(), 2);
760 if let Some(list0_items) = list0.elements() {
761 assert_eq!(list0_items[0].as_primitive().typed_value::<i32>(), Some(1));
762 assert_eq!(list0_items[1].as_primitive().typed_value::<i32>(), Some(2));
763 }
764
765 let scalar1 = array.execute_scalar(1, &mut ctx).unwrap();
766 let list1 = scalar1.as_list();
767 assert_eq!(list1.len(), 3);
768 if let Some(list1_items) = list1.elements() {
769 assert_eq!(list1_items[0].as_primitive().typed_value::<i32>(), Some(3));
770 assert_eq!(list1_items[1].as_primitive().typed_value::<i32>(), Some(4));
771 assert_eq!(list1_items[2].as_primitive().typed_value::<i32>(), Some(5));
772 }
773
774 let scalar2 = array.execute_scalar(2, &mut ctx).unwrap();
775 let list2 = scalar2.as_list();
776 assert!(list2.is_null()); assert!(
780 array
781 .validity()
782 .vortex_expect("list validity should be derivable")
783 .execute_is_valid(0, &mut ctx)
784 .unwrap()
785 );
786 assert!(
787 array
788 .validity()
789 .vortex_expect("list validity should be derivable")
790 .execute_is_valid(1, &mut ctx)
791 .unwrap()
792 );
793 assert!(
794 !array
795 .validity()
796 .vortex_expect("list validity should be derivable")
797 .execute_is_valid(2, &mut ctx)
798 .unwrap()
799 );
800
801 let mut builder = ListBuilder::<u64>::with_capacity(dtype, NonNullable, 20, 10);
803 let wrong_scalar = Scalar::from(42i32);
804 assert!(builder.append_scalar(&wrong_scalar).is_err());
805 }
806
807 #[test]
808 fn test_append_array_as_list() {
809 let dtype: Arc<DType> = Arc::new(I32.into());
810 let mut ctx = array_session().create_execution_ctx();
811 let mut builder =
812 ListBuilder::<u32>::with_capacity(Arc::clone(&dtype), NonNullable, 20, 10);
813
814 let arr1 = buffer![1i32, 2, 3].into_array();
816 builder.append_array_as_list(&arr1, &mut ctx).unwrap();
817
818 builder
820 .append_value(
821 Scalar::list(
822 Arc::clone(&dtype),
823 vec![10i32.into(), 11i32.into()],
824 NonNullable,
825 )
826 .as_list(),
827 )
828 .unwrap();
829
830 let arr2 = buffer![4i32, 5].into_array();
832 builder.append_array_as_list(&arr2, &mut ctx).unwrap();
833
834 let arr3 = buffer![0i32; 0].into_array();
836 builder.append_array_as_list(&arr3, &mut ctx).unwrap();
837
838 builder
840 .append_value(Scalar::list_empty(Arc::clone(&dtype), NonNullable).as_list())
841 .unwrap();
842
843 let list = builder.finish_into_list();
844 assert_eq!(list.len(), 5);
845
846 assert_arrays_eq!(
848 list.elements(),
849 PrimitiveArray::from_iter([1i32, 2, 3, 10, 11, 4, 5]),
850 &mut ctx
851 );
852
853 assert_arrays_eq!(
855 list.offsets(),
856 PrimitiveArray::from_iter([0u32, 3, 5, 7, 7, 7]),
857 &mut ctx
858 );
859
860 let mut builder = ListBuilder::<u32>::with_capacity(dtype, NonNullable, 20, 10);
862 let wrong_dtype_arr = buffer![1i64, 2, 3].into_array();
863 assert!(
864 builder
865 .append_array_as_list(&wrong_dtype_arr, &mut ctx)
866 .is_err()
867 );
868 }
869}