Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark MutableBuffer::typed_data_mut unsafe #1029

Merged
merged 4 commits into from Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 13 additions & 8 deletions arrow/src/buffer/mutable.rs
Expand Up @@ -273,15 +273,20 @@ impl MutableBuffer {
}

/// View this buffer asa slice of a specific type.
///
/// # Safety
/// This function must only be used when this buffer was extended with items of type `T`.
/// Failure to do so results in undefined behavior.
pub fn typed_data_mut<T: ArrowNativeType>(&mut self) -> &mut [T] {
unsafe {
let (prefix, offsets, suffix) = self.as_slice_mut().align_to_mut::<T>();
assert!(prefix.is_empty() && suffix.is_empty());
offsets
}
///
/// This function must only be used with buffers which are treated
/// as type `T` (e.g. extended with items of type `T`).
///
/// # Panics
///
/// This function panics if the underlying buffer is not aligned
/// correctly for type `T`.
pub unsafe fn typed_data_mut<T: ArrowNativeType>(&mut self) -> &mut [T] {
let (prefix, offsets, suffix) = self.as_slice_mut().align_to_mut::<T>();
assert!(prefix.is_empty() && suffix.is_empty());
offsets
}

/// Extends this buffer from a slice of items that can be represented in bytes, increasing its capacity if needed.
Expand Down
5 changes: 4 additions & 1 deletion arrow/src/buffer/ops.rs
Expand Up @@ -168,7 +168,10 @@ where
MutableBuffer::new(ceil(len_in_bits, 8)).with_bitset(len_in_bits / 64 * 8, false);

let left_chunks = left.bit_chunks(offset_in_bits, len_in_bits);
let result_chunks = result.typed_data_mut::<u64>().iter_mut();

// Safety: buffer is always treated as type `u64` in the code
// below.
let result_chunks = unsafe { result.typed_data_mut::<u64>().iter_mut() };

result_chunks
.zip(left_chunks.iter())
Expand Down
6 changes: 4 additions & 2 deletions arrow/src/compute/kernels/sort.rs
Expand Up @@ -471,7 +471,8 @@ fn sort_boolean(
let mut result = MutableBuffer::new(result_capacity);
// sets len to capacity so we can access the whole buffer as a typed slice
result.resize(result_capacity, 0);
let result_slice: &mut [u32] = result.typed_data_mut();
// Safety: the buffer is always treated as `u32` in the code below
let result_slice: &mut [u32] = unsafe { result.typed_data_mut() };

if options.nulls_first {
let size = nulls_len.min(len);
Expand Down Expand Up @@ -559,7 +560,8 @@ where
let mut result = MutableBuffer::new(result_capacity);
// sets len to capacity so we can access the whole buffer as a typed slice
result.resize(result_capacity, 0);
let result_slice: &mut [u32] = result.typed_data_mut();
// Safety: the buffer is always treated as `u32` in the code below
let result_slice: &mut [u32] = unsafe { result.typed_data_mut() };

if options.nulls_first {
let size = nulls_len.min(len);
Expand Down
3 changes: 2 additions & 1 deletion arrow/src/compute/kernels/take.rs
Expand Up @@ -632,7 +632,8 @@ where
let bytes_offset = (data_len + 1) * std::mem::size_of::<OffsetSize>();
let mut offsets_buffer = MutableBuffer::from_len_zeroed(bytes_offset);

let offsets = offsets_buffer.typed_data_mut();
// Safety: the buffer is always treated as as a type of `OffsetSize` in the code below
let offsets = unsafe { offsets_buffer.typed_data_mut() };
let mut values = MutableBuffer::new(0);
let mut length_so_far = OffsetSize::zero();
offsets[0] = length_so_far;
Expand Down
3 changes: 2 additions & 1 deletion parquet/src/arrow/array_reader.rs
Expand Up @@ -1154,7 +1154,8 @@ impl ArrayReader for StructArrayReader {
let mut def_level_data_buffer = MutableBuffer::new(buffer_size);
def_level_data_buffer.resize(buffer_size, 0);

let def_level_data = def_level_data_buffer.typed_data_mut();
// Safety: the buffer is always treated as `u16` in the code below
let def_level_data = unsafe { def_level_data_buffer.typed_data_mut() };

def_level_data
.iter_mut()
Expand Down