Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions arrow-array/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,14 @@ pub unsafe fn from_ffi(array: FFI_ArrowArray, schema: &FFI_ArrowSchema) -> Resul
data_type: dt,
owner: &array,
};
tmp.consume()
let mut data = tmp.consume()?;
// arrow-rs has stricter alignment requirements than the C Data Interface spec;
// a no-op when buffers are already aligned. Unreachable under
// `cfg(feature = "force_validate")`; tracked in #10034.
// See https://github.com/apache/arrow/issues/43552 and
// https://github.com/apache/arrow-rs/issues/10028 for context.
data.align_buffers();
Ok(data)
}

/// Import [ArrayData] from the C Data Interface
Expand All @@ -299,7 +306,14 @@ pub unsafe fn from_ffi_and_data_type(
data_type,
owner: &array,
};
tmp.consume()
let mut data = tmp.consume()?;
// arrow-rs has stricter alignment requirements than the C Data Interface spec;
// a no-op when buffers are already aligned. Unreachable under
// `cfg(feature = "force_validate")`; tracked in #10034.
// See https://github.com/apache/arrow/issues/43552 and
// https://github.com/apache/arrow-rs/issues/10028 for context.
data.align_buffers();
Comment thread
mbutrovich marked this conversation as resolved.
Ok(data)
}

#[derive(Debug)]
Expand Down Expand Up @@ -667,6 +681,40 @@ mod tests_to_then_from_ffi {
}
// case with nulls is tested in the docs, through the example on this module.

#[test]
#[cfg(not(feature = "force_validate"))]
fn test_decimal128_under_aligned_round_trip() -> Result<()> {
// Construct an 8-aligned-but-not-16-aligned i128 data buffer to model
// an FFI producer that only guarantees the C Data Interface's
// recommended 8-byte alignment (e.g. arrow-java).
let aligned = Buffer::from_vec(vec![0_i128, 1_i128, 2_i128]);
let under_aligned = aligned.slice(8);
assert_eq!(under_aligned.as_ptr().align_offset(8), 0);
assert_ne!(under_aligned.as_ptr().align_offset(16), 0);

// SAFETY: buffer is large enough for 2 i128 elements; misaligned
// input is the condition under test.
let data = unsafe {
ArrayData::builder(DataType::Decimal128(10, 2))
.len(2)
.add_buffer(under_aligned)
.build_unchecked()
};

let schema = FFI_ArrowSchema::try_from(data.data_type()).unwrap();
let array = FFI_ArrowArray::new(&data);

let imported = unsafe { from_ffi(array, &schema) }?;
let array = Decimal128Array::from(imported);

// The little-endian byte layout of [0i128, 1, 2] sliced 8 bytes in
// yields elements `1 << 64` and `2 << 64`.
assert_eq!(array.len(), 2);
assert_eq!(array.value(0), 1_i128 << 64);
assert_eq!(array.value(1), 2_i128 << 64);
Ok(())
}

#[test]
fn test_null_count_handling() {
let int32_data = ArrayData::builder(DataType::Int32)
Expand Down
7 changes: 1 addition & 6 deletions arrow-pyarrow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,19 +353,14 @@ impl FromPyArrow for RecordBatch {
.pointer_checked(Some(ARROW_ARRAY_CAPSULE_NAME))?
.cast::<FFI_ArrowArray>();
let ffi_array = unsafe { FFI_ArrowArray::from_raw(array_ptr.as_ptr()) };
let mut array_data =
let array_data =
unsafe { ffi::from_ffi(ffi_array, schema_ptr.as_ref()) }.map_err(to_py_err)?;
if !matches!(array_data.data_type(), DataType::Struct(_)) {
return Err(PyTypeError::new_err(
"Expected Struct type from __arrow_c_array.",
));
}
let options = RecordBatchOptions::default().with_row_count(Some(array_data.len()));
// Ensure data is aligned (by potentially copying the buffers).
// This is needed because some python code (for example the
// python flight client) produces unaligned buffers
// See https://github.com/apache/arrow/issues/43552 for details
array_data.align_buffers();
let array = StructArray::from(array_data);
// StructArray does not embed metadata from schema. We need to override
// the output schema with the schema from the capsule.
Expand Down
Loading