rasi_ext/utils/
read_buf.rs

1use bytes::{Buf, BufMut, Bytes, BytesMut};
2
3/// A wrapper around a byte buffer that is incrementally filled and initialized.
4///
5/// This type is a sort of "double cursor". It tracks three regions in the
6/// buffer: a region at the beginning of the buffer that has been logically
7/// filled with data, a region that has been initialized at some point but not
8/// yet logically filled, and a region at the end that may be uninitialized.
9/// The filled region is guaranteed to be a subset of the initialized region.
10///
11/// In summary, the contents of the buffer can be visualized as:
12///
13/// ```not_rust
14/// [             capacity              ]
15/// [ filled |         unfilled         ]
16/// [    initialized    | uninitialized ]
17/// ```
18///
19/// It is undefined behavior to de-initialize any bytes from the uninitialized
20/// region, since it is merely unknown whether this region is uninitialized or
21/// not, and if part of it turns out to be initialized, it must stay initialized.
22pub struct ReadBuf {
23    inner: BytesMut,
24}
25
26impl ReadBuf {
27    /// Creates a new `ReadBuf` with the specified capacity.
28    ///
29    /// The returned `ReadBuf` will be able to hold at least `capacity` bytes
30    /// without reallocating.
31    pub fn with_capacity(capacity: usize) -> Self {
32        Self {
33            inner: BytesMut::with_capacity(capacity),
34        }
35    }
36
37    /// Returns a mutable slice starting at the current BufMut position and of
38    /// length between 0 and [`ReadBuf::remaining_mut()`]. Note that this *can* be shorter than the
39    /// whole remainder of the buffer (this allows non-continuous implementation).
40    pub fn chunk_mut(&mut self) -> &mut [u8] {
41        let dst = self.inner.chunk_mut();
42
43        unsafe { &mut *(dst as *mut _ as *mut [u8]) }
44    }
45
46    /// Returns the number of bytes that can be written from the current
47    /// position until the end of the buffer is reached.
48    ///
49    /// This value is greater than or equal to the length of the slice returned
50    /// by `chunk_mut()`.
51    pub fn remaining_mut(&self) -> usize {
52        self.inner.remaining_mut()
53    }
54
55    /// Advance the internal cursor of the BufMut
56    ///
57    /// The next call to [`chunk_mut`](Self::chunk_mut) will return a slice starting `cnt` bytes
58    /// further into the underlying buffer.
59    pub fn advance_mut(&mut self, advance: usize) {
60        unsafe {
61            self.inner.advance_mut(advance);
62        }
63    }
64
65    /// Consume [`ReadBuf`] and convert into [`BytesMut`]
66    pub fn into_bytes_mut(mut self, advance: Option<usize>) -> BytesMut {
67        if let Some(advance) = advance {
68            self.advance_mut(advance);
69        }
70
71        self.inner
72    }
73
74    /// Consume [`ReadBuf`] and convert into [`Bytes`]
75    pub fn into_bytes(self, advance: Option<usize>) -> Bytes {
76        self.into_bytes_mut(advance).into()
77    }
78
79    /// Returns a slice starting at the current position and of length between 0
80    /// and [`ReadBuf::remaining()`](Self::remaining). Note that this *can* return shorter slice (this allows
81    /// non-continuous internal representation).
82    pub fn chunk(&self) -> &[u8] {
83        self.inner.chunk()
84    }
85
86    /// Returns the number of bytes between the current position and the end of
87    /// the buffer.
88    ///
89    /// This value is greater than or equal to the length of the slice returned
90    /// by [`chunk()`](Self::chunk).
91    pub fn remaining(&self) -> usize {
92        self.inner.remaining()
93    }
94
95    /// Splits the buffer into two at the given index.
96    ///
97    /// Afterwards `self` contains elements `[at, len)`, and the returned `BytesMut`
98    /// contains elements `[0, at)`.
99    ///
100    /// This is an `O(1)` operation that just increases the reference count and
101    /// sets a few indices.
102    pub fn split_to(&mut self, at: usize) -> BytesMut {
103        self.inner.split_to(at)
104    }
105}