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