buf_min/
lib.rs

1// Adapted from [`bytes`](https://github.com/tokio-rs/bytes)
2
3/// Minimal Buffer trait with utf-8 safety
4pub trait Buffer {
5    /// Into immutable type
6    type Freeze;
7
8    /// Returns new `Buffer` with capacity
9    fn with_capacity(capacity: usize) -> Self
10    where
11        Self: Sized;
12
13    /// Returns true if the `Buffer` has a length of 0.
14    fn is_empty(&self) -> bool;
15
16    /// Appends given str to this `Buffer`.
17    ///
18    /// # Panics
19    /// Can panic if current length plus `src` length overflows usize
20    #[inline]
21    fn extend(&mut self, src: &str) {
22        // SAFETY: utf-8 checked
23        unsafe {
24            self.extend_from_slice(src.as_bytes());
25        }
26    }
27
28    fn len(&self) -> usize;
29
30    /// Appends given bytes to this `Buffer`.
31    ///
32    /// # Safety
33    /// Broke utf-8 safety
34    ///
35    /// # Panics
36    /// Can panic if current length plus `src` length overflows usize
37    unsafe fn extend_from_slice(&mut self, src: &[u8]);
38
39    /// Reserves capacity for at least `additional` more bytes to be inserted
40    /// into the given `Buffer`.
41    ///
42    /// # Panics
43    /// Can panic if current capacity plus `additional` overflows usize
44    fn reserve(&mut self, additional: usize);
45
46    /// Converts `self` into a Freeze type
47    fn freeze(self) -> Self::Freeze;
48
49    /// Advance the internal cursor of the `Buffer`
50    ///
51    /// # Safety
52    /// Can't advance more than capacity of the `Buffer`
53    ///
54    /// # Panics
55    /// Can panic if length plus `cnt` is bigger than capacity
56    unsafe fn advance(&mut self, cnt: usize);
57
58    /// Return unsafe ptr to current `Buffer` position
59    ///
60    /// # Safety
61    /// If buffer is full, can return invalid pointer
62    unsafe fn buf_ptr(&mut self) -> *mut u8;
63}
64
65impl Buffer for Vec<u8> {
66    type Freeze = Vec<u8>;
67
68    #[inline]
69    fn with_capacity(capacity: usize) -> Self
70    where
71        Self: Sized,
72    {
73        Vec::with_capacity(capacity)
74    }
75
76    #[inline]
77    fn is_empty(&self) -> bool {
78        self.is_empty()
79    }
80
81    #[inline]
82    fn len(&self) -> usize {
83        self.len()
84    }
85
86    #[inline]
87    unsafe fn extend_from_slice(&mut self, src: &[u8]) {
88        Buffer::reserve(self, src.len());
89        debug_assert!(self.capacity() - self.len() >= src.len());
90        std::ptr::copy_nonoverlapping(src.as_ptr(), self.buf_ptr(), src.len());
91        Buffer::advance(self, src.len())
92    }
93
94    #[inline]
95    fn reserve(&mut self, additional: usize) {
96        debug_assert!(self.len() <= self.capacity());
97        if self.capacity().wrapping_sub(self.len()) < additional {
98            self.reserve(additional);
99        }
100    }
101
102    #[inline]
103    fn freeze(mut self) -> Self::Freeze {
104        self.shrink_to_fit();
105        self
106    }
107
108    #[inline]
109    unsafe fn advance(&mut self, cnt: usize) {
110        self.set_len(self.len() + cnt);
111    }
112
113    #[inline]
114    unsafe fn buf_ptr(&mut self) -> *mut u8 {
115        self.as_mut_ptr().add(self.len())
116    }
117}
118
119impl Buffer for String {
120    type Freeze = String;
121
122    #[inline]
123    fn with_capacity(capacity: usize) -> Self
124    where
125        Self: Sized,
126    {
127        String::with_capacity(capacity)
128    }
129
130    #[inline]
131    fn is_empty(&self) -> bool {
132        self.is_empty()
133    }
134
135    #[inline]
136    fn len(&self) -> usize {
137        self.len()
138    }
139
140    #[inline]
141    unsafe fn extend_from_slice(&mut self, src: &[u8]) {
142        Buffer::reserve(self, src.len());
143        debug_assert!(self.capacity() - self.len() >= src.len());
144        std::ptr::copy_nonoverlapping(src.as_ptr(), self.buf_ptr(), src.len());
145        Buffer::advance(self, src.len())
146    }
147
148    #[inline]
149    fn reserve(&mut self, additional: usize) {
150        debug_assert!(self.len() <= self.capacity());
151        if self.capacity().wrapping_sub(self.len()) < additional {
152            self.reserve(additional);
153        }
154    }
155
156    #[inline]
157    fn freeze(mut self) -> Self::Freeze {
158        self.shrink_to_fit();
159        self
160    }
161
162    #[inline]
163    unsafe fn advance(&mut self, cnt: usize) {
164        let len = self.len() + cnt;
165        self.as_mut_vec().set_len(len);
166    }
167
168    #[inline]
169    unsafe fn buf_ptr(&mut self) -> *mut u8 {
170        self.as_mut_ptr().add(self.len())
171    }
172}
173
174#[cfg(any(feature = "bytes", feature = "ntex-bytes"))]
175macro_rules! implement {
176    ($base:path) => {
177        pub use $base::{Bytes, BytesMut};
178
179        impl Buffer for BytesMut {
180            type Freeze = Bytes;
181
182            #[inline]
183            fn with_capacity(capacity: usize) -> Self
184            where
185                Self: Sized,
186            {
187                BytesMut::with_capacity(capacity)
188            }
189
190            #[inline]
191            fn is_empty(&self) -> bool {
192                self.is_empty()
193            }
194
195            #[inline]
196            fn len(&self) -> usize {
197                self.len()
198            }
199
200            #[inline]
201            unsafe fn extend_from_slice(&mut self, src: &[u8]) {
202                Buffer::reserve(self, src.len());
203                debug_assert!(self.capacity() - self.len() >= src.len());
204                std::ptr::copy_nonoverlapping(src.as_ptr(), Buffer::buf_ptr(self), src.len());
205                Buffer::advance(self, src.len());
206            }
207
208            #[inline(always)]
209            fn reserve(&mut self, additional: usize) {
210                self.reserve(additional);
211            }
212
213            #[inline(always)]
214            fn freeze(self) -> Self::Freeze {
215                self.freeze()
216            }
217
218            #[inline]
219            unsafe fn advance(&mut self, cnt: usize) {
220                let new_len = self.len() + cnt;
221                debug_assert!(
222                    new_len <= self.capacity(),
223                    "new_len = {}; capacity = {}",
224                    new_len,
225                    self.capacity()
226                );
227                self.set_len(new_len);
228            }
229
230            #[inline]
231            unsafe fn buf_ptr(&mut self) -> *mut u8 {
232                self.as_mut_ptr().add(self.len())
233            }
234        }
235
236        #[cfg(test)]
237        mod test_bytes {
238            use super::*;
239
240            #[test]
241            fn test() {
242                let e = "Hello world!";
243                let mut buf: BytesMut = Buffer::with_capacity(0);
244                Buffer::extend(&mut buf, e);
245                assert_eq!(e.as_bytes(), &Buffer::freeze(buf)[..]);
246
247                let mut buf: BytesMut = Buffer::with_capacity(124);
248                Buffer::extend(&mut buf, e);
249                assert_eq!(e.as_bytes(), &Buffer::freeze(buf)[..]);
250            }
251        }
252    };
253}
254
255#[cfg(feature = "bytes")]
256pub mod tokio_bytes {
257    use super::*;
258    implement!(bytes);
259}
260
261#[cfg(feature = "ntex-bytes")]
262pub mod ntex {
263    use super::*;
264    implement!(ntex_bytes);
265}
266
267#[cfg(test)]
268mod test {
269    use super::*;
270
271    #[test]
272    fn test() {
273        let e = "Hello world!";
274        let mut buf: Vec<u8> = Buffer::with_capacity(0);
275        Buffer::extend(&mut buf, e);
276        assert_eq!(e.as_bytes(), &Buffer::freeze(buf)[..]);
277
278        let mut buf: Vec<u8> = Buffer::with_capacity(124);
279        Buffer::extend(&mut buf, e);
280        assert_eq!(e.as_bytes(), &Buffer::freeze(buf)[..]);
281
282        let mut buf: Vec<u8> = Buffer::with_capacity(14);
283        Buffer::extend(&mut buf, e);
284    }
285}