From 7146a7ab031c928ce7594e1747d5447b5e5fbf26 Mon Sep 17 00:00:00 2001 From: Raphael Taylor-Davies Date: Wed, 8 May 2024 07:45:03 +0100 Subject: [PATCH] Add ByteView::try_new --- arrow-array/src/array/byte_view_array.rs | 16 +++++++--------- arrow-data/src/byte_view.rs | 14 +++++++++++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/arrow-array/src/array/byte_view_array.rs b/arrow-array/src/array/byte_view_array.rs index 79f2d47587a..32ca911ac0f 100644 --- a/arrow-array/src/array/byte_view_array.rs +++ b/arrow-array/src/array/byte_view_array.rs @@ -237,15 +237,13 @@ impl GenericByteViewArray { /// Caller is responsible for ensuring that the index is within the bounds of the array pub unsafe fn value_unchecked(&self, idx: usize) -> &T::Native { let v = self.views.get_unchecked(idx); - let len = *v as u32; - let b = if len <= 12 { - let ptr = self.views.as_ptr() as *const u8; - std::slice::from_raw_parts(ptr.add(idx * 16 + 4), len as usize) - } else { - let view = ByteView::from(*v); - let data = self.buffers.get_unchecked(view.buffer_index as usize); - let offset = view.offset as usize; - data.get_unchecked(offset..offset + len as usize) + let b = match ByteView::try_new(v) { + Ok(view) => { + let data = self.buffers.get_unchecked(view.buffer_index as usize); + let offset = view.offset as usize; + data.get_unchecked(offset..offset + view.length as usize) + } + Err(b) => b, }; T::Native::from_bytes_unchecked(b) } diff --git a/arrow-data/src/byte_view.rs b/arrow-data/src/byte_view.rs index b8b1731ac60..ac7df4ff85d 100644 --- a/arrow-data/src/byte_view.rs +++ b/arrow-data/src/byte_view.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use arrow_buffer::Buffer; +use arrow_buffer::{Buffer, ToByteSlice}; use arrow_schema::ArrowError; #[derive(Debug, Copy, Clone, Default)] @@ -32,6 +32,18 @@ pub struct ByteView { } impl ByteView { + /// Try to create a [`ByteView`] from the provided `v` + /// + /// If `v` instead contains the binary data inline, returns an `Err` containing it + #[inline] + pub fn try_new(v: &u128) -> Result { + let len = *v as u32; + match len <= 12 { + true => Err(&v.to_byte_slice()[4..4 + len as usize]), + false => Ok(Self::from(*v)), + } + } + #[inline(always)] pub fn as_u128(self) -> u128 { (self.length as u128)