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}