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