use std::ops::Deref;
use crate::{ArrowNativeType, OffsetBuffer};
#[derive(Debug)]
pub struct OffsetBufferBuilder<O: ArrowNativeType> {
offsets: Vec<O>,
last_offset: usize,
}
impl<O: ArrowNativeType> OffsetBufferBuilder<O> {
pub fn new(capacity: usize) -> Self {
let mut offsets = Vec::with_capacity(capacity + 1);
offsets.push(O::usize_as(0));
Self {
offsets,
last_offset: 0,
}
}
#[inline]
pub fn push_length(&mut self, length: usize) {
self.last_offset = self.last_offset.checked_add(length).expect("overflow");
self.offsets.push(O::usize_as(self.last_offset))
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.offsets.reserve(additional);
}
pub fn finish(self) -> OffsetBuffer<O> {
O::from_usize(self.last_offset).expect("overflow");
unsafe { OffsetBuffer::new_unchecked(self.offsets.into()) }
}
pub fn finish_cloned(&self) -> OffsetBuffer<O> {
let cloned = Self {
offsets: self.offsets.clone(),
last_offset: self.last_offset,
};
cloned.finish()
}
}
impl<O: ArrowNativeType> Deref for OffsetBufferBuilder<O> {
type Target = [O];
fn deref(&self) -> &Self::Target {
self.offsets.as_ref()
}
}
#[cfg(test)]
mod tests {
use crate::OffsetBufferBuilder;
#[test]
fn test_basic() {
let mut builder = OffsetBufferBuilder::<i32>::new(5);
assert_eq!(builder.len(), 1);
assert_eq!(&*builder, &[0]);
let finished = builder.finish_cloned();
assert_eq!(finished.len(), 1);
assert_eq!(&*finished, &[0]);
builder.push_length(2);
builder.push_length(6);
builder.push_length(0);
builder.push_length(13);
let finished = builder.finish();
assert_eq!(&*finished, &[0, 2, 8, 8, 21]);
}
#[test]
#[should_panic(expected = "overflow")]
fn test_usize_overflow() {
let mut builder = OffsetBufferBuilder::<i32>::new(5);
builder.push_length(1);
builder.push_length(usize::MAX);
builder.finish();
}
#[test]
#[should_panic(expected = "overflow")]
fn test_i32_overflow() {
let mut builder = OffsetBufferBuilder::<i32>::new(5);
builder.push_length(1);
builder.push_length(i32::MAX as usize);
builder.finish();
}
}