1use std::{mem, ptr, slice};
10
11use crate::OFLOW;
12
13pub const MIN_CAP: u32 = 16;
14pub const MAX_LEN: usize = u32::MAX as usize;
15
16pub struct Buf32<H> {
19 pub ptr: *mut H,
20 pub len: u32,
21 pub cap: u32,
22}
23
24#[inline(always)]
25fn bytes_to_vec_capacity<H>(x: u32) -> usize {
26 let header = mem::size_of::<H>();
27 debug_assert!(header > 0);
28 let x = (x as usize).checked_add(header).expect(OFLOW);
29 1 + ((x - 1) / header)
31}
32
33impl<H> Buf32<H> {
34 #[inline]
35 pub unsafe fn with_capacity(mut cap: u32, h: H) -> Buf32<H> {
36 if cap < MIN_CAP {
37 cap = MIN_CAP;
38 }
39
40 let mut vec = Vec::<H>::with_capacity(bytes_to_vec_capacity::<H>(cap));
41 let ptr = vec.as_mut_ptr();
42 mem::forget(vec);
43 ptr::write(ptr, h);
44
45 Buf32 { ptr, len: 0, cap }
46 }
47
48 #[inline]
49 pub unsafe fn destroy(self) {
50 mem::drop(Vec::from_raw_parts(
51 self.ptr,
52 1,
53 bytes_to_vec_capacity::<H>(self.cap),
54 ));
55 }
56
57 #[inline(always)]
58 pub unsafe fn data_ptr(&self) -> *mut u8 {
59 (self.ptr as *mut u8).add(mem::size_of::<H>())
60 }
61
62 #[inline(always)]
63 pub unsafe fn data(&self) -> &[u8] {
64 slice::from_raw_parts(self.data_ptr(), self.len as usize)
65 }
66
67 #[inline(always)]
68 pub unsafe fn data_mut(&mut self) -> &mut [u8] {
69 slice::from_raw_parts_mut(self.data_ptr(), self.len as usize)
70 }
71
72 #[inline]
76 pub unsafe fn grow(&mut self, new_cap: u32) {
77 if new_cap <= self.cap {
78 return;
79 }
80
81 let new_cap = new_cap.checked_next_power_of_two().expect(OFLOW);
82 let mut vec = Vec::from_raw_parts(self.ptr, 0, bytes_to_vec_capacity::<H>(self.cap));
83 vec.reserve_exact(bytes_to_vec_capacity::<H>(new_cap));
84 self.ptr = vec.as_mut_ptr();
85 self.cap = new_cap;
86 mem::forget(vec);
87 }
88}
89
90#[cfg(test)]
91mod test {
92 use super::Buf32;
93 use std::ptr;
94
95 #[test]
96 fn smoke_test() {
97 unsafe {
98 let mut b = Buf32::with_capacity(0, 0u8);
99 assert_eq!(b"", b.data());
100
101 b.grow(5);
102 ptr::copy_nonoverlapping(b"Hello".as_ptr(), b.data_ptr(), 5);
103
104 assert_eq!(b"", b.data());
105 b.len = 5;
106 assert_eq!(b"Hello", b.data());
107
108 b.grow(1337);
109 assert!(b.cap >= 1337);
110 assert_eq!(b"Hello", b.data());
111
112 b.destroy();
113 }
114 }
115}