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 tmp.consume()
258}
259
260pub unsafe fn from_ffi_and_data_type(
266 array: FFI_ArrowArray,
267 data_type: DataType,
268) -> Result<ArrayData> {
269 let array = Arc::new(array);
270 let tmp = ImportedArrowArray {
271 array: &array,
272 data_type,
273 owner: &array,
274 };
275 tmp.consume()
277}
278
279#[derive(Debug)]
280struct ImportedArrowArray<'a> {
281 array: &'a FFI_ArrowArray,
282 data_type: DataType,
283 owner: &'a Arc<FFI_ArrowArray>,
284}
285
286impl ImportedArrowArray<'_> {
287 fn consume(self) -> Result<ArrayData> {
288 let len = self.array.len();
289 let offset = self.array.offset();
290 let null_count = match &self.data_type {
291 DataType::Null => Some(0),
292 _ => self.array.null_count_opt(),
293 };
294
295 let data_layout = layout(&self.data_type);
296 let buffers = self.buffers(data_layout.can_contain_null_mask, data_layout.variadic)?;
297
298 let null_bit_buffer = if data_layout.can_contain_null_mask {
299 self.null_bit_buffer()
300 } else {
301 None
302 };
303
304 let mut child_data = self.consume_children()?;
305
306 if let Some(d) = self.dictionary()? {
307 assert!(child_data.is_empty());
310 child_data.push(d.consume()?);
311 }
312
313 let mut builder = ArrayData::builder(self.data_type)
317 .len(len)
318 .offset(offset)
319 .null_bit_buffer(null_bit_buffer)
320 .buffers(buffers)
321 .child_data(child_data)
322 .align_buffers(true);
323 if let Some(null_count) = null_count {
325 builder = builder.null_count(null_count);
326 }
327 unsafe { builder.skip_validation(true) }.build()
329 }
330
331 fn consume_children(&self) -> Result<Vec<ArrayData>> {
332 match &self.data_type {
333 DataType::List(field)
334 | DataType::FixedSizeList(field, _)
335 | DataType::LargeList(field)
336 | DataType::ListView(field)
337 | DataType::LargeListView(field)
338 | DataType::Map(field, _) => Ok([self.consume_child(0, field.data_type())?].to_vec()),
339 DataType::Struct(fields) => {
340 assert_eq!(fields.len(), self.array.num_children());
341 fields
342 .iter()
343 .enumerate()
344 .map(|(i, field)| self.consume_child(i, field.data_type()))
345 .collect::<Result<Vec<_>>>()
346 }
347 DataType::Union(union_fields, _) => {
348 assert_eq!(union_fields.len(), self.array.num_children());
349 union_fields
350 .iter()
351 .enumerate()
352 .map(|(i, (_, field))| self.consume_child(i, field.data_type()))
353 .collect::<Result<Vec<_>>>()
354 }
355 DataType::RunEndEncoded(run_ends_field, values_field) => Ok([
356 self.consume_child(0, run_ends_field.data_type())?,
357 self.consume_child(1, values_field.data_type())?,
358 ]
359 .to_vec()),
360 _ => Ok(Vec::new()),
361 }
362 }
363
364 fn consume_child(&self, index: usize, child_type: &DataType) -> Result<ArrayData> {
365 ImportedArrowArray {
366 array: self.array.child(index),
367 data_type: child_type.clone(),
368 owner: self.owner,
369 }
370 .consume()
371 }
372
373 fn buffers(&self, can_contain_null_mask: bool, variadic: bool) -> Result<Vec<Buffer>> {
376 let buffer_begin = can_contain_null_mask as usize;
378 let buffer_end = self.array.num_buffers() - usize::from(variadic);
379
380 let variadic_buffer_lens = if variadic {
381 let num_variadic_buffers =
384 self.array.num_buffers() - (2 + usize::from(can_contain_null_mask));
385 if num_variadic_buffers == 0 {
386 &[]
387 } else {
388 let lengths = self.array.buffer(self.array.num_buffers() - 1);
389 #[expect(
392 clippy::cast_ptr_alignment,
393 reason = "the C data interface requires aligned buffers"
394 )]
395 unsafe {
396 std::slice::from_raw_parts(lengths.cast::<i64>(), num_variadic_buffers)
397 }
398 }
399 } else {
400 &[]
401 };
402
403 (buffer_begin..buffer_end)
404 .map(|index| {
405 let len = self.buffer_len(index, variadic_buffer_lens, &self.data_type)?;
406 match unsafe { create_buffer(self.owner.clone(), self.array, index, len) } {
407 Some(buf) => {
408 if buf.is_empty() {
413 Ok(MutableBuffer::new(0).into())
414 } else {
415 Ok(buf)
416 }
417 }
418 None if len == 0 => {
419 Ok(MutableBuffer::new(0).into())
422 }
423 None => Err(ArrowError::CDataInterface(format!(
424 "The external buffer at position {index} is null."
425 ))),
426 }
427 })
428 .collect()
429 }
430
431 fn buffer_len(
436 &self,
437 i: usize,
438 variadic_buffer_lengths: &[i64],
439 dt: &DataType,
440 ) -> Result<usize> {
441 let data_type = match dt {
443 DataType::Dictionary(key_data_type, _) => key_data_type.as_ref(),
444 dt => dt,
445 };
446
447 let length = self.array.len() + self.array.offset();
450
451 Ok(match (&data_type, i) {
453 (
454 DataType::Utf8
455 | DataType::LargeUtf8
456 | DataType::Binary
457 | DataType::LargeBinary
458 | DataType::List(_)
459 | DataType::LargeList(_)
460 | DataType::Map(_, _),
461 1,
462 ) => {
463 let bits = bit_width(data_type, i)?;
465 debug_assert_eq!(bits % 8, 0);
466 (length + 1) * (bits / 8)
467 }
468 (DataType::ListView(_) | DataType::LargeListView(_), 1 | 2) => {
469 let bits = bit_width(data_type, i)?;
470 debug_assert_eq!(bits % 8, 0);
471 length * (bits / 8)
472 }
473 (DataType::Utf8 | DataType::Binary, 2) => {
474 if self.array.is_empty() && self.array.offset() == 0 {
483 return Ok(0);
484 }
485
486 let len = self.buffer_len(1, variadic_buffer_lengths, dt)?;
488 #[expect(clippy::cast_ptr_alignment)]
491 let offset_buffer = self.array.buffer(1).cast::<i32>();
492 (unsafe { *offset_buffer.add(len / size_of::<i32>() - 1) }) as usize
496 }
497 (DataType::LargeUtf8 | DataType::LargeBinary, 2) => {
498 if self.array.is_empty() && self.array.offset() == 0 {
500 return Ok(0);
501 }
502
503 let len = self.buffer_len(1, variadic_buffer_lengths, dt)?;
505 #[expect(clippy::cast_ptr_alignment)]
508 let offset_buffer = self.array.buffer(1).cast::<i64>();
509 (unsafe { *offset_buffer.add(len / size_of::<i64>() - 1) }) as usize
511 }
512 (DataType::Utf8View | DataType::BinaryView, 1) => std::mem::size_of::<u128>() * length,
517 (DataType::Utf8View | DataType::BinaryView, i) => {
518 variadic_buffer_lengths[i - 2] as usize
519 }
520 _ => {
522 let bits = bit_width(data_type, i)?;
523 bit_util::ceil(length * bits, 8)
524 }
525 })
526 }
527
528 fn null_bit_buffer(&self) -> Option<Buffer> {
532 let length = self.array.len() + self.array.offset();
536 let buffer_len = bit_util::ceil(length, 8);
537
538 unsafe { create_buffer(self.owner.clone(), self.array, 0, buffer_len) }
539 }
540
541 fn dictionary(&self) -> Result<Option<ImportedArrowArray<'_>>> {
542 match (self.array.dictionary(), &self.data_type) {
543 (Some(array), DataType::Dictionary(_, value_type)) => Ok(Some(ImportedArrowArray {
544 array,
545 data_type: value_type.as_ref().clone(),
546 owner: self.owner,
547 })),
548 (Some(_), _) => Err(ArrowError::CDataInterface(
549 "Got dictionary in FFI_ArrowArray for non-dictionary data type".to_string(),
550 )),
551 (None, DataType::Dictionary(_, _)) => Err(ArrowError::CDataInterface(
552 "Missing dictionary in FFI_ArrowArray for dictionary data type".to_string(),
553 )),
554 (_, _) => Ok(None),
555 }
556 }
557}
558
559#[cfg(test)]
560mod tests_to_then_from_ffi {
561 use std::collections::HashMap;
562 use std::mem::ManuallyDrop;
563
564 use arrow_buffer::{ArrowNativeType, NullBuffer};
565 use arrow_schema::Field;
566
567 use crate::builder::UnionBuilder;
568 use crate::cast::AsArray;
569 use crate::types::{Float64Type, Int8Type, Int32Type};
570 use crate::*;
571
572 use super::*;
573
574 #[test]
575 fn test_round_trip() {
576 let array = Int32Array::from(vec![1, 2, 3]);
578
579 let (array, schema) = to_ffi(&array.into_data()).unwrap();
581
582 let array = Int32Array::from(unsafe { from_ffi(array, &schema) }.unwrap());
584
585 assert_eq!(array, Int32Array::from(vec![1, 2, 3]));
587 }
588
589 #[test]
590 fn test_import() {
591 let data = Int32Array::from(vec![1, 2, 3]).into_data();
595 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
596 let array = FFI_ArrowArray::new(&data);
597
598 let schema = Box::new(ManuallyDrop::new(schema));
600 let array = Box::new(ManuallyDrop::new(array));
601
602 let schema_ptr = std::ptr::from_ref(&**schema);
603 let array_ptr = std::ptr::from_ref(&**array);
604
605 let data =
609 unsafe { from_ffi(std::ptr::read(array_ptr), &std::ptr::read(schema_ptr)).unwrap() };
610
611 let array = Int32Array::from(data);
612 assert_eq!(array, Int32Array::from(vec![1, 2, 3]));
613 }
614
615 #[test]
616 fn test_round_trip_with_offset() -> Result<()> {
617 let array = Int32Array::from(vec![Some(1), Some(2), None, Some(3), None]);
619
620 let array = array.slice(1, 2);
621
622 let (array, schema) = to_ffi(&array.to_data())?;
624
625 let data = unsafe { from_ffi(array, &schema) }?;
627 let array = make_array(data);
628 let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
629
630 assert_eq!(array, &Int32Array::from(vec![Some(2), None]));
631
632 Ok(())
634 }
635
636 #[test]
637 #[cfg(not(feature = "force_validate"))]
638 fn test_decimal_round_trip() -> Result<()> {
639 let original_array = [Some(12345_i128), Some(-12345_i128), None]
641 .into_iter()
642 .collect::<Decimal128Array>()
643 .with_precision_and_scale(6, 2)
644 .unwrap();
645
646 let (array, schema) = to_ffi(&original_array.to_data())?;
648
649 let data = unsafe { from_ffi(array, &schema) }?;
651 let array = make_array(data);
652
653 let array = array.as_any().downcast_ref::<Decimal128Array>().unwrap();
655
656 assert_eq!(array, &original_array);
658
659 Ok(())
661 }
662 #[test]
665 fn test_decimal128_under_aligned_import() -> Result<()> {
666 let aligned = Buffer::from_vec(vec![0_i128, 1_i128, 2_i128]);
670 let under_aligned = aligned.slice(8);
671 assert_eq!(under_aligned.as_ptr().align_offset(8), 0);
672 assert_ne!(under_aligned.as_ptr().align_offset(16), 0);
673
674 let data = ArrayData::builder(DataType::FixedSizeBinary(16))
675 .len(2)
676 .add_buffer(under_aligned)
677 .build()?;
678
679 let array = FFI_ArrowArray::new(&data);
680 let imported = unsafe { from_ffi_and_data_type(array, DataType::Decimal128(10, 2)) }?;
681 let array = Decimal128Array::from(imported);
682
683 assert_eq!(array.len(), 2);
685 assert_eq!(array.value(0), 1_i128 << 64);
686 assert_eq!(array.value(1), 2_i128 << 64);
687 Ok(())
688 }
689
690 #[test]
691 fn test_null_count_handling() {
692 let int32_data = ArrayData::builder(DataType::Int32)
693 .len(10)
694 .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
695 .null_bit_buffer(Some(Buffer::from([0b01011111, 0b00000001])))
696 .build()
697 .unwrap();
698 let mut ffi_array = FFI_ArrowArray::new(&int32_data);
699 assert_eq!(3, ffi_array.null_count());
700 assert_eq!(Some(3), ffi_array.null_count_opt());
701 unsafe {
703 ffi_array.set_null_count(-1);
704 }
705 assert_eq!(None, ffi_array.null_count_opt());
706 let int32_data = unsafe { from_ffi_and_data_type(ffi_array, DataType::Int32) }.unwrap();
707 assert_eq!(3, int32_data.null_count());
708
709 let null_data = &ArrayData::new_null(&DataType::Null, 10);
710 let mut ffi_array = FFI_ArrowArray::new(null_data);
711 assert_eq!(10, ffi_array.null_count());
712 assert_eq!(Some(10), ffi_array.null_count_opt());
713 unsafe {
715 ffi_array.set_null_count(-1);
716 }
717 assert_eq!(None, ffi_array.null_count_opt());
718 let null_data = unsafe { from_ffi_and_data_type(ffi_array, DataType::Null) }.unwrap();
719 assert_eq!(0, null_data.null_count());
720 }
721
722 fn test_generic_string<Offset: OffsetSizeTrait>() -> Result<()> {
723 let array = GenericStringArray::<Offset>::from(vec![Some("a"), None, Some("aaa")]);
725
726 let (array, schema) = to_ffi(&array.to_data())?;
728
729 let data = unsafe { from_ffi(array, &schema) }?;
731 let array = make_array(data);
732
733 let array = array
735 .as_any()
736 .downcast_ref::<GenericStringArray<Offset>>()
737 .unwrap();
738
739 let expected = GenericStringArray::<Offset>::from(vec![Some("a"), None, Some("aaa")]);
741 assert_eq!(array, &expected);
742
743 Ok(())
745 }
746
747 #[test]
748 fn test_string() -> Result<()> {
749 test_generic_string::<i32>()
750 }
751
752 #[test]
753 fn test_large_string() -> Result<()> {
754 test_generic_string::<i64>()
755 }
756
757 fn test_generic_list<Offset: OffsetSizeTrait>() -> Result<()> {
758 let value_data = ArrayData::builder(DataType::Int32)
760 .len(8)
761 .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7]))
762 .build()
763 .unwrap();
764
765 let value_offsets = [0_usize, 3, 6, 8]
768 .iter()
769 .map(|i| Offset::from_usize(*i).unwrap())
770 .collect::<Buffer>();
771
772 let list_data_type = GenericListArray::<Offset>::DATA_TYPE_CONSTRUCTOR(Arc::new(
774 Field::new_list_field(DataType::Int32, false),
775 ));
776
777 let list_data = ArrayData::builder(list_data_type)
778 .len(3)
779 .add_buffer(value_offsets)
780 .add_child_data(value_data)
781 .build()
782 .unwrap();
783
784 let array = GenericListArray::<Offset>::from(list_data.clone());
786
787 let (array, schema) = to_ffi(&array.to_data())?;
789
790 let data = unsafe { from_ffi(array, &schema) }?;
792 let array = make_array(data);
793
794 let array = array
796 .as_any()
797 .downcast_ref::<GenericListArray<Offset>>()
798 .unwrap();
799
800 let expected = GenericListArray::<Offset>::from(list_data);
802 assert_eq!(&array.value(0), &expected.value(0));
803 assert_eq!(&array.value(1), &expected.value(1));
804 assert_eq!(&array.value(2), &expected.value(2));
805
806 Ok(())
808 }
809
810 #[test]
811 fn test_list() -> Result<()> {
812 test_generic_list::<i32>()
813 }
814
815 #[test]
816 fn test_large_list() -> Result<()> {
817 test_generic_list::<i64>()
818 }
819
820 fn test_generic_list_view<Offset: OffsetSizeTrait + ArrowNativeType>() -> Result<()> {
821 let value_data = ArrayData::builder(DataType::Int16)
823 .len(8)
824 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
825 .build()
826 .unwrap();
827
828 let value_offsets = [0_usize, 3, 6]
831 .iter()
832 .map(|i| Offset::from_usize(*i).unwrap())
833 .collect::<Buffer>();
834
835 let sizes_buffer = [3_usize, 3, 2]
836 .iter()
837 .map(|i| Offset::from_usize(*i).unwrap())
838 .collect::<Buffer>();
839
840 let list_view_dt = GenericListViewArray::<Offset>::DATA_TYPE_CONSTRUCTOR(Arc::new(
842 Field::new_list_field(DataType::Int16, false),
843 ));
844
845 let list_data = ArrayData::builder(list_view_dt)
846 .len(3)
847 .add_buffer(value_offsets)
848 .add_buffer(sizes_buffer)
849 .add_child_data(value_data)
850 .build()
851 .unwrap();
852
853 let original = GenericListViewArray::<Offset>::from(list_data.clone());
854
855 let (array, schema) = to_ffi(&original.to_data())?;
857
858 let data = unsafe { from_ffi(array, &schema) }?;
860 let array = make_array(data);
861
862 let array = array
864 .as_any()
865 .downcast_ref::<GenericListViewArray<Offset>>()
866 .unwrap();
867
868 assert_eq!(&array.value(0), &original.value(0));
869 assert_eq!(&array.value(1), &original.value(1));
870 assert_eq!(&array.value(2), &original.value(2));
871
872 Ok(())
873 }
874
875 #[test]
876 fn test_list_view() -> Result<()> {
877 test_generic_list_view::<i32>()
878 }
879
880 #[test]
881 fn test_large_list_view() -> Result<()> {
882 test_generic_list_view::<i64>()
883 }
884
885 fn test_generic_binary<Offset: OffsetSizeTrait>() -> Result<()> {
886 let array: Vec<Option<&[u8]>> = vec![Some(b"a"), None, Some(b"aaa")];
888 let array = GenericBinaryArray::<Offset>::from(array);
889
890 let (array, schema) = to_ffi(&array.to_data())?;
892
893 let data = unsafe { from_ffi(array, &schema) }?;
895 let array = make_array(data);
896 let array = array
897 .as_any()
898 .downcast_ref::<GenericBinaryArray<Offset>>()
899 .unwrap();
900
901 let expected: Vec<Option<&[u8]>> = vec![Some(b"a"), None, Some(b"aaa")];
903 let expected = GenericBinaryArray::<Offset>::from(expected);
904 assert_eq!(array, &expected);
905
906 Ok(())
908 }
909
910 #[test]
911 fn test_binary() -> Result<()> {
912 test_generic_binary::<i32>()
913 }
914
915 #[test]
916 fn test_large_binary() -> Result<()> {
917 test_generic_binary::<i64>()
918 }
919
920 #[test]
921 fn test_bool() -> Result<()> {
922 let array = BooleanArray::from(vec![None, Some(true), Some(false)]);
924
925 let (array, schema) = to_ffi(&array.to_data())?;
927
928 let data = unsafe { from_ffi(array, &schema) }?;
930 let array = make_array(data);
931 let array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
932
933 assert_eq!(
935 array,
936 &BooleanArray::from(vec![None, Some(true), Some(false)])
937 );
938
939 Ok(())
941 }
942
943 #[test]
944 fn test_time32() -> Result<()> {
945 let array = Time32MillisecondArray::from(vec![None, Some(1), Some(2)]);
947
948 let (array, schema) = to_ffi(&array.to_data())?;
950
951 let data = unsafe { from_ffi(array, &schema) }?;
953 let array = make_array(data);
954 let array = array
955 .as_any()
956 .downcast_ref::<Time32MillisecondArray>()
957 .unwrap();
958
959 assert_eq!(
961 array,
962 &Time32MillisecondArray::from(vec![None, Some(1), Some(2)])
963 );
964
965 Ok(())
967 }
968
969 #[test]
970 fn test_timestamp() -> Result<()> {
971 let array = TimestampMillisecondArray::from(vec![None, Some(1), Some(2)]);
973
974 let (array, schema) = to_ffi(&array.to_data())?;
976
977 let data = unsafe { from_ffi(array, &schema) }?;
979 let array = make_array(data);
980 let array = array
981 .as_any()
982 .downcast_ref::<TimestampMillisecondArray>()
983 .unwrap();
984
985 assert_eq!(
987 array,
988 &TimestampMillisecondArray::from(vec![None, Some(1), Some(2)])
989 );
990
991 Ok(())
993 }
994
995 #[test]
996 fn test_fixed_size_binary_array() -> Result<()> {
997 let values = vec![
998 None,
999 Some(vec![10, 10, 10]),
1000 None,
1001 Some(vec![20, 20, 20]),
1002 Some(vec![30, 30, 30]),
1003 None,
1004 ];
1005 let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 3)?;
1006
1007 let (array, schema) = to_ffi(&array.to_data())?;
1009
1010 let data = unsafe { from_ffi(array, &schema) }?;
1012 let array = make_array(data);
1013 let array = array
1014 .as_any()
1015 .downcast_ref::<FixedSizeBinaryArray>()
1016 .unwrap();
1017
1018 assert_eq!(
1020 array,
1021 &FixedSizeBinaryArray::try_from_sparse_iter_with_size(
1022 vec![
1023 None,
1024 Some(vec![10, 10, 10]),
1025 None,
1026 Some(vec![20, 20, 20]),
1027 Some(vec![30, 30, 30]),
1028 None,
1029 ]
1030 .into_iter(),
1031 3
1032 )?
1033 );
1034
1035 Ok(())
1037 }
1038
1039 #[test]
1040 fn test_fixed_size_list_array() -> Result<()> {
1041 let mut validity_bits: [u8; 1] = [0; 1];
1043 bit_util::set_bit(&mut validity_bits, 2);
1044
1045 let v: Vec<i32> = (0..9).collect();
1046 let value_data = ArrayData::builder(DataType::Int32)
1047 .len(9)
1048 .add_buffer(Buffer::from_slice_ref(&v))
1049 .build()?;
1050
1051 let list_data_type =
1052 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int32, false)), 3);
1053 let list_data = ArrayData::builder(list_data_type.clone())
1054 .len(3)
1055 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1056 .add_child_data(value_data)
1057 .build()?;
1058
1059 let (array, schema) = to_ffi(&list_data)?;
1061
1062 let data = unsafe { from_ffi(array, &schema) }?;
1064 let array = make_array(data);
1065 let array = array.as_any().downcast_ref::<FixedSizeListArray>().unwrap();
1066
1067 let mut expected_validity_bits: [u8; 1] = [0; 1];
1069 bit_util::set_bit(&mut expected_validity_bits, 2);
1070 bit_util::set_bit(&mut expected_validity_bits, 5);
1071
1072 let mut w = vec![];
1073 w.extend_from_slice(&v);
1074
1075 let expected_value_data = ArrayData::builder(DataType::Int32)
1076 .len(9)
1077 .add_buffer(Buffer::from_slice_ref(&w))
1078 .build()?;
1079
1080 let expected_list_data = ArrayData::builder(list_data_type)
1081 .len(3)
1082 .null_bit_buffer(Some(Buffer::from(expected_validity_bits)))
1083 .add_child_data(expected_value_data)
1084 .build()?;
1085 let expected_array = FixedSizeListArray::from(expected_list_data);
1086
1087 assert_eq!(array, &expected_array);
1089
1090 Ok(())
1092 }
1093
1094 #[test]
1095 fn test_dictionary() -> Result<()> {
1096 let values = vec!["a", "aaa", "aaa"];
1098 let dict_array: DictionaryArray<Int8Type> = values.into_iter().collect();
1099
1100 let (array, schema) = to_ffi(&dict_array.to_data())?;
1102
1103 let data = unsafe { from_ffi(array, &schema) }?;
1105 let array = make_array(data);
1106 let actual = array
1107 .as_any()
1108 .downcast_ref::<DictionaryArray<Int8Type>>()
1109 .unwrap();
1110
1111 let new_values = vec!["a", "aaa", "aaa"];
1113 let expected: DictionaryArray<Int8Type> = new_values.into_iter().collect();
1114 assert_eq!(actual, &expected);
1115
1116 Ok(())
1118 }
1119
1120 #[test]
1121 fn test_duration() -> Result<()> {
1122 let array = DurationSecondArray::from(vec![None, Some(1), Some(2)]);
1124
1125 let (array, schema) = to_ffi(&array.to_data())?;
1127
1128 let data = unsafe { from_ffi(array, &schema) }?;
1130 let array = make_array(data);
1131 let array = array
1132 .as_any()
1133 .downcast_ref::<DurationSecondArray>()
1134 .unwrap();
1135
1136 assert_eq!(
1138 array,
1139 &DurationSecondArray::from(vec![None, Some(1), Some(2)])
1140 );
1141
1142 Ok(())
1144 }
1145
1146 #[test]
1147 fn test_map_array() -> Result<()> {
1148 let keys = vec!["a", "b", "c", "d", "e", "f", "g", "h"];
1149 let values_data = UInt32Array::from(vec![0u32, 10, 20, 30, 40, 50, 60, 70]);
1150
1151 let entry_offsets = [0, 3, 6, 8];
1154
1155 let map_array =
1156 MapArray::new_from_strings(keys.clone().into_iter(), &values_data, &entry_offsets)
1157 .unwrap();
1158
1159 let (array, schema) = to_ffi(&map_array.to_data())?;
1161
1162 let data = unsafe { from_ffi(array, &schema) }?;
1164 let array = make_array(data);
1165
1166 let array = array.as_any().downcast_ref::<MapArray>().unwrap();
1168 assert_eq!(array, &map_array);
1169
1170 Ok(())
1171 }
1172
1173 #[test]
1174 fn test_struct_array() -> Result<()> {
1175 let metadata: HashMap<String, String> =
1176 [("Hello".to_string(), "World! 😊".to_string())].into();
1177 let struct_array = StructArray::from(vec![(
1178 Arc::new(Field::new("a", DataType::Int32, false).with_metadata(metadata)),
1179 Arc::new(Int32Array::from(vec![2, 4, 6])) as Arc<dyn Array>,
1180 )]);
1181
1182 let (array, schema) = to_ffi(&struct_array.to_data())?;
1184
1185 let data = unsafe { from_ffi(array, &schema) }?;
1187 let array = make_array(data);
1188
1189 let array = array.as_any().downcast_ref::<StructArray>().unwrap();
1191 assert_eq!(array.data_type(), struct_array.data_type());
1192 assert_eq!(array, &struct_array);
1193
1194 Ok(())
1195 }
1196
1197 #[test]
1198 fn test_union_sparse_array() -> Result<()> {
1199 let mut builder = UnionBuilder::new_sparse();
1200 builder.append::<Int32Type>("a", 1).unwrap();
1201 builder.append_null::<Int32Type>("a").unwrap();
1202 builder.append::<Float64Type>("c", 3.0).unwrap();
1203 builder.append::<Int32Type>("a", 4).unwrap();
1204 let union = builder.build().unwrap();
1205
1206 let (array, schema) = to_ffi(&union.to_data())?;
1208
1209 let data = unsafe { from_ffi(array, &schema) }?;
1211 let array = make_array(data);
1212
1213 let array = array.as_any().downcast_ref::<UnionArray>().unwrap();
1214
1215 let expected_type_ids = vec![0_i8, 0, 1, 0];
1216
1217 assert_eq!(*array.type_ids(), expected_type_ids);
1219 for (i, id) in expected_type_ids.iter().enumerate() {
1220 assert_eq!(id, &array.type_id(i));
1221 }
1222
1223 assert!(array.offsets().is_none());
1225
1226 for i in 0..array.len() {
1227 let slot = array.value(i);
1228 match i {
1229 0 => {
1230 let slot = slot.as_primitive::<Int32Type>();
1231 assert!(!slot.is_null(0));
1232 assert_eq!(slot.len(), 1);
1233 let value = slot.value(0);
1234 assert_eq!(1_i32, value);
1235 }
1236 1 => assert!(slot.is_null(0)),
1237 2 => {
1238 let slot = slot.as_primitive::<Float64Type>();
1239 assert!(!slot.is_null(0));
1240 assert_eq!(slot.len(), 1);
1241 let value = slot.value(0);
1242 assert_eq!(value, 3_f64);
1243 }
1244 3 => {
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!(4_i32, value);
1250 }
1251 _ => unreachable!(),
1252 }
1253 }
1254
1255 Ok(())
1256 }
1257
1258 #[test]
1259 fn test_union_dense_array() -> Result<()> {
1260 let mut builder = UnionBuilder::new_dense();
1261 builder.append::<Int32Type>("a", 1).unwrap();
1262 builder.append_null::<Int32Type>("a").unwrap();
1263 builder.append::<Float64Type>("c", 3.0).unwrap();
1264 builder.append::<Int32Type>("a", 4).unwrap();
1265 let union = builder.build().unwrap();
1266
1267 let (array, schema) = to_ffi(&union.to_data())?;
1269
1270 let data = unsafe { from_ffi(array, &schema) }?;
1272 let array = UnionArray::from(data);
1273
1274 let expected_type_ids = vec![0_i8, 0, 1, 0];
1275
1276 assert_eq!(*array.type_ids(), expected_type_ids);
1278 for (i, id) in expected_type_ids.iter().enumerate() {
1279 assert_eq!(id, &array.type_id(i));
1280 }
1281
1282 assert!(array.offsets().is_some());
1283
1284 for i in 0..array.len() {
1285 let slot = array.value(i);
1286 match i {
1287 0 => {
1288 let slot = slot.as_primitive::<Int32Type>();
1289 assert!(!slot.is_null(0));
1290 assert_eq!(slot.len(), 1);
1291 let value = slot.value(0);
1292 assert_eq!(1_i32, value);
1293 }
1294 1 => assert!(slot.is_null(0)),
1295 2 => {
1296 let slot = slot.as_primitive::<Float64Type>();
1297 assert!(!slot.is_null(0));
1298 assert_eq!(slot.len(), 1);
1299 let value = slot.value(0);
1300 assert_eq!(value, 3_f64);
1301 }
1302 3 => {
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!(4_i32, value);
1308 }
1309 _ => unreachable!(),
1310 }
1311 }
1312
1313 Ok(())
1314 }
1315
1316 #[test]
1317 fn test_run_array() -> Result<()> {
1318 let value_data =
1319 PrimitiveArray::<Int8Type>::from_iter_values([10_i8, 11, 12, 13, 14, 15, 16, 17]);
1320
1321 let run_ends_values = [4_i32, 6, 7, 9, 13, 18, 20, 22];
1323 let run_ends_data =
1324 PrimitiveArray::<Int32Type>::from_iter_values(run_ends_values.iter().copied());
1325
1326 let ree_array = RunArray::<Int32Type>::try_new(&run_ends_data, &value_data).unwrap();
1328
1329 let (array, schema) = to_ffi(&ree_array.to_data())?;
1331
1332 let data = unsafe { from_ffi(array, &schema) }?;
1334 let array = make_array(data);
1335
1336 let array = array
1338 .as_any()
1339 .downcast_ref::<RunArray<Int32Type>>()
1340 .unwrap();
1341 assert_eq!(array.data_type(), ree_array.data_type());
1342 assert_eq!(array.run_ends().values(), ree_array.run_ends().values());
1343 assert_eq!(array.values(), ree_array.values());
1344
1345 Ok(())
1346 }
1347
1348 #[test]
1349 fn test_nullable_run_array() -> Result<()> {
1350 let nulls = NullBuffer::from(vec![true, false, true, true, false]);
1351 let value_data =
1352 PrimitiveArray::<Int8Type>::new(vec![1_i8, 2, 3, 4, 5].into(), Some(nulls));
1353
1354 let run_ends_values = [5_i32, 6, 7, 8, 10];
1356 let run_ends_data =
1357 PrimitiveArray::<Int32Type>::from_iter_values(run_ends_values.iter().copied());
1358
1359 let ree_array = RunArray::<Int32Type>::try_new(&run_ends_data, &value_data).unwrap();
1361
1362 let (array, schema) = to_ffi(&ree_array.to_data())?;
1364
1365 let data = unsafe { from_ffi(array, &schema) }?;
1367 let array = make_array(data);
1368
1369 let array = array
1371 .as_any()
1372 .downcast_ref::<RunArray<Int32Type>>()
1373 .unwrap();
1374 assert_eq!(array.data_type(), ree_array.data_type());
1375 assert_eq!(array.run_ends().values(), ree_array.run_ends().values());
1376 assert_eq!(array.values(), ree_array.values());
1377
1378 Ok(())
1379 }
1380}
1381
1382#[cfg(test)]
1383mod tests_from_ffi {
1384 #[cfg(not(feature = "force_validate"))]
1385 use std::ptr::NonNull;
1386 use std::sync::Arc;
1387
1388 use arrow_buffer::NullBuffer;
1389 #[cfg(not(feature = "force_validate"))]
1390 use arrow_buffer::{ScalarBuffer, bit_util, buffer::Buffer};
1391 #[cfg(feature = "force_validate")]
1392 use arrow_buffer::{bit_util, buffer::Buffer};
1393
1394 use arrow_data::ArrayData;
1395 use arrow_data::transform::MutableArrayData;
1396 use arrow_schema::{DataType, Field};
1397
1398 use super::Result;
1399
1400 use crate::builder::GenericByteViewBuilder;
1401 use crate::types::{BinaryViewType, ByteViewType, Int32Type, StringViewType};
1402 use crate::{
1403 ArrayRef, GenericByteViewArray, ListArray,
1404 array::{
1405 Array, BooleanArray, DictionaryArray, FixedSizeBinaryArray, FixedSizeListArray,
1406 Int32Array, Int64Array, StringArray, StructArray, UInt32Array, UInt64Array,
1407 },
1408 ffi::{FFI_ArrowArray, FFI_ArrowSchema, from_ffi},
1409 make_array,
1410 };
1411
1412 fn test_round_trip(expected: &ArrayData) -> Result<()> {
1413 let array = FFI_ArrowArray::new(expected);
1415 let schema = FFI_ArrowSchema::try_from(expected.data_type())?;
1416
1417 let result = &unsafe { from_ffi(array, &schema) }?;
1419
1420 assert_eq!(result, expected);
1421 Ok(())
1422 }
1423
1424 #[test]
1425 fn test_u32() -> Result<()> {
1426 let array = UInt32Array::from(vec![Some(2), None, Some(1), None]);
1427 let data = array.into_data();
1428 test_round_trip(&data)
1429 }
1430
1431 #[test]
1432 fn test_u64() -> Result<()> {
1433 let array = UInt64Array::from(vec![Some(2), None, Some(1), None]);
1434 let data = array.into_data();
1435 test_round_trip(&data)
1436 }
1437
1438 #[test]
1439 fn test_i64() -> Result<()> {
1440 let array = Int64Array::from(vec![Some(2), None, Some(1), None]);
1441 let data = array.into_data();
1442 test_round_trip(&data)
1443 }
1444
1445 #[test]
1446 fn test_struct() -> Result<()> {
1447 let inner = StructArray::from(vec![
1448 (
1449 Arc::new(Field::new("a1", DataType::Boolean, false)),
1450 Arc::new(BooleanArray::from(vec![true, true, false, false])) as Arc<dyn Array>,
1451 ),
1452 (
1453 Arc::new(Field::new("a2", DataType::UInt32, false)),
1454 Arc::new(UInt32Array::from(vec![1, 2, 3, 4])),
1455 ),
1456 ]);
1457
1458 let array = StructArray::from(vec![
1459 (
1460 Arc::new(Field::new("a", inner.data_type().clone(), false)),
1461 Arc::new(inner) as Arc<dyn Array>,
1462 ),
1463 (
1464 Arc::new(Field::new("b", DataType::Boolean, false)),
1465 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
1466 ),
1467 (
1468 Arc::new(Field::new("c", DataType::UInt32, false)),
1469 Arc::new(UInt32Array::from(vec![42, 28, 19, 31])),
1470 ),
1471 ]);
1472 let data = array.into_data();
1473 test_round_trip(&data)
1474 }
1475
1476 #[test]
1477 fn test_dictionary() -> Result<()> {
1478 let values = StringArray::from(vec![Some("foo"), Some("bar"), None]);
1479 let keys = Int32Array::from(vec![
1480 Some(0),
1481 Some(1),
1482 None,
1483 Some(1),
1484 Some(1),
1485 None,
1486 Some(1),
1487 Some(2),
1488 Some(1),
1489 None,
1490 ]);
1491 let array = DictionaryArray::new(keys, Arc::new(values));
1492
1493 let data = array.into_data();
1494 test_round_trip(&data)
1495 }
1496
1497 #[test]
1498 fn test_fixed_size_binary() -> Result<()> {
1499 let values = vec![vec![10, 10, 10], vec![20, 20, 20], vec![30, 30, 30]];
1500 let array = FixedSizeBinaryArray::try_from_iter(values.into_iter())?;
1501
1502 let data = array.into_data();
1503 test_round_trip(&data)
1504 }
1505
1506 #[test]
1507 fn test_fixed_size_binary_with_nulls() -> Result<()> {
1508 let values = vec![
1509 None,
1510 Some(vec![10, 10, 10]),
1511 None,
1512 Some(vec![20, 20, 20]),
1513 Some(vec![30, 30, 30]),
1514 None,
1515 ];
1516 let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size(values.into_iter(), 3)?;
1517
1518 let data = array.into_data();
1519 test_round_trip(&data)
1520 }
1521
1522 #[test]
1523 fn test_fixed_size_list() -> Result<()> {
1524 let v: Vec<i64> = (0..9).collect();
1525 let value_data = ArrayData::builder(DataType::Int64)
1526 .len(9)
1527 .add_buffer(Buffer::from_slice_ref(v))
1528 .build()?;
1529 let list_data_type =
1530 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int64, false)), 3);
1531 let list_data = ArrayData::builder(list_data_type)
1532 .len(3)
1533 .add_child_data(value_data)
1534 .build()?;
1535 let array = FixedSizeListArray::from(list_data);
1536
1537 let data = array.into_data();
1538 test_round_trip(&data)
1539 }
1540
1541 #[test]
1542 fn test_fixed_size_list_with_nulls() -> Result<()> {
1543 let mut validity_bits: [u8; 1] = [0; 1];
1545 bit_util::set_bit(&mut validity_bits, 1);
1546 bit_util::set_bit(&mut validity_bits, 2);
1547 bit_util::set_bit(&mut validity_bits, 6);
1548
1549 let v: Vec<i16> = (0..16).collect();
1550 let value_data = ArrayData::builder(DataType::Int16)
1551 .len(16)
1552 .add_buffer(Buffer::from_slice_ref(v))
1553 .build()?;
1554 let list_data_type =
1555 DataType::FixedSizeList(Arc::new(Field::new("f", DataType::Int16, false)), 2);
1556 let list_data = ArrayData::builder(list_data_type)
1557 .len(8)
1558 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1559 .add_child_data(value_data)
1560 .build()?;
1561 let array = FixedSizeListArray::from(list_data);
1562
1563 let data = array.into_data();
1564 test_round_trip(&data)
1565 }
1566
1567 #[test]
1568 fn test_fixed_size_list_nested() -> Result<()> {
1569 let v: Vec<i32> = (0..16).collect();
1570 let value_data = ArrayData::builder(DataType::Int32)
1571 .len(16)
1572 .add_buffer(Buffer::from_slice_ref(v))
1573 .build()?;
1574
1575 let offsets: Vec<i32> = vec![0, 2, 4, 6, 8, 10, 12, 14, 16];
1576 let value_offsets = Buffer::from_slice_ref(offsets);
1577 let inner_list_data_type =
1578 DataType::List(Arc::new(Field::new_list_field(DataType::Int32, false)));
1579 let inner_list_data = ArrayData::builder(inner_list_data_type.clone())
1580 .len(8)
1581 .add_buffer(value_offsets)
1582 .add_child_data(value_data)
1583 .build()?;
1584
1585 let mut validity_bits: [u8; 1] = [0; 1];
1587 bit_util::set_bit(&mut validity_bits, 2);
1588
1589 let list_data_type =
1590 DataType::FixedSizeList(Arc::new(Field::new("f", inner_list_data_type, false)), 2);
1591 let list_data = ArrayData::builder(list_data_type)
1592 .len(4)
1593 .null_bit_buffer(Some(Buffer::from(validity_bits)))
1594 .add_child_data(inner_list_data)
1595 .build()?;
1596
1597 let array = FixedSizeListArray::from(list_data);
1598
1599 let data = array.into_data();
1600 test_round_trip(&data)
1601 }
1602
1603 #[test]
1604 fn test_list_view() -> Result<()> {
1605 let value_data = ArrayData::builder(DataType::Int16)
1607 .len(8)
1608 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
1609 .build()
1610 .unwrap();
1611
1612 let value_offsets = Buffer::from(vec![0_i32, 3, 6]);
1615 let sizes_buffer = Buffer::from(vec![3_i32, 3, 2]);
1616
1617 let list_view_dt =
1619 DataType::ListView(Arc::new(Field::new_list_field(DataType::Int16, false)));
1620
1621 let list_view_data = ArrayData::builder(list_view_dt)
1622 .len(3)
1623 .add_buffer(value_offsets)
1624 .add_buffer(sizes_buffer)
1625 .add_child_data(value_data)
1626 .build()
1627 .unwrap();
1628
1629 test_round_trip(&list_view_data)
1630 }
1631
1632 #[test]
1633 fn test_list_view_with_nulls() -> Result<()> {
1634 let value_data = ArrayData::builder(DataType::Int16)
1636 .len(8)
1637 .add_buffer(Buffer::from_slice_ref([0_i16, 1, 2, 3, 4, 5, 6, 7]))
1638 .build()
1639 .unwrap();
1640
1641 let value_offsets = Buffer::from(vec![0_i32, 3, 6, 8]);
1644 let sizes_buffer = Buffer::from(vec![3_i32, 3, 2, 0]);
1645
1646 let list_view_dt =
1648 DataType::ListView(Arc::new(Field::new_list_field(DataType::Int16, true)));
1649
1650 let list_view_data = ArrayData::builder(list_view_dt)
1651 .len(4)
1652 .add_buffer(value_offsets)
1653 .add_buffer(sizes_buffer)
1654 .add_child_data(value_data)
1655 .nulls(Some(NullBuffer::from(vec![true, true, true, false])))
1656 .build()
1657 .unwrap();
1658
1659 test_round_trip(&list_view_data)
1660 }
1661
1662 #[test]
1663 #[cfg(not(feature = "force_validate"))]
1664 fn test_empty_string_with_non_zero_offset() -> Result<()> {
1665 use super::ImportedArrowArray;
1666 use arrow_buffer::{MutableBuffer, OffsetBuffer};
1667
1668 let data: Buffer = MutableBuffer::new(0).into();
1670 let offsets = OffsetBuffer::new(vec![123].into());
1671 let string_array =
1672 unsafe { StringArray::new_unchecked(offsets.clone(), data.clone(), None) };
1673
1674 let data = string_array.into_data();
1675
1676 let array = FFI_ArrowArray::new(&data);
1677 let schema = FFI_ArrowSchema::try_from(data.data_type())?;
1678
1679 let dt = DataType::try_from(&schema)?;
1680 let array = Arc::new(array);
1681 let imported_array = ImportedArrowArray {
1682 array: &array,
1683 data_type: dt,
1684 owner: &array,
1685 };
1686
1687 let offset_buf_len = imported_array.buffer_len(1, &[], &imported_array.data_type)?;
1688 let data_buf_len = imported_array.buffer_len(2, &[], &imported_array.data_type)?;
1689
1690 assert_eq!(offset_buf_len, 4);
1691 assert_eq!(data_buf_len, 0);
1692
1693 test_round_trip(&imported_array.consume()?)
1694 }
1695
1696 #[test]
1703 fn test_zero_length_bytes_at_non_zero_offset() -> Result<()> {
1704 let small = Buffer::from_slice_ref([0i32, 1, 3, 5]);
1706 let large = Buffer::from_slice_ref([0i64, 1, 3, 5]);
1707 let values = Buffer::from(b"xaabb".as_slice());
1708
1709 for (data_type, offsets) in [
1710 (DataType::Utf8, &small),
1711 (DataType::Binary, &small),
1712 (DataType::LargeUtf8, &large),
1713 (DataType::LargeBinary, &large),
1714 ] {
1715 for offset in 0..4 {
1716 let data = ArrayData::try_new(
1717 data_type.clone(),
1718 0,
1719 None,
1720 offset,
1721 vec![offsets.clone(), values.clone()],
1722 vec![],
1723 )?;
1724
1725 let array = FFI_ArrowArray::new(&data);
1726 let schema = FFI_ArrowSchema::try_from(&data_type)?;
1727 let imported = unsafe { from_ffi(array, &schema) }?;
1728
1729 imported.validate_full()?;
1732 assert_eq!(imported.len(), 0);
1733 assert_eq!(imported, data);
1734
1735 assert_eq!(imported.buffers()[1].len(), [0, 1, 3, 5][offset]);
1738 }
1739 }
1740
1741 Ok(())
1742 }
1743
1744 fn roundtrip_string_array(array: StringArray) -> StringArray {
1745 let data = array.into_data();
1746
1747 let array = FFI_ArrowArray::new(&data);
1748 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1749
1750 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1751 StringArray::from(array)
1752 }
1753
1754 fn roundtrip_byte_view_array<T: ByteViewType>(
1755 array: GenericByteViewArray<T>,
1756 ) -> GenericByteViewArray<T> {
1757 let data = array.into_data();
1758
1759 let array = FFI_ArrowArray::new(&data);
1760 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1761
1762 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1763 GenericByteViewArray::<T>::from(array)
1764 }
1765
1766 fn extend_array(array: &dyn Array) -> ArrayRef {
1767 let len = array.len();
1768 let data = array.to_data();
1769
1770 let mut mutable = MutableArrayData::new(vec![&data], false, len);
1771 mutable.try_extend(0, 0, len).unwrap();
1772 make_array(mutable.freeze())
1773 }
1774
1775 #[test]
1776 fn test_extend_imported_string_slice() {
1777 let mut strings = vec![];
1778
1779 for i in 0..1000 {
1780 strings.push(format!("string: {i}"));
1781 }
1782
1783 let string_array = StringArray::from(strings);
1784
1785 let imported = roundtrip_string_array(string_array.clone());
1786 assert_eq!(imported.len(), 1000);
1787 assert_eq!(imported.value(0), "string: 0");
1788 assert_eq!(imported.value(499), "string: 499");
1789
1790 let copied = extend_array(&imported);
1791 assert_eq!(
1792 copied.as_any().downcast_ref::<StringArray>().unwrap(),
1793 &imported
1794 );
1795
1796 let slice = string_array.slice(500, 500);
1797
1798 let imported = roundtrip_string_array(slice);
1799 assert_eq!(imported.len(), 500);
1800 assert_eq!(imported.value(0), "string: 500");
1801 assert_eq!(imported.value(499), "string: 999");
1802
1803 let copied = extend_array(&imported);
1804 assert_eq!(
1805 copied.as_any().downcast_ref::<StringArray>().unwrap(),
1806 &imported
1807 );
1808 }
1809
1810 fn roundtrip_list_array(array: ListArray) -> ListArray {
1811 let data = array.into_data();
1812
1813 let array = FFI_ArrowArray::new(&data);
1814 let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
1815
1816 let array = unsafe { from_ffi(array, &schema) }.unwrap();
1817 ListArray::from(array)
1818 }
1819
1820 #[test]
1821 fn test_extend_imported_list_slice() {
1822 let mut data = vec![];
1823
1824 for i in 0..1000 {
1825 let mut list = vec![];
1826 for j in 0..100 {
1827 list.push(Some(i * 1000 + j));
1828 }
1829 data.push(Some(list));
1830 }
1831
1832 let list_array = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1833
1834 let slice = list_array.slice(500, 500);
1835 let imported = roundtrip_list_array(slice.clone());
1836 assert_eq!(imported.len(), 500);
1837 assert_eq!(&slice, &imported);
1838
1839 let copied = extend_array(&imported);
1840 assert_eq!(
1841 copied.as_any().downcast_ref::<ListArray>().unwrap(),
1842 &imported
1843 );
1844 }
1845
1846 trait NativeFromStr {
1849 fn from_str(value: &str) -> &Self;
1850 }
1851
1852 impl NativeFromStr for str {
1853 fn from_str(value: &str) -> &Self {
1854 value
1855 }
1856 }
1857
1858 impl NativeFromStr for [u8] {
1859 fn from_str(value: &str) -> &Self {
1860 value.as_bytes()
1861 }
1862 }
1863
1864 #[test]
1865 #[cfg(not(feature = "force_validate"))]
1866 fn test_utf8_view_ffi_from_dangling_pointer() {
1867 let empty = GenericByteViewBuilder::<StringViewType>::new().finish();
1868 let buffers = Arc::clone(empty.data_buffers());
1869 let nulls = empty.nulls().cloned();
1870
1871 let alloc = Arc::new(1);
1873 let buffer = unsafe { Buffer::from_custom_allocation(NonNull::<u8>::dangling(), 0, alloc) };
1874 let views = unsafe { ScalarBuffer::new_unchecked(buffer) };
1875
1876 let str_view: GenericByteViewArray<StringViewType> =
1877 unsafe { GenericByteViewArray::new_unchecked(views, buffers, nulls) };
1878 let imported = roundtrip_byte_view_array(str_view);
1879 assert_eq!(imported.len(), 0);
1880 assert_eq!(&imported, &empty);
1881 }
1882
1883 #[test]
1884 fn test_round_trip_byte_view() {
1885 fn test_case<T>()
1886 where
1887 T: ByteViewType,
1888 T::Native: NativeFromStr,
1889 {
1890 macro_rules! run_test_case {
1891 ($array:expr) => {{
1892 let len = $array.len();
1894 let imported = roundtrip_byte_view_array($array);
1895 assert_eq!(imported.len(), len);
1896
1897 let copied = extend_array(&imported);
1898 assert_eq!(
1899 copied
1900 .as_any()
1901 .downcast_ref::<GenericByteViewArray<T>>()
1902 .unwrap(),
1903 &imported
1904 );
1905 }};
1906 }
1907
1908 let empty = GenericByteViewBuilder::<T>::new().finish();
1910 run_test_case!(empty);
1911
1912 let mut all_inlined = GenericByteViewBuilder::<T>::new();
1914 all_inlined.append_value(T::Native::from_str("inlined1"));
1915 all_inlined.append_value(T::Native::from_str("inlined2"));
1916 all_inlined.append_value(T::Native::from_str("inlined3"));
1917 let all_inlined = all_inlined.finish();
1918 assert_eq!(all_inlined.data_buffers().len(), 0);
1919 run_test_case!(all_inlined);
1920
1921 let mixed_one_variadic = {
1923 let mut builder = GenericByteViewBuilder::<T>::new();
1924 builder.append_value(T::Native::from_str("inlined"));
1925 let block_id = builder.append_block(Buffer::from(b"non-inlined-string-buffer"));
1926 builder.try_append_view(block_id, 0, 25).unwrap();
1927 builder.finish()
1928 };
1929 assert_eq!(mixed_one_variadic.data_buffers().len(), 1);
1930 run_test_case!(mixed_one_variadic);
1931
1932 let mixed_two_variadic = {
1934 let mut builder = GenericByteViewBuilder::<T>::new();
1935 builder.append_value(T::Native::from_str("inlined"));
1936 let block_id = builder.append_block(Buffer::from(b"non-inlined-string-buffer"));
1937 builder.try_append_view(block_id, 0, 25).unwrap();
1938
1939 let block_id = builder
1940 .append_block(Buffer::from("another-non-inlined-string-buffer".as_bytes()));
1941 builder.try_append_view(block_id, 0, 33).unwrap();
1942 builder.finish()
1943 };
1944 assert_eq!(mixed_two_variadic.data_buffers().len(), 2);
1945 run_test_case!(mixed_two_variadic);
1946 }
1947
1948 test_case::<StringViewType>();
1949 test_case::<BinaryViewType>();
1950 }
1951}