cl_generic_read_buf/lib.rs
1//! ReadBuf types and methods. See https://github.com/rust-lang/rust/issues/78485
2
3use cl_generic_vec::{raw::Storage, ArrayVec, HeapVec, SimpleVec, SliceVec};
4use std::{cmp, fmt, io, mem::MaybeUninit, ops::Deref};
5
6/// A [`Storage`] of [`u8`]s
7pub trait Bytes: Storage<Item = u8> {}
8impl<S: Storage<Item = u8>> Bytes for S {}
9
10/// A wrapper over [`io::Read`] to provide the custom read_buf* methods on stable
11pub trait Read: io::Read {
12 /// Pull some bytes from this source into the specified buffer.
13 ///
14 /// This is equivalent to the [`read`](io::Read::read) method, except that it is passed a [`ReadBufRef`] rather than `[u8]` to allow use
15 /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`.
16 ///
17 /// The default implementation delegates to `read`.
18 fn read_buf(&mut self, buf: ReadBufRef<'_, impl Bytes>) -> io::Result<()> {
19 default_read_buf(|b| self.read(b), buf)
20 }
21
22 /// Read the exact number of bytes required to fill `buf`.
23 ///
24 /// This is equivalent to the [`read_exact`](io::Read::read_exact) method, except that it is passed a [`ReadBufRef`] rather than `[u8]` to
25 /// allow use with uninitialized buffers.
26 fn read_buf_exact(&mut self, mut buf: ReadBufRef<'_, impl Bytes>) -> io::Result<()> {
27 while buf.remaining() > 0 {
28 let prev_filled = buf.filled().len();
29 match Read::read_buf(self, buf.reborrow()) {
30 Ok(()) => {}
31 Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
32 Err(e) => return Err(e),
33 }
34
35 if buf.filled().len() == prev_filled {
36 return Err(io::Error::new(
37 io::ErrorKind::UnexpectedEof,
38 "failed to fill buffer",
39 ));
40 }
41 }
42
43 Ok(())
44 }
45}
46
47impl<R: io::Read> Read for R {}
48
49pub(crate) fn default_read_buf<F>(read: F, mut buf: ReadBufRef<'_, impl Bytes>) -> io::Result<()>
50where
51 F: FnOnce(&mut [u8]) -> io::Result<usize>,
52{
53 let n = read(buf.initialize_unfilled())?;
54 buf.add_filled(n);
55 Ok(())
56}
57
58/// A wrapper around a byte buffer that is incrementally filled and initialized.
59///
60/// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the
61/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet
62/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a
63/// subset of the initialized region.
64///
65/// In summary, the contents of the buffer can be visualized as:
66/// ```not_rust
67/// [ capacity ]
68/// [ filled | unfilled ]
69/// [ initialized | uninitialized ]
70/// ```
71pub struct ReadBuf<S: Bytes> {
72 filled: usize,
73 buf: SimpleVec<S>,
74}
75
76impl<S: Bytes> fmt::Debug for ReadBuf<S> {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 f.debug_struct("ReadBuf")
79 .field("init", &self.buf.len())
80 .field("filled", &self.filled)
81 .field("capacity", &self.buf.capacity())
82 .finish()
83 }
84}
85
86/// A [`ReadBuf`] that takes it's buffer from an existing slice
87pub type ReadSlice<'a> = ReadBuf<&'a mut [MaybeUninit<u8>]>;
88/// A [`ReadBuf`] that owns it's buffer using a [`Vec<u8>`]
89pub type ReadVec = ReadBuf<Box<[MaybeUninit<u8>]>>;
90/// A [`ReadBuf`] that owns it's buffer using a [`[MaybeUninit<u8>; N]`](array)
91pub type ReadArray<const N: usize> = ReadBuf<[MaybeUninit<u8>; N]>;
92
93impl<const N: usize> ReadArray<N> {
94 /// Create a new uninitialised [`ReadBuf`] backed by an array
95 /// Will begin with 0 filled bytes.
96 pub fn new_uninit_array() -> Self {
97 Self {
98 filled: 0,
99 buf: ArrayVec::new(),
100 }
101 }
102}
103
104/// Create a [`ReadBuf`] from a fully initialised array of bytes.
105/// Will begin with 0 filled bytes.
106impl<const N: usize> From<[u8; N]> for ReadArray<N> {
107 fn from(buf: [u8; N]) -> Self {
108 ReadBuf {
109 filled: 0,
110 buf: ArrayVec::from_array(buf),
111 }
112 }
113}
114
115/// Create a [`ReadBuf`] from a partially initialised vec of bytes.
116/// Will begin with 0 filled bytes.
117impl From<Vec<u8>> for ReadVec {
118 fn from(buf: Vec<u8>) -> Self {
119 ReadBuf {
120 filled: 0,
121 buf: buf.into(),
122 }
123 }
124}
125
126/// Create a [`ReadBuf`] from an uninitialised boxed-slice of bytes.
127/// Will begin with 0 filled bytes.
128impl From<Box<[MaybeUninit<u8>]>> for ReadVec {
129 fn from(buf: Box<[MaybeUninit<u8>]>) -> Self {
130 ReadBuf {
131 filled: 0,
132 buf: HeapVec::with_storage(buf),
133 }
134 }
135}
136
137/// Create a [`ReadBuf`] from an initialised slice of bytes.
138/// Will begin with 0 filled bytes.
139impl<'a> From<&'a mut [u8]> for ReadSlice<'a> {
140 fn from(buf: &'a mut [u8]) -> Self {
141 ReadBuf {
142 filled: 0,
143 buf: SliceVec::full(buf),
144 }
145 }
146}
147
148/// Create a [`ReadBuf`] from an uninitialised slice of bytes.
149/// Will begin with 0 filled bytes.
150impl<'a> From<&'a mut [MaybeUninit<u8>]> for ReadSlice<'a> {
151 fn from(buf: &'a mut [MaybeUninit<u8>]) -> Self {
152 ReadBuf {
153 filled: 0,
154 buf: unsafe { SliceVec::new(buf) },
155 }
156 }
157}
158
159impl<S: Bytes> ReadBuf<S> {
160 /// Extract the bytes from the [`ReadBuf`]
161 pub fn into_inner(self) -> SimpleVec<S> {
162 assert_eq!(self.filled, self.buf.len());
163 self.buf
164 }
165
166 /// Creates a new [`ReadBufRef`] referencing this `ReadBuf`.
167 #[inline]
168 pub fn borrow(&mut self) -> ReadBufRef<'_, S> {
169 ReadBufRef { read_buf: self }
170 }
171
172 /// Returns the total capacity of the buffer.
173 #[inline]
174 pub fn capacity(&self) -> usize {
175 self.buf.capacity()
176 }
177
178 /// Returns a shared reference to the filled portion of the buffer.
179 #[inline]
180 pub fn filled(&self) -> &[u8] {
181 &self.buf[..self.filled]
182 }
183
184 /// Returns a mutable reference to the filled portion of the buffer.
185 #[inline]
186 pub fn filled_mut(&mut self) -> &mut [u8] {
187 &mut self.buf[..self.filled]
188 }
189
190 /// Returns a shared reference to the initialized portion of the buffer.
191 ///
192 /// This includes the filled portion.
193 #[inline]
194 pub fn initialized(&self) -> &[u8] {
195 self.buf.as_slice()
196 }
197
198 /// Returns a mutable reference to the initialized portion of the buffer.
199 ///
200 /// This includes the filled portion.
201 #[inline]
202 pub fn initialized_mut(&mut self) -> &mut [u8] {
203 self.buf.as_mut_slice()
204 }
205
206 /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully
207 /// initialized.
208 ///
209 /// # Safety
210 ///
211 /// The caller must not de-initialize portions of the buffer that have already been initialized.
212 #[inline]
213 pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
214 &mut self.buf.storage_mut().as_mut()[self.filled..]
215 }
216
217 /// Returns a mutable reference to the uninitialized part of the buffer.
218 ///
219 /// It is safe to uninitialize any of these bytes.
220 #[inline]
221 pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit<u8>] {
222 self.buf.spare_capacity_mut()
223 }
224
225 /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized.
226 ///
227 /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after
228 /// the first use.
229 #[inline]
230 pub fn initialize_unfilled(&mut self) -> &mut [u8] {
231 // should optimize out the assertion
232 self.initialize_unfilled_to(self.remaining())
233 }
234
235 /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is
236 /// fully initialized.
237 ///
238 /// # Panics
239 ///
240 /// Panics if `self.remaining()` is less than `n`.
241 #[inline]
242 pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
243 assert!(self.remaining() >= n);
244
245 let extra_init = self.buf.len() - self.filled;
246 // If we don't have enough initialized, do zeroing
247 if n > extra_init {
248 let uninit = n - extra_init;
249 let unfilled = &mut self.uninitialized_mut()[0..uninit];
250
251 for byte in unfilled.iter_mut() {
252 byte.write(0);
253 }
254
255 // SAFETY: we just initialized uninit bytes, and the previous bytes were already init
256 unsafe {
257 self.assume_init(n);
258 }
259 }
260
261 let filled = self.filled;
262
263 &mut self.initialized_mut()[filled..filled + n]
264 }
265
266 /// Returns the number of bytes at the end of the slice that have not yet been filled.
267 #[inline]
268 pub fn remaining(&self) -> usize {
269 self.capacity() - self.filled
270 }
271
272 /// Clears the buffer, resetting the filled region to empty.
273 ///
274 /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
275 #[inline]
276 pub fn clear(&mut self) {
277 self.set_filled(0); // The assertion in `set_filled` is optimized out
278 }
279
280 /// Increases the size of the filled region of the buffer.
281 ///
282 /// The number of initialized bytes is not changed.
283 ///
284 /// # Panics
285 ///
286 /// Panics if the filled region of the buffer would become larger than the initialized region.
287 #[inline]
288 pub fn add_filled(&mut self, n: usize) {
289 self.set_filled(self.filled + n);
290 }
291
292 /// Sets the size of the filled region of the buffer.
293 ///
294 /// The number of initialized bytes is not changed.
295 ///
296 /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for
297 /// example, by a `Read` implementation that compresses data in-place).
298 ///
299 /// # Panics
300 ///
301 /// Panics if the filled region of the buffer would become larger than the initialized region.
302 #[inline]
303 pub fn set_filled(&mut self, n: usize) {
304 assert!(n <= self.buf.len());
305
306 self.filled = n;
307 }
308
309 /// Asserts that the first `n` unfilled bytes of the buffer are initialized.
310 ///
311 /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
312 /// bytes than are already known to be initialized.
313 ///
314 /// # Safety
315 ///
316 /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized.
317 #[inline]
318 pub unsafe fn assume_init(&mut self, n: usize) {
319 self.buf
320 .set_len_unchecked(cmp::max(self.buf.len(), self.filled + n));
321 }
322
323 /// Appends data to the buffer, advancing the written position and possibly also the initialized position.
324 ///
325 /// # Panics
326 ///
327 /// Panics if `self.remaining()` is less than `buf.len()`.
328 #[inline]
329 pub fn append(&mut self, buf: &[u8]) {
330 assert!(self.remaining() >= buf.len());
331
332 // SAFETY: we do not de-initialize any of the elements of the slice
333 unsafe {
334 write_slice(&mut self.unfilled_mut()[..buf.len()], buf);
335 }
336
337 // SAFETY: We just added the entire contents of buf to the filled section.
338 unsafe { self.assume_init(buf.len()) }
339 self.add_filled(buf.len());
340 }
341
342 /// Returns the amount of bytes that have been filled.
343 #[inline]
344 pub fn filled_len(&self) -> usize {
345 self.filled
346 }
347
348 /// Returns the amount of bytes that have been initialized.
349 #[inline]
350 pub fn initialized_len(&self) -> usize {
351 self.buf.len()
352 }
353}
354
355// from MaybeUninit::write_slice
356unsafe fn write_slice<T>(this: &mut [MaybeUninit<T>], src: &[T])
357where
358 T: Copy,
359{
360 // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
361 let uninit_src: &[MaybeUninit<T>] = core::mem::transmute(src);
362
363 this.copy_from_slice(uninit_src);
364}
365
366/// A wrapper around [`&mut ReadBuf`](ReadBuf) which prevents the buffer that the [`ReadBuf`] points to from being replaced.
367#[derive(Debug)]
368pub struct ReadBufRef<'a, S: Bytes> {
369 read_buf: &'a mut ReadBuf<S>,
370}
371
372impl<'a, S: Bytes> ReadBufRef<'a, S> {
373 /// Creates a new `ReadBufRef` referencing the same `ReadBuf` as this one.
374 pub fn reborrow(&mut self) -> ReadBufRef<'_, S> {
375 ReadBufRef {
376 read_buf: self.read_buf,
377 }
378 }
379
380 /// Returns a mutable reference to the filled portion of the buffer.
381 #[inline]
382 pub fn filled_mut(&mut self) -> &mut [u8] {
383 self.read_buf.filled_mut()
384 }
385
386 /// Returns a mutable reference to the initialized portion of the buffer.
387 ///
388 /// This includes the filled portion.
389 #[inline]
390 pub fn initialized_mut(&mut self) -> &mut [u8] {
391 self.read_buf.initialized_mut()
392 }
393
394 /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully
395 /// initialized.
396 ///
397 /// # Safety
398 ///
399 /// The caller must not de-initialize portions of the buffer that have already been initialized.
400 #[inline]
401 pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
402 self.read_buf.unfilled_mut()
403 }
404
405 /// Returns a mutable reference to the uninitialized part of the buffer.
406 ///
407 /// It is safe to uninitialize any of these bytes.
408 #[inline]
409 pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit<u8>] {
410 self.read_buf.uninitialized_mut()
411 }
412
413 /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized.
414 ///
415 /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after
416 /// the first use.
417 #[inline]
418 pub fn initialize_unfilled(&mut self) -> &mut [u8] {
419 self.read_buf.initialize_unfilled()
420 }
421
422 /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is
423 /// fully initialized.
424 ///
425 /// # Panics
426 ///
427 /// Panics if `self.remaining()` is less than `n`.
428 #[inline]
429 pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
430 self.read_buf.initialize_unfilled_to(n)
431 }
432
433 /// Clears the buffer, resetting the filled region to empty.
434 ///
435 /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
436 #[inline]
437 pub fn clear(&mut self) {
438 self.read_buf.clear()
439 }
440
441 /// Increases the size of the filled region of the buffer.
442 ///
443 /// The number of initialized bytes is not changed.
444 ///
445 /// # Panics
446 ///
447 /// Panics if the filled region of the buffer would become larger than the initialized region.
448 #[inline]
449 pub fn add_filled(&mut self, n: usize) {
450 self.read_buf.add_filled(n)
451 }
452
453 /// Sets the size of the filled region of the buffer.
454 ///
455 /// The number of initialized bytes is not changed.
456 ///
457 /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for
458 /// example, by a `Read` implementation that compresses data in-place).
459 ///
460 /// # Panics
461 ///
462 /// Panics if the filled region of the buffer would become larger than the initialized region.
463 #[inline]
464 pub fn set_filled(&mut self, n: usize) {
465 self.read_buf.set_filled(n)
466 }
467
468 /// Asserts that the first `n` unfilled bytes of the buffer are initialized.
469 ///
470 /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
471 /// bytes than are already known to be initialized.
472 ///
473 /// # Safety
474 ///
475 /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized.
476 #[inline]
477 pub unsafe fn assume_init(&mut self, n: usize) {
478 self.read_buf.assume_init(n)
479 }
480
481 /// Appends data to the buffer, advancing the written position and possibly also the initialized position.
482 ///
483 /// # Panics
484 ///
485 /// Panics if `self.remaining()` is less than `buf.len()`.
486 #[inline]
487 pub fn append(&mut self, buf: &[u8]) {
488 self.read_buf.append(buf)
489 }
490}
491
492impl<'a, S: Bytes> Deref for ReadBufRef<'a, S> {
493 type Target = ReadBuf<S>;
494
495 fn deref(&self) -> &ReadBuf<S> {
496 &*self.read_buf
497 }
498}