1use std::{mem::size_of, ptr::NonNull, sync::Arc};
105
106use arrow_buffer::{Buffer, MutableBuffer, bit_util};
107pub use arrow_data::ffi::FFI_ArrowArray;
108use arrow_data::{ArrayData, layout};
109pub use arrow_schema::ffi::FFI_ArrowSchema;
110use arrow_schema::{ArrowError, DataType, UnionMode};
111
112type Result<T> = std::result::Result<T, ArrowError>;
113
114fn bit_width(data_type: &DataType, i: usize) -> Result<usize> {
117 if let Some(primitive) = data_type.primitive_width() {
118 return match i {
119 0 => Err(ArrowError::CDataInterface(format!(
120 "The datatype \"{data_type}\" doesn't expect buffer at index 0. Please verify that the C data interface is correctly implemented."
121 ))),
122 1 => Ok(primitive * 8),
123 i => Err(ArrowError::CDataInterface(format!(
124 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
125 ))),
126 };
127 }
128
129 Ok(match (data_type, i) {
130 (DataType::Boolean, 1) => 1,
131 (DataType::Boolean, _) => {
132 return Err(ArrowError::CDataInterface(format!(
133 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
134 )));
135 }
136 (DataType::FixedSizeBinary(num_bytes), 1) => {
137 TryInto::<usize>::try_into(*num_bytes).map_err(|_| {
138 ArrowError::InvalidArgumentError(format!(
139 "cannot determine bit_width for FixedSizeBinary({num_bytes})"
140 ))
141 })? * u8::BITS as usize
142 }
143 (DataType::FixedSizeList(f, num_elems), 1) => {
144 let child_bit_width = bit_width(f.data_type(), 1)?;
145 child_bit_width * (*num_elems as usize)
146 }
147 (DataType::FixedSizeBinary(_) | DataType::FixedSizeList(_, _), _) => {
148 return Err(ArrowError::CDataInterface(format!(
149 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
150 )));
151 }
152 (DataType::Utf8 | DataType::Binary | DataType::List(_) | DataType::Map(_, _), 1) => {
156 i32::BITS as _
157 }
158 (DataType::Utf8 | DataType::Binary, 2) => u8::BITS as _,
159 (DataType::ListView(_), 1 | 2) => i32::BITS as _,
161 (DataType::LargeListView(_), 1 | 2) => i64::BITS as _,
163 (DataType::List(_) | DataType::Map(_, _), _) => {
164 return Err(ArrowError::CDataInterface(format!(
165 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
166 )));
167 }
168 (DataType::Utf8 | DataType::Binary, _) => {
169 return Err(ArrowError::CDataInterface(format!(
170 "The datatype \"{data_type}\" expects 3 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
171 )));
172 }
173 (DataType::LargeUtf8 | DataType::LargeBinary | DataType::LargeList(_), 1) => i64::BITS as _,
176 (DataType::LargeUtf8 | DataType::LargeBinary | DataType::LargeList(_), 2) => u8::BITS as _,
177 (DataType::LargeUtf8 | DataType::LargeBinary | DataType::LargeList(_), _) => {
178 return Err(ArrowError::CDataInterface(format!(
179 "The datatype \"{data_type}\" expects 3 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
180 )));
181 }
182 (DataType::Utf8View | DataType::BinaryView, 1) => u128::BITS as _,
186 (DataType::Utf8View | DataType::BinaryView, _) => u8::BITS as _,
187 (DataType::Union(_, _), 0) => i8::BITS as _,
189 (DataType::Union(_, UnionMode::Dense), 1) => i32::BITS as _,
191 (DataType::Union(_, UnionMode::Sparse), _) => {
192 return Err(ArrowError::CDataInterface(format!(
193 "The datatype \"{data_type}\" expects 1 buffer, but requested {i}. Please verify that the C data interface is correctly implemented."
194 )));
195 }
196 (DataType::Union(_, UnionMode::Dense), _) => {
197 return Err(ArrowError::CDataInterface(format!(
198 "The datatype \"{data_type}\" expects 2 buffer, but requested {i}. Please verify that the C data interface is correctly implemented."
199 )));
200 }
201 (_, 0) => {
202 return Err(ArrowError::CDataInterface(format!(
205 "The datatype \"{data_type}\" doesn't expect buffer at index 0. Please verify that the C data interface is correctly implemented."
206 )));
207 }
208 _ => {
209 return Err(ArrowError::CDataInterface(format!(
210 "The datatype \"{data_type}\" is still not supported in Rust implementation"
211 )));
212 }
213 })
214}
215
216unsafe fn create_buffer(
224 owner: Arc<FFI_ArrowArray>,
225 array: &FFI_ArrowArray,
226 index: usize,
227 len: usize,
228) -> Option<Buffer> {
229 if array.num_buffers() == 0 {
230 return None;
231 }
232 NonNull::new(array.buffer(index).cast_mut())
233 .map(|ptr| unsafe { Buffer::from_custom_allocation(ptr, len, owner) })
234}
235
236pub fn to_ffi(data: &ArrayData) -> Result<(FFI_ArrowArray, FFI_ArrowSchema)> {
238 let array = FFI_ArrowArray::new(data);
239 let schema = FFI_ArrowSchema::try_from(data.data_type())?;
240 Ok((array, schema))
241}
242
243pub unsafe fn from_ffi(array: FFI_ArrowArray, schema: &FFI_ArrowSchema) -> Result<ArrayData> {
249 let dt = DataType::try_from(schema)?;
250 let array = Arc::new(array);
251 let tmp = ImportedArrowArray {
252 array: &array,
253 data_type: dt,
254 owner: &array,
255 };
256 let mut data = tmp.consume()?;
257 data.align_buffers();
263 Ok(data)
264}
265
266pub unsafe fn from_ffi_and_data_type(
272 array: FFI_ArrowArray,
273 data_type: DataType,
274) -> Result<ArrayData> {
275 let array = Arc::new(array);
276 let tmp = ImportedArrowArray {
277 array: &array,
278 data_type,
279 owner: &array,
280 };
281 let mut data = tmp.consume()?;
282 data.align_buffers();
288 Ok(data)
289}
290
291#[derive(Debug)]
292struct ImportedArrowArray<'a> {
293 array: &'a FFI_ArrowArray,
294 data_type: DataType,
295 owner: &'a Arc<FFI_ArrowArray>,
296}
297
298impl ImportedArrowArray<'_> {
299 fn consume(self) -> Result<ArrayData> {
300 let len = self.array.len();
301 let offset = self.array.offset();
302 let null_count = match &self.data_type {
303 DataType::Null => Some(0),
304 _ => self.array.null_count_opt(),
305 };
306
307 let data_layout = layout(&self.data_type);
308 let buffers = self.buffers(data_layout.can_contain_null_mask, data_layout.variadic)?;
309
310 let null_bit_buffer = if data_layout.can_contain_null_mask {
311 self.null_bit_buffer()
312 } else {
313 None
314 };
315
316 let mut child_data = self.consume_children()?;
317
318 if let Some(d) = self.dictionary()? {
319 assert!(child_data.is_empty());
322 child_data.push(d.consume()?);
323 }
324
325 Ok(unsafe {
327 ArrayData::new_unchecked(
328 self.data_type,
329 len,
330 null_count,
331 null_bit_buffer,
332 offset,
333 buffers,
334 child_data,
335 )
336 })
337 }
338
339 fn consume_children(&self) -> Result<Vec<ArrayData>> {
340 match &self.data_type {
341 DataType::List(field)
342 | DataType::FixedSizeList(field, _)
343 | DataType::LargeList(field)
344 | DataType::ListView(field)
345 | DataType::LargeListView(field)
346 | DataType::Map(field, _) => Ok([self.consume_child(0, field.data_type())?].to_vec()),
347 DataType::Struct(fields) => {
348 assert!(fields.len() == self.array.num_children());
349 fields
350 .iter()
351 .enumerate()
352 .map(|(i, field)| self.consume_child(i, field.data_type()))
353 .collect::<Result<Vec<_>>>()
354 }
355 DataType::Union(union_fields, _) => {
356 assert!(union_fields.len() == self.array.num_children());
357 union_fields
358 .iter()
359 .enumerate()
360 .map(|(i, (_, field))| self.consume_child(i, field.data_type()))
361 .collect::<Result<Vec<_>>>()
362 }
363 DataType::RunEndEncoded(run_ends_field, values_field) => Ok([
364 self.consume_child(0, run_ends_field.data_type())?,
365 self.consume_child(1, values_field.data_type())?,
366 ]
367 .to_vec()),
368 _ => Ok(Vec::new()),
369 }
370 }
371
372 fn consume_child(&self, index: usize, child_type: &DataType) -> Result<ArrayData> {
373 ImportedArrowArray {
374 array: self.array.child(index),
375 data_type: child_type.clone(),
376 owner: self.owner,
377 }
378 .consume()
379 }
380
381 fn buffers(&self, can_contain_null_mask: bool, variadic: bool) -> Result<Vec<Buffer>> {
384 let buffer_begin = can_contain_null_mask as usize;
386 let buffer_end = self.array.num_buffers() - usize::from(variadic);
387
388 let variadic_buffer_lens = if variadic {
389 let num_variadic_buffers =
392 self.array.num_buffers() - (2 + usize::from(can_contain_null_mask));
393 if num_variadic_buffers == 0 {
394 &[]
395 } else {
396 let lengths = self.array.buffer(self.array.num_buffers() - 1);
397 unsafe { std::slice::from_raw_parts(lengths.cast::<i64>(), num_variadic_buffers) }
399 }
400 } else {
401 &[]
402 };
403
404 (buffer_begin..buffer_end)
405 .map(|index| {
406 let len = self.buffer_len(index, variadic_buffer_lens, &self.data_type)?;
407 match unsafe { create_buffer(self.owner.clone(), self.array, index, len) } {
408 Some(buf) => {
409 if buf.is_empty() {
414 Ok(MutableBuffer::new(0).into())
415 } else {
416 Ok(buf)
417 }
418 }
419 None if len == 0 => {
420 Ok(MutableBuffer::new(0).into())
423 }
424 None => Err(ArrowError::CDataInterface(format!(
425 "The external buffer at position {index} is null."
426 ))),
427 }
428 })
429 .collect()
430 }
431
432 fn buffer_len(
437 &self,
438 i: usize,
439 variadic_buffer_lengths: &[i64],
440 dt: &DataType,
441 ) -> Result<usize> {
442 let data_type = match dt {
444 DataType::Dictionary(key_data_type, _) => key_data_type.as_ref(),
445 dt => dt,
446 };
447
448 let length = self.array.len() + self.array.offset();
451
452 Ok(match (&data_type, i) {
454 (
455 DataType::Utf8
456 | DataType::LargeUtf8
457 | DataType::Binary
458 | DataType::LargeBinary
459 | DataType::List(_)
460 | DataType::LargeList(_)
461 | DataType::Map(_, _),
462 1,
463 ) => {
464 let bits = bit_width(data_type, i)?;
466 debug_assert_eq!(bits % 8, 0);
467 (length + 1) * (bits / 8)
468 }
469 (DataType::ListView(_) | DataType::LargeListView(_), 1 | 2) => {
470 let bits = bit_width(data_type, i)?;
471 debug_assert_eq!(bits % 8, 0);
472 length * (bits / 8)
473 }
474 (DataType::Utf8 | DataType::Binary, 2) => {
475 if self.array.is_empty() {
476 return Ok(0);
477 }
478
479 let len = self.buffer_len(1, variadic_buffer_lengths, dt)?;
481 #[expect(clippy::cast_ptr_alignment)]
484 let offset_buffer = self.array.buffer(1) as *const i32;
485 (unsafe { *offset_buffer.add(len / size_of::<i32>() - 1) }) as usize
487 }
488 (DataType::LargeUtf8 | DataType::LargeBinary, 2) => {
489 if self.array.is_empty() {
490 return Ok(0);
491 }
492
493 let len = self.buffer_len(1, variadic_buffer_lengths, dt)?;
495 #[expect(clippy::cast_ptr_alignment)]
498 let offset_buffer = self.array.buffer(1) as *const i64;
499 (unsafe { *offset_buffer.add(len / size_of::<i64>() - 1) }) as usize
501 }
502 (DataType::Utf8View | DataType::BinaryView, 1) => std::mem::size_of::<u128>() * length,
507 (DataType::Utf8View | DataType::BinaryView, i) => {
508 variadic_buffer_lengths[i - 2] as usize
509 }
510 _ => {
512 let bits = bit_width(data_type, i)?;
513 bit_util::ceil(length * bits, 8)
514 }
515 })
516 }
517
518 fn null_bit_buffer(&self) -> Option<Buffer> {
522 let length = self.array.len() + self.array.offset();
526 let buffer_len = bit_util::ceil(length, 8);
527
528 unsafe { create_buffer(self.owner.clone(), self.array, 0, buffer_len) }
529 }
530
531 fn dictionary(&self) -> Result<Option<ImportedArrowArray<'_>>> {
532 match (self.array.dictionary(), &self.data_type) {
533 (Some(array), DataType::Dictionary(_, value_type)) => Ok(Some(ImportedArrowArray {
534 array,
535 data_type: value_type.as_ref().clone(),
536 owner: self.owner,
537 })),
538 (Some(_), _) => Err(ArrowError::CDataInterface(
539 "Got dictionary in FFI_ArrowArray for non-dictionary data type".to_string(),
540 )),
541 (None, DataType::Dictionary(_, _)) => Err(ArrowError::CDataInterface(
542 "Missing dictionary in FFI_ArrowArray for dictionary data type".to_string(),
543 )),
544 (_, _) => Ok(None),
545 }
546 }
547}
548
549#[cfg(test)]
550mod tests_to_then_from_ffi {
551 use std::collections::HashMap;
552 use std::mem::ManuallyDrop;
553
554 use arrow_buffer::{ArrowNativeType, NullBuffer};
555 use arrow_schema::Field;
556
557 use crate::builder::UnionBuilder;
558 use crate::cast::AsArray;
559 use crate::types::{Float64Type, Int8Type, Int32Type};
560 use crate::*;
561
562 use super::*;
563
564 #[test]
565 fn test_round_trip() {
566 let array = Int32Array::from(vec![1, 2, 3]);
568
569 let (array, schema) = to_ffi(&array.into_data()).unwrap();
571
572 let array = Int32Array::from(unsafe { from_ffi(array, &schema) }.unwrap());
574
575 assert_eq!(array, Int32Array::from(vec![1, 2, 3]));
577 }
578
579 #[test]
580 fn test_import() {
581 let data = Int32Array::from(vec![1, 2, 3]).into_data();
585 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
586 let array = FFI_ArrowArray::new(&data);
587
588 let schema = Box::new(ManuallyDrop::new(schema));
590 let array = Box::new(ManuallyDrop::new(array));
591
592 let schema_ptr = &**schema as *const _;
593 let array_ptr = &**array as *const _;
594
595 let data =
599 unsafe { from_ffi(std::ptr::read(array_ptr), &std::ptr::read(schema_ptr)).unwrap() };
600
601 let array = Int32Array::from(data);
602 assert_eq!(array, Int32Array::from(vec![1, 2, 3]));
603 }
604
605 #[test]
606 fn test_round_trip_with_offset() -> Result<()> {
607 let array = Int32Array::from(vec![Some(1), Some(2), None, Some(3), None]);
609
610 let array = array.slice(1, 2);
611
612 let (array, schema) = to_ffi(&array.to_data())?;
614
615 let data = unsafe { from_ffi(array, &schema) }?;
617 let array = make_array(data);
618 let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
619
620 assert_eq!(array, &Int32Array::from(vec![Some(2), None]));
621
622 Ok(())
624 }
625
626 #[test]
627 #[cfg(not(feature = "force_validate"))]
628 fn test_decimal_round_trip() -> Result<()> {
629 let original_array = [Some(12345_i128), Some(-12345_i128), None]
631 .into_iter()
632 .collect::<Decimal128Array>()
633 .with_precision_and_scale(6, 2)
634 .unwrap();
635
636 let (array, schema) = to_ffi(&original_array.to_data())?;
638
639 let data = unsafe { from_ffi(array, &schema) }?;
641 let array = make_array(data);
642
643 let array = array.as_any().downcast_ref::<Decimal128Array>().unwrap();
645
646 assert_eq!(array, &original_array);
648
649 Ok(())
651 }
652 #[test]
655 #[cfg(not(feature = "force_validate"))]
656 fn test_decimal128_under_aligned_round_trip() -> Result<()> {
657 let aligned = Buffer::from_vec(vec![0_i128, 1_i128, 2_i128]);
661 let under_aligned = aligned.slice(8);
662 assert_eq!(under_aligned.as_ptr().align_offset(8), 0);
663 assert_ne!(under_aligned.as_ptr().align_offset(16), 0);
664
665 let data = unsafe {
668 ArrayData::builder(DataType::Decimal128(10, 2))
669 .len(2)
670 .add_buffer(under_aligned)
671 .build_unchecked()
672 };
673
674 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
675 let array = FFI_ArrowArray::new(&data);
676
677 let imported = unsafe { from_ffi(array, &schema) }?;
678 let array = Decimal128Array::from(imported);
679
680 assert_eq!(array.len(), 2);
683 assert_eq!(array.value(0), 1_i128 << 64);
684 assert_eq!(array.value(1), 2_i128 << 64);
685 Ok(())
686 }
687
688 #[test]
689 fn test_null_count_handling() {
690 let int32_data = ArrayData::builder(DataType::Int32)
691 .len(10)
692 .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
693 .null_bit_buffer(Some(Buffer::from([0b01011111, 0b00000001])))
694 .build()
695 .unwrap();
696 let mut ffi_array = FFI_ArrowArray::new(&int32_data);
697 assert_eq!(3, ffi_array.null_count());
698 assert_eq!(Some(3), ffi_array.null_count_opt());
699 unsafe {
701 ffi_array.set_null_count(-1);
702 }
703 assert_eq!(None, ffi_array.null_count_opt());
704 let int32_data = unsafe { from_ffi_and_data_type(ffi_array, DataType::Int32) }.unwrap();
705 assert_eq!(3, int32_data.null_count());
706
707 let null_data = &ArrayData::new_null(&DataType::Null, 10);
708 let mut ffi_array = FFI_ArrowArray::new(null_data);
709 assert_eq!(10, ffi_array.null_count());
710 assert_eq!(Some(10), ffi_array.null_count_opt());
711 unsafe {
713 ffi_array.set_null_count(-1);
714 }
715 assert_eq!(None, ffi_array.null_count_opt());
716 let null_data = unsafe { from_ffi_and_data_type(ffi_array, DataType::Null) }.unwrap();
717 assert_eq!(0, null_data.null_count());
718 }
719
720 fn test_generic_string<Offset: OffsetSizeTrait>() -> Result<()> {
721 let array = GenericStringArray::<Offset>::from(vec![Some("a"), None, Some("aaa")]);
723
724 let (array, schema) = to_ffi(&array.to_data())?;
726
727 let data = unsafe { from_ffi(array, &schema) }?;
729 let array = make_array(data);
730
731 let array = array
733 .as_any()
734 .downcast_ref::<GenericStringArray<Offset>>()
735 .unwrap();
736
737 let expected = GenericStringArray::<Offset>::from(vec![Some("a"), None, Some("aaa")]);
739 assert_eq!(array, &expected);
740
741 Ok(())
743 }
744
745 #[test]
746 fn test_string() -> Result<()> {
747 test_generic_string::<i32>()
748 }
749
750 #[test]
751 fn test_large_string() -> Result<()> {
752 test_generic_string::<i64>()
753 }
754
755 fn test_generic_list<Offset: OffsetSizeTrait>() -> Result<()> {
756 let value_data = ArrayData::builder(DataType::Int32)
758 .len(8)
759 .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7]))
760 .build()
761 .unwrap();
762
763 let value_offsets = [0_usize, 3, 6, 8]
766 .iter()
767 .map(|i| Offset::from_usize(*i).unwrap())
768 .collect::<Buffer>();
769
770 let list_data_type = GenericListArray::<Offset>::DATA_TYPE_CONSTRUCTOR(Arc::new(
772 Field::new_list_field(DataType::Int32, false),
773 ));
774
775 let list_data = ArrayData::builder(list_data_type)
776 .len(3)
777 .add_buffer(value_offsets)
778 .add_child_data(value_data)
779 .build()
780 .unwrap();
781
782 let array = GenericListArray::<Offset>::from(list_data.clone());
784
785 let (array, schema) = to_ffi(&array.to_data())?;
787
788 let data = unsafe { from_ffi(array, &schema) }?;
790 let array = make_array(data);
791
792 let array = array
794 .as_any()
795 .downcast_ref::<GenericListArray<Offset>>()
796 .unwrap();
797
798 let expected = GenericListArray::<Offset>::from(list_data);
800 assert_eq!(&array.value(0), &expected.value(0));
801 assert_eq!(&array.value(1), &expected.value(1));
802 assert_eq!(&array.value(2), &expected.value(2));
803
804 Ok(())
806 }
807
808 #[test]
809 fn test_list() -> Result<()> {
810 test_generic_list::<i32>()
811 }
812
813 #[test]
814 fn test_large_list() -> Result<()> {
815 test_generic_list::<i64>()
816 }
817
818 fn test_generic_list_view<Offset: OffsetSizeTrait + ArrowNativeType>() -> Result<()> {
819 let value_data = ArrayData::builder(DataType::Int16)
821 .len(8)
822 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
823 .build()
824 .unwrap();
825
826 let value_offsets = [0_usize, 3, 6]
829 .iter()
830 .map(|i| Offset::from_usize(*i).unwrap())
831 .collect::<Buffer>();
832
833 let sizes_buffer = [3_usize, 3, 2]
834 .iter()
835 .map(|i| Offset::from_usize(*i).unwrap())
836 .collect::<Buffer>();
837
838 let list_view_dt = GenericListViewArray::<Offset>::DATA_TYPE_CONSTRUCTOR(Arc::new(
840 Field::new_list_field(DataType::Int16, false),
841 ));
842
843 let list_data = ArrayData::builder(list_view_dt)
844 .len(3)
845 .add_buffer(value_offsets)
846 .add_buffer(sizes_buffer)
847 .add_child_data(value_data)
848 .build()
849 .unwrap();
850
851 let original = GenericListViewArray::<Offset>::from(list_data.clone());
852
853 let (array, schema) = to_ffi(&original.to_data())?;
855
856 let data = unsafe { from_ffi(array, &schema) }?;
858 let array = make_array(data);
859
860 let array = array
862 .as_any()
863 .downcast_ref::<GenericListViewArray<Offset>>()
864 .unwrap();
865
866 assert_eq!(&array.value(0), &original.value(0));
867 assert_eq!(&array.value(1), &original.value(1));
868 assert_eq!(&array.value(2), &original.value(2));
869
870 Ok(())
871 }
872
873 #[test]
874 fn test_list_view() -> Result<()> {
875 test_generic_list_view::<i32>()
876 }
877
878 #[test]
879 fn test_large_list_view() -> Result<()> {
880 test_generic_list_view::<i64>()
881 }
882
883 fn test_generic_binary<Offset: OffsetSizeTrait>() -> Result<()> {
884 let array: Vec<Option<&[u8]>> = vec![Some(b"a"), None, Some(b"aaa")];
886 let array = GenericBinaryArray::<Offset>::from(array);
887
888 let (array, schema) = to_ffi(&array.to_data())?;
890
891 let data = unsafe { from_ffi(array, &schema) }?;
893 let array = make_array(data);
894 let array = array
895 .as_any()
896 .downcast_ref::<GenericBinaryArray<Offset>>()
897 .unwrap();
898
899 let expected: Vec<Option<&[u8]>> = vec![Some(b"a"), None, Some(b"aaa")];
901 let expected = GenericBinaryArray::<Offset>::from(expected);
902 assert_eq!(array, &expected);
903
904 Ok(())
906 }
907
908 #[test]
909 fn test_binary() -> Result<()> {
910 test_generic_binary::<i32>()
911 }
912
913 #[test]
914 fn test_large_binary() -> Result<()> {
915 test_generic_binary::<i64>()
916 }
917
918 #[test]
919 fn test_bool() -> Result<()> {
920 let array = BooleanArray::from(vec![None, Some(true), Some(false)]);
922
923 let (array, schema) = to_ffi(&array.to_data())?;
925
926 let data = unsafe { from_ffi(array, &schema) }?;
928 let array = make_array(data);
929 let array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
930
931 assert_eq!(
933 array,
934 &BooleanArray::from(vec![None, Some(true), Some(false)])
935 );
936
937 Ok(())
939 }
940
941 #[test]
942 fn test_time32() -> Result<()> {
943 let array = Time32MillisecondArray::from(vec![None, Some(1), Some(2)]);
945
946 let (array, schema) = to_ffi(&array.to_data())?;
948
949 let data = unsafe { from_ffi(array, &schema) }?;
951 let array = make_array(data);
952 let array = array
953 .as_any()
954 .downcast_ref::<Time32MillisecondArray>()
955 .unwrap();
956
957 assert_eq!(
959 array,
960 &Time32MillisecondArray::from(vec![None, Some(1), Some(2)])
961 );
962
963 Ok(())
965 }
966
967 #[test]
968 fn test_timestamp() -> Result<()> {
969 let array = TimestampMillisecondArray::from(vec![None, Some(1), Some(2)]);
971
972 let (array, schema) = to_ffi(&array.to_data())?;
974
975 let data = unsafe { from_ffi(array, &schema) }?;
977 let array = make_array(data);
978 let array = array
979 .as_any()
980 .downcast_ref::<TimestampMillisecondArray>()
981 .unwrap();
982
983 assert_eq!(
985 array,
986 &TimestampMillisecondArray::from(vec![None, Some(1), Some(2)])
987 );
988
989 Ok(())
991 }
992
993 #[test]
994 fn test_fixed_size_binary_array() -> Result<()> {
995 let values = vec![
996 None,
997 Some(vec![10, 10, 10]),
998 None,
999 Some(vec![20, 20, 20]),
1000 Some(vec![30, 30, 30]),
1001 None,
1002 ];
1003 let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 3)?;
1004
1005 let (array, schema) = to_ffi(&array.to_data())?;
1007
1008 let data = unsafe { from_ffi(array, &schema) }?;
1010 let array = make_array(data);
1011 let array = array
1012 .as_any()
1013 .downcast_ref::<FixedSizeBinaryArray>()
1014 .unwrap();
1015
1016 assert_eq!(
1018 array,
1019 &FixedSizeBinaryArray::try_from_sparse_iter_with_size(
1020 vec![
1021 None,
1022 Some(vec![10, 10, 10]),
1023 None,
1024 Some(vec![20, 20, 20]),
1025 Some(vec![30, 30, 30]),
1026 None,
1027 ]
1028 .into_iter(),
1029 3
1030 )?
1031 );
1032
1033 Ok(())
1035 }
1036
1037 #[test]
1038 fn test_fixed_size_list_array() -> Result<()> {
1039 let mut validity_bits: [u8; 1] = [0; 1];
1041 bit_util::set_bit(&mut validity_bits, 2);
1042
1043 let v: Vec<i32> = (0..9).collect();
1044 let value_data = ArrayData::builder(DataType::Int32)
1045 .len(9)
1046 .add_buffer(Buffer::from_slice_ref(&v))
1047 .build()?;
1048
1049 let list_data_type =
1050 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int32, false)), 3);
1051 let list_data = ArrayData::builder(list_data_type.clone())
1052 .len(3)
1053 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1054 .add_child_data(value_data)
1055 .build()?;
1056
1057 let (array, schema) = to_ffi(&list_data)?;
1059
1060 let data = unsafe { from_ffi(array, &schema) }?;
1062 let array = make_array(data);
1063 let array = array.as_any().downcast_ref::<FixedSizeListArray>().unwrap();
1064
1065 let mut expected_validity_bits: [u8; 1] = [0; 1];
1067 bit_util::set_bit(&mut expected_validity_bits, 2);
1068 bit_util::set_bit(&mut expected_validity_bits, 5);
1069
1070 let mut w = vec![];
1071 w.extend_from_slice(&v);
1072
1073 let expected_value_data = ArrayData::builder(DataType::Int32)
1074 .len(9)
1075 .add_buffer(Buffer::from_slice_ref(&w))
1076 .build()?;
1077
1078 let expected_list_data = ArrayData::builder(list_data_type)
1079 .len(3)
1080 .null_bit_buffer(Some(Buffer::from(expected_validity_bits)))
1081 .add_child_data(expected_value_data)
1082 .build()?;
1083 let expected_array = FixedSizeListArray::from(expected_list_data);
1084
1085 assert_eq!(array, &expected_array);
1087
1088 Ok(())
1090 }
1091
1092 #[test]
1093 fn test_dictionary() -> Result<()> {
1094 let values = vec!["a", "aaa", "aaa"];
1096 let dict_array: DictionaryArray<Int8Type> = values.into_iter().collect();
1097
1098 let (array, schema) = to_ffi(&dict_array.to_data())?;
1100
1101 let data = unsafe { from_ffi(array, &schema) }?;
1103 let array = make_array(data);
1104 let actual = array
1105 .as_any()
1106 .downcast_ref::<DictionaryArray<Int8Type>>()
1107 .unwrap();
1108
1109 let new_values = vec!["a", "aaa", "aaa"];
1111 let expected: DictionaryArray<Int8Type> = new_values.into_iter().collect();
1112 assert_eq!(actual, &expected);
1113
1114 Ok(())
1116 }
1117
1118 #[test]
1119 fn test_duration() -> Result<()> {
1120 let array = DurationSecondArray::from(vec![None, Some(1), Some(2)]);
1122
1123 let (array, schema) = to_ffi(&array.to_data())?;
1125
1126 let data = unsafe { from_ffi(array, &schema) }?;
1128 let array = make_array(data);
1129 let array = array
1130 .as_any()
1131 .downcast_ref::<DurationSecondArray>()
1132 .unwrap();
1133
1134 assert_eq!(
1136 array,
1137 &DurationSecondArray::from(vec![None, Some(1), Some(2)])
1138 );
1139
1140 Ok(())
1142 }
1143
1144 #[test]
1145 fn test_map_array() -> Result<()> {
1146 let keys = vec!["a", "b", "c", "d", "e", "f", "g", "h"];
1147 let values_data = UInt32Array::from(vec![0u32, 10, 20, 30, 40, 50, 60, 70]);
1148
1149 let entry_offsets = [0, 3, 6, 8];
1152
1153 let map_array =
1154 MapArray::new_from_strings(keys.clone().into_iter(), &values_data, &entry_offsets)
1155 .unwrap();
1156
1157 let (array, schema) = to_ffi(&map_array.to_data())?;
1159
1160 let data = unsafe { from_ffi(array, &schema) }?;
1162 let array = make_array(data);
1163
1164 let array = array.as_any().downcast_ref::<MapArray>().unwrap();
1166 assert_eq!(array, &map_array);
1167
1168 Ok(())
1169 }
1170
1171 #[test]
1172 fn test_struct_array() -> Result<()> {
1173 let metadata: HashMap<String, String> =
1174 [("Hello".to_string(), "World! 😊".to_string())].into();
1175 let struct_array = StructArray::from(vec![(
1176 Arc::new(Field::new("a", DataType::Int32, false).with_metadata(metadata)),
1177 Arc::new(Int32Array::from(vec![2, 4, 6])) as Arc<dyn Array>,
1178 )]);
1179
1180 let (array, schema) = to_ffi(&struct_array.to_data())?;
1182
1183 let data = unsafe { from_ffi(array, &schema) }?;
1185 let array = make_array(data);
1186
1187 let array = array.as_any().downcast_ref::<StructArray>().unwrap();
1189 assert_eq!(array.data_type(), struct_array.data_type());
1190 assert_eq!(array, &struct_array);
1191
1192 Ok(())
1193 }
1194
1195 #[test]
1196 fn test_union_sparse_array() -> Result<()> {
1197 let mut builder = UnionBuilder::new_sparse();
1198 builder.append::<Int32Type>("a", 1).unwrap();
1199 builder.append_null::<Int32Type>("a").unwrap();
1200 builder.append::<Float64Type>("c", 3.0).unwrap();
1201 builder.append::<Int32Type>("a", 4).unwrap();
1202 let union = builder.build().unwrap();
1203
1204 let (array, schema) = to_ffi(&union.to_data())?;
1206
1207 let data = unsafe { from_ffi(array, &schema) }?;
1209 let array = make_array(data);
1210
1211 let array = array.as_any().downcast_ref::<UnionArray>().unwrap();
1212
1213 let expected_type_ids = vec![0_i8, 0, 1, 0];
1214
1215 assert_eq!(*array.type_ids(), expected_type_ids);
1217 for (i, id) in expected_type_ids.iter().enumerate() {
1218 assert_eq!(id, &array.type_id(i));
1219 }
1220
1221 assert!(array.offsets().is_none());
1223
1224 for i in 0..array.len() {
1225 let slot = array.value(i);
1226 match i {
1227 0 => {
1228 let slot = slot.as_primitive::<Int32Type>();
1229 assert!(!slot.is_null(0));
1230 assert_eq!(slot.len(), 1);
1231 let value = slot.value(0);
1232 assert_eq!(1_i32, value);
1233 }
1234 1 => assert!(slot.is_null(0)),
1235 2 => {
1236 let slot = slot.as_primitive::<Float64Type>();
1237 assert!(!slot.is_null(0));
1238 assert_eq!(slot.len(), 1);
1239 let value = slot.value(0);
1240 assert_eq!(value, 3_f64);
1241 }
1242 3 => {
1243 let slot = slot.as_primitive::<Int32Type>();
1244 assert!(!slot.is_null(0));
1245 assert_eq!(slot.len(), 1);
1246 let value = slot.value(0);
1247 assert_eq!(4_i32, value);
1248 }
1249 _ => unreachable!(),
1250 }
1251 }
1252
1253 Ok(())
1254 }
1255
1256 #[test]
1257 fn test_union_dense_array() -> Result<()> {
1258 let mut builder = UnionBuilder::new_dense();
1259 builder.append::<Int32Type>("a", 1).unwrap();
1260 builder.append_null::<Int32Type>("a").unwrap();
1261 builder.append::<Float64Type>("c", 3.0).unwrap();
1262 builder.append::<Int32Type>("a", 4).unwrap();
1263 let union = builder.build().unwrap();
1264
1265 let (array, schema) = to_ffi(&union.to_data())?;
1267
1268 let data = unsafe { from_ffi(array, &schema) }?;
1270 let array = UnionArray::from(data);
1271
1272 let expected_type_ids = vec![0_i8, 0, 1, 0];
1273
1274 assert_eq!(*array.type_ids(), expected_type_ids);
1276 for (i, id) in expected_type_ids.iter().enumerate() {
1277 assert_eq!(id, &array.type_id(i));
1278 }
1279
1280 assert!(array.offsets().is_some());
1281
1282 for i in 0..array.len() {
1283 let slot = array.value(i);
1284 match i {
1285 0 => {
1286 let slot = slot.as_primitive::<Int32Type>();
1287 assert!(!slot.is_null(0));
1288 assert_eq!(slot.len(), 1);
1289 let value = slot.value(0);
1290 assert_eq!(1_i32, value);
1291 }
1292 1 => assert!(slot.is_null(0)),
1293 2 => {
1294 let slot = slot.as_primitive::<Float64Type>();
1295 assert!(!slot.is_null(0));
1296 assert_eq!(slot.len(), 1);
1297 let value = slot.value(0);
1298 assert_eq!(value, 3_f64);
1299 }
1300 3 => {
1301 let slot = slot.as_primitive::<Int32Type>();
1302 assert!(!slot.is_null(0));
1303 assert_eq!(slot.len(), 1);
1304 let value = slot.value(0);
1305 assert_eq!(4_i32, value);
1306 }
1307 _ => unreachable!(),
1308 }
1309 }
1310
1311 Ok(())
1312 }
1313
1314 #[test]
1315 fn test_run_array() -> Result<()> {
1316 let value_data =
1317 PrimitiveArray::<Int8Type>::from_iter_values([10_i8, 11, 12, 13, 14, 15, 16, 17]);
1318
1319 let run_ends_values = [4_i32, 6, 7, 9, 13, 18, 20, 22];
1321 let run_ends_data =
1322 PrimitiveArray::<Int32Type>::from_iter_values(run_ends_values.iter().copied());
1323
1324 let ree_array = RunArray::<Int32Type>::try_new(&run_ends_data, &value_data).unwrap();
1326
1327 let (array, schema) = to_ffi(&ree_array.to_data())?;
1329
1330 let data = unsafe { from_ffi(array, &schema) }?;
1332 let array = make_array(data);
1333
1334 let array = array
1336 .as_any()
1337 .downcast_ref::<RunArray<Int32Type>>()
1338 .unwrap();
1339 assert_eq!(array.data_type(), ree_array.data_type());
1340 assert_eq!(array.run_ends().values(), ree_array.run_ends().values());
1341 assert_eq!(array.values(), ree_array.values());
1342
1343 Ok(())
1344 }
1345
1346 #[test]
1347 fn test_nullable_run_array() -> Result<()> {
1348 let nulls = NullBuffer::from(vec![true, false, true, true, false]);
1349 let value_data =
1350 PrimitiveArray::<Int8Type>::new(vec![1_i8, 2, 3, 4, 5].into(), Some(nulls));
1351
1352 let run_ends_values = [5_i32, 6, 7, 8, 10];
1354 let run_ends_data =
1355 PrimitiveArray::<Int32Type>::from_iter_values(run_ends_values.iter().copied());
1356
1357 let ree_array = RunArray::<Int32Type>::try_new(&run_ends_data, &value_data).unwrap();
1359
1360 let (array, schema) = to_ffi(&ree_array.to_data())?;
1362
1363 let data = unsafe { from_ffi(array, &schema) }?;
1365 let array = make_array(data);
1366
1367 let array = array
1369 .as_any()
1370 .downcast_ref::<RunArray<Int32Type>>()
1371 .unwrap();
1372 assert_eq!(array.data_type(), ree_array.data_type());
1373 assert_eq!(array.run_ends().values(), ree_array.run_ends().values());
1374 assert_eq!(array.values(), ree_array.values());
1375
1376 Ok(())
1377 }
1378}
1379
1380#[cfg(test)]
1381mod tests_from_ffi {
1382 #[cfg(not(feature = "force_validate"))]
1383 use std::ptr::NonNull;
1384 use std::sync::Arc;
1385
1386 use arrow_buffer::NullBuffer;
1387 #[cfg(not(feature = "force_validate"))]
1388 use arrow_buffer::{ScalarBuffer, bit_util, buffer::Buffer};
1389 #[cfg(feature = "force_validate")]
1390 use arrow_buffer::{bit_util, buffer::Buffer};
1391
1392 use arrow_data::ArrayData;
1393 use arrow_data::transform::MutableArrayData;
1394 use arrow_schema::{DataType, Field};
1395
1396 use super::Result;
1397
1398 use crate::builder::GenericByteViewBuilder;
1399 use crate::types::{BinaryViewType, ByteViewType, Int32Type, StringViewType};
1400 use crate::{
1401 ArrayRef, GenericByteViewArray, ListArray,
1402 array::{
1403 Array, BooleanArray, DictionaryArray, FixedSizeBinaryArray, FixedSizeListArray,
1404 Int32Array, Int64Array, StringArray, StructArray, UInt32Array, UInt64Array,
1405 },
1406 ffi::{FFI_ArrowArray, FFI_ArrowSchema, from_ffi},
1407 make_array,
1408 };
1409
1410 fn test_round_trip(expected: &ArrayData) -> Result<()> {
1411 let array = FFI_ArrowArray::new(expected);
1413 let schema = FFI_ArrowSchema::try_from(expected.data_type())?;
1414
1415 let result = &unsafe { from_ffi(array, &schema) }?;
1417
1418 assert_eq!(result, expected);
1419 Ok(())
1420 }
1421
1422 #[test]
1423 fn test_u32() -> Result<()> {
1424 let array = UInt32Array::from(vec![Some(2), None, Some(1), None]);
1425 let data = array.into_data();
1426 test_round_trip(&data)
1427 }
1428
1429 #[test]
1430 fn test_u64() -> Result<()> {
1431 let array = UInt64Array::from(vec![Some(2), None, Some(1), None]);
1432 let data = array.into_data();
1433 test_round_trip(&data)
1434 }
1435
1436 #[test]
1437 fn test_i64() -> Result<()> {
1438 let array = Int64Array::from(vec![Some(2), None, Some(1), None]);
1439 let data = array.into_data();
1440 test_round_trip(&data)
1441 }
1442
1443 #[test]
1444 fn test_struct() -> Result<()> {
1445 let inner = StructArray::from(vec![
1446 (
1447 Arc::new(Field::new("a1", DataType::Boolean, false)),
1448 Arc::new(BooleanArray::from(vec![true, true, false, false])) as Arc<dyn Array>,
1449 ),
1450 (
1451 Arc::new(Field::new("a2", DataType::UInt32, false)),
1452 Arc::new(UInt32Array::from(vec![1, 2, 3, 4])),
1453 ),
1454 ]);
1455
1456 let array = StructArray::from(vec![
1457 (
1458 Arc::new(Field::new("a", inner.data_type().clone(), false)),
1459 Arc::new(inner) as Arc<dyn Array>,
1460 ),
1461 (
1462 Arc::new(Field::new("b", DataType::Boolean, false)),
1463 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
1464 ),
1465 (
1466 Arc::new(Field::new("c", DataType::UInt32, false)),
1467 Arc::new(UInt32Array::from(vec![42, 28, 19, 31])),
1468 ),
1469 ]);
1470 let data = array.into_data();
1471 test_round_trip(&data)
1472 }
1473
1474 #[test]
1475 fn test_dictionary() -> Result<()> {
1476 let values = StringArray::from(vec![Some("foo"), Some("bar"), None]);
1477 let keys = Int32Array::from(vec![
1478 Some(0),
1479 Some(1),
1480 None,
1481 Some(1),
1482 Some(1),
1483 None,
1484 Some(1),
1485 Some(2),
1486 Some(1),
1487 None,
1488 ]);
1489 let array = DictionaryArray::new(keys, Arc::new(values));
1490
1491 let data = array.into_data();
1492 test_round_trip(&data)
1493 }
1494
1495 #[test]
1496 fn test_fixed_size_binary() -> Result<()> {
1497 let values = vec![vec![10, 10, 10], vec![20, 20, 20], vec![30, 30, 30]];
1498 let array = FixedSizeBinaryArray::try_from_iter(values.into_iter())?;
1499
1500 let data = array.into_data();
1501 test_round_trip(&data)
1502 }
1503
1504 #[test]
1505 fn test_fixed_size_binary_with_nulls() -> Result<()> {
1506 let values = vec![
1507 None,
1508 Some(vec![10, 10, 10]),
1509 None,
1510 Some(vec![20, 20, 20]),
1511 Some(vec![30, 30, 30]),
1512 None,
1513 ];
1514 let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 3)?;
1515
1516 let data = array.into_data();
1517 test_round_trip(&data)
1518 }
1519
1520 #[test]
1521 fn test_fixed_size_list() -> Result<()> {
1522 let v: Vec<i64> = (0..9).collect();
1523 let value_data = ArrayData::builder(DataType::Int64)
1524 .len(9)
1525 .add_buffer(Buffer::from_slice_ref(v))
1526 .build()?;
1527 let list_data_type =
1528 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int64, false)), 3);
1529 let list_data = ArrayData::builder(list_data_type)
1530 .len(3)
1531 .add_child_data(value_data)
1532 .build()?;
1533 let array = FixedSizeListArray::from(list_data);
1534
1535 let data = array.into_data();
1536 test_round_trip(&data)
1537 }
1538
1539 #[test]
1540 fn test_fixed_size_list_with_nulls() -> Result<()> {
1541 let mut validity_bits: [u8; 1] = [0; 1];
1543 bit_util::set_bit(&mut validity_bits, 1);
1544 bit_util::set_bit(&mut validity_bits, 2);
1545 bit_util::set_bit(&mut validity_bits, 6);
1546
1547 let v: Vec<i16> = (0..16).collect();
1548 let value_data = ArrayData::builder(DataType::Int16)
1549 .len(16)
1550 .add_buffer(Buffer::from_slice_ref(v))
1551 .build()?;
1552 let list_data_type =
1553 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int16, false)), 2);
1554 let list_data = ArrayData::builder(list_data_type)
1555 .len(8)
1556 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1557 .add_child_data(value_data)
1558 .build()?;
1559 let array = FixedSizeListArray::from(list_data);
1560
1561 let data = array.into_data();
1562 test_round_trip(&data)
1563 }
1564
1565 #[test]
1566 fn test_fixed_size_list_nested() -> Result<()> {
1567 let v: Vec<i32> = (0..16).collect();
1568 let value_data = ArrayData::builder(DataType::Int32)
1569 .len(16)
1570 .add_buffer(Buffer::from_slice_ref(v))
1571 .build()?;
1572
1573 let offsets: Vec<i32> = vec![0, 2, 4, 6, 8, 10, 12, 14, 16];
1574 let value_offsets = Buffer::from_slice_ref(offsets);
1575 let inner_list_data_type =
1576 DataType::List(Arc::new(Field::new_list_field(DataType::Int32, false)));
1577 let inner_list_data = ArrayData::builder(inner_list_data_type.clone())
1578 .len(8)
1579 .add_buffer(value_offsets)
1580 .add_child_data(value_data)
1581 .build()?;
1582
1583 let mut validity_bits: [u8; 1] = [0; 1];
1585 bit_util::set_bit(&mut validity_bits, 2);
1586
1587 let list_data_type =
1588 DataType::FixedSizeList(Arc::new(Field::new("f", inner_list_data_type, false)), 2);
1589 let list_data = ArrayData::builder(list_data_type)
1590 .len(4)
1591 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1592 .add_child_data(inner_list_data)
1593 .build()?;
1594
1595 let array = FixedSizeListArray::from(list_data);
1596
1597 let data = array.into_data();
1598 test_round_trip(&data)
1599 }
1600
1601 #[test]
1602 fn test_list_view() -> Result<()> {
1603 let value_data = ArrayData::builder(DataType::Int16)
1605 .len(8)
1606 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
1607 .build()
1608 .unwrap();
1609
1610 let value_offsets = Buffer::from(vec![0_i32, 3, 6]);
1613 let sizes_buffer = Buffer::from(vec![3_i32, 3, 2]);
1614
1615 let list_view_dt =
1617 DataType::ListView(Arc::new(Field::new_list_field(DataType::Int16, false)));
1618
1619 let list_view_data = ArrayData::builder(list_view_dt)
1620 .len(3)
1621 .add_buffer(value_offsets)
1622 .add_buffer(sizes_buffer)
1623 .add_child_data(value_data)
1624 .build()
1625 .unwrap();
1626
1627 test_round_trip(&list_view_data)
1628 }
1629
1630 #[test]
1631 fn test_list_view_with_nulls() -> Result<()> {
1632 let value_data = ArrayData::builder(DataType::Int16)
1634 .len(8)
1635 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
1636 .build()
1637 .unwrap();
1638
1639 let value_offsets = Buffer::from(vec![0_i32, 3, 6, 8]);
1642 let sizes_buffer = Buffer::from(vec![3_i32, 3, 2, 0]);
1643
1644 let list_view_dt =
1646 DataType::ListView(Arc::new(Field::new_list_field(DataType::Int16, true)));
1647
1648 let list_view_data = ArrayData::builder(list_view_dt)
1649 .len(4)
1650 .add_buffer(value_offsets)
1651 .add_buffer(sizes_buffer)
1652 .add_child_data(value_data)
1653 .nulls(Some(NullBuffer::from(vec![true, true, true, false])))
1654 .build()
1655 .unwrap();
1656
1657 test_round_trip(&list_view_data)
1658 }
1659
1660 #[test]
1661 #[cfg(not(feature = "force_validate"))]
1662 fn test_empty_string_with_non_zero_offset() -> Result<()> {
1663 use super::ImportedArrowArray;
1664 use arrow_buffer::{MutableBuffer, OffsetBuffer};
1665
1666 let data: Buffer = MutableBuffer::new(0).into();
1668 let offsets = OffsetBuffer::new(vec![123].into());
1669 let string_array =
1670 unsafe { StringArray::new_unchecked(offsets.clone(), data.clone(), None) };
1671
1672 let data = string_array.into_data();
1673
1674 let array = FFI_ArrowArray::new(&data);
1675 let schema = FFI_ArrowSchema::try_from(data.data_type())?;
1676
1677 let dt = DataType::try_from(&schema)?;
1678 let array = Arc::new(array);
1679 let imported_array = ImportedArrowArray {
1680 array: &array,
1681 data_type: dt,
1682 owner: &array,
1683 };
1684
1685 let offset_buf_len = imported_array.buffer_len(1, &[], &imported_array.data_type)?;
1686 let data_buf_len = imported_array.buffer_len(2, &[], &imported_array.data_type)?;
1687
1688 assert_eq!(offset_buf_len, 4);
1689 assert_eq!(data_buf_len, 0);
1690
1691 test_round_trip(&imported_array.consume()?)
1692 }
1693
1694 fn roundtrip_string_array(array: StringArray) -> StringArray {
1695 let data = array.into_data();
1696
1697 let array = FFI_ArrowArray::new(&data);
1698 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1699
1700 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1701 StringArray::from(array)
1702 }
1703
1704 fn roundtrip_byte_view_array<T: ByteViewType>(
1705 array: GenericByteViewArray<T>,
1706 ) -> GenericByteViewArray<T> {
1707 let data = array.into_data();
1708
1709 let array = FFI_ArrowArray::new(&data);
1710 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1711
1712 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1713 GenericByteViewArray::<T>::from(array)
1714 }
1715
1716 fn extend_array(array: &dyn Array) -> ArrayRef {
1717 let len = array.len();
1718 let data = array.to_data();
1719
1720 let mut mutable = MutableArrayData::new(vec![&data], false, len);
1721 mutable.try_extend(0, 0, len).unwrap();
1722 make_array(mutable.freeze())
1723 }
1724
1725 #[test]
1726 fn test_extend_imported_string_slice() {
1727 let mut strings = vec![];
1728
1729 for i in 0..1000 {
1730 strings.push(format!("string: {i}"));
1731 }
1732
1733 let string_array = StringArray::from(strings);
1734
1735 let imported = roundtrip_string_array(string_array.clone());
1736 assert_eq!(imported.len(), 1000);
1737 assert_eq!(imported.value(0), "string: 0");
1738 assert_eq!(imported.value(499), "string: 499");
1739
1740 let copied = extend_array(&imported);
1741 assert_eq!(
1742 copied.as_any().downcast_ref::<StringArray>().unwrap(),
1743 &imported
1744 );
1745
1746 let slice = string_array.slice(500, 500);
1747
1748 let imported = roundtrip_string_array(slice);
1749 assert_eq!(imported.len(), 500);
1750 assert_eq!(imported.value(0), "string: 500");
1751 assert_eq!(imported.value(499), "string: 999");
1752
1753 let copied = extend_array(&imported);
1754 assert_eq!(
1755 copied.as_any().downcast_ref::<StringArray>().unwrap(),
1756 &imported
1757 );
1758 }
1759
1760 fn roundtrip_list_array(array: ListArray) -> ListArray {
1761 let data = array.into_data();
1762
1763 let array = FFI_ArrowArray::new(&data);
1764 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1765
1766 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1767 ListArray::from(array)
1768 }
1769
1770 #[test]
1771 fn test_extend_imported_list_slice() {
1772 let mut data = vec![];
1773
1774 for i in 0..1000 {
1775 let mut list = vec![];
1776 for j in 0..100 {
1777 list.push(Some(i * 1000 + j));
1778 }
1779 data.push(Some(list));
1780 }
1781
1782 let list_array = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1783
1784 let slice = list_array.slice(500, 500);
1785 let imported = roundtrip_list_array(slice.clone());
1786 assert_eq!(imported.len(), 500);
1787 assert_eq!(&slice, &imported);
1788
1789 let copied = extend_array(&imported);
1790 assert_eq!(
1791 copied.as_any().downcast_ref::<ListArray>().unwrap(),
1792 &imported
1793 );
1794 }
1795
1796 trait NativeFromStr {
1799 fn from_str(value: &str) -> &Self;
1800 }
1801
1802 impl NativeFromStr for str {
1803 fn from_str(value: &str) -> &Self {
1804 value
1805 }
1806 }
1807
1808 impl NativeFromStr for [u8] {
1809 fn from_str(value: &str) -> &Self {
1810 value.as_bytes()
1811 }
1812 }
1813
1814 #[test]
1815 #[cfg(not(feature = "force_validate"))]
1816 fn test_utf8_view_ffi_from_dangling_pointer() {
1817 let empty = GenericByteViewBuilder::<StringViewType>::new().finish();
1818 let buffers = empty.data_buffers().to_vec();
1819 let nulls = empty.nulls().cloned();
1820
1821 let alloc = Arc::new(1);
1823 let buffer = unsafe { Buffer::from_custom_allocation(NonNull::<u8>::dangling(), 0, alloc) };
1824 let views = unsafe { ScalarBuffer::new_unchecked(buffer) };
1825
1826 let str_view: GenericByteViewArray<StringViewType> =
1827 unsafe { GenericByteViewArray::new_unchecked(views, buffers, nulls) };
1828 let imported = roundtrip_byte_view_array(str_view);
1829 assert_eq!(imported.len(), 0);
1830 assert_eq!(&imported, &empty);
1831 }
1832
1833 #[test]
1834 fn test_round_trip_byte_view() {
1835 fn test_case<T>()
1836 where
1837 T: ByteViewType,
1838 T::Native: NativeFromStr,
1839 {
1840 macro_rules! run_test_case {
1841 ($array:expr) => {{
1842 let len = $array.len();
1844 let imported = roundtrip_byte_view_array($array);
1845 assert_eq!(imported.len(), len);
1846
1847 let copied = extend_array(&imported);
1848 assert_eq!(
1849 copied
1850 .as_any()
1851 .downcast_ref::<GenericByteViewArray<T>>()
1852 .unwrap(),
1853 &imported
1854 );
1855 }};
1856 }
1857
1858 let empty = GenericByteViewBuilder::<T>::new().finish();
1860 run_test_case!(empty);
1861
1862 let mut all_inlined = GenericByteViewBuilder::<T>::new();
1864 all_inlined.append_value(T::Native::from_str("inlined1"));
1865 all_inlined.append_value(T::Native::from_str("inlined2"));
1866 all_inlined.append_value(T::Native::from_str("inlined3"));
1867 let all_inlined = all_inlined.finish();
1868 assert_eq!(all_inlined.data_buffers().len(), 0);
1869 run_test_case!(all_inlined);
1870
1871 let mixed_one_variadic = {
1873 let mut builder = GenericByteViewBuilder::<T>::new();
1874 builder.append_value(T::Native::from_str("inlined"));
1875 let block_id =
1876 builder.append_block(Buffer::from("non-inlined-string-buffer".as_bytes()));
1877 builder.try_append_view(block_id, 0, 25).unwrap();
1878 builder.finish()
1879 };
1880 assert_eq!(mixed_one_variadic.data_buffers().len(), 1);
1881 run_test_case!(mixed_one_variadic);
1882
1883 let mixed_two_variadic = {
1885 let mut builder = GenericByteViewBuilder::<T>::new();
1886 builder.append_value(T::Native::from_str("inlined"));
1887 let block_id =
1888 builder.append_block(Buffer::from("non-inlined-string-buffer".as_bytes()));
1889 builder.try_append_view(block_id, 0, 25).unwrap();
1890
1891 let block_id = builder
1892 .append_block(Buffer::from("another-non-inlined-string-buffer".as_bytes()));
1893 builder.try_append_view(block_id, 0, 33).unwrap();
1894 builder.finish()
1895 };
1896 assert_eq!(mixed_two_variadic.data_buffers().len(), 2);
1897 run_test_case!(mixed_two_variadic);
1898 }
1899
1900 test_case::<StringViewType>();
1901 test_case::<BinaryViewType>();
1902 }
1903}