arrow_buffer/builder/offset.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
use std::ops::Deref;
use crate::{ArrowNativeType, OffsetBuffer};
/// Builder of [`OffsetBuffer`]
#[derive(Debug)]
pub struct OffsetBufferBuilder<O: ArrowNativeType> {
offsets: Vec<O>,
last_offset: usize,
}
impl<O: ArrowNativeType> OffsetBufferBuilder<O> {
/// Create a new builder with space for `capacity + 1` offsets
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,
}
}
/// Push a slice of `length` bytes
///
/// # Panics
///
/// Panics if adding `length` would overflow `usize`
#[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))
}
/// Reserve space for at least `additional` further offsets
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.offsets.reserve(additional);
}
/// Takes the builder itself and returns an [`OffsetBuffer`]
///
/// # Panics
///
/// Panics if offsets overflow `O`
pub fn finish(self) -> OffsetBuffer<O> {
O::from_usize(self.last_offset).expect("overflow");
unsafe { OffsetBuffer::new_unchecked(self.offsets.into()) }
}
/// Builds the [OffsetBuffer] without resetting the builder.
///
/// # Panics
///
/// Panics if offsets overflow `O`
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();
}
}