/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 | | } |