1use vortex_error::VortexExpect;
5use vortex_error::VortexResult;
6
7use crate::ArrayRef;
8use crate::Canonical;
9use crate::ExecutionCtx;
10use crate::IntoArray;
11use crate::arrays::ExtensionArray;
12use crate::arrays::FixedSizeListArray;
13use crate::arrays::ListArray;
14use crate::arrays::ListViewArray;
15use crate::arrays::PrimitiveArray;
16use crate::arrays::StructArray;
17use crate::arrays::extension::ExtensionArrayExt;
18use crate::arrays::fixed_size_list::FixedSizeListArrayExt;
19use crate::arrays::fixed_size_list::FixedSizeListArraySlotsExt;
20use crate::arrays::list::ListArrayExt;
21use crate::arrays::list::ListArraySlotsExt;
22use crate::arrays::listview::ListViewArrayExt;
23use crate::arrays::listview::ListViewArraySlotsExt;
24use crate::arrays::listview::ListViewRebuildMode;
25use crate::arrays::struct_::StructArrayExt;
26use crate::builders::PrimitiveBuilder;
27use crate::dtype::IntegerPType;
28use crate::dtype::Nullability;
29use crate::match_each_integer_ptype;
30
31pub fn list_view_from_list(list: ListArray, ctx: &mut ExecutionCtx) -> VortexResult<ListViewArray> {
36 if list.is_empty() {
39 return Ok(Canonical::empty(list.dtype()).into_listview());
40 }
41
42 let list = list.reset_offsets(false, ctx)?;
46 let list_offsets = list.offsets().clone();
47
48 let sizes = match_each_integer_ptype!(list_offsets.dtype().as_ptype(), |O| {
51 build_sizes_from_offsets::<O>(&list, ctx)?
52 });
53
54 debug_assert_eq!(list_offsets.len(), list.len() + 1);
56 let adjusted_offsets = list_offsets.slice(0..list.len())?;
57
58 Ok(unsafe {
62 ListViewArray::new_unchecked(
63 list.elements().clone(),
64 adjusted_offsets,
65 sizes,
66 list.validity()?,
67 )
68 .with_zero_copy_to_list(true)
69 })
70}
71
72fn build_sizes_from_offsets<O: IntegerPType>(
74 list: &ListArray,
75 ctx: &mut ExecutionCtx,
76) -> VortexResult<ArrayRef> {
77 let len = list.len();
78 let mut sizes_builder = PrimitiveBuilder::<O>::with_capacity(Nullability::NonNullable, len);
79
80 let mut sizes_range = sizes_builder.uninit_range(len);
82
83 let offsets = list.offsets().clone().execute::<PrimitiveArray>(ctx)?;
84 let offsets_slice = offsets.as_slice::<O>();
85 debug_assert_eq!(len + 1, offsets_slice.len());
86 debug_assert!(offsets_slice.is_sorted());
87
88 for i in 0..len {
90 let size = offsets_slice[i + 1] - offsets_slice[i];
91 sizes_range.set_value(i, size);
92 }
93
94 unsafe {
96 sizes_range.finish();
97 }
98
99 Ok(sizes_builder.finish_into_primitive().into_array())
100}
101
102pub fn list_from_list_view(
112 list_view: ListViewArray,
113 ctx: &mut ExecutionCtx,
114) -> VortexResult<ListArray> {
115 let zctl_array = list_view.rebuild(ListViewRebuildMode::MakeExact, ctx)?;
117 debug_assert!(zctl_array.is_zero_copy_to_list());
118
119 let list_offsets = match_each_integer_ptype!(zctl_array.offsets().dtype().as_ptype(), |O| {
120 unsafe { build_list_offsets_from_list_view::<O>(&zctl_array, ctx) }
123 });
124
125 Ok(unsafe {
129 ListArray::new_unchecked(
130 zctl_array.elements().clone(),
131 list_offsets,
132 zctl_array.validity()?,
133 )
134 })
135}
136
137unsafe fn build_list_offsets_from_list_view<O: IntegerPType>(
147 list_view: &ListViewArray,
148 ctx: &mut ExecutionCtx,
149) -> ArrayRef {
150 let len = list_view.len();
151 let mut offsets_builder =
152 PrimitiveBuilder::<O>::with_capacity(Nullability::NonNullable, len + 1);
153
154 let mut offsets_range = offsets_builder.uninit_range(len + 1);
156
157 let offsets = list_view
158 .offsets()
159 .clone()
160 .execute::<PrimitiveArray>(ctx)
161 .vortex_expect("list view offsets must be primitive after rebuild");
162 let offsets_slice = offsets.as_slice::<O>();
163 debug_assert!(offsets_slice.is_sorted());
164
165 offsets_range.copy_from_slice(0, offsets_slice);
167
168 let final_offset = if len != 0 {
170 let last_offset = offsets_slice[len - 1];
171
172 let last_size = list_view.size_at(len - 1);
173 let last_size =
174 O::from_usize(last_size).vortex_expect("size somehow did not fit into offsets");
175
176 last_offset + last_size
177 } else {
178 O::zero()
179 };
180
181 offsets_range.set_value(len, final_offset);
182
183 unsafe {
185 offsets_range.finish();
186 }
187
188 offsets_builder.finish_into_primitive().into_array()
189}
190
191pub fn recursive_list_from_list_view(
195 array: ArrayRef,
196 ctx: &mut ExecutionCtx,
197) -> VortexResult<ArrayRef> {
198 if !array.dtype().is_nested() {
199 return Ok(array);
200 }
201
202 let canonical = array.execute::<Canonical>(ctx)?;
203
204 Ok(match canonical {
205 Canonical::List(listview) => {
206 let converted_elements =
207 recursive_list_from_list_view(listview.elements().clone(), ctx)?;
208 debug_assert_eq!(converted_elements.len(), listview.elements().len());
209
210 let listview_with_converted_elements =
212 if !ArrayRef::ptr_eq(&converted_elements, listview.elements()) {
213 unsafe {
216 ListViewArray::new_unchecked(
217 converted_elements,
218 listview.offsets().clone(),
219 listview.sizes().clone(),
220 listview.validity()?,
221 )
222 .with_zero_copy_to_list(listview.is_zero_copy_to_list())
223 }
224 } else {
225 listview
226 };
227
228 let list_array = list_from_list_view(listview_with_converted_elements, ctx)?;
230 list_array.into_array()
231 }
232 Canonical::FixedSizeList(fixed_size_list) => {
233 let converted_elements =
234 recursive_list_from_list_view(fixed_size_list.elements().clone(), ctx)?;
235
236 if !ArrayRef::ptr_eq(&converted_elements, fixed_size_list.elements()) {
238 FixedSizeListArray::try_new(
239 converted_elements,
240 fixed_size_list.list_size(),
241 fixed_size_list.validity()?,
242 fixed_size_list.len(),
243 )
244 .vortex_expect(
245 "FixedSizeListArray reconstruction should not fail with valid components",
246 )
247 .into_array()
248 } else {
249 fixed_size_list.into_array()
250 }
251 }
252 Canonical::Struct(struct_array) => {
253 let fields = struct_array.unmasked_fields();
254 let mut converted_fields = Vec::with_capacity(fields.len());
255 let mut any_changed = false;
256
257 for field in fields.iter() {
258 let converted_field = recursive_list_from_list_view(field.clone(), ctx)?;
259 any_changed |= !ArrayRef::ptr_eq(&converted_field, field);
261 converted_fields.push(converted_field);
262 }
263
264 if any_changed {
265 StructArray::try_new(
266 struct_array.names().clone(),
267 converted_fields,
268 struct_array.len(),
269 struct_array.validity()?,
270 )
271 .vortex_expect("StructArray reconstruction should not fail with valid components")
272 .into_array()
273 } else {
274 struct_array.into_array()
275 }
276 }
277 Canonical::Extension(ext_array) => {
278 let converted_storage =
279 recursive_list_from_list_view(ext_array.storage_array().clone(), ctx)?;
280
281 if !ArrayRef::ptr_eq(&converted_storage, ext_array.storage_array()) {
283 ExtensionArray::new(ext_array.ext_dtype().clone(), converted_storage).into_array()
284 } else {
285 ext_array.into_array()
286 }
287 }
288 _ => unreachable!(),
289 })
290}
291
292#[cfg(test)]
293mod tests {
294
295 use vortex_buffer::buffer;
296 use vortex_error::VortexExpect;
297 use vortex_error::VortexResult;
298
299 use super::super::tests::common::SESSION;
300 use super::super::tests::common::create_basic_listview;
301 use super::super::tests::common::create_empty_lists_listview;
302 use super::super::tests::common::create_nullable_listview;
303 use super::super::tests::common::create_overlapping_listview;
304 use super::recursive_list_from_list_view;
305 use crate::ArrayEq;
306 use crate::ArrayRef;
307 use crate::EqMode;
308 use crate::IntoArray;
309 use crate::VortexSessionExecute;
310 use crate::arrays::BoolArray;
311 use crate::arrays::FixedSizeListArray;
312 use crate::arrays::ListArray;
313 use crate::arrays::ListViewArray;
314 use crate::arrays::PrimitiveArray;
315 use crate::arrays::StructArray;
316 use crate::arrays::VarBinViewArray;
317 use crate::arrays::list::ListArrayExt;
318 use crate::arrays::list::ListArraySlotsExt;
319 use crate::arrays::listview::ListViewArraySlotsExt;
320 use crate::arrays::listview::list_from_list_view;
321 use crate::arrays::listview::list_view_from_list;
322 use crate::assert_arrays_eq;
323 use crate::dtype::FieldNames;
324 use crate::validity::Validity;
325
326 #[test]
327 fn test_list_to_listview_basic() -> VortexResult<()> {
328 let elements = buffer![0i32, 1, 2, 3, 4, 5, 6, 7, 8, 9].into_array();
330 let offsets = buffer![0u32, 3, 5, 7, 10].into_array();
331 let list_array = ListArray::try_new(elements.clone(), offsets, Validity::NonNullable)?;
332
333 let mut ctx = SESSION.create_execution_ctx();
334 let list_view = list_view_from_list(list_array.clone(), &mut ctx)?;
335
336 assert_eq!(list_view.len(), 4);
338 assert_arrays_eq!(elements, list_view.elements().clone(), &mut ctx);
339
340 let expected_offsets = buffer![0u32, 3, 5, 7].into_array();
342 assert_arrays_eq!(expected_offsets, list_view.offsets().clone(), &mut ctx);
343
344 let expected_sizes = buffer![3u32, 2, 2, 3].into_array();
346 assert_arrays_eq!(expected_sizes, list_view.sizes().clone(), &mut ctx);
347
348 assert_arrays_eq!(list_array, list_view, &mut ctx);
350 Ok(())
351 }
352
353 #[test]
354 fn test_listview_to_list_zero_copy() -> VortexResult<()> {
355 let mut ctx = SESSION.create_execution_ctx();
356 let list_view = create_basic_listview();
357 let list_array =
358 list_from_list_view(list_view.clone(), &mut SESSION.create_execution_ctx())?;
359
360 assert_arrays_eq!(
362 list_view.elements().clone(),
363 list_array.elements().clone(),
364 &mut ctx
365 );
366
367 let list_array_offsets_without_last = list_array.offsets().slice(0..list_view.len())?;
370 assert_arrays_eq!(
371 list_view.offsets().clone(),
372 list_array_offsets_without_last,
373 &mut ctx
374 );
375
376 assert_arrays_eq!(list_view, list_array, &mut ctx);
378 Ok(())
379 }
380
381 #[test]
382 fn test_empty_array_conversions() -> VortexResult<()> {
383 let empty_elements = PrimitiveArray::from_iter::<[i32; 0]>([]).into_array();
385 let empty_offsets = buffer![0u32].into_array();
386 let empty_list = ListArray::try_new(empty_elements, empty_offsets, Validity::NonNullable)?;
387
388 let mut ctx = SESSION.create_execution_ctx();
391 let empty_list_view = list_view_from_list(empty_list.clone(), &mut ctx)?;
392 assert_eq!(empty_list_view.len(), 0);
393
394 let converted_back = list_from_list_view(empty_list_view, &mut ctx)?;
396 assert_eq!(converted_back.len(), 0);
397 assert_eq!(empty_list.len(), converted_back.len());
400 Ok(())
401 }
402
403 #[test]
404 fn test_nullable_conversions() -> VortexResult<()> {
405 let elements = buffer![10i32, 20, 30, 40, 50].into_array();
407 let offsets = buffer![0u32, 2, 4, 5].into_array();
408 let validity = Validity::Array(BoolArray::from_iter(vec![true, false, true]).into_array());
409 let nullable_list = ListArray::try_new(elements, offsets, validity.clone())?;
410
411 let mut ctx = SESSION.create_execution_ctx();
412 let nullable_list_view = list_view_from_list(nullable_list.clone(), &mut ctx)?;
413
414 assert!(
416 nullable_list_view
417 .validity()
418 .vortex_expect("listview validity should be derivable")
419 .array_eq(&validity, EqMode::Ptr)
420 );
421 assert_eq!(nullable_list_view.len(), 3);
422
423 let converted_back = list_from_list_view(nullable_list_view, &mut ctx)?;
425 assert_arrays_eq!(nullable_list, converted_back, &mut ctx);
426 Ok(())
427 }
428
429 #[test]
430 fn test_non_zero_copy_listview_to_list() -> VortexResult<()> {
431 let mut ctx = SESSION.create_execution_ctx();
432 let list_view = create_overlapping_listview();
434 let list_array =
435 list_from_list_view(list_view.clone(), &mut SESSION.create_execution_ctx())?;
436
437 for i in 0..list_array.len() {
439 let start = list_array.offset_at(i)?;
440 let end = list_array.offset_at(i + 1)?;
441 assert!(end >= start, "Offsets should be monotonic after conversion");
442 }
443
444 assert_arrays_eq!(list_view, list_array, &mut ctx);
446 Ok(())
447 }
448
449 #[test]
450 fn test_empty_sublists() -> VortexResult<()> {
451 let mut ctx = SESSION.create_execution_ctx();
452 let empty_lists_view = create_empty_lists_listview();
453
454 let list_array = list_from_list_view(empty_lists_view.clone(), &mut ctx)?;
456 assert_eq!(list_array.len(), 4);
457
458 for i in 0..list_array.len() {
460 assert_eq!(list_array.list_elements_at(i)?.len(), 0);
461 }
462
463 let converted_back = list_view_from_list(list_array, &mut ctx)?;
465 assert_arrays_eq!(empty_lists_view, converted_back, &mut ctx);
466 Ok(())
467 }
468
469 #[test]
470 fn test_different_offset_types() -> VortexResult<()> {
471 let elements = buffer![1i32, 2, 3, 4, 5].into_array();
473 let i32_offsets = buffer![0i32, 2, 5].into_array();
474 let list_i32 =
475 ListArray::try_new(elements.clone(), i32_offsets.clone(), Validity::NonNullable)?;
476
477 let mut ctx = SESSION.create_execution_ctx();
478 let list_view_i32 = list_view_from_list(list_i32.clone(), &mut ctx)?;
479 assert_eq!(list_view_i32.offsets().dtype(), i32_offsets.dtype());
480 assert_eq!(list_view_i32.sizes().dtype(), i32_offsets.dtype());
481
482 let i64_offsets = buffer![0i64, 2, 5].into_array();
484 let list_i64 = ListArray::try_new(elements, i64_offsets.clone(), Validity::NonNullable)?;
485
486 let list_view_i64 = list_view_from_list(list_i64.clone(), &mut ctx)?;
487 assert_eq!(list_view_i64.offsets().dtype(), i64_offsets.dtype());
488 assert_eq!(list_view_i64.sizes().dtype(), i64_offsets.dtype());
489
490 assert_arrays_eq!(list_i32, list_view_i32, &mut ctx);
492 assert_arrays_eq!(list_i64, list_view_i64, &mut ctx);
493 Ok(())
494 }
495
496 #[test]
497 fn test_round_trip_conversions() -> VortexResult<()> {
498 let mut ctx = SESSION.create_execution_ctx();
499
500 let original = create_basic_listview();
502 let to_list = list_from_list_view(original.clone(), &mut ctx)?;
503 let back_to_view = list_view_from_list(to_list, &mut ctx)?;
504 assert_arrays_eq!(original, back_to_view, &mut ctx);
505
506 let nullable = create_nullable_listview();
508 let nullable_to_list = list_from_list_view(nullable.clone(), &mut ctx)?;
509 let nullable_back = list_view_from_list(nullable_to_list, &mut ctx)?;
510 assert_arrays_eq!(nullable, nullable_back, &mut ctx);
511
512 let overlapping = create_overlapping_listview();
514
515 let overlapping_to_list = list_from_list_view(overlapping.clone(), &mut ctx)?;
516 let overlapping_back = list_view_from_list(overlapping_to_list, &mut ctx)?;
517 assert_arrays_eq!(overlapping, overlapping_back, &mut ctx);
518 Ok(())
519 }
520
521 #[test]
522 fn test_single_element_lists() -> VortexResult<()> {
523 let elements = buffer![100i32, 200, 300].into_array();
525 let offsets = buffer![0u32, 1, 2, 3].into_array();
526 let single_elem_list = ListArray::try_new(elements, offsets, Validity::NonNullable)?;
527
528 let mut ctx = SESSION.create_execution_ctx();
529 let list_view = list_view_from_list(single_elem_list.clone(), &mut ctx)?;
530 assert_eq!(list_view.len(), 3);
531
532 let expected_sizes = buffer![1u32, 1, 1].into_array();
534 assert_arrays_eq!(expected_sizes, list_view.sizes().clone(), &mut ctx);
535
536 let converted_back = list_from_list_view(list_view, &mut ctx)?;
538 assert_arrays_eq!(single_elem_list, converted_back, &mut ctx);
539 Ok(())
540 }
541
542 #[test]
543 fn test_mixed_empty_and_non_empty_lists() -> VortexResult<()> {
544 let elements = buffer![1i32, 2, 3, 4, 5, 6].into_array();
546 let offsets = buffer![0u32, 2, 2, 3, 3, 6].into_array();
547 let mixed_list = ListArray::try_new(elements, offsets, Validity::NonNullable)?;
548
549 let mut ctx = SESSION.create_execution_ctx();
550 let list_view = list_view_from_list(mixed_list.clone(), &mut ctx)?;
551 assert_eq!(list_view.len(), 5);
552
553 let expected_sizes = buffer![2u32, 0, 1, 0, 3].into_array();
555 assert_arrays_eq!(expected_sizes, list_view.sizes().clone(), &mut ctx);
556
557 let converted_back = list_from_list_view(list_view, &mut ctx)?;
559 assert_arrays_eq!(mixed_list, converted_back, &mut ctx);
560 Ok(())
561 }
562
563 #[test]
564 fn test_recursive_simple_listview() -> VortexResult<()> {
565 let mut ctx = SESSION.create_execution_ctx();
566 let list_view = create_basic_listview();
567 let result = recursive_list_from_list_view(
568 list_view.clone().into_array(),
569 &mut SESSION.create_execution_ctx(),
570 )?;
571
572 assert_eq!(result.len(), list_view.len());
573 assert_arrays_eq!(list_view.into_array(), result, &mut ctx);
574 Ok(())
575 }
576
577 #[test]
578 fn test_recursive_nested_listview() -> VortexResult<()> {
579 let mut ctx = SESSION.create_execution_ctx();
580 let inner_elements = buffer![1i32, 2, 3].into_array();
581 let inner_offsets = buffer![0u32, 2].into_array();
582 let inner_sizes = buffer![2u32, 1].into_array();
583 let inner_listview = unsafe {
584 ListViewArray::new_unchecked(
585 inner_elements,
586 inner_offsets,
587 inner_sizes,
588 Validity::NonNullable,
589 )
590 .with_zero_copy_to_list(true)
591 };
592
593 let outer_offsets = buffer![0u32, 1].into_array();
594 let outer_sizes = buffer![1u32, 1].into_array();
595 let outer_listview = unsafe {
596 ListViewArray::new_unchecked(
597 inner_listview.into_array(),
598 outer_offsets,
599 outer_sizes,
600 Validity::NonNullable,
601 )
602 .with_zero_copy_to_list(true)
603 };
604
605 let result = recursive_list_from_list_view(
606 outer_listview.clone().into_array(),
607 &mut SESSION.create_execution_ctx(),
608 )?;
609
610 assert_eq!(result.len(), 2);
611 assert_arrays_eq!(outer_listview.into_array(), result, &mut ctx);
612 Ok(())
613 }
614
615 #[test]
616 fn test_recursive_struct_with_listview_fields() -> VortexResult<()> {
617 let mut ctx = SESSION.create_execution_ctx();
618 let listview_field = create_basic_listview().into_array();
619 let primitive_field = buffer![10i32, 20, 30, 40].into_array();
620
621 let struct_array = StructArray::try_new(
622 FieldNames::from(["lists", "values"]),
623 vec![listview_field, primitive_field],
624 4,
625 Validity::NonNullable,
626 )?;
627
628 let result = recursive_list_from_list_view(
629 struct_array.clone().into_array(),
630 &mut SESSION.create_execution_ctx(),
631 )?;
632
633 assert_eq!(result.len(), 4);
634 assert_arrays_eq!(struct_array.into_array(), result, &mut ctx);
635 Ok(())
636 }
637
638 #[test]
639 fn test_recursive_fixed_size_list_with_listview_elements() -> VortexResult<()> {
640 let mut ctx = SESSION.create_execution_ctx();
641 let lv1_elements = buffer![1i32, 2].into_array();
642 let lv1_offsets = buffer![0u32].into_array();
643 let lv1_sizes = buffer![2u32].into_array();
644 let lv1 = unsafe {
645 ListViewArray::new_unchecked(
646 lv1_elements,
647 lv1_offsets,
648 lv1_sizes,
649 Validity::NonNullable,
650 )
651 .with_zero_copy_to_list(true)
652 };
653
654 let lv2_elements = buffer![3i32, 4].into_array();
655 let lv2_offsets = buffer![0u32].into_array();
656 let lv2_sizes = buffer![2u32].into_array();
657 let lv2 = unsafe {
658 ListViewArray::new_unchecked(
659 lv2_elements,
660 lv2_offsets,
661 lv2_sizes,
662 Validity::NonNullable,
663 )
664 .with_zero_copy_to_list(true)
665 };
666
667 let dtype = lv1.dtype().clone();
668 let chunked_listviews =
669 crate::arrays::ChunkedArray::try_new(vec![lv1.into_array(), lv2.into_array()], dtype)?;
670
671 let fixed_list =
672 FixedSizeListArray::new(chunked_listviews.into_array(), 1, Validity::NonNullable, 2);
673
674 let result = recursive_list_from_list_view(
675 fixed_list.clone().into_array(),
676 &mut SESSION.create_execution_ctx(),
677 )?;
678
679 assert_eq!(result.len(), 2);
680 assert_arrays_eq!(fixed_list.into_array(), result, &mut ctx);
681 Ok(())
682 }
683
684 #[test]
685 fn test_recursive_deep_nesting() -> VortexResult<()> {
686 let mut ctx = SESSION.create_execution_ctx();
687 let innermost_elements = buffer![1i32, 2, 3].into_array();
688 let innermost_offsets = buffer![0u32, 2].into_array();
689 let innermost_sizes = buffer![2u32, 1].into_array();
690 let innermost_listview = unsafe {
691 ListViewArray::new_unchecked(
692 innermost_elements,
693 innermost_offsets,
694 innermost_sizes,
695 Validity::NonNullable,
696 )
697 .with_zero_copy_to_list(true)
698 };
699
700 let struct_array = StructArray::try_new(
701 FieldNames::from(["inner_lists"]),
702 vec![innermost_listview.into_array()],
703 2,
704 Validity::NonNullable,
705 )?;
706
707 let outer_offsets = buffer![0u32, 1].into_array();
708 let outer_sizes = buffer![1u32, 1].into_array();
709 let outer_listview = unsafe {
710 ListViewArray::new_unchecked(
711 struct_array.into_array(),
712 outer_offsets,
713 outer_sizes,
714 Validity::NonNullable,
715 )
716 .with_zero_copy_to_list(true)
717 };
718
719 let result = recursive_list_from_list_view(
720 outer_listview.clone().into_array(),
721 &mut SESSION.create_execution_ctx(),
722 )?;
723
724 assert_eq!(result.len(), 2);
725 assert_arrays_eq!(outer_listview.into_array(), result, &mut ctx);
726 Ok(())
727 }
728
729 #[test]
730 fn test_recursive_primitive_unchanged() -> VortexResult<()> {
731 let prim = buffer![1i32, 2, 3].into_array();
732 let prim_clone = prim.clone();
733 let result = recursive_list_from_list_view(prim, &mut SESSION.create_execution_ctx())?;
734
735 assert!(ArrayRef::ptr_eq(&result, &prim_clone));
736 Ok(())
737 }
738
739 #[test]
740 fn test_recursive_mixed_listview_and_list() -> VortexResult<()> {
741 let mut ctx = SESSION.create_execution_ctx();
742 let listview = create_basic_listview();
743 let list = list_from_list_view(listview.clone(), &mut ctx)?;
744
745 let struct_array = StructArray::try_new(
746 FieldNames::from(["listview_field", "list_field"]),
747 vec![listview.into_array(), list.into_array()],
748 4,
749 Validity::NonNullable,
750 )?;
751
752 let result = recursive_list_from_list_view(struct_array.clone().into_array(), &mut ctx)?;
753
754 assert_eq!(result.len(), 4);
755 assert_arrays_eq!(struct_array.into_array(), result, &mut ctx);
756 Ok(())
757 }
758
759 #[test]
765 fn test_empty_listview_to_list_without_zctl_flag() -> VortexResult<()> {
766 let elements = VarBinViewArray::from_iter_str(Vec::<&str>::new()).into_array();
767 let offsets = PrimitiveArray::from_iter(Vec::<i16>::new()).into_array();
768 let sizes = PrimitiveArray::from_iter(Vec::<i16>::new()).into_array();
769 let list_view = ListViewArray::try_new(elements, offsets, sizes, Validity::AllValid)?;
770
771 assert!(!list_view.is_zero_copy_to_list());
773
774 let list_array = list_from_list_view(list_view, &mut SESSION.create_execution_ctx())?;
775 assert_eq!(list_array.len(), 0);
776 Ok(())
777 }
778}