use arrow_buffer::ArrowNativeType;
use arrow_buffer::OffsetBuffer;
use vortex_error::vortex_panic;
use crate::Alignment;
use crate::Buffer;
use crate::ByteBuffer;
impl<T: ArrowNativeType> Buffer<T> {
pub fn into_arrow_scalar_buffer(self) -> arrow_buffer::ScalarBuffer<T> {
if self.is_empty() {
return Vec::new().into();
}
let buffer = self.into_byte_buffer().into_arrow_buffer();
arrow_buffer::ScalarBuffer::from(buffer)
}
pub fn from_arrow_scalar_buffer(arrow: arrow_buffer::ScalarBuffer<T>) -> Self {
let length = arrow.len();
let arrow = arrow.into_inner();
let alignment = Alignment::of::<T>();
if arrow.as_ptr().align_offset(alignment.as_usize()) != 0 {
vortex_panic!(
"Arrow buffer is not aligned to the requested alignment: {}",
alignment
);
}
debug_assert_eq!(length, arrow.len() / size_of::<T>());
Self::from_arrow_owner(arrow, length, alignment)
}
pub fn into_arrow_offset_buffer(self) -> OffsetBuffer<T> {
unsafe { OffsetBuffer::new_unchecked(self.into_arrow_scalar_buffer()) }
}
}
impl ByteBuffer {
pub fn into_arrow_buffer(self) -> arrow_buffer::Buffer {
if let Some(crate::BufferBacking::Arrow(arrow)) = self.backing.as_deref() {
let offset = self.ptr.addr().get() - arrow.as_ptr().addr();
return arrow.slice_with_length(offset, self.length);
}
arrow_buffer::Buffer::from(self.into_bytes())
}
pub fn from_arrow_buffer(arrow: arrow_buffer::Buffer, alignment: Alignment) -> Self {
let length = arrow.len();
if arrow.as_ptr().align_offset(alignment.as_usize()) != 0 {
vortex_panic!(
"Arrow buffer is not aligned to the requested alignment: {}",
alignment
);
}
Self::from_arrow_owner(arrow, length, alignment)
}
}
#[cfg(test)]
mod test {
use arrow_buffer::Buffer as ArrowBuffer;
use arrow_buffer::ScalarBuffer;
use crate::Alignment;
use crate::Buffer;
use crate::buffer;
#[test]
fn into_arrow_buffer() {
let buf = buffer![0u8, 1, 2];
let arrow: ArrowBuffer = buf.clone().into_arrow_buffer();
assert_eq!(arrow.as_ref(), buf.as_slice(), "Buffer values differ");
assert_eq!(arrow.as_ptr(), buf.as_ptr(), "Conversion not zero-copy")
}
#[test]
fn into_arrow_scalar_buffer() {
let buf = buffer![0i32, 1, 2];
let scalar: ScalarBuffer<i32> = buf.clone().into_arrow_scalar_buffer();
assert_eq!(scalar.as_ref(), buf.as_slice(), "Buffer values differ");
assert_eq!(scalar.as_ptr(), buf.as_ptr(), "Conversion not zero-copy")
}
#[test]
fn empty_into_arrow_scalar_buffer() {
let scalar = Buffer::<i64>::empty().into_arrow_scalar_buffer();
assert!(scalar.is_empty());
assert_eq!(scalar.as_ptr().align_offset(align_of::<i64>()), 0);
}
#[test]
fn from_arrow_buffer() {
let arrow = ArrowBuffer::from_vec(vec![0i32, 1, 2]);
let buf = Buffer::from_arrow_buffer(arrow.clone(), Alignment::of::<i32>());
assert_eq!(arrow.as_ref(), buf.as_slice(), "Buffer values differ");
assert_eq!(arrow.as_ptr(), buf.as_ptr(), "Conversion not zero-copy");
let round_trip = buf.into_arrow_buffer();
assert_eq!(round_trip.as_ptr(), arrow.as_ptr());
}
}