Coverage Report

Created: 2025-08-26 07:03

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