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