Coverage Report

Created: 2025-10-10 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tendril-0.4.3/src/buf32.rs
Line
Count
Source
1
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
4
// option. This file may not be copied, modified, or distributed
5
// except according to those terms.
6
7
//! Provides an unsafe owned buffer type, used in implementing `Tendril`.
8
9
use std::{mem, ptr, slice, u32};
10
11
use OFLOW;
12
13
pub const MIN_CAP: u32 = 16;
14
15
pub const MAX_LEN: usize = u32::MAX as usize;
16
17
/// A buffer points to a header of type `H`, which is followed by `MIN_CAP` or more
18
/// bytes of storage.
19
pub struct Buf32<H> {
20
    pub ptr: *mut H,
21
    pub len: u32,
22
    pub cap: u32,
23
}
24
25
#[inline(always)]
26
0
fn bytes_to_vec_capacity<H>(x: u32) -> usize {
27
0
    let header = mem::size_of::<H>();
28
0
    debug_assert!(header > 0);
29
0
    let x = (x as usize).checked_add(header).expect(OFLOW);
30
    // Integer ceil https://stackoverflow.com/a/2745086/1162888
31
0
    1 + ((x - 1) / header)
32
0
}
Unexecuted instantiation: tendril::buf32::bytes_to_vec_capacity::<tendril::tendril::Header<tendril::tendril::NonAtomic>>
Unexecuted instantiation: tendril::buf32::bytes_to_vec_capacity::<tendril::tendril::Header<tendril::tendril::NonAtomic>>
Unexecuted instantiation: tendril::buf32::bytes_to_vec_capacity::<_>
33
34
impl<H> Buf32<H> {
35
    #[inline]
36
0
    pub unsafe fn with_capacity(mut cap: u32, h: H) -> Buf32<H> {
37
0
        if cap < MIN_CAP {
38
0
            cap = MIN_CAP;
39
0
        }
40
41
0
        let mut vec = Vec::<H>::with_capacity(bytes_to_vec_capacity::<H>(cap));
42
0
        let ptr = vec.as_mut_ptr();
43
0
        mem::forget(vec);
44
0
        ptr::write(ptr, h);
45
46
0
        Buf32 {
47
0
            ptr: ptr,
48
0
            len: 0,
49
0
            cap: cap,
50
0
        }
51
0
    }
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::with_capacity
Unexecuted instantiation: <tendril::buf32::Buf32<_>>::with_capacity
52
53
    #[inline]
54
0
    pub unsafe fn destroy(self) {
55
0
        mem::drop(Vec::from_raw_parts(
56
0
            self.ptr,
57
            1,
58
0
            bytes_to_vec_capacity::<H>(self.cap),
59
        ));
60
0
    }
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::destroy
Unexecuted instantiation: <tendril::buf32::Buf32<_>>::destroy
61
62
    #[inline(always)]
63
0
    pub unsafe fn data_ptr(&self) -> *mut u8 {
64
0
        (self.ptr as *mut u8).offset(mem::size_of::<H>() as isize)
65
0
    }
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::data_ptr
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::data_ptr
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::data_ptr
Unexecuted instantiation: <tendril::buf32::Buf32<_>>::data_ptr
66
67
    #[inline(always)]
68
0
    pub unsafe fn data(&self) -> &[u8] {
69
0
        slice::from_raw_parts(self.data_ptr(), self.len as usize)
70
0
    }
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::data
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::data
Unexecuted instantiation: <tendril::buf32::Buf32<_>>::data
71
72
    #[inline(always)]
73
0
    pub unsafe fn data_mut(&mut self) -> &mut [u8] {
74
0
        slice::from_raw_parts_mut(self.data_ptr(), self.len as usize)
75
0
    }
76
77
    /// Grow the capacity to at least `new_cap`.
78
    ///
79
    /// This will panic if the capacity calculation overflows `u32`.
80
    #[inline]
81
0
    pub unsafe fn grow(&mut self, new_cap: u32) {
82
0
        if new_cap <= self.cap {
83
0
            return;
84
0
        }
85
86
0
        let new_cap = new_cap.checked_next_power_of_two().expect(OFLOW);
87
0
        let mut vec = Vec::from_raw_parts(self.ptr, 0, bytes_to_vec_capacity::<H>(self.cap));
88
0
        vec.reserve_exact(bytes_to_vec_capacity::<H>(new_cap));
89
0
        self.ptr = vec.as_mut_ptr();
90
0
        self.cap = new_cap;
91
0
        mem::forget(vec);
92
0
    }
Unexecuted instantiation: <tendril::buf32::Buf32<tendril::tendril::Header<tendril::tendril::NonAtomic>>>::grow
Unexecuted instantiation: <tendril::buf32::Buf32<_>>::grow
93
}
94
95
#[cfg(test)]
96
mod test {
97
    use super::Buf32;
98
    use std::ptr;
99
100
    #[test]
101
    fn smoke_test() {
102
        unsafe {
103
            let mut b = Buf32::with_capacity(0, 0u8);
104
            assert_eq!(b"", b.data());
105
106
            b.grow(5);
107
            ptr::copy_nonoverlapping(b"Hello".as_ptr(), b.data_ptr(), 5);
108
109
            assert_eq!(b"", b.data());
110
            b.len = 5;
111
            assert_eq!(b"Hello", b.data());
112
113
            b.grow(1337);
114
            assert!(b.cap >= 1337);
115
            assert_eq!(b"Hello", b.data());
116
117
            b.destroy();
118
        }
119
    }
120
}