Skip to content

Commit 84d0e83

Browse files
committed
Add a safe way to fill a ReadBuf
Closes hyperium#3509 Signed-off-by: John Nunley <[email protected]>
1 parent a9fa893 commit 84d0e83

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

Diff for: src/rt/io.rs

+35
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,41 @@ impl<'data> ReadBufCursor<'data> {
244244
self.buf.init = self.buf.filled.max(self.buf.init);
245245
}
246246

247+
/// Read into a byte slice safely.
248+
///
249+
/// This function provides a safe alternative to the [`as_mut`] and
250+
/// [`advance`] APIS. It initializes the uninitialized part of the
251+
/// buffer (if one exists) and passed it as a slice to the provided
252+
/// closure. Then, it advances the filled part of the buffer by the
253+
/// returned value.
254+
#[inline]
255+
pub fn read_with<E>(&mut self, f: impl FnOnce(&mut [u8]) -> Result<usize, E>) -> Result<(), E> {
256+
// Initialize the unfilled portion of this cursor.
257+
if self.buf.init < self.buf.raw.len() {
258+
self.buf.raw[self.buf.init..].fill(MaybeUninit::new(0));
259+
self.buf.init = self.buf.raw.len();
260+
}
261+
262+
// SAFETY: The full buffer is initialized now.
263+
let slice = unsafe {
264+
core::slice::from_raw_parts_mut(
265+
self.buf.raw[self.buf.filled..].as_mut_ptr() as *mut u8,
266+
self.buf.raw.len() - self.buf.filled,
267+
)
268+
};
269+
270+
// Call the function.
271+
let n = match f(slice) {
272+
Ok(n) => n,
273+
Err(e) => return Err(e),
274+
};
275+
276+
// Advance the buffer.
277+
self.buf.filled = self.buf.filled.checked_add(n).expect("overflow");
278+
279+
Ok(())
280+
}
281+
247282
#[inline]
248283
pub(crate) fn remaining(&self) -> usize {
249284
self.buf.remaining()

0 commit comments

Comments
 (0)