This is an automated email from the ASF dual-hosted git repository.
tustvold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/master by this push:
new 88b296ca9 [ffi] Fix arrow-array null_count error during conversion
from C to Rust (#6674)
88b296ca9 is described below
commit 88b296ca97e18c0514313f1022b91edbeb705c2c
Author: lambda <[email protected]>
AuthorDate: Wed Nov 6 07:45:33 2024 +0800
[ffi] Fix arrow-array null_count error during conversion from C to Rust
(#6674)
* Fix arrow-array null_count error during conversion from C to Rust
* add ffi_array.null_count_opt
* add Safety to follow clippy
* add Safety to follow clippy
---
arrow-array/src/ffi.rs | 38 +++++++++++++++++++++++++++++++++++---
arrow-data/src/ffi.rs | 15 +++++++++++++++
2 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/arrow-array/src/ffi.rs b/arrow-array/src/ffi.rs
index 29414eae6..4426e0986 100644
--- a/arrow-array/src/ffi.rs
+++ b/arrow-array/src/ffi.rs
@@ -302,8 +302,8 @@ impl ImportedArrowArray<'_> {
let len = self.array.len();
let offset = self.array.offset();
let null_count = match &self.data_type {
- DataType::Null => 0,
- _ => self.array.null_count(),
+ DataType::Null => Some(0),
+ _ => self.array.null_count_opt(),
};
let data_layout = layout(&self.data_type);
@@ -329,7 +329,7 @@ impl ImportedArrowArray<'_> {
ArrayData::new_unchecked(
self.data_type,
len,
- Some(null_count),
+ null_count,
null_bit_buffer,
offset,
buffers,
@@ -635,6 +635,38 @@ mod tests_to_then_from_ffi {
}
// case with nulls is tested in the docs, through the example on this
module.
+ #[test]
+ fn test_null_count_handling() {
+ let int32_data = ArrayData::builder(DataType::Int32)
+ .len(10)
+ .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
+ .null_bit_buffer(Some(Buffer::from([0b01011111, 0b00000001])))
+ .build()
+ .unwrap();
+ let mut ffi_array = FFI_ArrowArray::new(&int32_data);
+ assert_eq!(3, ffi_array.null_count());
+ assert_eq!(Some(3), ffi_array.null_count_opt());
+ // Simulating uninitialized state
+ unsafe {
+ ffi_array.set_null_count(-1);
+ }
+ assert_eq!(None, ffi_array.null_count_opt());
+ let int32_data = unsafe { from_ffi_and_data_type(ffi_array,
DataType::Int32) }.unwrap();
+ assert_eq!(3, int32_data.null_count());
+
+ let null_data = &ArrayData::new_null(&DataType::Null, 10);
+ let mut ffi_array = FFI_ArrowArray::new(null_data);
+ assert_eq!(10, ffi_array.null_count());
+ assert_eq!(Some(10), ffi_array.null_count_opt());
+ // Simulating uninitialized state
+ unsafe {
+ ffi_array.set_null_count(-1);
+ }
+ assert_eq!(None, ffi_array.null_count_opt());
+ let null_data = unsafe { from_ffi_and_data_type(ffi_array,
DataType::Null) }.unwrap();
+ assert_eq!(0, null_data.null_count());
+ }
+
fn test_generic_string<Offset: OffsetSizeTrait>() -> Result<()> {
// create an array natively
let array = GenericStringArray::<Offset>::from(vec![Some("a"), None,
Some("aaa")]);
diff --git a/arrow-data/src/ffi.rs b/arrow-data/src/ffi.rs
index cd283d326..04599bc47 100644
--- a/arrow-data/src/ffi.rs
+++ b/arrow-data/src/ffi.rs
@@ -271,6 +271,21 @@ impl FFI_ArrowArray {
self.null_count as usize
}
+ /// Returns the null count, checking for validity
+ #[inline]
+ pub fn null_count_opt(&self) -> Option<usize> {
+ usize::try_from(self.null_count).ok()
+ }
+
+ /// Set the null count of the array
+ ///
+ /// # Safety
+ /// Null count must match that of null buffer
+ #[inline]
+ pub unsafe fn set_null_count(&mut self, null_count: i64) {
+ self.null_count = null_count;
+ }
+
/// Returns the buffer at the provided index
///
/// # Panic