1 | use std::fmt; |
2 | use std::mem::MaybeUninit; |
3 | |
4 | /// A wrapper around a byte buffer that is incrementally filled and initialized. |
5 | /// |
6 | /// This type is a sort of "double cursor". It tracks three regions in the |
7 | /// buffer: a region at the beginning of the buffer that has been logically |
8 | /// filled with data, a region that has been initialized at some point but not |
9 | /// yet logically filled, and a region at the end that may be uninitialized. |
10 | /// The filled region is guaranteed to be a subset of the initialized region. |
11 | /// |
12 | /// In summary, the contents of the buffer can be visualized as: |
13 | /// |
14 | /// ```not_rust |
15 | /// [ capacity ] |
16 | /// [ filled | unfilled ] |
17 | /// [ initialized | uninitialized ] |
18 | /// ``` |
19 | /// |
20 | /// It is undefined behavior to de-initialize any bytes from the uninitialized |
21 | /// region, since it is merely unknown whether this region is uninitialized or |
22 | /// not, and if part of it turns out to be initialized, it must stay initialized. |
23 | pub struct ReadBuf<'a> { |
24 | buf: &'a mut [MaybeUninit<u8>], |
25 | filled: usize, |
26 | initialized: usize, |
27 | } |
28 | |
29 | impl<'a> ReadBuf<'a> { |
30 | /// Creates a new `ReadBuf` from a fully initialized buffer. |
31 | #[inline ] |
32 | pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> { |
33 | let initialized = buf.len(); |
34 | let buf = unsafe { slice_to_uninit_mut(buf) }; |
35 | ReadBuf { |
36 | buf, |
37 | filled: 0, |
38 | initialized, |
39 | } |
40 | } |
41 | |
42 | /// Creates a new `ReadBuf` from a buffer that may be uninitialized. |
43 | /// |
44 | /// The internal cursor will mark the entire buffer as uninitialized. If |
45 | /// the buffer is known to be partially initialized, then use `assume_init` |
46 | /// to move the internal cursor. |
47 | #[inline ] |
48 | pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> { |
49 | ReadBuf { |
50 | buf, |
51 | filled: 0, |
52 | initialized: 0, |
53 | } |
54 | } |
55 | |
56 | /// Returns the total capacity of the buffer. |
57 | #[inline ] |
58 | pub fn capacity(&self) -> usize { |
59 | self.buf.len() |
60 | } |
61 | |
62 | /// Returns a shared reference to the filled portion of the buffer. |
63 | #[inline ] |
64 | pub fn filled(&self) -> &[u8] { |
65 | let slice = &self.buf[..self.filled]; |
66 | // safety: filled describes how far into the buffer that the |
67 | // user has filled with bytes, so it's been initialized. |
68 | unsafe { slice_assume_init(slice) } |
69 | } |
70 | |
71 | /// Returns a mutable reference to the filled portion of the buffer. |
72 | #[inline ] |
73 | pub fn filled_mut(&mut self) -> &mut [u8] { |
74 | let slice = &mut self.buf[..self.filled]; |
75 | // safety: filled describes how far into the buffer that the |
76 | // user has filled with bytes, so it's been initialized. |
77 | unsafe { slice_assume_init_mut(slice) } |
78 | } |
79 | |
80 | /// Returns a new `ReadBuf` comprised of the unfilled section up to `n`. |
81 | #[inline ] |
82 | pub fn take(&mut self, n: usize) -> ReadBuf<'_> { |
83 | let max = std::cmp::min(self.remaining(), n); |
84 | // Safety: We don't set any of the `unfilled_mut` with `MaybeUninit::uninit`. |
85 | unsafe { ReadBuf::uninit(&mut self.unfilled_mut()[..max]) } |
86 | } |
87 | |
88 | /// Returns a shared reference to the initialized portion of the buffer. |
89 | /// |
90 | /// This includes the filled portion. |
91 | #[inline ] |
92 | pub fn initialized(&self) -> &[u8] { |
93 | let slice = &self.buf[..self.initialized]; |
94 | // safety: initialized describes how far into the buffer that the |
95 | // user has at some point initialized with bytes. |
96 | unsafe { slice_assume_init(slice) } |
97 | } |
98 | |
99 | /// Returns a mutable reference to the initialized portion of the buffer. |
100 | /// |
101 | /// This includes the filled portion. |
102 | #[inline ] |
103 | pub fn initialized_mut(&mut self) -> &mut [u8] { |
104 | let slice = &mut self.buf[..self.initialized]; |
105 | // safety: initialized describes how far into the buffer that the |
106 | // user has at some point initialized with bytes. |
107 | unsafe { slice_assume_init_mut(slice) } |
108 | } |
109 | |
110 | /// Returns a mutable reference to the entire buffer, without ensuring that it has been fully |
111 | /// initialized. |
112 | /// |
113 | /// The elements between 0 and `self.filled().len()` are filled, and those between 0 and |
114 | /// `self.initialized().len()` are initialized (and so can be converted to a `&mut [u8]`). |
115 | /// |
116 | /// The caller of this method must ensure that these invariants are upheld. For example, if the |
117 | /// caller initializes some of the uninitialized section of the buffer, it must call |
118 | /// [`assume_init`](Self::assume_init) with the number of bytes initialized. |
119 | /// |
120 | /// # Safety |
121 | /// |
122 | /// The caller must not de-initialize portions of the buffer that have already been initialized. |
123 | /// This includes any bytes in the region marked as uninitialized by `ReadBuf`. |
124 | #[inline ] |
125 | pub unsafe fn inner_mut(&mut self) -> &mut [MaybeUninit<u8>] { |
126 | self.buf |
127 | } |
128 | |
129 | /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully |
130 | /// initialized. |
131 | /// |
132 | /// # Safety |
133 | /// |
134 | /// The caller must not de-initialize portions of the buffer that have already been initialized. |
135 | /// This includes any bytes in the region marked as uninitialized by `ReadBuf`. |
136 | #[inline ] |
137 | pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] { |
138 | &mut self.buf[self.filled..] |
139 | } |
140 | |
141 | /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized. |
142 | /// |
143 | /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after |
144 | /// the first use. |
145 | #[inline ] |
146 | pub fn initialize_unfilled(&mut self) -> &mut [u8] { |
147 | self.initialize_unfilled_to(self.remaining()) |
148 | } |
149 | |
150 | /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is |
151 | /// fully initialized. |
152 | /// |
153 | /// # Panics |
154 | /// |
155 | /// Panics if `self.remaining()` is less than `n`. |
156 | #[inline ] |
157 | #[track_caller ] |
158 | pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] { |
159 | assert!(self.remaining() >= n, "n overflows remaining" ); |
160 | |
161 | // This can't overflow, otherwise the assert above would have failed. |
162 | let end = self.filled + n; |
163 | |
164 | if self.initialized < end { |
165 | unsafe { |
166 | self.buf[self.initialized..end] |
167 | .as_mut_ptr() |
168 | .write_bytes(0, end - self.initialized); |
169 | } |
170 | self.initialized = end; |
171 | } |
172 | |
173 | let slice = &mut self.buf[self.filled..end]; |
174 | // safety: just above, we checked that the end of the buf has |
175 | // been initialized to some value. |
176 | unsafe { slice_assume_init_mut(slice) } |
177 | } |
178 | |
179 | /// Returns the number of bytes at the end of the slice that have not yet been filled. |
180 | #[inline ] |
181 | pub fn remaining(&self) -> usize { |
182 | self.capacity() - self.filled |
183 | } |
184 | |
185 | /// Clears the buffer, resetting the filled region to empty. |
186 | /// |
187 | /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. |
188 | #[inline ] |
189 | pub fn clear(&mut self) { |
190 | self.filled = 0; |
191 | } |
192 | |
193 | /// Advances the size of the filled region of the buffer. |
194 | /// |
195 | /// The number of initialized bytes is not changed. |
196 | /// |
197 | /// # Panics |
198 | /// |
199 | /// Panics if the filled region of the buffer would become larger than the initialized region. |
200 | #[inline ] |
201 | #[track_caller ] |
202 | pub fn advance(&mut self, n: usize) { |
203 | let new = self.filled.checked_add(n).expect("filled overflow" ); |
204 | self.set_filled(new); |
205 | } |
206 | |
207 | /// Sets the size of the filled region of the buffer. |
208 | /// |
209 | /// The number of initialized bytes is not changed. |
210 | /// |
211 | /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for |
212 | /// example, by a `AsyncRead` implementation that compresses data in-place). |
213 | /// |
214 | /// # Panics |
215 | /// |
216 | /// Panics if the filled region of the buffer would become larger than the initialized region. |
217 | #[inline ] |
218 | #[track_caller ] |
219 | pub fn set_filled(&mut self, n: usize) { |
220 | assert!( |
221 | n <= self.initialized, |
222 | "filled must not become larger than initialized" |
223 | ); |
224 | self.filled = n; |
225 | } |
226 | |
227 | /// Asserts that the first `n` unfilled bytes of the buffer are initialized. |
228 | /// |
229 | /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer |
230 | /// bytes than are already known to be initialized. |
231 | /// |
232 | /// # Safety |
233 | /// |
234 | /// The caller must ensure that `n` unfilled bytes of the buffer have already been initialized. |
235 | #[inline ] |
236 | pub unsafe fn assume_init(&mut self, n: usize) { |
237 | let new = self.filled + n; |
238 | if new > self.initialized { |
239 | self.initialized = new; |
240 | } |
241 | } |
242 | |
243 | /// Appends data to the buffer, advancing the written position and possibly also the initialized position. |
244 | /// |
245 | /// # Panics |
246 | /// |
247 | /// Panics if `self.remaining()` is less than `buf.len()`. |
248 | #[inline ] |
249 | #[track_caller ] |
250 | pub fn put_slice(&mut self, buf: &[u8]) { |
251 | assert!( |
252 | self.remaining() >= buf.len(), |
253 | "buf.len() must fit in remaining(); buf.len() = {}, remaining() = {}" , |
254 | buf.len(), |
255 | self.remaining() |
256 | ); |
257 | |
258 | let amt = buf.len(); |
259 | // Cannot overflow, asserted above |
260 | let end = self.filled + amt; |
261 | |
262 | // Safety: the length is asserted above |
263 | unsafe { |
264 | self.buf[self.filled..end] |
265 | .as_mut_ptr() |
266 | .cast::<u8>() |
267 | .copy_from_nonoverlapping(buf.as_ptr(), amt); |
268 | } |
269 | |
270 | if self.initialized < end { |
271 | self.initialized = end; |
272 | } |
273 | self.filled = end; |
274 | } |
275 | } |
276 | |
277 | #[cfg (feature = "io-util" )] |
278 | #[cfg_attr (docsrs, doc(cfg(feature = "io-util" )))] |
279 | unsafe impl<'a> bytes::BufMut for ReadBuf<'a> { |
280 | fn remaining_mut(&self) -> usize { |
281 | self.remaining() |
282 | } |
283 | |
284 | // SAFETY: The caller guarantees that at least `cnt` unfilled bytes have been initialized. |
285 | unsafe fn advance_mut(&mut self, cnt: usize) { |
286 | self.assume_init(cnt); |
287 | self.advance(cnt); |
288 | } |
289 | |
290 | fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice { |
291 | // SAFETY: No region of `unfilled` will be deinitialized because it is |
292 | // exposed as an `UninitSlice`, whose API guarantees that the memory is |
293 | // never deinitialized. |
294 | let unfilled: &mut [MaybeUninit] = unsafe { self.unfilled_mut() }; |
295 | let len: usize = unfilled.len(); |
296 | let ptr: *mut u8 = unfilled.as_mut_ptr() as *mut u8; |
297 | |
298 | // SAFETY: The pointer is valid for `len` bytes because it comes from a |
299 | // slice of that length. |
300 | unsafe { bytes::buf::UninitSlice::from_raw_parts_mut(ptr, len) } |
301 | } |
302 | } |
303 | |
304 | impl fmt::Debug for ReadBuf<'_> { |
305 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
306 | f&mut DebugStruct<'_, '_>.debug_struct("ReadBuf" ) |
307 | .field("filled" , &self.filled) |
308 | .field("initialized" , &self.initialized) |
309 | .field(name:"capacity" , &self.capacity()) |
310 | .finish() |
311 | } |
312 | } |
313 | |
314 | unsafe fn slice_to_uninit_mut(slice: &mut [u8]) -> &mut [MaybeUninit<u8>] { |
315 | &mut *(slice as *mut [u8] as *mut [MaybeUninit<u8>]) |
316 | } |
317 | |
318 | // TODO: This could use `MaybeUninit::slice_assume_init` when it is stable. |
319 | unsafe fn slice_assume_init(slice: &[MaybeUninit<u8>]) -> &[u8] { |
320 | &*(slice as *const [MaybeUninit<u8>] as *const [u8]) |
321 | } |
322 | |
323 | // TODO: This could use `MaybeUninit::slice_assume_init_mut` when it is stable. |
324 | unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] { |
325 | &mut *(slice as *mut [MaybeUninit<u8>] as *mut [u8]) |
326 | } |
327 | |