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]
new(buf: &'a mut [u8]) -> ReadBuf<'a>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]
uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a>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]
capacity(&self) -> usize56     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]
filled(&self) -> &[u8]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]
filled_mut(&mut self) -> &mut [u8]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]
take(&mut self, n: usize) -> ReadBuf<'_>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]
initialized(&self) -> &[u8]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]
initialized_mut(&mut self) -> &mut [u8]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]
inner_mut(&mut self) -> &mut [MaybeUninit<u8>]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]
unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>]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]
initialize_unfilled(&mut self) -> &mut [u8]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]
initialize_unfilled_to(&mut self, n: usize) -> &mut [u8]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]
remaining(&self) -> usize179     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]
clear(&mut self)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]
advance(&mut self, n: usize)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]
set_filled(&mut self, n: usize)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]
assume_init(&mut self, n: usize)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]
put_slice(&mut self, buf: &[u8])248     pub fn put_slice(&mut self, buf: &[u8]) {
249         assert!(
250             self.remaining() >= buf.len(),
251             "buf.len() must fit in remaining(); buf.len() = {}, remaining() = {}",
252             buf.len(),
253             self.remaining()
254         );
255 
256         let amt = buf.len();
257         // Cannot overflow, asserted above
258         let end = self.filled + amt;
259 
260         // Safety: the length is asserted above
261         unsafe {
262             self.buf[self.filled..end]
263                 .as_mut_ptr()
264                 .cast::<u8>()
265                 .copy_from_nonoverlapping(buf.as_ptr(), amt);
266         }
267 
268         if self.initialized < end {
269             self.initialized = end;
270         }
271         self.filled = end;
272     }
273 }
274 
275 #[cfg(feature = "io-util")]
276 #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
277 unsafe impl<'a> bytes::BufMut for ReadBuf<'a> {
remaining_mut(&self) -> usize278     fn remaining_mut(&self) -> usize {
279         self.remaining()
280     }
281 
282     // SAFETY: The caller guarantees that at least `cnt` unfilled bytes have been initialized.
advance_mut(&mut self, cnt: usize)283     unsafe fn advance_mut(&mut self, cnt: usize) {
284         self.assume_init(cnt);
285         self.advance(cnt);
286     }
287 
chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice288     fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
289         // SAFETY: No region of `unfilled` will be deinitialized because it is
290         // exposed as an `UninitSlice`, whose API guarantees that the memory is
291         // never deinitialized.
292         let unfilled = unsafe { self.unfilled_mut() };
293         let len = unfilled.len();
294         let ptr = unfilled.as_mut_ptr() as *mut u8;
295 
296         // SAFETY: The pointer is valid for `len` bytes because it comes from a
297         // slice of that length.
298         unsafe { bytes::buf::UninitSlice::from_raw_parts_mut(ptr, len) }
299     }
300 }
301 
302 impl fmt::Debug for ReadBuf<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result303     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304         f.debug_struct("ReadBuf")
305             .field("filled", &self.filled)
306             .field("initialized", &self.initialized)
307             .field("capacity", &self.capacity())
308             .finish()
309     }
310 }
311 
slice_to_uninit_mut(slice: &mut [u8]) -> &mut [MaybeUninit<u8>]312 unsafe fn slice_to_uninit_mut(slice: &mut [u8]) -> &mut [MaybeUninit<u8>] {
313     &mut *(slice as *mut [u8] as *mut [MaybeUninit<u8>])
314 }
315 
316 // TODO: This could use `MaybeUninit::slice_assume_init` when it is stable.
slice_assume_init(slice: &[MaybeUninit<u8>]) -> &[u8]317 unsafe fn slice_assume_init(slice: &[MaybeUninit<u8>]) -> &[u8] {
318     &*(slice as *const [MaybeUninit<u8>] as *const [u8])
319 }
320 
321 // TODO: This could use `MaybeUninit::slice_assume_init_mut` when it is stable.
slice_assume_init_mut(slice: &mut [MaybeUninit<u8>]) -> &mut [u8]322 unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
323     &mut *(slice as *mut [MaybeUninit<u8>] as *mut [u8])
324 }
325