Skip to content

Commit ebcc4a5

Browse files
authored
Align buffers in ArrayData.child_data as well (#6462)
1 parent 5804f21 commit ebcc4a5

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

arrow-data/src/data.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,15 +693,21 @@ impl ArrayData {
693693
///
694694
/// This can be useful for when interacting with data sent over IPC or FFI, that may
695695
/// not meet the minimum alignment requirements
696+
///
697+
/// This also aligns buffers of children data
696698
pub fn align_buffers(&mut self) {
697699
let layout = layout(&self.data_type);
698700
for (buffer, spec) in self.buffers.iter_mut().zip(&layout.buffers) {
699701
if let BufferSpec::FixedWidth { alignment, .. } = spec {
700702
if buffer.as_ptr().align_offset(*alignment) != 0 {
701-
*buffer = Buffer::from_slice_ref(buffer.as_ref())
703+
*buffer = Buffer::from_slice_ref(buffer.as_ref());
702704
}
703705
}
704706
}
707+
// align children data recursively
708+
for data in self.child_data.iter_mut() {
709+
data.align_buffers()
710+
}
705711
}
706712

707713
/// "cheap" validation of an `ArrayData`. Ensures buffers are
@@ -1961,7 +1967,7 @@ impl From<ArrayData> for ArrayDataBuilder {
19611967
#[cfg(test)]
19621968
mod tests {
19631969
use super::*;
1964-
use arrow_schema::Field;
1970+
use arrow_schema::{Field, Fields};
19651971

19661972
// See arrow/tests/array_data_validation.rs for test of array validation
19671973

@@ -2224,6 +2230,7 @@ mod tests {
22242230
};
22252231
data.validate_full().unwrap();
22262232

2233+
// break alignment in data
22272234
data.buffers[0] = sliced;
22282235
let err = data.validate().unwrap_err();
22292236

@@ -2236,6 +2243,44 @@ mod tests {
22362243
data.validate_full().unwrap();
22372244
}
22382245

2246+
#[test]
2247+
fn test_alignment_struct() {
2248+
let buffer = Buffer::from_vec(vec![1_i32, 2_i32, 3_i32]);
2249+
let sliced = buffer.slice(1);
2250+
2251+
let child_data = ArrayData {
2252+
data_type: DataType::Int32,
2253+
len: 0,
2254+
offset: 0,
2255+
buffers: vec![buffer],
2256+
child_data: vec![],
2257+
nulls: None,
2258+
};
2259+
2260+
let schema = DataType::Struct(Fields::from(vec![Field::new("a", DataType::Int32, false)]));
2261+
let mut data = ArrayData {
2262+
data_type: schema,
2263+
len: 0,
2264+
offset: 0,
2265+
buffers: vec![],
2266+
child_data: vec![child_data],
2267+
nulls: None,
2268+
};
2269+
data.validate_full().unwrap();
2270+
2271+
// break alignment in child data
2272+
data.child_data[0].buffers[0] = sliced;
2273+
let err = data.validate().unwrap_err();
2274+
2275+
assert_eq!(
2276+
err.to_string(),
2277+
"Invalid argument error: Misaligned buffers[0] in array of type Int32, offset from expected alignment of 4 by 1"
2278+
);
2279+
2280+
data.align_buffers();
2281+
data.validate_full().unwrap();
2282+
}
2283+
22392284
#[test]
22402285
fn test_null_view_types() {
22412286
let array_len = 32;

0 commit comments

Comments
 (0)