1use std::{borrow::Cow, mem::size_of, ptr::NonNull, sync::Arc};
92
93use arrow_buffer::{Buffer, MutableBuffer, bit_util};
94pub use arrow_data::ffi::FFI_ArrowArray;
95use arrow_data::{ArrayData, layout};
96pub use arrow_schema::ffi::FFI_ArrowSchema;
97use arrow_schema::{ArrowError, DataType, UnionMode};
98
99type Result<T> = std::result::Result<T, ArrowError>;
100
101fn bit_width(data_type: &DataType, i: usize) -> Result<usize> {
104 if let Some(primitive) = data_type.primitive_width() {
105 return match i {
106 0 => Err(ArrowError::CDataInterface(format!(
107 "The datatype \"{data_type}\" doesn't expect buffer at index 0. Please verify that the C data interface is correctly implemented."
108 ))),
109 1 => Ok(primitive * 8),
110 i => Err(ArrowError::CDataInterface(format!(
111 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
112 ))),
113 };
114 }
115
116 Ok(match (data_type, i) {
117 (DataType::Boolean, 1) => 1,
118 (DataType::Boolean, _) => {
119 return Err(ArrowError::CDataInterface(format!(
120 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
121 )));
122 }
123 (DataType::FixedSizeBinary(num_bytes), 1) => {
124 TryInto::<usize>::try_into(*num_bytes).map_err(|_| {
125 ArrowError::InvalidArgumentError(format!(
126 "cannot determine bit_width for FixedSizeBinary({num_bytes})"
127 ))
128 })? * u8::BITS as usize
129 }
130 (DataType::FixedSizeList(f, num_elems), 1) => {
131 let child_bit_width = bit_width(f.data_type(), 1)?;
132 child_bit_width * (*num_elems as usize)
133 }
134 (DataType::FixedSizeBinary(_) | DataType::FixedSizeList(_, _), _) => {
135 return Err(ArrowError::CDataInterface(format!(
136 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
137 )));
138 }
139 (DataType::Utf8 | DataType::Binary | DataType::List(_) | DataType::Map(_, _), 1) => {
143 i32::BITS as _
144 }
145 (DataType::Utf8 | DataType::Binary, 2) => u8::BITS as _,
146 (DataType::ListView(_), 1 | 2) => i32::BITS as _,
148 (DataType::LargeListView(_), 1 | 2) => i64::BITS as _,
150 (DataType::List(_) | DataType::Map(_, _), _) => {
151 return Err(ArrowError::CDataInterface(format!(
152 "The datatype \"{data_type}\" expects 2 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
153 )));
154 }
155 (DataType::Utf8 | DataType::Binary, _) => {
156 return Err(ArrowError::CDataInterface(format!(
157 "The datatype \"{data_type}\" expects 3 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
158 )));
159 }
160 (DataType::LargeUtf8 | DataType::LargeBinary | DataType::LargeList(_), 1) => i64::BITS as _,
163 (DataType::LargeUtf8 | DataType::LargeBinary | DataType::LargeList(_), 2) => u8::BITS as _,
164 (DataType::LargeUtf8 | DataType::LargeBinary | DataType::LargeList(_), _) => {
165 return Err(ArrowError::CDataInterface(format!(
166 "The datatype \"{data_type}\" expects 3 buffers, but requested {i}. Please verify that the C data interface is correctly implemented."
167 )));
168 }
169 (DataType::Utf8View | DataType::BinaryView, 1) => u128::BITS as _,
173 (DataType::Utf8View | DataType::BinaryView, _) => u8::BITS as _,
174 (DataType::Union(_, _), 0) => i8::BITS as _,
176 (DataType::Union(_, UnionMode::Dense), 1) => i32::BITS as _,
178 (DataType::Union(_, UnionMode::Sparse), _) => {
179 return Err(ArrowError::CDataInterface(format!(
180 "The datatype \"{data_type}\" expects 1 buffer, but requested {i}. Please verify that the C data interface is correctly implemented."
181 )));
182 }
183 (DataType::Union(_, UnionMode::Dense), _) => {
184 return Err(ArrowError::CDataInterface(format!(
185 "The datatype \"{data_type}\" expects 2 buffer, but requested {i}. Please verify that the C data interface is correctly implemented."
186 )));
187 }
188 (_, 0) => {
189 return Err(ArrowError::CDataInterface(format!(
192 "The datatype \"{data_type}\" doesn't expect buffer at index 0. Please verify that the C data interface is correctly implemented."
193 )));
194 }
195 _ => {
196 return Err(ArrowError::CDataInterface(format!(
197 "The datatype \"{data_type}\" is still not supported in Rust implementation"
198 )));
199 }
200 })
201}
202
203unsafe fn create_buffer(
211 owner: Arc<FFI_ArrowArray>,
212 array: &FFI_ArrowArray,
213 index: usize,
214 len: usize,
215) -> Option<Buffer> {
216 if array.num_buffers() == 0 {
217 return None;
218 }
219 NonNull::new(array.buffer(index).cast_mut())
220 .map(|ptr| unsafe { Buffer::from_custom_allocation(ptr, len, owner) })
221}
222
223pub fn to_ffi(data: &ArrayData) -> Result<(FFI_ArrowArray, FFI_ArrowSchema)> {
225 let array = FFI_ArrowArray::new(data);
226 let schema = FFI_ArrowSchema::try_from(data.data_type())?;
227 Ok((array, schema))
228}
229
230pub unsafe fn from_ffi(array: FFI_ArrowArray, schema: &FFI_ArrowSchema) -> Result<ArrayData> {
236 let dt = DataType::try_from(schema)?;
237 let array = Arc::new(array);
238 let tmp = ImportedArrowArray {
239 array: &array,
240 data_type: dt,
241 owner: &array,
242 };
243 tmp.consume()
245}
246
247pub unsafe fn from_ffi_and_data_type(
253 array: FFI_ArrowArray,
254 data_type: DataType,
255) -> Result<ArrayData> {
256 let array = Arc::new(array);
257 let tmp = ImportedArrowArray {
258 array: &array,
259 data_type,
260 owner: &array,
261 };
262 tmp.consume()
264}
265
266#[derive(Debug)]
267struct ImportedArrowArray<'a> {
268 array: &'a FFI_ArrowArray,
269 data_type: DataType,
270 owner: &'a Arc<FFI_ArrowArray>,
271}
272
273impl ImportedArrowArray<'_> {
274 fn consume(self) -> Result<ArrayData> {
275 let len = self.array.len();
276 let offset = self.array.offset();
277 let null_count = match &self.data_type {
278 DataType::Null => Some(0),
279 _ => self.array.null_count_opt(),
280 };
281
282 let data_layout = layout(&self.data_type);
283 let mut buffers = self.buffers(data_layout.can_contain_null_mask, data_layout.variadic)?;
284
285 if len == 0
288 && offset == 0
289 && matches!(
290 self.data_type,
291 DataType::Utf8 | DataType::Binary | DataType::LargeUtf8 | DataType::LargeBinary
292 )
293 {
294 buffers[0] = MutableBuffer::try_from_len_zeroed(buffers[0].len())
295 .map_err(|e| ArrowError::MemoryError(e.to_string()))?
296 .into();
297 }
298
299 let null_bit_buffer = if data_layout.can_contain_null_mask {
300 self.null_bit_buffer()
301 } else {
302 None
303 };
304
305 let mut child_data = self.consume_children()?;
306
307 if let Some(d) = self.dictionary()? {
308 assert!(child_data.is_empty());
311 child_data.push(d.consume()?);
312 }
313
314 let mut builder = ArrayData::builder(self.data_type)
318 .len(len)
319 .offset(offset)
320 .null_bit_buffer(null_bit_buffer)
321 .buffers(buffers)
322 .child_data(child_data)
323 .align_buffers(true);
324 if let Some(null_count) = null_count {
326 builder = builder.null_count(null_count);
327 }
328 unsafe { builder.skip_validation(true) }.build()
330 }
331
332 fn consume_children(&self) -> Result<Vec<ArrayData>> {
333 match &self.data_type {
334 DataType::List(field)
335 | DataType::FixedSizeList(field, _)
336 | DataType::LargeList(field)
337 | DataType::ListView(field)
338 | DataType::LargeListView(field)
339 | DataType::Map(field, _) => Ok([self.consume_child(0, field.data_type())?].to_vec()),
340 DataType::Struct(fields) => {
341 assert_eq!(fields.len(), self.array.num_children());
342 fields
343 .iter()
344 .enumerate()
345 .map(|(i, field)| self.consume_child(i, field.data_type()))
346 .collect::<Result<Vec<_>>>()
347 }
348 DataType::Union(union_fields, _) => {
349 assert_eq!(union_fields.len(), self.array.num_children());
350 union_fields
351 .iter()
352 .enumerate()
353 .map(|(i, (_, field))| self.consume_child(i, field.data_type()))
354 .collect::<Result<Vec<_>>>()
355 }
356 DataType::RunEndEncoded(run_ends_field, values_field) => Ok([
357 self.consume_child(0, run_ends_field.data_type())?,
358 self.consume_child(1, values_field.data_type())?,
359 ]
360 .to_vec()),
361 _ => Ok(Vec::new()),
362 }
363 }
364
365 fn consume_child(&self, index: usize, child_type: &DataType) -> Result<ArrayData> {
366 ImportedArrowArray {
367 array: self.array.child(index),
368 data_type: child_type.clone(),
369 owner: self.owner,
370 }
371 .consume()
372 }
373
374 fn buffers(&self, can_contain_null_mask: bool, variadic: bool) -> Result<Vec<Buffer>> {
377 let buffer_begin = can_contain_null_mask as usize;
379 let buffer_end = self.array.num_buffers() - usize::from(variadic);
380
381 let variadic_buffer_lens: Cow<'_, [i64]> = if variadic {
382 let num_variadic_buffers =
385 self.array.num_buffers() - (2 + usize::from(can_contain_null_mask));
386 #[expect(clippy::cast_ptr_alignment)]
388 let lengths = self
389 .array
390 .buffer(self.array.num_buffers() - 1)
391 .cast::<i64>();
392 if num_variadic_buffers == 0 {
393 Cow::Borrowed(&[])
395 } else if lengths.is_aligned() {
396 Cow::Borrowed(unsafe { std::slice::from_raw_parts(lengths, num_variadic_buffers) })
398 } else {
399 Cow::Owned(
401 (0..num_variadic_buffers)
402 .map(|i| unsafe { lengths.add(i).read_unaligned() })
403 .collect(),
404 )
405 }
406 } else {
407 Cow::Borrowed(&[])
408 };
409
410 (buffer_begin..buffer_end)
411 .map(|index| {
412 let len = self.buffer_len(index, &variadic_buffer_lens, &self.data_type)?;
413 match unsafe { create_buffer(self.owner.clone(), self.array, index, len) } {
414 Some(buf) => {
415 if buf.is_empty() {
420 Ok(MutableBuffer::default().into())
421 } else {
422 Ok(buf)
423 }
424 }
425 None if len == 0 => {
426 Ok(MutableBuffer::default().into())
429 }
430 None => Err(ArrowError::CDataInterface(format!(
431 "The external buffer at position {index} is null."
432 ))),
433 }
434 })
435 .collect()
436 }
437
438 fn buffer_len(
443 &self,
444 i: usize,
445 variadic_buffer_lengths: &[i64],
446 dt: &DataType,
447 ) -> Result<usize> {
448 let data_type = match dt {
450 DataType::Dictionary(key_data_type, _) => key_data_type.as_ref(),
451 dt => dt,
452 };
453
454 let length = self.array.len() + self.array.offset();
457
458 Ok(match (&data_type, i) {
460 (
461 DataType::Utf8
462 | DataType::LargeUtf8
463 | DataType::Binary
464 | DataType::LargeBinary
465 | DataType::List(_)
466 | DataType::LargeList(_)
467 | DataType::Map(_, _),
468 1,
469 ) => {
470 let bits = bit_width(data_type, i)?;
472 debug_assert_eq!(bits % 8, 0);
473 (length + 1) * (bits / 8)
474 }
475 (DataType::ListView(_) | DataType::LargeListView(_), 1 | 2) => {
476 let bits = bit_width(data_type, i)?;
477 debug_assert_eq!(bits % 8, 0);
478 length * (bits / 8)
479 }
480 (DataType::Utf8 | DataType::Binary, 2) => {
481 if self.array.is_empty() && self.array.offset() == 0 {
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).cast::<i32>();
499 (unsafe {
503 offset_buffer
504 .add(len / size_of::<i32>() - 1)
505 .read_unaligned()
506 }) as usize
507 }
508 (DataType::LargeUtf8 | DataType::LargeBinary, 2) => {
509 if self.array.is_empty() && self.array.offset() == 0 {
511 return Ok(0);
512 }
513
514 let len = self.buffer_len(1, variadic_buffer_lengths, dt)?;
516 #[expect(clippy::cast_ptr_alignment)]
519 let offset_buffer = self.array.buffer(1).cast::<i64>();
520 (unsafe {
522 offset_buffer
523 .add(len / size_of::<i64>() - 1)
524 .read_unaligned()
525 }) as usize
526 }
527 (DataType::Utf8View | DataType::BinaryView, 1) => std::mem::size_of::<u128>() * length,
532 (DataType::Utf8View | DataType::BinaryView, i) => {
533 variadic_buffer_lengths[i - 2] as usize
534 }
535 _ => {
537 let bits = bit_width(data_type, i)?;
538 bit_util::ceil(length * bits, 8)
539 }
540 })
541 }
542
543 fn null_bit_buffer(&self) -> Option<Buffer> {
547 let length = self.array.len() + self.array.offset();
551 let buffer_len = bit_util::ceil(length, 8);
552
553 unsafe { create_buffer(self.owner.clone(), self.array, 0, buffer_len) }
554 }
555
556 fn dictionary(&self) -> Result<Option<ImportedArrowArray<'_>>> {
557 match (self.array.dictionary(), &self.data_type) {
558 (Some(array), DataType::Dictionary(_, value_type)) => Ok(Some(ImportedArrowArray {
559 array,
560 data_type: value_type.as_ref().clone(),
561 owner: self.owner,
562 })),
563 (Some(_), _) => Err(ArrowError::CDataInterface(
564 "Got dictionary in FFI_ArrowArray for non-dictionary data type".to_string(),
565 )),
566 (None, DataType::Dictionary(_, _)) => Err(ArrowError::CDataInterface(
567 "Missing dictionary in FFI_ArrowArray for dictionary data type".to_string(),
568 )),
569 (_, _) => Ok(None),
570 }
571 }
572}
573
574#[cfg(test)]
575mod tests_to_then_from_ffi {
576 use std::collections::HashMap;
577 use std::mem::ManuallyDrop;
578
579 use arrow_buffer::{ArrowNativeType, NullBuffer};
580 use arrow_schema::Field;
581
582 use crate::builder::UnionBuilder;
583 use crate::cast::AsArray;
584 use crate::types::{Float64Type, Int8Type, Int32Type};
585 use crate::*;
586
587 use super::*;
588
589 #[test]
590 fn test_round_trip() {
591 let array = Int32Array::from(vec![1, 2, 3]);
593
594 let (array, schema) = to_ffi(&array.into_data()).unwrap();
596
597 let array = Int32Array::from(unsafe { from_ffi(array, &schema) }.unwrap());
599
600 assert_eq!(array, Int32Array::from(vec![1, 2, 3]));
602 }
603
604 #[test]
605 fn test_import() {
606 let data = Int32Array::from(vec![1, 2, 3]).into_data();
610 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
611 let array = FFI_ArrowArray::new(&data);
612
613 let schema = Box::new(ManuallyDrop::new(schema));
615 let array = Box::new(ManuallyDrop::new(array));
616
617 let schema_ptr = std::ptr::from_ref(&**schema);
618 let array_ptr = std::ptr::from_ref(&**array);
619
620 let data =
624 unsafe { from_ffi(std::ptr::read(array_ptr), &std::ptr::read(schema_ptr)).unwrap() };
625
626 let array = Int32Array::from(data);
627 assert_eq!(array, Int32Array::from(vec![1, 2, 3]));
628 }
629
630 #[test]
631 fn test_round_trip_with_offset() -> Result<()> {
632 let array = Int32Array::from(vec![Some(1), Some(2), None, Some(3), None]);
634
635 let array = array.slice(1, 2);
636
637 let (array, schema) = to_ffi(&array.to_data())?;
639
640 let data = unsafe { from_ffi(array, &schema) }?;
642 let array = make_array(data);
643 let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
644
645 assert_eq!(array, &Int32Array::from(vec![Some(2), None]));
646
647 Ok(())
649 }
650
651 #[test]
652 #[cfg(not(feature = "force_validate"))]
653 fn test_decimal_round_trip() -> Result<()> {
654 let original_array = [Some(12345_i128), Some(-12345_i128), None]
656 .into_iter()
657 .collect::<Decimal128Array>()
658 .with_precision_and_scale(6, 2)
659 .unwrap();
660
661 let (array, schema) = to_ffi(&original_array.to_data())?;
663
664 let data = unsafe { from_ffi(array, &schema) }?;
666 let array = make_array(data);
667
668 let array = array.as_any().downcast_ref::<Decimal128Array>().unwrap();
670
671 assert_eq!(array, &original_array);
673
674 Ok(())
676 }
677 #[test]
680 fn test_decimal128_under_aligned_import() -> Result<()> {
681 let aligned = Buffer::from_vec(vec![0_i128, 1_i128, 2_i128]);
685 let under_aligned = aligned.slice(8);
686 assert_eq!(under_aligned.as_ptr().align_offset(8), 0);
687 assert_ne!(under_aligned.as_ptr().align_offset(16), 0);
688
689 let data = ArrayData::builder(DataType::FixedSizeBinary(16))
690 .len(2)
691 .add_buffer(under_aligned)
692 .build()?;
693
694 let array = FFI_ArrowArray::new(&data);
695 let imported = unsafe { from_ffi_and_data_type(array, DataType::Decimal128(10, 2)) }?;
696 let array = Decimal128Array::from(imported);
697
698 assert_eq!(array.len(), 2);
700 assert_eq!(array.value(0), 1_i128 << 64);
701 assert_eq!(array.value(1), 2_i128 << 64);
702 Ok(())
703 }
704
705 #[test]
706 fn test_null_count_handling() {
707 let int32_data = ArrayData::builder(DataType::Int32)
708 .len(10)
709 .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
710 .null_bit_buffer(Some(Buffer::from([0b01011111, 0b00000001])))
711 .build()
712 .unwrap();
713 let mut ffi_array = FFI_ArrowArray::new(&int32_data);
714 assert_eq!(3, ffi_array.null_count());
715 assert_eq!(Some(3), ffi_array.null_count_opt());
716 unsafe {
718 ffi_array.set_null_count(-1);
719 }
720 assert_eq!(None, ffi_array.null_count_opt());
721 let int32_data = unsafe { from_ffi_and_data_type(ffi_array, DataType::Int32) }.unwrap();
722 assert_eq!(3, int32_data.null_count());
723
724 let null_data = &ArrayData::new_null(&DataType::Null, 10);
725 let mut ffi_array = FFI_ArrowArray::new(null_data);
726 assert_eq!(10, ffi_array.null_count());
727 assert_eq!(Some(10), ffi_array.null_count_opt());
728 unsafe {
730 ffi_array.set_null_count(-1);
731 }
732 assert_eq!(None, ffi_array.null_count_opt());
733 let null_data = unsafe { from_ffi_and_data_type(ffi_array, DataType::Null) }.unwrap();
734 assert_eq!(0, null_data.null_count());
735 }
736
737 fn test_generic_string<Offset: OffsetSizeTrait>() -> Result<()> {
738 let array = GenericStringArray::<Offset>::from(vec![Some("a"), None, Some("aaa")]);
740
741 let (array, schema) = to_ffi(&array.to_data())?;
743
744 let data = unsafe { from_ffi(array, &schema) }?;
746 let array = make_array(data);
747
748 let array = array
750 .as_any()
751 .downcast_ref::<GenericStringArray<Offset>>()
752 .unwrap();
753
754 let expected = GenericStringArray::<Offset>::from(vec![Some("a"), None, Some("aaa")]);
756 assert_eq!(array, &expected);
757
758 Ok(())
760 }
761
762 #[test]
763 fn test_string() -> Result<()> {
764 test_generic_string::<i32>()
765 }
766
767 #[test]
768 fn test_large_string() -> Result<()> {
769 test_generic_string::<i64>()
770 }
771
772 fn test_generic_list<Offset: OffsetSizeTrait>() -> Result<()> {
773 let value_data = ArrayData::builder(DataType::Int32)
775 .len(8)
776 .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7]))
777 .build()
778 .unwrap();
779
780 let value_offsets = [0_usize, 3, 6, 8]
783 .iter()
784 .map(|i| Offset::from_usize(*i).unwrap())
785 .collect::<Buffer>();
786
787 let list_data_type = GenericListArray::<Offset>::DATA_TYPE_CONSTRUCTOR(Arc::new(
789 Field::new_list_field(DataType::Int32, false),
790 ));
791
792 let list_data = ArrayData::builder(list_data_type)
793 .len(3)
794 .add_buffer(value_offsets)
795 .add_child_data(value_data)
796 .build()
797 .unwrap();
798
799 let array = GenericListArray::<Offset>::from(list_data.clone());
801
802 let (array, schema) = to_ffi(&array.to_data())?;
804
805 let data = unsafe { from_ffi(array, &schema) }?;
807 let array = make_array(data);
808
809 let array = array
811 .as_any()
812 .downcast_ref::<GenericListArray<Offset>>()
813 .unwrap();
814
815 let expected = GenericListArray::<Offset>::from(list_data);
817 assert_eq!(&array.value(0), &expected.value(0));
818 assert_eq!(&array.value(1), &expected.value(1));
819 assert_eq!(&array.value(2), &expected.value(2));
820
821 Ok(())
823 }
824
825 #[test]
826 fn test_list() -> Result<()> {
827 test_generic_list::<i32>()
828 }
829
830 #[test]
831 fn test_large_list() -> Result<()> {
832 test_generic_list::<i64>()
833 }
834
835 fn test_generic_list_view<Offset: OffsetSizeTrait + ArrowNativeType>() -> Result<()> {
836 let value_data = ArrayData::builder(DataType::Int16)
838 .len(8)
839 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
840 .build()
841 .unwrap();
842
843 let value_offsets = [0_usize, 3, 6]
846 .iter()
847 .map(|i| Offset::from_usize(*i).unwrap())
848 .collect::<Buffer>();
849
850 let sizes_buffer = [3_usize, 3, 2]
851 .iter()
852 .map(|i| Offset::from_usize(*i).unwrap())
853 .collect::<Buffer>();
854
855 let list_view_dt = GenericListViewArray::<Offset>::DATA_TYPE_CONSTRUCTOR(Arc::new(
857 Field::new_list_field(DataType::Int16, false),
858 ));
859
860 let list_data = ArrayData::builder(list_view_dt)
861 .len(3)
862 .add_buffer(value_offsets)
863 .add_buffer(sizes_buffer)
864 .add_child_data(value_data)
865 .build()
866 .unwrap();
867
868 let original = GenericListViewArray::<Offset>::from(list_data.clone());
869
870 let (array, schema) = to_ffi(&original.to_data())?;
872
873 let data = unsafe { from_ffi(array, &schema) }?;
875 let array = make_array(data);
876
877 let array = array
879 .as_any()
880 .downcast_ref::<GenericListViewArray<Offset>>()
881 .unwrap();
882
883 assert_eq!(&array.value(0), &original.value(0));
884 assert_eq!(&array.value(1), &original.value(1));
885 assert_eq!(&array.value(2), &original.value(2));
886
887 Ok(())
888 }
889
890 #[test]
891 fn test_list_view() -> Result<()> {
892 test_generic_list_view::<i32>()
893 }
894
895 #[test]
896 fn test_large_list_view() -> Result<()> {
897 test_generic_list_view::<i64>()
898 }
899
900 fn test_generic_binary<Offset: OffsetSizeTrait>() -> Result<()> {
901 let array: Vec<Option<&[u8]>> = vec![Some(b"a"), None, Some(b"aaa")];
903 let array = GenericBinaryArray::<Offset>::from(array);
904
905 let (array, schema) = to_ffi(&array.to_data())?;
907
908 let data = unsafe { from_ffi(array, &schema) }?;
910 let array = make_array(data);
911 let array = array
912 .as_any()
913 .downcast_ref::<GenericBinaryArray<Offset>>()
914 .unwrap();
915
916 let expected: Vec<Option<&[u8]>> = vec![Some(b"a"), None, Some(b"aaa")];
918 let expected = GenericBinaryArray::<Offset>::from(expected);
919 assert_eq!(array, &expected);
920
921 Ok(())
923 }
924
925 #[test]
926 fn test_binary() -> Result<()> {
927 test_generic_binary::<i32>()
928 }
929
930 #[test]
931 fn test_large_binary() -> Result<()> {
932 test_generic_binary::<i64>()
933 }
934
935 #[test]
936 fn test_bool() -> Result<()> {
937 let array = BooleanArray::from(vec![None, Some(true), Some(false)]);
939
940 let (array, schema) = to_ffi(&array.to_data())?;
942
943 let data = unsafe { from_ffi(array, &schema) }?;
945 let array = make_array(data);
946 let array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
947
948 assert_eq!(
950 array,
951 &BooleanArray::from(vec![None, Some(true), Some(false)])
952 );
953
954 Ok(())
956 }
957
958 #[test]
959 fn test_time32() -> Result<()> {
960 let array = Time32MillisecondArray::from(vec![None, Some(1), Some(2)]);
962
963 let (array, schema) = to_ffi(&array.to_data())?;
965
966 let data = unsafe { from_ffi(array, &schema) }?;
968 let array = make_array(data);
969 let array = array
970 .as_any()
971 .downcast_ref::<Time32MillisecondArray>()
972 .unwrap();
973
974 assert_eq!(
976 array,
977 &Time32MillisecondArray::from(vec![None, Some(1), Some(2)])
978 );
979
980 Ok(())
982 }
983
984 #[test]
985 fn test_timestamp() -> Result<()> {
986 let array = TimestampMillisecondArray::from(vec![None, Some(1), Some(2)]);
988
989 let (array, schema) = to_ffi(&array.to_data())?;
991
992 let data = unsafe { from_ffi(array, &schema) }?;
994 let array = make_array(data);
995 let array = array
996 .as_any()
997 .downcast_ref::<TimestampMillisecondArray>()
998 .unwrap();
999
1000 assert_eq!(
1002 array,
1003 &TimestampMillisecondArray::from(vec![None, Some(1), Some(2)])
1004 );
1005
1006 Ok(())
1008 }
1009
1010 #[test]
1011 fn test_fixed_size_binary_array() -> Result<()> {
1012 let values = vec![
1013 None,
1014 Some(vec![10, 10, 10]),
1015 None,
1016 Some(vec![20, 20, 20]),
1017 Some(vec![30, 30, 30]),
1018 None,
1019 ];
1020 let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 3)?;
1021
1022 let (array, schema) = to_ffi(&array.to_data())?;
1024
1025 let data = unsafe { from_ffi(array, &schema) }?;
1027 let array = make_array(data);
1028 let array = array
1029 .as_any()
1030 .downcast_ref::<FixedSizeBinaryArray>()
1031 .unwrap();
1032
1033 assert_eq!(
1035 array,
1036 &FixedSizeBinaryArray::try_from_sparse_iter_with_size(
1037 vec![
1038 None,
1039 Some(vec![10, 10, 10]),
1040 None,
1041 Some(vec![20, 20, 20]),
1042 Some(vec![30, 30, 30]),
1043 None,
1044 ]
1045 .into_iter(),
1046 3
1047 )?
1048 );
1049
1050 Ok(())
1052 }
1053
1054 #[test]
1055 fn test_fixed_size_list_array() -> Result<()> {
1056 let mut validity_bits: [u8; 1] = [0; 1];
1058 bit_util::set_bit(&mut validity_bits, 2);
1059
1060 let v: Vec<i32> = (0..9).collect();
1061 let value_data = ArrayData::builder(DataType::Int32)
1062 .len(9)
1063 .add_buffer(Buffer::from_slice_ref(&v))
1064 .build()?;
1065
1066 let list_data_type =
1067 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int32, false)), 3);
1068 let list_data = ArrayData::builder(list_data_type.clone())
1069 .len(3)
1070 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1071 .add_child_data(value_data)
1072 .build()?;
1073
1074 let (array, schema) = to_ffi(&list_data)?;
1076
1077 let data = unsafe { from_ffi(array, &schema) }?;
1079 let array = make_array(data);
1080 let array = array.as_any().downcast_ref::<FixedSizeListArray>().unwrap();
1081
1082 let mut expected_validity_bits: [u8; 1] = [0; 1];
1084 bit_util::set_bit(&mut expected_validity_bits, 2);
1085 bit_util::set_bit(&mut expected_validity_bits, 5);
1086
1087 let mut w = vec![];
1088 w.extend_from_slice(&v);
1089
1090 let expected_value_data = ArrayData::builder(DataType::Int32)
1091 .len(9)
1092 .add_buffer(Buffer::from_slice_ref(&w))
1093 .build()?;
1094
1095 let expected_list_data = ArrayData::builder(list_data_type)
1096 .len(3)
1097 .null_bit_buffer(Some(Buffer::from(expected_validity_bits)))
1098 .add_child_data(expected_value_data)
1099 .build()?;
1100 let expected_array = FixedSizeListArray::from(expected_list_data);
1101
1102 assert_eq!(array, &expected_array);
1104
1105 Ok(())
1107 }
1108
1109 #[test]
1110 fn test_dictionary() -> Result<()> {
1111 let values = vec!["a", "aaa", "aaa"];
1113 let dict_array: DictionaryArray<Int8Type> = values.into_iter().collect();
1114
1115 let (array, schema) = to_ffi(&dict_array.to_data())?;
1117
1118 let data = unsafe { from_ffi(array, &schema) }?;
1120 let array = make_array(data);
1121 let actual = array
1122 .as_any()
1123 .downcast_ref::<DictionaryArray<Int8Type>>()
1124 .unwrap();
1125
1126 let new_values = vec!["a", "aaa", "aaa"];
1128 let expected: DictionaryArray<Int8Type> = new_values.into_iter().collect();
1129 assert_eq!(actual, &expected);
1130
1131 Ok(())
1133 }
1134
1135 #[test]
1136 fn test_duration() -> Result<()> {
1137 let array = DurationSecondArray::from(vec![None, Some(1), Some(2)]);
1139
1140 let (array, schema) = to_ffi(&array.to_data())?;
1142
1143 let data = unsafe { from_ffi(array, &schema) }?;
1145 let array = make_array(data);
1146 let array = array
1147 .as_any()
1148 .downcast_ref::<DurationSecondArray>()
1149 .unwrap();
1150
1151 assert_eq!(
1153 array,
1154 &DurationSecondArray::from(vec![None, Some(1), Some(2)])
1155 );
1156
1157 Ok(())
1159 }
1160
1161 #[test]
1162 fn test_map_array() -> Result<()> {
1163 let keys = vec!["a", "b", "c", "d", "e", "f", "g", "h"];
1164 let values_data = UInt32Array::from(vec![0u32, 10, 20, 30, 40, 50, 60, 70]);
1165
1166 let entry_offsets = [0, 3, 6, 8];
1169
1170 let map_array =
1171 MapArray::new_from_strings(keys.clone().into_iter(), &values_data, &entry_offsets)
1172 .unwrap();
1173
1174 let (array, schema) = to_ffi(&map_array.to_data())?;
1176
1177 let data = unsafe { from_ffi(array, &schema) }?;
1179 let array = make_array(data);
1180
1181 let array = array.as_any().downcast_ref::<MapArray>().unwrap();
1183 assert_eq!(array, &map_array);
1184
1185 Ok(())
1186 }
1187
1188 #[test]
1189 fn test_struct_array() -> Result<()> {
1190 let metadata: HashMap<String, String> =
1191 [("Hello".to_string(), "World! 😊".to_string())].into();
1192 let struct_array = StructArray::from(vec![(
1193 Arc::new(Field::new("a", DataType::Int32, false).with_metadata(metadata)),
1194 Arc::new(Int32Array::from(vec![2, 4, 6])) as Arc<dyn Array>,
1195 )]);
1196
1197 let (array, schema) = to_ffi(&struct_array.to_data())?;
1199
1200 let data = unsafe { from_ffi(array, &schema) }?;
1202 let array = make_array(data);
1203
1204 let array = array.as_any().downcast_ref::<StructArray>().unwrap();
1206 assert_eq!(array.data_type(), struct_array.data_type());
1207 assert_eq!(array, &struct_array);
1208
1209 Ok(())
1210 }
1211
1212 #[test]
1213 fn test_union_sparse_array() -> Result<()> {
1214 let mut builder = UnionBuilder::new_sparse();
1215 builder.append::<Int32Type>("a", 1).unwrap();
1216 builder.append_null::<Int32Type>("a").unwrap();
1217 builder.append::<Float64Type>("c", 3.0).unwrap();
1218 builder.append::<Int32Type>("a", 4).unwrap();
1219 let union = builder.build().unwrap();
1220
1221 let (array, schema) = to_ffi(&union.to_data())?;
1223
1224 let data = unsafe { from_ffi(array, &schema) }?;
1226 let array = make_array(data);
1227
1228 let array = array.as_any().downcast_ref::<UnionArray>().unwrap();
1229
1230 let expected_type_ids = vec![0_i8, 0, 1, 0];
1231
1232 assert_eq!(*array.type_ids(), expected_type_ids);
1234 for (i, id) in expected_type_ids.iter().enumerate() {
1235 assert_eq!(id, &array.type_id(i));
1236 }
1237
1238 assert!(array.offsets().is_none());
1240
1241 for i in 0..array.len() {
1242 let slot = array.value(i);
1243 match i {
1244 0 => {
1245 let slot = slot.as_primitive::<Int32Type>();
1246 assert!(!slot.is_null(0));
1247 assert_eq!(slot.len(), 1);
1248 let value = slot.value(0);
1249 assert_eq!(1_i32, value);
1250 }
1251 1 => assert!(slot.is_null(0)),
1252 2 => {
1253 let slot = slot.as_primitive::<Float64Type>();
1254 assert!(!slot.is_null(0));
1255 assert_eq!(slot.len(), 1);
1256 let value = slot.value(0);
1257 assert_eq!(value, 3_f64);
1258 }
1259 3 => {
1260 let slot = slot.as_primitive::<Int32Type>();
1261 assert!(!slot.is_null(0));
1262 assert_eq!(slot.len(), 1);
1263 let value = slot.value(0);
1264 assert_eq!(4_i32, value);
1265 }
1266 _ => unreachable!(),
1267 }
1268 }
1269
1270 Ok(())
1271 }
1272
1273 #[test]
1274 fn test_union_dense_array() -> Result<()> {
1275 let mut builder = UnionBuilder::new_dense();
1276 builder.append::<Int32Type>("a", 1).unwrap();
1277 builder.append_null::<Int32Type>("a").unwrap();
1278 builder.append::<Float64Type>("c", 3.0).unwrap();
1279 builder.append::<Int32Type>("a", 4).unwrap();
1280 let union = builder.build().unwrap();
1281
1282 let (array, schema) = to_ffi(&union.to_data())?;
1284
1285 let data = unsafe { from_ffi(array, &schema) }?;
1287 let array = UnionArray::from(data);
1288
1289 let expected_type_ids = vec![0_i8, 0, 1, 0];
1290
1291 assert_eq!(*array.type_ids(), expected_type_ids);
1293 for (i, id) in expected_type_ids.iter().enumerate() {
1294 assert_eq!(id, &array.type_id(i));
1295 }
1296
1297 assert!(array.offsets().is_some());
1298
1299 for i in 0..array.len() {
1300 let slot = array.value(i);
1301 match i {
1302 0 => {
1303 let slot = slot.as_primitive::<Int32Type>();
1304 assert!(!slot.is_null(0));
1305 assert_eq!(slot.len(), 1);
1306 let value = slot.value(0);
1307 assert_eq!(1_i32, value);
1308 }
1309 1 => assert!(slot.is_null(0)),
1310 2 => {
1311 let slot = slot.as_primitive::<Float64Type>();
1312 assert!(!slot.is_null(0));
1313 assert_eq!(slot.len(), 1);
1314 let value = slot.value(0);
1315 assert_eq!(value, 3_f64);
1316 }
1317 3 => {
1318 let slot = slot.as_primitive::<Int32Type>();
1319 assert!(!slot.is_null(0));
1320 assert_eq!(slot.len(), 1);
1321 let value = slot.value(0);
1322 assert_eq!(4_i32, value);
1323 }
1324 _ => unreachable!(),
1325 }
1326 }
1327
1328 Ok(())
1329 }
1330
1331 #[test]
1332 fn test_run_array() -> Result<()> {
1333 let value_data =
1334 PrimitiveArray::<Int8Type>::from_iter_values([10_i8, 11, 12, 13, 14, 15, 16, 17]);
1335
1336 let run_ends_values = [4_i32, 6, 7, 9, 13, 18, 20, 22];
1338 let run_ends_data =
1339 PrimitiveArray::<Int32Type>::from_iter_values(run_ends_values.iter().copied());
1340
1341 let ree_array = RunArray::<Int32Type>::try_new(&run_ends_data, &value_data).unwrap();
1343
1344 let (array, schema) = to_ffi(&ree_array.to_data())?;
1346
1347 let data = unsafe { from_ffi(array, &schema) }?;
1349 let array = make_array(data);
1350
1351 let array = array
1353 .as_any()
1354 .downcast_ref::<RunArray<Int32Type>>()
1355 .unwrap();
1356 assert_eq!(array.data_type(), ree_array.data_type());
1357 assert_eq!(array.run_ends().values(), ree_array.run_ends().values());
1358 assert_eq!(array.values(), ree_array.values());
1359
1360 Ok(())
1361 }
1362
1363 #[test]
1364 fn test_nullable_run_array() -> Result<()> {
1365 let nulls = NullBuffer::from(vec![true, false, true, true, false]);
1366 let value_data =
1367 PrimitiveArray::<Int8Type>::new(vec![1_i8, 2, 3, 4, 5].into(), Some(nulls));
1368
1369 let run_ends_values = [5_i32, 6, 7, 8, 10];
1371 let run_ends_data =
1372 PrimitiveArray::<Int32Type>::from_iter_values(run_ends_values.iter().copied());
1373
1374 let ree_array = RunArray::<Int32Type>::try_new(&run_ends_data, &value_data).unwrap();
1376
1377 let (array, schema) = to_ffi(&ree_array.to_data())?;
1379
1380 let data = unsafe { from_ffi(array, &schema) }?;
1382 let array = make_array(data);
1383
1384 let array = array
1386 .as_any()
1387 .downcast_ref::<RunArray<Int32Type>>()
1388 .unwrap();
1389 assert_eq!(array.data_type(), ree_array.data_type());
1390 assert_eq!(array.run_ends().values(), ree_array.run_ends().values());
1391 assert_eq!(array.values(), ree_array.values());
1392
1393 Ok(())
1394 }
1395}
1396
1397#[cfg(test)]
1398mod tests_from_ffi {
1399 #[cfg(not(feature = "force_validate"))]
1400 use std::ptr::NonNull;
1401 use std::sync::Arc;
1402
1403 use arrow_buffer::NullBuffer;
1404 #[cfg(not(feature = "force_validate"))]
1405 use arrow_buffer::{ScalarBuffer, bit_util, buffer::Buffer};
1406 #[cfg(feature = "force_validate")]
1407 use arrow_buffer::{bit_util, buffer::Buffer};
1408
1409 use arrow_data::ArrayData;
1410 use arrow_data::transform::MutableArrayData;
1411 use arrow_schema::{DataType, Field};
1412
1413 use super::Result;
1414
1415 use crate::builder::GenericByteViewBuilder;
1416 use crate::types::{BinaryViewType, ByteViewType, Int32Type, StringViewType};
1417 use crate::{
1418 ArrayRef, GenericByteViewArray, ListArray,
1419 array::{
1420 Array, BinaryArray, BooleanArray, DictionaryArray, FixedSizeBinaryArray,
1421 FixedSizeListArray, Int32Array, Int64Array, LargeBinaryArray, LargeStringArray,
1422 StringArray, StructArray, UInt32Array, UInt64Array,
1423 },
1424 ffi::{FFI_ArrowArray, FFI_ArrowSchema, from_ffi, to_ffi},
1425 make_array,
1426 };
1427
1428 fn test_round_trip(expected: &ArrayData) -> Result<()> {
1429 let array = FFI_ArrowArray::new(expected);
1431 let schema = FFI_ArrowSchema::try_from(expected.data_type())?;
1432
1433 let result = &unsafe { from_ffi(array, &schema) }?;
1435
1436 assert_eq!(result, expected);
1437 Ok(())
1438 }
1439
1440 #[test]
1441 fn test_u32() -> Result<()> {
1442 let array = UInt32Array::from(vec![Some(2), None, Some(1), None]);
1443 let data = array.into_data();
1444 test_round_trip(&data)
1445 }
1446
1447 #[test]
1448 fn test_u64() -> Result<()> {
1449 let array = UInt64Array::from(vec![Some(2), None, Some(1), None]);
1450 let data = array.into_data();
1451 test_round_trip(&data)
1452 }
1453
1454 #[test]
1455 fn test_i64() -> Result<()> {
1456 let array = Int64Array::from(vec![Some(2), None, Some(1), None]);
1457 let data = array.into_data();
1458 test_round_trip(&data)
1459 }
1460
1461 #[test]
1462 fn test_struct() -> Result<()> {
1463 let inner = StructArray::from(vec![
1464 (
1465 Arc::new(Field::new("a1", DataType::Boolean, false)),
1466 Arc::new(BooleanArray::from(vec![true, true, false, false])) as Arc<dyn Array>,
1467 ),
1468 (
1469 Arc::new(Field::new("a2", DataType::UInt32, false)),
1470 Arc::new(UInt32Array::from(vec![1, 2, 3, 4])),
1471 ),
1472 ]);
1473
1474 let array = StructArray::from(vec![
1475 (
1476 Arc::new(Field::new("a", inner.data_type().clone(), false)),
1477 Arc::new(inner) as Arc<dyn Array>,
1478 ),
1479 (
1480 Arc::new(Field::new("b", DataType::Boolean, false)),
1481 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
1482 ),
1483 (
1484 Arc::new(Field::new("c", DataType::UInt32, false)),
1485 Arc::new(UInt32Array::from(vec![42, 28, 19, 31])),
1486 ),
1487 ]);
1488 let data = array.into_data();
1489 test_round_trip(&data)
1490 }
1491
1492 #[test]
1493 fn test_dictionary() -> Result<()> {
1494 let values = StringArray::from(vec![Some("foo"), Some("bar"), None]);
1495 let keys = Int32Array::from(vec![
1496 Some(0),
1497 Some(1),
1498 None,
1499 Some(1),
1500 Some(1),
1501 None,
1502 Some(1),
1503 Some(2),
1504 Some(1),
1505 None,
1506 ]);
1507 let array = DictionaryArray::new(keys, Arc::new(values));
1508
1509 let data = array.into_data();
1510 test_round_trip(&data)
1511 }
1512
1513 #[test]
1514 fn test_fixed_size_binary() -> Result<()> {
1515 let values = vec![vec![10, 10, 10], vec![20, 20, 20], vec![30, 30, 30]];
1516 let array = FixedSizeBinaryArray::try_from_iter(values.into_iter())?;
1517
1518 let data = array.into_data();
1519 test_round_trip(&data)
1520 }
1521
1522 #[test]
1523 fn test_fixed_size_binary_with_nulls() -> Result<()> {
1524 let values = vec![
1525 None,
1526 Some(vec![10, 10, 10]),
1527 None,
1528 Some(vec![20, 20, 20]),
1529 Some(vec![30, 30, 30]),
1530 None,
1531 ];
1532 let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 3)?;
1533
1534 let data = array.into_data();
1535 test_round_trip(&data)
1536 }
1537
1538 #[test]
1539 fn test_fixed_size_list() -> Result<()> {
1540 let v: Vec<i64> = (0..9).collect();
1541 let value_data = ArrayData::builder(DataType::Int64)
1542 .len(9)
1543 .add_buffer(Buffer::from_slice_ref(v))
1544 .build()?;
1545 let list_data_type =
1546 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int64, false)), 3);
1547 let list_data = ArrayData::builder(list_data_type)
1548 .len(3)
1549 .add_child_data(value_data)
1550 .build()?;
1551 let array = FixedSizeListArray::from(list_data);
1552
1553 let data = array.into_data();
1554 test_round_trip(&data)
1555 }
1556
1557 #[test]
1558 fn test_fixed_size_list_with_nulls() -> Result<()> {
1559 let mut validity_bits: [u8; 1] = [0; 1];
1561 bit_util::set_bit(&mut validity_bits, 1);
1562 bit_util::set_bit(&mut validity_bits, 2);
1563 bit_util::set_bit(&mut validity_bits, 6);
1564
1565 let v: Vec<i16> = (0..16).collect();
1566 let value_data = ArrayData::builder(DataType::Int16)
1567 .len(16)
1568 .add_buffer(Buffer::from_slice_ref(v))
1569 .build()?;
1570 let list_data_type =
1571 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int16, false)), 2);
1572 let list_data = ArrayData::builder(list_data_type)
1573 .len(8)
1574 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1575 .add_child_data(value_data)
1576 .build()?;
1577 let array = FixedSizeListArray::from(list_data);
1578
1579 let data = array.into_data();
1580 test_round_trip(&data)
1581 }
1582
1583 #[test]
1584 fn test_fixed_size_list_nested() -> Result<()> {
1585 let v: Vec<i32> = (0..16).collect();
1586 let value_data = ArrayData::builder(DataType::Int32)
1587 .len(16)
1588 .add_buffer(Buffer::from_slice_ref(v))
1589 .build()?;
1590
1591 let offsets: Vec<i32> = vec![0, 2, 4, 6, 8, 10, 12, 14, 16];
1592 let value_offsets = Buffer::from_slice_ref(offsets);
1593 let inner_list_data_type =
1594 DataType::List(Arc::new(Field::new_list_field(DataType::Int32, false)));
1595 let inner_list_data = ArrayData::builder(inner_list_data_type.clone())
1596 .len(8)
1597 .add_buffer(value_offsets)
1598 .add_child_data(value_data)
1599 .build()?;
1600
1601 let mut validity_bits: [u8; 1] = [0; 1];
1603 bit_util::set_bit(&mut validity_bits, 2);
1604
1605 let list_data_type =
1606 DataType::FixedSizeList(Arc::new(Field::new("f", inner_list_data_type, false)), 2);
1607 let list_data = ArrayData::builder(list_data_type)
1608 .len(4)
1609 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1610 .add_child_data(inner_list_data)
1611 .build()?;
1612
1613 let array = FixedSizeListArray::from(list_data);
1614
1615 let data = array.into_data();
1616 test_round_trip(&data)
1617 }
1618
1619 #[test]
1620 fn test_list_view() -> Result<()> {
1621 let value_data = ArrayData::builder(DataType::Int16)
1623 .len(8)
1624 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
1625 .build()
1626 .unwrap();
1627
1628 let value_offsets = Buffer::from(vec![0_i32, 3, 6]);
1631 let sizes_buffer = Buffer::from(vec![3_i32, 3, 2]);
1632
1633 let list_view_dt =
1635 DataType::ListView(Arc::new(Field::new_list_field(DataType::Int16, false)));
1636
1637 let list_view_data = ArrayData::builder(list_view_dt)
1638 .len(3)
1639 .add_buffer(value_offsets)
1640 .add_buffer(sizes_buffer)
1641 .add_child_data(value_data)
1642 .build()
1643 .unwrap();
1644
1645 test_round_trip(&list_view_data)
1646 }
1647
1648 #[test]
1649 fn test_list_view_with_nulls() -> Result<()> {
1650 let value_data = ArrayData::builder(DataType::Int16)
1652 .len(8)
1653 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
1654 .build()
1655 .unwrap();
1656
1657 let value_offsets = Buffer::from(vec![0_i32, 3, 6, 8]);
1660 let sizes_buffer = Buffer::from(vec![3_i32, 3, 2, 0]);
1661
1662 let list_view_dt =
1664 DataType::ListView(Arc::new(Field::new_list_field(DataType::Int16, true)));
1665
1666 let list_view_data = ArrayData::builder(list_view_dt)
1667 .len(4)
1668 .add_buffer(value_offsets)
1669 .add_buffer(sizes_buffer)
1670 .add_child_data(value_data)
1671 .nulls(Some(NullBuffer::from(vec![true, true, true, false])))
1672 .build()
1673 .unwrap();
1674
1675 test_round_trip(&list_view_data)
1676 }
1677
1678 #[test]
1679 #[cfg(not(feature = "force_validate"))]
1680 fn test_empty_string_with_non_zero_offset() -> Result<()> {
1681 use super::ImportedArrowArray;
1682 use arrow_buffer::{MutableBuffer, OffsetBuffer};
1683
1684 let data: Buffer = MutableBuffer::new(0).into();
1686 let offsets = OffsetBuffer::new(vec![123].into());
1687 let string_array =
1688 unsafe { StringArray::new_unchecked(offsets.clone(), data.clone(), None) };
1689
1690 let data = string_array.into_data();
1691
1692 let array = FFI_ArrowArray::new(&data);
1693 let schema = FFI_ArrowSchema::try_from(data.data_type())?;
1694
1695 let dt = DataType::try_from(&schema)?;
1696 let array = Arc::new(array);
1697 let imported_array = ImportedArrowArray {
1698 array: &array,
1699 data_type: dt,
1700 owner: &array,
1701 };
1702
1703 let offset_buf_len = imported_array.buffer_len(1, &[], &imported_array.data_type)?;
1704 let data_buf_len = imported_array.buffer_len(2, &[], &imported_array.data_type)?;
1705
1706 assert_eq!(offset_buf_len, 4);
1707 assert_eq!(data_buf_len, 0);
1708
1709 test_round_trip(&imported_array.consume()?)
1710 }
1711
1712 #[test]
1719 fn test_zero_length_bytes_at_non_zero_offset() -> Result<()> {
1720 let small = Buffer::from_slice_ref([0i32, 1, 3, 5]);
1722 let large = Buffer::from_slice_ref([0i64, 1, 3, 5]);
1723 let values = Buffer::from(b"xaabb".as_slice());
1724
1725 for (data_type, offsets) in [
1726 (DataType::Utf8, &small),
1727 (DataType::Binary, &small),
1728 (DataType::LargeUtf8, &large),
1729 (DataType::LargeBinary, &large),
1730 ] {
1731 for offset in 0..4 {
1732 let data = ArrayData::try_new(
1733 data_type.clone(),
1734 0,
1735 None,
1736 offset,
1737 vec![offsets.clone(), values.clone()],
1738 vec![],
1739 )?;
1740
1741 let array = FFI_ArrowArray::new(&data);
1742 let schema = FFI_ArrowSchema::try_from(&data_type)?;
1743 let imported = unsafe { from_ffi(array, &schema) }?;
1744
1745 imported.validate_full()?;
1748 assert_eq!(imported.len(), 0);
1749 assert_eq!(imported, data);
1750
1751 assert_eq!(imported.buffers()[1].len(), [0, 1, 3, 5][offset]);
1754 }
1755 }
1756
1757 Ok(())
1758 }
1759
1760 #[test]
1765 fn test_empty_slice_of_bytes() -> Result<()> {
1766 let arrays: [ArrayRef; 4] = [
1767 Arc::new(StringArray::from(vec!["ab", "c"])),
1768 Arc::new(BinaryArray::from(vec![b"ab".as_ref(), b"c"])),
1769 Arc::new(LargeStringArray::from(vec!["ab", "c"])),
1770 Arc::new(LargeBinaryArray::from(vec![b"ab".as_ref(), b"c"])),
1771 ];
1772 for array in arrays {
1773 let data = array.slice(1, 0).to_data();
1774 let (array, schema) = to_ffi(&data)?;
1775 let imported = unsafe { from_ffi(array, &schema) }?;
1776
1777 imported.validate_full()?;
1778 assert_eq!(imported, data);
1779 }
1780
1781 Ok(())
1782 }
1783
1784 #[repr(C)]
1786 struct RawArrowArray {
1787 length: i64,
1788 null_count: i64,
1789 offset: i64,
1790 n_buffers: i64,
1791 n_children: i64,
1792 buffers: *mut *const std::ffi::c_void,
1793 children: *mut *mut RawArrowArray,
1794 dictionary: *mut RawArrowArray,
1795 release: Option<unsafe extern "C" fn(arg1: *mut FFI_ArrowArray)>,
1796 private_data: *mut std::ffi::c_void,
1797 }
1798
1799 unsafe extern "C" fn release_raw(array: *mut FFI_ArrowArray) {
1801 unsafe { (*array).set_release(None) };
1802 }
1803
1804 fn import_raw(data: &ArrayData, buffers: &mut [*const std::ffi::c_void]) -> Result<ArrayData> {
1806 let mut raw = RawArrowArray {
1807 length: data.len() as i64,
1808 null_count: 0,
1809 offset: 0,
1810 n_buffers: buffers.len() as i64,
1811 n_children: 0,
1812 buffers: buffers.as_mut_ptr(),
1813 children: std::ptr::null_mut(),
1814 dictionary: std::ptr::null_mut(),
1815 release: Some(release_raw),
1816 private_data: std::ptr::null_mut(),
1817 };
1818 let array = unsafe { FFI_ArrowArray::from_raw((&raw mut raw).cast()) };
1819 let schema = FFI_ArrowSchema::try_from(data.data_type())?;
1820 unsafe { from_ffi(array, &schema) }
1821 }
1822
1823 #[test]
1828 #[cfg(not(feature = "force_validate"))]
1829 fn test_bytes_with_unaligned_offsets() -> Result<()> {
1830 let arrays: [ArrayRef; 4] = [
1831 Arc::new(StringArray::from(vec!["a", "bb", "ccc"])),
1832 Arc::new(BinaryArray::from(vec![b"a".as_ref(), b"bb", b"ccc"])),
1833 Arc::new(LargeStringArray::from(vec!["a", "bb", "ccc"])),
1834 Arc::new(LargeBinaryArray::from(vec![b"a".as_ref(), b"bb", b"ccc"])),
1835 ];
1836 for array in arrays {
1837 let data = array.to_data();
1838 let mut offsets = arrow_buffer::MutableBuffer::from_len_zeroed(1);
1840 offsets.extend_from_slice(data.buffers()[0].as_slice());
1841 let offsets = Buffer::from(offsets).slice(1);
1842 assert_ne!(offsets.as_ptr().align_offset(4), 0);
1843
1844 let unaligned = unsafe {
1846 data.clone()
1847 .into_builder()
1848 .buffers(vec![offsets, data.buffers()[1].clone()])
1849 .build_unchecked()
1850 };
1851 let (array, schema) = to_ffi(&unaligned)?;
1852 let imported = unsafe { from_ffi(array, &schema) }?;
1853
1854 imported.validate_full()?;
1855 assert_eq!(imported, data);
1856 }
1857
1858 Ok(())
1859 }
1860
1861 #[test]
1866 fn test_views_with_unaligned_variadic_buffer_lengths() -> Result<()> {
1867 let values = ["first long value", "second long one", "third long value"];
1870 let mut strings = GenericByteViewBuilder::<StringViewType>::new().with_fixed_block_size(16);
1871 let mut binaries =
1872 GenericByteViewBuilder::<BinaryViewType>::new().with_fixed_block_size(16);
1873 for value in values {
1874 strings.append_value(value);
1875 binaries.append_value(value.as_bytes());
1876 }
1877 let arrays: [ArrayRef; 2] = [Arc::new(strings.finish()), Arc::new(binaries.finish())];
1878
1879 for array in arrays {
1880 let data = array.to_data();
1881 assert_eq!(data.buffers().len(), 4);
1882 let mut lengths = arrow_buffer::MutableBuffer::from_len_zeroed(1);
1884 for buffer in &data.buffers()[1..] {
1885 lengths.extend_from_slice(&(buffer.len() as i64).to_ne_bytes());
1886 }
1887 let lengths = &lengths[1..];
1888 assert_ne!(lengths.as_ptr().align_offset(8), 0);
1889
1890 let mut buffers = std::iter::once(std::ptr::null())
1891 .chain(data.buffers().iter().map(|b| b.as_ptr().cast()))
1892 .chain(std::iter::once(lengths.as_ptr().cast()))
1893 .collect::<Vec<_>>();
1894 let imported = import_raw(&data, &mut buffers)?;
1895
1896 imported.validate_full()?;
1897 assert_eq!(imported, data);
1898 }
1899
1900 Ok(())
1901 }
1902
1903 #[test]
1906 fn test_empty_slice_of_lists() -> Result<()> {
1907 use crate::builder::{
1908 Int32Builder, LargeListBuilder, ListBuilder, MapBuilder, StringBuilder,
1909 };
1910
1911 let mut list = ListBuilder::new(Int32Builder::new());
1912 list.append_value([Some(1), Some(2)]);
1913 list.append_value([Some(3)]);
1914 let mut large_list = LargeListBuilder::new(Int32Builder::new());
1915 large_list.append_value([Some(1), Some(2)]);
1916 large_list.append_value([Some(3)]);
1917 let mut map = MapBuilder::new(None, StringBuilder::new(), Int32Builder::new());
1918 for (k, v) in [("a", 1), ("b", 2)] {
1919 map.keys().append_value(k);
1920 map.values().append_value(v);
1921 map.append(true).unwrap();
1922 }
1923 let arrays: [ArrayRef; 3] = [
1924 Arc::new(list.finish()),
1925 Arc::new(large_list.finish()),
1926 Arc::new(map.finish()),
1927 ];
1928 for array in arrays {
1929 let data = array.slice(1, 0).to_data();
1930 let (array, schema) = to_ffi(&data)?;
1931 let imported = unsafe { from_ffi(array, &schema) }?;
1932
1933 imported.validate_full()?;
1934 assert_eq!(imported, data);
1935 }
1936
1937 Ok(())
1938 }
1939
1940 fn roundtrip_string_array(array: StringArray) -> StringArray {
1941 let data = array.into_data();
1942
1943 let array = FFI_ArrowArray::new(&data);
1944 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1945
1946 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1947 StringArray::from(array)
1948 }
1949
1950 fn roundtrip_byte_view_array<T: ByteViewType>(
1951 array: GenericByteViewArray<T>,
1952 ) -> GenericByteViewArray<T> {
1953 let data = array.into_data();
1954
1955 let array = FFI_ArrowArray::new(&data);
1956 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1957
1958 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1959 GenericByteViewArray::<T>::from(array)
1960 }
1961
1962 fn extend_array(array: &dyn Array) -> ArrayRef {
1963 let len = array.len();
1964 let data = array.to_data();
1965
1966 let mut mutable = MutableArrayData::new(vec![&data], false, len);
1967 mutable.try_extend(0, 0, len).unwrap();
1968 make_array(mutable.freeze())
1969 }
1970
1971 #[test]
1972 fn test_extend_imported_string_slice() {
1973 let mut strings = vec![];
1974
1975 for i in 0..1000 {
1976 strings.push(format!("string: {i}"));
1977 }
1978
1979 let string_array = StringArray::from(strings);
1980
1981 let imported = roundtrip_string_array(string_array.clone());
1982 assert_eq!(imported.len(), 1000);
1983 assert_eq!(imported.value(0), "string: 0");
1984 assert_eq!(imported.value(499), "string: 499");
1985
1986 let copied = extend_array(&imported);
1987 assert_eq!(
1988 copied.as_any().downcast_ref::<StringArray>().unwrap(),
1989 &imported
1990 );
1991
1992 let slice = string_array.slice(500, 500);
1993
1994 let imported = roundtrip_string_array(slice);
1995 assert_eq!(imported.len(), 500);
1996 assert_eq!(imported.value(0), "string: 500");
1997 assert_eq!(imported.value(499), "string: 999");
1998
1999 let copied = extend_array(&imported);
2000 assert_eq!(
2001 copied.as_any().downcast_ref::<StringArray>().unwrap(),
2002 &imported
2003 );
2004 }
2005
2006 fn roundtrip_list_array(array: ListArray) -> ListArray {
2007 let data = array.into_data();
2008
2009 let array = FFI_ArrowArray::new(&data);
2010 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
2011
2012 let array = unsafe { from_ffi(array, &schema) }.unwrap();
2013 ListArray::from(array)
2014 }
2015
2016 #[test]
2017 fn test_extend_imported_list_slice() {
2018 let mut data = vec![];
2019
2020 for i in 0..1000 {
2021 let mut list = vec![];
2022 for j in 0..100 {
2023 list.push(Some(i * 1000 + j));
2024 }
2025 data.push(Some(list));
2026 }
2027
2028 let list_array = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
2029
2030 let slice = list_array.slice(500, 500);
2031 let imported = roundtrip_list_array(slice.clone());
2032 assert_eq!(imported.len(), 500);
2033 assert_eq!(&slice, &imported);
2034
2035 let copied = extend_array(&imported);
2036 assert_eq!(
2037 copied.as_any().downcast_ref::<ListArray>().unwrap(),
2038 &imported
2039 );
2040 }
2041
2042 trait NativeFromStr {
2045 fn from_str(value: &str) -> &Self;
2046 }
2047
2048 impl NativeFromStr for str {
2049 fn from_str(value: &str) -> &Self {
2050 value
2051 }
2052 }
2053
2054 impl NativeFromStr for [u8] {
2055 fn from_str(value: &str) -> &Self {
2056 value.as_bytes()
2057 }
2058 }
2059
2060 #[test]
2061 #[cfg(not(feature = "force_validate"))]
2062 fn test_utf8_view_ffi_from_dangling_pointer() {
2063 let empty = GenericByteViewBuilder::<StringViewType>::new().finish();
2064 let buffers = Arc::clone(empty.data_buffers());
2065 let nulls = empty.nulls().cloned();
2066
2067 let alloc = Arc::new(1);
2069 let buffer = unsafe { Buffer::from_custom_allocation(NonNull::<u8>::dangling(), 0, alloc) };
2070 let views = unsafe { ScalarBuffer::new_unchecked(buffer) };
2071
2072 let str_view: GenericByteViewArray<StringViewType> =
2073 unsafe { GenericByteViewArray::new_unchecked(views, buffers, nulls) };
2074 let imported = roundtrip_byte_view_array(str_view);
2075 assert_eq!(imported.len(), 0);
2076 assert_eq!(&imported, &empty);
2077 }
2078
2079 #[test]
2080 fn test_round_trip_byte_view() {
2081 fn test_case<T>()
2082 where
2083 T: ByteViewType,
2084 T::Native: NativeFromStr,
2085 {
2086 macro_rules! run_test_case {
2087 ($array:expr) => {{
2088 let len = $array.len();
2090 let imported = roundtrip_byte_view_array($array);
2091 assert_eq!(imported.len(), len);
2092
2093 let copied = extend_array(&imported);
2094 assert_eq!(
2095 copied
2096 .as_any()
2097 .downcast_ref::<GenericByteViewArray<T>>()
2098 .unwrap(),
2099 &imported
2100 );
2101 }};
2102 }
2103
2104 let empty = GenericByteViewBuilder::<T>::new().finish();
2106 run_test_case!(empty);
2107
2108 let mut all_inlined = GenericByteViewBuilder::<T>::new();
2110 all_inlined.append_value(T::Native::from_str("inlined1"));
2111 all_inlined.append_value(T::Native::from_str("inlined2"));
2112 all_inlined.append_value(T::Native::from_str("inlined3"));
2113 let all_inlined = all_inlined.finish();
2114 assert_eq!(all_inlined.data_buffers().len(), 0);
2115 run_test_case!(all_inlined);
2116
2117 let mixed_one_variadic = {
2119 let mut builder = GenericByteViewBuilder::<T>::new();
2120 builder.append_value(T::Native::from_str("inlined"));
2121 let block_id = builder.append_block(Buffer::from(b"non-inlined-string-buffer"));
2122 builder.try_append_view(block_id, 0, 25).unwrap();
2123 builder.finish()
2124 };
2125 assert_eq!(mixed_one_variadic.data_buffers().len(), 1);
2126 run_test_case!(mixed_one_variadic);
2127
2128 let mixed_two_variadic = {
2130 let mut builder = GenericByteViewBuilder::<T>::new();
2131 builder.append_value(T::Native::from_str("inlined"));
2132 let block_id = builder.append_block(Buffer::from(b"non-inlined-string-buffer"));
2133 builder.try_append_view(block_id, 0, 25).unwrap();
2134
2135 let block_id = builder
2136 .append_block(Buffer::from("another-non-inlined-string-buffer".as_bytes()));
2137 builder.try_append_view(block_id, 0, 33).unwrap();
2138 builder.finish()
2139 };
2140 assert_eq!(mixed_two_variadic.data_buffers().len(), 2);
2141 run_test_case!(mixed_two_variadic);
2142 }
2143
2144 test_case::<StringViewType>();
2145 test_case::<BinaryViewType>();
2146 }
2147}