use crate::buffer::ScalarBuffer;
use crate::{ArrowNativeType, MutableBuffer};
use std::ops::Deref;
#[derive(Debug, Clone)]
pub struct OffsetBuffer<O: ArrowNativeType>(ScalarBuffer<O>);
impl<O: ArrowNativeType> OffsetBuffer<O> {
pub fn new(buffer: ScalarBuffer<O>) -> Self {
assert!(!buffer.is_empty(), "offsets cannot be empty");
assert!(buffer[0] > O::usize_as(0), "offsets must be greater than 0");
assert!(
buffer.windows(2).all(|w| w[0] <= w[1]),
"offsets must be monotonically increasing"
);
Self(buffer)
}
pub unsafe fn new_unchecked(buffer: ScalarBuffer<O>) -> Self {
Self(buffer)
}
pub fn new_empty() -> Self {
let buffer = MutableBuffer::from_len_zeroed(std::mem::size_of::<O>());
Self(buffer.into_buffer().into())
}
pub fn inner(&self) -> &ScalarBuffer<O> {
&self.0
}
pub fn into_inner(self) -> ScalarBuffer<O> {
self.0
}
pub fn slice(&self, offset: usize, len: usize) -> Self {
Self(self.0.slice(offset, len.saturating_add(1)))
}
}
impl<T: ArrowNativeType> Deref for OffsetBuffer<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: ArrowNativeType> AsRef<[T]> for OffsetBuffer<T> {
#[inline]
fn as_ref(&self) -> &[T] {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic(expected = "offsets cannot be empty")]
fn empty_offsets() {
OffsetBuffer::new(Vec::<i32>::new().into());
}
#[test]
#[should_panic(expected = "offsets must be greater than 0")]
fn negative_offsets() {
OffsetBuffer::new(vec![-1, 0, 1].into());
}
#[test]
#[should_panic(expected = "offsets must be monotonically increasing")]
fn non_monotonic_offsets() {
OffsetBuffer::new(vec![1, 2, 0].into());
}
}