Skip to content

Commit

Permalink
Add a safe way to fill a ReadBuf
Browse files Browse the repository at this point in the history
Closes hyperium#3509

Signed-off-by: John Nunley <dev@notgull.net>
  • Loading branch information
notgull committed Jan 5, 2024
1 parent a9fa893 commit 84d0e83
Showing 1 changed file with 35 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/rt/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,41 @@ impl<'data> ReadBufCursor<'data> {
self.buf.init = self.buf.filled.max(self.buf.init);
}

/// Read into a byte slice safely.
///
/// This function provides a safe alternative to the [`as_mut`] and
/// [`advance`] APIS. It initializes the uninitialized part of the
/// buffer (if one exists) and passed it as a slice to the provided
/// closure. Then, it advances the filled part of the buffer by the
/// returned value.
#[inline]
pub fn read_with<E>(&mut self, f: impl FnOnce(&mut [u8]) -> Result<usize, E>) -> Result<(), E> {
// Initialize the unfilled portion of this cursor.
if self.buf.init < self.buf.raw.len() {
self.buf.raw[self.buf.init..].fill(MaybeUninit::new(0));
self.buf.init = self.buf.raw.len();
}

// SAFETY: The full buffer is initialized now.
let slice = unsafe {
core::slice::from_raw_parts_mut(
self.buf.raw[self.buf.filled..].as_mut_ptr() as *mut u8,
self.buf.raw.len() - self.buf.filled,
)
};

// Call the function.
let n = match f(slice) {
Ok(n) => n,
Err(e) => return Err(e),
};

// Advance the buffer.
self.buf.filled = self.buf.filled.checked_add(n).expect("overflow");

Ok(())
}

#[inline]
pub(crate) fn remaining(&self) -> usize {
self.buf.remaining()
Expand Down

0 comments on commit 84d0e83

Please sign in to comment.