From c1aae4d27902aaaa0d8e7d1a76d030b4fc90f329 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 13 May 2022 15:06:36 +0100 Subject: [PATCH 1/4] std::io: migrate ReadBuf to BorrowBuf/BorrowCursor Signed-off-by: Nick Cameron --- library/std/src/fs.rs | 10 +- library/std/src/io/buffered/bufreader.rs | 15 +- library/std/src/io/buffered/tests.rs | 32 +-- library/std/src/io/copy.rs | 34 ++-- library/std/src/io/cursor.rs | 10 +- library/std/src/io/impls.rs | 16 +- library/std/src/io/mod.rs | 83 ++++---- library/std/src/io/readbuf.rs | 243 +++++++++++------------ library/std/src/io/readbuf/tests.rs | 172 +++++----------- library/std/src/io/tests.rs | 20 +- library/std/src/io/util.rs | 14 +- library/std/src/io/util/tests.rs | 48 ++--- library/std/src/sys/unix/fd.rs | 11 +- library/std/src/sys/unix/fs.rs | 6 +- 14 files changed, 324 insertions(+), 390 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c8e131b6ee14c..d41f32b5b3f21 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -13,7 +13,7 @@ mod tests; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; +use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -703,8 +703,8 @@ impl Read for File { self.inner.read_vectored(bufs) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.inner.read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + self.inner.read_buf(cursor) } #[inline] @@ -755,8 +755,8 @@ impl Read for &File { self.inner.read(buf) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.inner.read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + self.inner.read_buf(cursor) } fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index f7fbaa9c27649..1f19ac11bf101 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -2,7 +2,8 @@ mod buffer; use crate::fmt; use crate::io::{ - self, BufRead, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, + self, BorrowBuf, BorrowCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, + DEFAULT_BUF_SIZE, }; use buffer::Buffer; @@ -266,21 +267,21 @@ impl Read for BufReader { Ok(nread) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. - if self.buf.pos() == self.buf.filled() && buf.remaining() >= self.capacity() { + if self.buf.pos() == self.buf.filled() && cursor.capacity() >= self.capacity() { self.discard_buffer(); - return self.inner.read_buf(buf); + return self.inner.read_buf(cursor); } - let prev = buf.filled_len(); + let prev = cursor.written(); let mut rem = self.fill_buf()?; - rem.read_buf(buf)?; + rem.read_buf(cursor.clone())?; - self.consume(buf.filled_len() - prev); //slice impl of read_buf known to never unfill buf + self.consume(cursor.written() - prev); //slice impl of read_buf known to never unfill buf Ok(()) } diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index fe45b13263844..c93b69bf1f7c1 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -1,5 +1,5 @@ use crate::io::prelude::*; -use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom}; use crate::mem::MaybeUninit; use crate::panic; use crate::sync::atomic::{AtomicUsize, Ordering}; @@ -61,48 +61,48 @@ fn test_buffered_reader_read_buf() { let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; let mut reader = BufReader::with_capacity(2, inner); - let mut buf = [MaybeUninit::uninit(); 3]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [5, 6, 7]); assert_eq!(reader.buffer(), []); - let mut buf = [MaybeUninit::uninit(); 2]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 2]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [0, 1]); assert_eq!(reader.buffer(), []); - let mut buf = [MaybeUninit::uninit(); 1]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [2]); assert_eq!(reader.buffer(), [3]); - let mut buf = [MaybeUninit::uninit(); 3]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [3]); assert_eq!(reader.buffer(), []); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [3, 4]); assert_eq!(reader.buffer(), []); buf.clear(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); - assert_eq!(buf.filled_len(), 0); + assert!(buf.filled().is_empty()); } #[test] diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 1a10245e4a5e3..193bcd47467c1 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,4 +1,4 @@ -use super::{BufWriter, ErrorKind, Read, ReadBuf, Result, Write, DEFAULT_BUF_SIZE}; +use super::{BorrowBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; use crate::mem::MaybeUninit; /// Copies the entire contents of a reader into a writer. @@ -97,37 +97,39 @@ impl BufferedCopySpec for BufWriter { loop { let buf = writer.buffer_mut(); - let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); + let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); - // SAFETY: init is either 0 or the initialized_len of the previous iteration unsafe { - read_buf.assume_init(init); + // SAFETY: init is either 0 or the init_len from the previous iteration. + read_buf.set_init(init); } if read_buf.capacity() >= DEFAULT_BUF_SIZE { - match reader.read_buf(&mut read_buf) { + let mut cursor = read_buf.unfilled(); + match reader.read_buf(cursor.clone()) { Ok(()) => { - let bytes_read = read_buf.filled_len(); + let bytes_read = cursor.written(); if bytes_read == 0 { return Ok(len); } - init = read_buf.initialized_len() - bytes_read; + init = read_buf.init_len() - bytes_read; + len += bytes_read as u64; - // SAFETY: ReadBuf guarantees all of its filled bytes are init + // SAFETY: BorrowBuf guarantees all of its filled bytes are init unsafe { buf.set_len(buf.len() + bytes_read) }; - len += bytes_read as u64; + // Read again if the buffer still has enough capacity, as BufWriter itself would do // This will occur if the reader returns short reads - continue; } - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } + } else { + writer.flush_buf()?; + init = 0; } - - writer.flush_buf()?; } } } @@ -136,13 +138,13 @@ fn stack_buffer_copy( reader: &mut R, writer: &mut W, ) -> Result { - let mut buf = [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; + let mut buf: BorrowBuf<'_> = buf.into(); let mut len = 0; loop { - match reader.read_buf(&mut buf) { + match reader.read_buf(buf.unfilled()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index f3fbfc4478951..460b1504ffbfc 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -5,7 +5,7 @@ use crate::io::prelude::*; use crate::alloc::Allocator; use crate::cmp; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; /// A `Cursor` wraps an in-memory buffer and provides it with a /// [`Seek`] implementation. @@ -323,12 +323,12 @@ where Ok(n) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - let prev_filled = buf.filled_len(); + fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + let prev_written = cursor.written(); - Read::read_buf(&mut self.fill_buf()?, buf)?; + Read::read_buf(&mut self.fill_buf()?, cursor.clone())?; - self.pos += (buf.filled_len() - prev_filled) as u64; + self.pos += (cursor.written() - prev_written) as u64; Ok(()) } diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 95072547302eb..eee5ab6ec1050 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -6,7 +6,7 @@ use crate::cmp; use crate::collections::VecDeque; use crate::fmt; use crate::io::{ - self, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write, + self, BorrowCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, }; use crate::mem; @@ -21,8 +21,8 @@ impl Read for &mut R { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - (**self).read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + (**self).read_buf(cursor) } #[inline] @@ -125,8 +125,8 @@ impl Read for Box { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - (**self).read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + (**self).read_buf(cursor) } #[inline] @@ -249,11 +249,11 @@ impl Read for &[u8] { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - let amt = cmp::min(buf.remaining(), self.len()); + fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + let amt = cmp::min(cursor.capacity(), self.len()); let (a, b) = self.split_at(amt); - buf.append(a); + cursor.append(a); *self = b; Ok(()) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 96addbd1a0558..b3218b2831d3f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -278,7 +278,7 @@ pub use self::{ }; #[unstable(feature = "read_buf", issue = "78485")] -pub use self::readbuf::ReadBuf; +pub use self::readbuf::{BorrowBuf, BorrowCursor}; pub(crate) use error::const_io_error; mod buffered; @@ -362,29 +362,30 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec buf.reserve(32); // buf is full, need more space } - let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); + let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); // SAFETY: These bytes were initialized but not filled in the previous loop unsafe { - read_buf.assume_init(initialized); + read_buf.set_init(initialized); } - match r.read_buf(&mut read_buf) { + let mut cursor = read_buf.unfilled(); + match r.read_buf(cursor.clone()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), } - if read_buf.filled_len() == 0 { + if cursor.written() == 0 { return Ok(buf.len() - start_len); } // store how much was initialized but not filled - initialized = read_buf.initialized_len() - read_buf.filled_len(); - let new_len = read_buf.filled_len() + buf.len(); + initialized = cursor.init_ref().len(); - // SAFETY: ReadBuf's invariants mean this much memory is init + // SAFETY: BorrowBuf's invariants mean this much memory is initialized. unsafe { + let new_len = read_buf.filled().len() + buf.len(); buf.set_len(new_len); } @@ -461,12 +462,15 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } -pub(crate) fn default_read_buf(read: F, buf: &mut ReadBuf<'_>) -> Result<()> +pub(crate) fn default_read_buf(read: F, mut cursor: BorrowCursor<'_, '_>) -> Result<()> where F: FnOnce(&mut [u8]) -> Result, { - let n = read(buf.initialize_unfilled())?; - buf.add_filled(n); + let n = read(cursor.ensure_init().init_mut())?; + unsafe { + // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to. + cursor.advance(n); + } Ok(()) } @@ -801,32 +805,33 @@ pub trait Read { default_read_exact(self, buf) } + // TODO naming, if should the method be read_cursor? Or should we change the names of the data structures? /// Pull some bytes from this source into the specified buffer. /// - /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to allow use + /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to allow use /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`. /// /// The default implementation delegates to `read`. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { + fn read_buf(&mut self, buf: BorrowCursor<'_, '_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) } - /// Read the exact number of bytes required to fill `buf`. + /// Read the exact number of bytes required to fill `cursor`. /// - /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to + /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to /// allow use with uninitialized buffers. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf_exact(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { - while buf.remaining() > 0 { - let prev_filled = buf.filled().len(); - match self.read_buf(buf) { + fn read_buf_exact(&mut self, mut cursor: BorrowCursor<'_, '_>) -> Result<()> { + while cursor.capacity() > 0 { + let prev_written = cursor.written(); + match self.read_buf(cursor.clone()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), } - if buf.filled().len() == prev_filled { + if cursor.written() == prev_written { return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer")); } } @@ -2582,50 +2587,48 @@ impl Read for Take { Ok(n) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { + fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> Result<()> { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(()); } - let prev_filled = buf.filled_len(); - - if self.limit <= buf.remaining() as u64 { + if self.limit <= buf.capacity() as u64 { // if we just use an as cast to convert, limit may wrap around on a 32 bit target let limit = cmp::min(self.limit, usize::MAX as u64) as usize; - let extra_init = cmp::min(limit as usize, buf.initialized_len() - buf.filled_len()); + let extra_init = cmp::min(limit as usize, buf.init_ref().len()); // SAFETY: no uninit data is written to ibuf - let ibuf = unsafe { &mut buf.unfilled_mut()[..limit] }; + let ibuf = unsafe { &mut buf.as_mut()[..limit] }; - let mut sliced_buf = ReadBuf::uninit(ibuf); + let mut sliced_buf: BorrowBuf<'_> = ibuf.into(); // SAFETY: extra_init bytes of ibuf are known to be initialized unsafe { - sliced_buf.assume_init(extra_init); + sliced_buf.set_init(extra_init); } - self.inner.read_buf(&mut sliced_buf)?; + let mut cursor = sliced_buf.unfilled(); + self.inner.read_buf(cursor.clone())?; - let new_init = sliced_buf.initialized_len(); - let filled = sliced_buf.filled_len(); + let new_init = cursor.init_ref().len(); + let filled = sliced_buf.len(); - // sliced_buf / ibuf must drop here + // cursor / sliced_buf / ibuf must drop here - // SAFETY: new_init bytes of buf's unfilled buffer have been initialized unsafe { - buf.assume_init(new_init); + // SAFETY: filled bytes have been filled and therefore initialized + buf.advance(filled); + // SAFETY: new_init bytes of buf's unfilled buffer have been initialized + buf.set_init(new_init); } - buf.add_filled(filled); - self.limit -= filled as u64; } else { - self.inner.read_buf(buf)?; - - //inner may unfill - self.limit -= buf.filled_len().saturating_sub(prev_filled) as u64; + let written = buf.written(); + self.inner.read_buf(buf.clone())?; + self.limit -= (buf.written() - written) as u64; } Ok(()) diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 78d1113f8375a..4578433b22a11 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -7,6 +7,7 @@ use crate::cmp; use crate::fmt::{self, Debug, Formatter}; use crate::mem::MaybeUninit; +// TODO docs /// A wrapper around a byte buffer that is incrementally filled and initialized. /// /// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the @@ -20,50 +21,66 @@ use crate::mem::MaybeUninit; /// [ filled | unfilled ] /// [ initialized | uninitialized ] /// ``` -pub struct ReadBuf<'a> { +pub struct BorrowBuf<'a> { buf: &'a mut [MaybeUninit], filled: usize, initialized: usize, } -impl Debug for ReadBuf<'_> { +impl Debug for BorrowBuf<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("ReadBuf") - .field("init", &self.initialized()) + .field("init", &self.initialized) .field("filled", &self.filled) .field("capacity", &self.capacity()) .finish() } } -impl<'a> ReadBuf<'a> { - /// Creates a new `ReadBuf` from a fully initialized buffer. +/// Creates a new `BorrowBuf` from a fully initialized slice. +impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { #[inline] - pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> { - let len = buf.len(); + fn from(slice: &'a mut [u8]) -> BorrowBuf<'a> { + let len = slice.len(); - ReadBuf { - //SAFETY: initialized data never becoming uninitialized is an invariant of ReadBuf - buf: unsafe { (buf as *mut [u8]).as_uninit_slice_mut().unwrap() }, + BorrowBuf { + //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowBuf + buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, filled: 0, initialized: len, } } +} - /// Creates a new `ReadBuf` from a fully uninitialized buffer. - /// - /// Use `assume_init` if part of the buffer is known to be already initialized. +/// Creates a new `BorrowBuf` from a fully uninitialized buffer. +/// +/// Use `set_init` if part of the buffer is known to be already initialized. +impl<'a> From<&'a mut [MaybeUninit]> for BorrowBuf<'a> { #[inline] - pub fn uninit(buf: &'a mut [MaybeUninit]) -> ReadBuf<'a> { - ReadBuf { buf, filled: 0, initialized: 0 } + fn from(buf: &'a mut [MaybeUninit]) -> BorrowBuf<'a> { + BorrowBuf { buf, filled: 0, initialized: 0 } } +} +impl<'a> BorrowBuf<'a> { /// Returns the total capacity of the buffer. #[inline] pub fn capacity(&self) -> usize { self.buf.len() } + /// Returns the length of the filled part of the buffer. + #[inline] + pub fn len(&self) -> usize { + self.filled + } + + /// Returns the length of the initialized part of the buffer. + #[inline] + pub fn init_len(&self) -> usize { + self.initialized + } + /// Returns a shared reference to the filled portion of the buffer. #[inline] pub fn filled(&self) -> &[u8] { @@ -71,179 +88,157 @@ impl<'a> ReadBuf<'a> { unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } } - /// Returns a mutable reference to the filled portion of the buffer. + /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn filled_mut(&mut self) -> &mut [u8] { - //SAFETY: We only slice the filled part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) } + pub fn unfilled<'b>(&'b mut self) -> BorrowCursor<'a, 'b> { + BorrowCursor { start: self.filled, buf: self } } - /// Returns a shared reference to the initialized portion of the buffer. + /// Clears the buffer, resetting the filled region to empty. /// - /// This includes the filled portion. + /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. #[inline] - pub fn initialized(&self) -> &[u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.initialized]) } + pub fn clear(&mut self) -> &mut Self { + self.filled = 0; + self } - /// Returns a mutable reference to the initialized portion of the buffer. + /// Asserts that the first `n` bytes of the buffer are initialized. /// - /// This includes the filled portion. - #[inline] - pub fn initialized_mut(&mut self) -> &mut [u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.initialized]) } - } - - /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully - /// initialized. + /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// bytes than are already known to be initialized. /// /// # Safety /// - /// The caller must not de-initialize portions of the buffer that have already been initialized. + /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. #[inline] - pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit] { - &mut self.buf[self.filled..] + pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { + self.initialized = cmp::max(self.initialized, n); + self } +} - /// Returns a mutable reference to the uninitialized part of the buffer. - /// - /// It is safe to uninitialize any of these bytes. +/// A cursor view of a [`BorrowBuf`](BorrowBuf). +/// +/// Provides mutable access to the unfilled portion (both initialised and uninitialised data) from +/// the buffer. +#[derive(Debug)] +pub struct BorrowCursor<'a, 'b> { + buf: &'b mut BorrowBuf<'a>, + start: usize, +} + +impl<'a, 'b> BorrowCursor<'a, 'b> { + /// Clone this cursor. #[inline] - pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit] { - &mut self.buf[self.initialized..] + pub fn clone<'c>(&'c mut self) -> BorrowCursor<'a, 'c> { + BorrowCursor { buf: self.buf, start: self.start } } - /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized. - /// - /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after - /// the first use. + /// Returns the available space in the cursor. #[inline] - pub fn initialize_unfilled(&mut self) -> &mut [u8] { - // should optimize out the assertion - self.initialize_unfilled_to(self.remaining()) + pub fn capacity(&self) -> usize { + self.buf.capacity() - self.buf.filled } - /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is - /// fully initialized. - /// - /// # Panics - /// - /// Panics if `self.remaining()` is less than `n`. + /// Returns the number of bytes written to this cursor. + // TODO check for reuse uses #[inline] - pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] { - assert!(self.remaining() >= n); - - let extra_init = self.initialized - self.filled; - // If we don't have enough initialized, do zeroing - if n > extra_init { - let uninit = n - extra_init; - let unfilled = &mut self.uninitialized_mut()[0..uninit]; - - for byte in unfilled.iter_mut() { - byte.write(0); - } + pub fn written(&self) -> usize { + self.buf.filled - self.start + } - // SAFETY: we just initialized uninit bytes, and the previous bytes were already init - unsafe { - self.assume_init(n); - } + /// Returns a shared reference to the initialized portion of the buffer. + #[inline] + pub fn init_ref(&self) -> &[u8] { + //SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { + MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.initialized]) } - - let filled = self.filled; - - &mut self.initialized_mut()[filled..filled + n] } - /// Returns the number of bytes at the end of the slice that have not yet been filled. + /// Returns a mutable reference to the initialized portion of the buffer. #[inline] - pub fn remaining(&self) -> usize { - self.capacity() - self.filled + pub fn init_mut(&mut self) -> &mut [u8] { + //SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { + MaybeUninit::slice_assume_init_mut( + &mut self.buf.buf[self.buf.filled..self.buf.initialized], + ) + } } - /// Clears the buffer, resetting the filled region to empty. + /// Returns a mutable reference to the uninitialized part of the buffer. /// - /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. + /// It is safe to uninitialize any of these bytes. #[inline] - pub fn clear(&mut self) -> &mut Self { - self.set_filled(0) // The assertion in `set_filled` is optimized out + pub fn uninit_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf.buf[self.buf.initialized..] + } + + /// A view of the cursor as a mutable slice of `MaybeUninit`. + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf.buf[self.buf.filled..] } /// Increases the size of the filled region of the buffer. /// - /// The number of initialized bytes is not changed. - /// - /// # Panics + /// # Safety /// - /// Panics if the filled region of the buffer would become larger than the initialized region. + /// The caller must ensure that the first `n` elements of the cursor have been properly + /// initialised. #[inline] - pub fn add_filled(&mut self, n: usize) -> &mut Self { - self.set_filled(self.filled + n) + pub unsafe fn advance(&mut self, n: usize) -> &mut Self { + self.buf.filled += n; + self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled); + self } - /// Sets the size of the filled region of the buffer. - /// - /// The number of initialized bytes is not changed. - /// - /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for - /// example, by a `Read` implementation that compresses data in-place). - /// - /// # Panics - /// - /// Panics if the filled region of the buffer would become larger than the initialized region. + /// Initialised all bytes in the cursor. #[inline] - pub fn set_filled(&mut self, n: usize) -> &mut Self { - assert!(n <= self.initialized); + pub fn ensure_init(&mut self) -> &mut Self { + for byte in self.uninit_mut() { + byte.write(0); + } + self.buf.initialized = self.buf.capacity(); - self.filled = n; self } - /// Asserts that the first `n` unfilled bytes of the buffer are initialized. + /// Asserts that the first `n` unfilled bytes of the cursor are initialized. /// - /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer /// bytes than are already known to be initialized. /// /// # Safety /// - /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. + /// The caller must ensure that the first `n` bytes of the buffer have already been initialized. #[inline] - pub unsafe fn assume_init(&mut self, n: usize) -> &mut Self { - self.initialized = cmp::max(self.initialized, self.filled + n); + pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { + self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled + n); self } - /// Appends data to the buffer, advancing the written position and possibly also the initialized position. + /// Appends data to the cursor, advancing the position within its buffer. /// /// # Panics /// - /// Panics if `self.remaining()` is less than `buf.len()`. + /// Panics if `self.capacity()` is less than `buf.len()`. #[inline] pub fn append(&mut self, buf: &[u8]) { - assert!(self.remaining() >= buf.len()); + assert!(self.capacity() >= buf.len()); // SAFETY: we do not de-initialize any of the elements of the slice unsafe { - MaybeUninit::write_slice(&mut self.unfilled_mut()[..buf.len()], buf); + MaybeUninit::write_slice(&mut self.as_mut()[..buf.len()], buf); } // SAFETY: We just added the entire contents of buf to the filled section. unsafe { - self.assume_init(buf.len()); - } - self.add_filled(buf.len()); - } - - /// Returns the amount of bytes that have been filled. - #[inline] - pub fn filled_len(&self) -> usize { - self.filled - } - /// Returns the amount of bytes that have been initialized. - #[inline] - pub fn initialized_len(&self) -> usize { - self.initialized + self.set_init(buf.len()); + } + self.buf.filled += buf.len(); } } diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index 3b7a5a56d2252..584e5de982e97 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -1,181 +1,117 @@ -use super::ReadBuf; +use super::BorrowBuf; use crate::mem::MaybeUninit; -/// Test that ReadBuf has the correct numbers when created with new +/// Test that BorrowBuf has the correct numbers when created with new #[test] fn new() { - let mut buf = [0; 16]; - let rbuf = ReadBuf::new(&mut buf); + let buf: &mut [_] = &mut [0; 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - assert_eq!(rbuf.filled_len(), 0); - assert_eq!(rbuf.initialized_len(), 16); + assert_eq!(rbuf.filled().len(), 0); + assert_eq!(rbuf.init_len(), 16); assert_eq!(rbuf.capacity(), 16); - assert_eq!(rbuf.remaining(), 16); + assert_eq!(rbuf.unfilled().capacity(), 16); } -/// Test that ReadBuf has the correct numbers when created with uninit +/// Test that BorrowBuf has the correct numbers when created with uninit #[test] fn uninit() { - let mut buf = [MaybeUninit::uninit(); 16]; - let rbuf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - assert_eq!(rbuf.filled_len(), 0); - assert_eq!(rbuf.initialized_len(), 0); + assert_eq!(rbuf.filled().len(), 0); + assert_eq!(rbuf.init_len(), 0); assert_eq!(rbuf.capacity(), 16); - assert_eq!(rbuf.remaining(), 16); + assert_eq!(rbuf.unfilled().capacity(), 16); } #[test] fn initialize_unfilled() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - rbuf.initialize_unfilled(); + rbuf.unfilled().ensure_init(); - assert_eq!(rbuf.initialized_len(), 16); -} - -#[test] -fn initialize_unfilled_to() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); - - rbuf.initialize_unfilled_to(8); - - assert_eq!(rbuf.initialized_len(), 8); - - rbuf.initialize_unfilled_to(4); - - assert_eq!(rbuf.initialized_len(), 8); - - rbuf.set_filled(8); - - rbuf.initialize_unfilled_to(6); - - assert_eq!(rbuf.initialized_len(), 14); - - rbuf.initialize_unfilled_to(8); - - assert_eq!(rbuf.initialized_len(), 16); + assert_eq!(rbuf.init_len(), 16); } #[test] fn add_filled() { - let mut buf = [0; 16]; - let mut rbuf = ReadBuf::new(&mut buf); - - rbuf.add_filled(1); - - assert_eq!(rbuf.filled_len(), 1); - assert_eq!(rbuf.remaining(), 15); -} + let buf: &mut [_] = &mut [0; 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); -#[test] -#[should_panic] -fn add_filled_panic() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); - - rbuf.add_filled(1); -} - -#[test] -fn set_filled() { - let mut buf = [0; 16]; - let mut rbuf = ReadBuf::new(&mut buf); - - rbuf.set_filled(16); - - assert_eq!(rbuf.filled_len(), 16); - assert_eq!(rbuf.remaining(), 0); - - rbuf.set_filled(6); - - assert_eq!(rbuf.filled_len(), 6); - assert_eq!(rbuf.remaining(), 10); -} - -#[test] -#[should_panic] -fn set_filled_panic() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); + unsafe { + rbuf.unfilled().advance(1); + } - rbuf.set_filled(16); + assert_eq!(rbuf.filled().len(), 1); + assert_eq!(rbuf.unfilled().capacity(), 15); } #[test] fn clear() { - let mut buf = [255; 16]; - let mut rbuf = ReadBuf::new(&mut buf); + let buf: &mut [_] = &mut [255; 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - rbuf.set_filled(16); + unsafe { + rbuf.unfilled().advance(16); + } - assert_eq!(rbuf.filled_len(), 16); - assert_eq!(rbuf.remaining(), 0); + assert_eq!(rbuf.filled().len(), 16); + assert_eq!(rbuf.unfilled().capacity(), 0); rbuf.clear(); - assert_eq!(rbuf.filled_len(), 0); - assert_eq!(rbuf.remaining(), 16); + assert_eq!(rbuf.filled().len(), 0); + assert_eq!(rbuf.unfilled().capacity(), 16); - assert_eq!(rbuf.initialized(), [255; 16]); + assert_eq!(rbuf.unfilled().init_ref(), [255; 16]); } #[test] -fn assume_init() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); +fn set_init() { + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); unsafe { - rbuf.assume_init(8); + rbuf.set_init(8); } - assert_eq!(rbuf.initialized_len(), 8); + assert_eq!(rbuf.init_len(), 8); - rbuf.add_filled(4); + unsafe { + rbuf.unfilled().advance(4); + } unsafe { - rbuf.assume_init(2); + rbuf.set_init(2); } - assert_eq!(rbuf.initialized_len(), 8); + assert_eq!(rbuf.init_len(), 8); unsafe { - rbuf.assume_init(8); + rbuf.set_init(8); } - assert_eq!(rbuf.initialized_len(), 12); + assert_eq!(rbuf.init_len(), 8); } #[test] fn append() { - let mut buf = [MaybeUninit::new(255); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::new(255); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - rbuf.append(&[0; 8]); + rbuf.unfilled().append(&[0; 8]); - assert_eq!(rbuf.initialized_len(), 8); - assert_eq!(rbuf.filled_len(), 8); + assert_eq!(rbuf.init_len(), 8); + assert_eq!(rbuf.filled().len(), 8); assert_eq!(rbuf.filled(), [0; 8]); rbuf.clear(); - rbuf.append(&[1; 16]); + rbuf.unfilled().append(&[1; 16]); - assert_eq!(rbuf.initialized_len(), 16); - assert_eq!(rbuf.filled_len(), 16); + assert_eq!(rbuf.init_len(), 16); + assert_eq!(rbuf.filled().len(), 16); assert_eq!(rbuf.filled(), [1; 16]); } - -#[test] -fn filled_mut() { - let mut buf = [0; 16]; - let mut rbuf = ReadBuf::new(&mut buf); - - rbuf.add_filled(8); - - let filled = rbuf.filled().to_vec(); - - assert_eq!(&*filled, &*rbuf.filled_mut()); -} diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index f357f33ec52c5..a1322a185651e 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -1,4 +1,4 @@ -use super::{repeat, Cursor, ReadBuf, SeekFrom}; +use super::{repeat, BorrowBuf, Cursor, SeekFrom}; use crate::cmp::{self, min}; use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{BufRead, BufReader, Read, Seek, Write}; @@ -159,24 +159,24 @@ fn read_exact_slice() { #[test] fn read_buf_exact() { - let mut buf = [0; 4]; - let mut buf = ReadBuf::new(&mut buf); + let buf: &mut [_] = &mut [0; 4]; + let mut buf: BorrowBuf<'_> = buf.into(); let mut c = Cursor::new(&b""[..]); - assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); + assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); let mut c = Cursor::new(&b"123456789"[..]); - c.read_buf_exact(&mut buf).unwrap(); + c.read_buf_exact(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), b"1234"); buf.clear(); - c.read_buf_exact(&mut buf).unwrap(); + c.read_buf_exact(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), b"5678"); buf.clear(); - assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); + assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); } #[test] @@ -614,10 +614,10 @@ fn bench_take_read(b: &mut test::Bencher) { #[bench] fn bench_take_read_buf(b: &mut test::Bencher) { b.iter(|| { - let mut buf = [MaybeUninit::uninit(); 64]; + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 64]; - let mut rbuf = ReadBuf::uninit(&mut buf); + let mut buf: BorrowBuf<'_> = buf.into(); - [255; 128].take(64).read_buf(&mut rbuf).unwrap(); + [255; 128].take(64).read_buf(buf.unfilled()).unwrap(); }); } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index c1300cd67c086..5149926fd519d 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -5,7 +5,7 @@ mod tests; use crate::fmt; use crate::io::{ - self, BufRead, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, Write, + self, BorrowCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; /// A reader which is always at EOF. @@ -47,7 +47,7 @@ impl Read for Empty { } #[inline] - fn read_buf(&mut self, _buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, _cursor: BorrowCursor<'_, '_>) -> io::Result<()> { Ok(()) } } @@ -130,21 +130,19 @@ impl Read for Repeat { Ok(buf.len()) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written - for slot in unsafe { buf.unfilled_mut() } { + for slot in unsafe { buf.as_mut() } { slot.write(self.byte); } - let remaining = buf.remaining(); + let remaining = buf.capacity(); // SAFETY: the entire unfilled portion of buf has been initialized unsafe { - buf.assume_init(remaining); + buf.advance(remaining); } - buf.add_filled(remaining); - Ok(()) } diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index 08972a59a833f..025173c3f446c 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,7 +1,7 @@ use crate::cmp::{max, min}; use crate::io::prelude::*; use crate::io::{ - copy, empty, repeat, sink, BufWriter, Empty, ReadBuf, Repeat, Result, SeekFrom, Sink, + copy, empty, repeat, sink, BorrowBuf, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, DEFAULT_BUF_SIZE, }; @@ -79,29 +79,29 @@ fn empty_reads() { assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); - let mut buf = []; - let mut buf = ReadBuf::uninit(&mut buf); - e.read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); - - let mut buf = [MaybeUninit::uninit()]; - let mut buf = ReadBuf::uninit(&mut buf); - e.read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); - - let mut buf = [MaybeUninit::uninit(); 1024]; - let mut buf = ReadBuf::uninit(&mut buf); - e.read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); - - let mut buf = [MaybeUninit::uninit(); 1024]; - let mut buf = ReadBuf::uninit(&mut buf); - e.by_ref().read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); + let buf: &mut [MaybeUninit<_>] = &mut []; + let mut buf: BorrowBuf<'_> = buf.into(); + e.read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit()]; + let mut buf: BorrowBuf<'_> = buf.into(); + e.read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowBuf<'_> = buf.into(); + e.read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowBuf<'_> = buf.into(); + e.by_ref().read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); } #[test] diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 30812dabb4e0d..6adb734fb0a2f 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -4,7 +4,7 @@ mod tests; use crate::cmp; -use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf}; +use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -131,20 +131,19 @@ impl FileDesc { } } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { let ret = cvt(unsafe { libc::read( self.as_raw_fd(), - buf.unfilled_mut().as_mut_ptr() as *mut libc::c_void, - cmp::min(buf.remaining(), READ_LIMIT), + cursor.as_mut().as_mut_ptr() as *mut libc::c_void, + cmp::min(cursor.capacity(), READ_LIMIT), ) })?; // Safety: `ret` bytes were written to the initialized portion of the buffer unsafe { - buf.assume_init(ret as usize); + cursor.advance(ret as usize); } - buf.add_filled(ret as usize); Ok(()) } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index b5cc8038ca44f..374f9f72d6d74 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::path::{Path, PathBuf}; @@ -1031,8 +1031,8 @@ impl File { self.0.read_at(buf, offset) } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.0.read_buf(buf) + pub fn read_buf(&self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + self.0.read_buf(cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { From b56cf67ce14580111ffb07a08a293e217566e116 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 22 May 2022 20:57:58 -0500 Subject: [PATCH 2/4] Add some docs for BorrowBuf Signed-off-by: Nick Cameron --- library/std/src/io/readbuf.rs | 84 +++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 4578433b22a11..8783763fd425f 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -7,8 +7,7 @@ use crate::cmp; use crate::fmt::{self, Debug, Formatter}; use crate::mem::MaybeUninit; -// TODO docs -/// A wrapper around a byte buffer that is incrementally filled and initialized. +/// A borrowed byte buffer which is incrementally filled and initialized. /// /// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the /// buffer that has been logically filled with data, a region that has been initialized at some point but not yet @@ -21,9 +20,20 @@ use crate::mem::MaybeUninit; /// [ filled | unfilled ] /// [ initialized | uninitialized ] /// ``` +/// +/// A `BorrowBuf` is created around some existing data (or capacity for data) via a unique reference +/// (`&mut`). The `BorrowBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise +/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowCursor`. The cursor +/// has write-only access to the unfilled portion of the buffer (you can think of it like a +/// write-only iterator). +/// +/// The lifetime `'a` is a bound on the lifetime of the underlying data. pub struct BorrowBuf<'a> { + /// The buffer's underlying data. buf: &'a mut [MaybeUninit], + /// The length of `self.buf` which is known to be filled. filled: usize, + /// The length of `self.buf` which is known to be initialized. initialized: usize, } @@ -37,7 +47,7 @@ impl Debug for BorrowBuf<'_> { } } -/// Creates a new `BorrowBuf` from a fully initialized slice. +/// Create a new `BorrowBuf` from a fully initialized slice. impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { #[inline] fn from(slice: &'a mut [u8]) -> BorrowBuf<'a> { @@ -52,7 +62,7 @@ impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { } } -/// Creates a new `BorrowBuf` from a fully uninitialized buffer. +/// Create a new `BorrowBuf` from an uninitialized buffer. /// /// Use `set_init` if part of the buffer is known to be already initialized. impl<'a> From<&'a mut [MaybeUninit]> for BorrowBuf<'a> { @@ -90,7 +100,7 @@ impl<'a> BorrowBuf<'a> { /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn unfilled<'b>(&'b mut self) -> BorrowCursor<'a, 'b> { + pub fn unfilled<'this>(&'this mut self) -> BorrowCursor<'this, 'a> { BorrowCursor { start: self.filled, buf: self } } @@ -118,20 +128,36 @@ impl<'a> BorrowBuf<'a> { } } -/// A cursor view of a [`BorrowBuf`](BorrowBuf). +/// A writeable view of the unfilled portion of a [`BorrowBuf`](BorrowBuf). +/// +/// Provides access to the initialized and uninitialized parts of the underlying `BorrowBuf`. +/// Data can be written directly to the cursor by using [`append`](BorrowCursor::append) or +/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the +/// indirect case, the caller must call [`advance`](BorrowCursor::advance) after writing to inform +/// the cursor how many bytes have been written. /// -/// Provides mutable access to the unfilled portion (both initialised and uninitialised data) from -/// the buffer. +/// Once data is written to the cursor, it becomes part of the filled portion of the underlying +/// `BorrowBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks +/// the unfilled part of the underlying `BorrowBuf`. +/// +/// The `'buf` lifetime is a bound on the lifetime of the underlying buffer. `'data` is a bound on +/// that buffer's underlying data. #[derive(Debug)] -pub struct BorrowCursor<'a, 'b> { - buf: &'b mut BorrowBuf<'a>, +pub struct BorrowCursor<'buf, 'data> { + /// The underlying buffer. + buf: &'buf mut BorrowBuf<'data>, + /// The length of the filled portion of the underlying buffer at the time of the cursor's + /// creation. start: usize, } -impl<'a, 'b> BorrowCursor<'a, 'b> { +impl<'buf, 'data> BorrowCursor<'buf, 'data> { /// Clone this cursor. + /// + /// Since a cursor maintains unique access to its underlying buffer, the cloned cursor is not + /// accessible while the clone is alive. #[inline] - pub fn clone<'c>(&'c mut self) -> BorrowCursor<'a, 'c> { + pub fn clone<'this>(&'this mut self) -> BorrowCursor<'this, 'data> { BorrowCursor { buf: self.buf, start: self.start } } @@ -141,14 +167,16 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { self.buf.capacity() - self.buf.filled } - /// Returns the number of bytes written to this cursor. - // TODO check for reuse uses + /// Returns the number of bytes written to this cursor since it was created from a `BorrowBuf`. + /// + /// Note that if this cursor is a clone of another, then the count returned is the count written + /// via either cursor, not the count since the cursor was cloned. #[inline] pub fn written(&self) -> usize { self.buf.filled - self.start } - /// Returns a shared reference to the initialized portion of the buffer. + /// Returns a shared reference to the initialized portion of the cursor. #[inline] pub fn init_ref(&self) -> &[u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid @@ -157,7 +185,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { } } - /// Returns a mutable reference to the initialized portion of the buffer. + /// Returns a mutable reference to the initialized portion of the cursor. #[inline] pub fn init_mut(&mut self) -> &mut [u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid @@ -168,7 +196,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { } } - /// Returns a mutable reference to the uninitialized part of the buffer. + /// Returns a mutable reference to the uninitialized part of the cursor. /// /// It is safe to uninitialize any of these bytes. #[inline] @@ -176,17 +204,25 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { &mut self.buf.buf[self.buf.initialized..] } - /// A view of the cursor as a mutable slice of `MaybeUninit`. + /// Returns a mutable reference to the whole cursor. + /// + /// # Safety + /// + /// The caller must not uninitialize any bytes in the initialized portion of the cursor. #[inline] pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit] { &mut self.buf.buf[self.buf.filled..] } - /// Increases the size of the filled region of the buffer. + /// Advance the cursor by asserting that `n` bytes have been filled. + /// + /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be + /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements + /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements. /// /// # Safety /// - /// The caller must ensure that the first `n` elements of the cursor have been properly + /// The caller must ensure that the first `n` bytes of the cursor have been properly /// initialised. #[inline] pub unsafe fn advance(&mut self, n: usize) -> &mut Self { @@ -195,7 +231,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { self } - /// Initialised all bytes in the cursor. + /// Initializes all bytes in the cursor. #[inline] pub fn ensure_init(&mut self) -> &mut Self { for byte in self.uninit_mut() { @@ -208,8 +244,8 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { /// Asserts that the first `n` unfilled bytes of the cursor are initialized. /// - /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer - /// bytes than are already known to be initialized. + /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when + /// called with fewer bytes than are already known to be initialized. /// /// # Safety /// @@ -220,7 +256,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { self } - /// Appends data to the cursor, advancing the position within its buffer. + /// Appends data to the cursor, advancing position within its buffer. /// /// # Panics /// From 1a2122fff015d1d7fb31fe3a55e49027d67d79af Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 7 Jun 2022 08:43:54 +0100 Subject: [PATCH 3/4] non-linux platforms Signed-off-by: Nick Cameron --- library/std/src/fs.rs | 6 +- library/std/src/io/buffered/bufreader.rs | 5 +- .../std/src/io/buffered/bufreader/buffer.rs | 12 +- library/std/src/io/buffered/tests.rs | 12 +- library/std/src/io/copy.rs | 8 +- library/std/src/io/cursor.rs | 4 +- library/std/src/io/impls.rs | 14 +-- library/std/src/io/mod.rs | 21 ++-- library/std/src/io/readbuf.rs | 107 ++++++++++-------- library/std/src/io/readbuf/tests.rs | 80 +++++++++++-- library/std/src/io/tests.rs | 6 +- library/std/src/io/util.rs | 6 +- library/std/src/io/util/tests.rs | 10 +- library/std/src/sys/hermit/fs.rs | 6 +- library/std/src/sys/solid/fs.rs | 12 +- library/std/src/sys/unix/fd.rs | 4 +- library/std/src/sys/unix/fs.rs | 4 +- library/std/src/sys/unsupported/fs.rs | 4 +- library/std/src/sys/wasi/fs.rs | 6 +- library/std/src/sys/windows/fs.rs | 6 +- library/std/src/sys/windows/handle.rs | 12 +- 21 files changed, 205 insertions(+), 140 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index d41f32b5b3f21..98aa40db32176 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -13,7 +13,7 @@ mod tests; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -703,7 +703,7 @@ impl Read for File { self.inner.read_vectored(bufs) } - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.inner.read_buf(cursor) } @@ -755,7 +755,7 @@ impl Read for &File { self.inner.read(buf) } - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.inner.read_buf(cursor) } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 1f19ac11bf101..dced922ea572e 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -2,8 +2,7 @@ mod buffer; use crate::fmt; use crate::io::{ - self, BorrowBuf, BorrowCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, - DEFAULT_BUF_SIZE, + self, BorrowedCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, }; use buffer::Buffer; @@ -267,7 +266,7 @@ impl Read for BufReader { Ok(nread) } - fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index 8ae01f3b0ad8a..b122a6c0ccc57 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -9,7 +9,7 @@ /// that user code which wants to do reads from a `BufReader` via `buffer` + `consume` can do so /// without encountering any runtime bounds checks. use crate::cmp; -use crate::io::{self, Read, ReadBuf}; +use crate::io::{self, BorrowedBuf, Read}; use crate::mem::MaybeUninit; pub struct Buffer { @@ -93,11 +93,15 @@ impl Buffer { if self.pos >= self.filled { debug_assert!(self.pos == self.filled); - let mut readbuf = ReadBuf::uninit(&mut self.buf); + let mut buf: BorrowedBuf<'_> = (&mut *self.buf).into(); + // SAFETY: `self.filled` bytes will always have been initialized. + unsafe { + buf.set_init(self.filled); + } - reader.read_buf(&mut readbuf)?; + reader.read_buf(buf.unfilled())?; - self.filled = readbuf.filled_len(); + self.filled = buf.len(); self.pos = 0; } Ok(self.buffer()) diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index c93b69bf1f7c1..bd6d95242ad94 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -1,5 +1,7 @@ use crate::io::prelude::*; -use crate::io::{self, BorrowBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom}; +use crate::io::{ + self, BorrowedBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom, +}; use crate::mem::MaybeUninit; use crate::panic; use crate::sync::atomic::{AtomicUsize, Ordering}; @@ -62,7 +64,7 @@ fn test_buffered_reader_read_buf() { let mut reader = BufReader::with_capacity(2, inner); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); @@ -70,7 +72,7 @@ fn test_buffered_reader_read_buf() { assert_eq!(reader.buffer(), []); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 2]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); @@ -78,7 +80,7 @@ fn test_buffered_reader_read_buf() { assert_eq!(reader.buffer(), []); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); @@ -86,7 +88,7 @@ fn test_buffered_reader_read_buf() { assert_eq!(reader.buffer(), [3]); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 193bcd47467c1..1efd98b92aa00 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,4 +1,4 @@ -use super::{BorrowBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; +use super::{BorrowedBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; use crate::mem::MaybeUninit; /// Copies the entire contents of a reader into a writer. @@ -97,7 +97,7 @@ impl BufferedCopySpec for BufWriter { loop { let buf = writer.buffer_mut(); - let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); + let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into(); unsafe { // SAFETY: init is either 0 or the init_len from the previous iteration. @@ -117,7 +117,7 @@ impl BufferedCopySpec for BufWriter { init = read_buf.init_len() - bytes_read; len += bytes_read as u64; - // SAFETY: BorrowBuf guarantees all of its filled bytes are init + // SAFETY: BorrowedBuf guarantees all of its filled bytes are init unsafe { buf.set_len(buf.len() + bytes_read) }; // Read again if the buffer still has enough capacity, as BufWriter itself would do @@ -139,7 +139,7 @@ fn stack_buffer_copy( writer: &mut W, ) -> Result { let buf: &mut [_] = &mut [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); let mut len = 0; diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 460b1504ffbfc..e00577b51073e 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -5,7 +5,7 @@ use crate::io::prelude::*; use crate::alloc::Allocator; use crate::cmp; -use crate::io::{self, BorrowCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; /// A `Cursor` wraps an in-memory buffer and provides it with a /// [`Seek`] implementation. @@ -323,7 +323,7 @@ where Ok(n) } - fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let prev_written = cursor.written(); Read::read_buf(&mut self.fill_buf()?, cursor.clone())?; diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index eee5ab6ec1050..183c8c660b490 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -6,7 +6,7 @@ use crate::cmp; use crate::collections::VecDeque; use crate::fmt; use crate::io::{ - self, BorrowCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, + self, BorrowedCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, }; use crate::mem; @@ -21,7 +21,7 @@ impl Read for &mut R { } #[inline] - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -125,7 +125,7 @@ impl Read for Box { } #[inline] - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -249,7 +249,7 @@ impl Read for &[u8] { } #[inline] - fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let amt = cmp::min(cursor.capacity(), self.len()); let (a, b) = self.split_at(amt); @@ -427,10 +427,10 @@ impl Read for VecDeque { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let (ref mut front, _) = self.as_slices(); - let n = cmp::min(buf.remaining(), front.len()); - Read::read_buf(front, buf)?; + let n = cmp::min(cursor.capacity(), front.len()); + Read::read_buf(front, cursor)?; self.drain(..n); Ok(()) } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index b3218b2831d3f..02f82a7e9957a 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -278,7 +278,7 @@ pub use self::{ }; #[unstable(feature = "read_buf", issue = "78485")] -pub use self::readbuf::{BorrowBuf, BorrowCursor}; +pub use self::readbuf::{BorrowedBuf, BorrowedCursor}; pub(crate) use error::const_io_error; mod buffered; @@ -362,7 +362,7 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec buf.reserve(32); // buf is full, need more space } - let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); + let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into(); // SAFETY: These bytes were initialized but not filled in the previous loop unsafe { @@ -383,7 +383,7 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec // store how much was initialized but not filled initialized = cursor.init_ref().len(); - // SAFETY: BorrowBuf's invariants mean this much memory is initialized. + // SAFETY: BorrowedBuf's invariants mean this much memory is initialized. unsafe { let new_len = read_buf.filled().len() + buf.len(); buf.set_len(new_len); @@ -462,7 +462,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } -pub(crate) fn default_read_buf(read: F, mut cursor: BorrowCursor<'_, '_>) -> Result<()> +pub(crate) fn default_read_buf(read: F, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> where F: FnOnce(&mut [u8]) -> Result, { @@ -805,24 +805,23 @@ pub trait Read { default_read_exact(self, buf) } - // TODO naming, if should the method be read_cursor? Or should we change the names of the data structures? /// Pull some bytes from this source into the specified buffer. /// - /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to allow use + /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`. /// /// The default implementation delegates to `read`. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf(&mut self, buf: BorrowCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, buf: BorrowedCursor<'_, '_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) } /// Read the exact number of bytes required to fill `cursor`. /// - /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to + /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to /// allow use with uninitialized buffers. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf_exact(&mut self, mut cursor: BorrowCursor<'_, '_>) -> Result<()> { + fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> { while cursor.capacity() > 0 { let prev_written = cursor.written(); match self.read_buf(cursor.clone()) { @@ -2587,7 +2586,7 @@ impl Read for Take { Ok(n) } - fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> Result<()> { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(()); @@ -2602,7 +2601,7 @@ impl Read for Take { // SAFETY: no uninit data is written to ibuf let ibuf = unsafe { &mut buf.as_mut()[..limit] }; - let mut sliced_buf: BorrowBuf<'_> = ibuf.into(); + let mut sliced_buf: BorrowedBuf<'_> = ibuf.into(); // SAFETY: extra_init bytes of ibuf are known to be initialized unsafe { diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 8783763fd425f..ae3fbcc6a2f14 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -5,6 +5,7 @@ mod tests; use crate::cmp; use crate::fmt::{self, Debug, Formatter}; +use crate::io::{Result, Write}; use crate::mem::MaybeUninit; /// A borrowed byte buffer which is incrementally filled and initialized. @@ -21,58 +22,58 @@ use crate::mem::MaybeUninit; /// [ initialized | uninitialized ] /// ``` /// -/// A `BorrowBuf` is created around some existing data (or capacity for data) via a unique reference -/// (`&mut`). The `BorrowBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise -/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowCursor`. The cursor +/// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference +/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise +/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor /// has write-only access to the unfilled portion of the buffer (you can think of it like a /// write-only iterator). /// -/// The lifetime `'a` is a bound on the lifetime of the underlying data. -pub struct BorrowBuf<'a> { +/// The lifetime `'data` is a bound on the lifetime of the underlying data. +pub struct BorrowedBuf<'data> { /// The buffer's underlying data. - buf: &'a mut [MaybeUninit], + buf: &'data mut [MaybeUninit], /// The length of `self.buf` which is known to be filled. filled: usize, /// The length of `self.buf` which is known to be initialized. - initialized: usize, + init: usize, } -impl Debug for BorrowBuf<'_> { +impl Debug for BorrowedBuf<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("ReadBuf") - .field("init", &self.initialized) + f.debug_struct("BorrowedBuf") + .field("init", &self.init) .field("filled", &self.filled) .field("capacity", &self.capacity()) .finish() } } -/// Create a new `BorrowBuf` from a fully initialized slice. -impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { +/// Create a new `BorrowedBuf` from a fully initialized slice. +impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> { #[inline] - fn from(slice: &'a mut [u8]) -> BorrowBuf<'a> { + fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> { let len = slice.len(); - BorrowBuf { - //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowBuf + BorrowedBuf { + //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, filled: 0, - initialized: len, + init: len, } } } -/// Create a new `BorrowBuf` from an uninitialized buffer. +/// Create a new `BorrowedBuf` from an uninitialized buffer. /// /// Use `set_init` if part of the buffer is known to be already initialized. -impl<'a> From<&'a mut [MaybeUninit]> for BorrowBuf<'a> { +impl<'data> From<&'data mut [MaybeUninit]> for BorrowedBuf<'data> { #[inline] - fn from(buf: &'a mut [MaybeUninit]) -> BorrowBuf<'a> { - BorrowBuf { buf, filled: 0, initialized: 0 } + fn from(buf: &'data mut [MaybeUninit]) -> BorrowedBuf<'data> { + BorrowedBuf { buf, filled: 0, init: 0 } } } -impl<'a> BorrowBuf<'a> { +impl<'data> BorrowedBuf<'data> { /// Returns the total capacity of the buffer. #[inline] pub fn capacity(&self) -> usize { @@ -88,7 +89,7 @@ impl<'a> BorrowBuf<'a> { /// Returns the length of the initialized part of the buffer. #[inline] pub fn init_len(&self) -> usize { - self.initialized + self.init } /// Returns a shared reference to the filled portion of the buffer. @@ -100,8 +101,8 @@ impl<'a> BorrowBuf<'a> { /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn unfilled<'this>(&'this mut self) -> BorrowCursor<'this, 'a> { - BorrowCursor { start: self.filled, buf: self } + pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { + BorrowedCursor { start: self.filled, buf: self } } /// Clears the buffer, resetting the filled region to empty. @@ -115,7 +116,7 @@ impl<'a> BorrowBuf<'a> { /// Asserts that the first `n` bytes of the buffer are initialized. /// - /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer /// bytes than are already known to be initialized. /// /// # Safety @@ -123,42 +124,42 @@ impl<'a> BorrowBuf<'a> { /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. #[inline] pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { - self.initialized = cmp::max(self.initialized, n); + self.init = cmp::max(self.init, n); self } } -/// A writeable view of the unfilled portion of a [`BorrowBuf`](BorrowBuf). +/// A writeable view of the unfilled portion of a [`BorrowedBuf`](BorrowedBuf). /// -/// Provides access to the initialized and uninitialized parts of the underlying `BorrowBuf`. -/// Data can be written directly to the cursor by using [`append`](BorrowCursor::append) or +/// Provides access to the initialized and uninitialized parts of the underlying `BorrowedBuf`. +/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or /// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the -/// indirect case, the caller must call [`advance`](BorrowCursor::advance) after writing to inform +/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform /// the cursor how many bytes have been written. /// /// Once data is written to the cursor, it becomes part of the filled portion of the underlying -/// `BorrowBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks -/// the unfilled part of the underlying `BorrowBuf`. +/// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks +/// the unfilled part of the underlying `BorrowedBuf`. /// /// The `'buf` lifetime is a bound on the lifetime of the underlying buffer. `'data` is a bound on /// that buffer's underlying data. #[derive(Debug)] -pub struct BorrowCursor<'buf, 'data> { +pub struct BorrowedCursor<'buf, 'data> { /// The underlying buffer. - buf: &'buf mut BorrowBuf<'data>, + buf: &'buf mut BorrowedBuf<'data>, /// The length of the filled portion of the underlying buffer at the time of the cursor's /// creation. start: usize, } -impl<'buf, 'data> BorrowCursor<'buf, 'data> { +impl<'buf, 'data> BorrowedCursor<'buf, 'data> { /// Clone this cursor. /// /// Since a cursor maintains unique access to its underlying buffer, the cloned cursor is not /// accessible while the clone is alive. #[inline] - pub fn clone<'this>(&'this mut self) -> BorrowCursor<'this, 'data> { - BorrowCursor { buf: self.buf, start: self.start } + pub fn clone<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { + BorrowedCursor { buf: self.buf, start: self.start } } /// Returns the available space in the cursor. @@ -167,7 +168,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { self.buf.capacity() - self.buf.filled } - /// Returns the number of bytes written to this cursor since it was created from a `BorrowBuf`. + /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`. /// /// Note that if this cursor is a clone of another, then the count returned is the count written /// via either cursor, not the count since the cursor was cloned. @@ -180,9 +181,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { #[inline] pub fn init_ref(&self) -> &[u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { - MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.initialized]) - } + unsafe { MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.init]) } } /// Returns a mutable reference to the initialized portion of the cursor. @@ -190,9 +189,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { pub fn init_mut(&mut self) -> &mut [u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { - MaybeUninit::slice_assume_init_mut( - &mut self.buf.buf[self.buf.filled..self.buf.initialized], - ) + MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init]) } } @@ -201,7 +198,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { /// It is safe to uninitialize any of these bytes. #[inline] pub fn uninit_mut(&mut self) -> &mut [MaybeUninit] { - &mut self.buf.buf[self.buf.initialized..] + &mut self.buf.buf[self.buf.init..] } /// Returns a mutable reference to the whole cursor. @@ -227,7 +224,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { #[inline] pub unsafe fn advance(&mut self, n: usize) -> &mut Self { self.buf.filled += n; - self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled); + self.buf.init = cmp::max(self.buf.init, self.buf.filled); self } @@ -237,14 +234,14 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { for byte in self.uninit_mut() { byte.write(0); } - self.buf.initialized = self.buf.capacity(); + self.buf.init = self.buf.capacity(); self } /// Asserts that the first `n` unfilled bytes of the cursor are initialized. /// - /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when + /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when /// called with fewer bytes than are already known to be initialized. /// /// # Safety @@ -252,7 +249,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { /// The caller must ensure that the first `n` bytes of the buffer have already been initialized. #[inline] pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { - self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled + n); + self.buf.init = cmp::max(self.buf.init, self.buf.filled + n); self } @@ -272,9 +269,19 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { // SAFETY: We just added the entire contents of buf to the filled section. unsafe { - self.set_init(buf.len()); } self.buf.filled += buf.len(); } } + +impl<'buf, 'data> Write for BorrowedCursor<'buf, 'data> { + fn write(&mut self, buf: &[u8]) -> Result { + self.append(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index 584e5de982e97..8037a95790899 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -1,11 +1,11 @@ -use super::BorrowBuf; +use super::BorrowedBuf; use crate::mem::MaybeUninit; -/// Test that BorrowBuf has the correct numbers when created with new +/// Test that BorrowedBuf has the correct numbers when created with new #[test] fn new() { let buf: &mut [_] = &mut [0; 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); assert_eq!(rbuf.filled().len(), 0); assert_eq!(rbuf.init_len(), 16); @@ -13,11 +13,11 @@ fn new() { assert_eq!(rbuf.unfilled().capacity(), 16); } -/// Test that BorrowBuf has the correct numbers when created with uninit +/// Test that BorrowedBuf has the correct numbers when created with uninit #[test] fn uninit() { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); assert_eq!(rbuf.filled().len(), 0); assert_eq!(rbuf.init_len(), 0); @@ -28,7 +28,7 @@ fn uninit() { #[test] fn initialize_unfilled() { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); rbuf.unfilled().ensure_init(); @@ -36,9 +36,9 @@ fn initialize_unfilled() { } #[test] -fn add_filled() { +fn addvance_filled() { let buf: &mut [_] = &mut [0; 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { rbuf.unfilled().advance(1); @@ -51,7 +51,7 @@ fn add_filled() { #[test] fn clear() { let buf: &mut [_] = &mut [255; 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { rbuf.unfilled().advance(16); @@ -71,7 +71,7 @@ fn clear() { #[test] fn set_init() { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { rbuf.set_init(8); @@ -99,7 +99,7 @@ fn set_init() { #[test] fn append() { let buf: &mut [_] = &mut [MaybeUninit::new(255); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); rbuf.unfilled().append(&[0; 8]); @@ -115,3 +115,61 @@ fn append() { assert_eq!(rbuf.filled().len(), 16); assert_eq!(rbuf.filled(), [1; 16]); } + +#[test] +fn clone_written() { + let buf: &mut [_] = &mut [MaybeUninit::new(0); 32]; + let mut buf: BorrowedBuf<'_> = buf.into(); + + let mut cursor = buf.unfilled(); + cursor.append(&[1; 16]); + + let mut cursor2 = cursor.clone(); + cursor2.append(&[2; 16]); + + assert_eq!(cursor2.written(), 32); + assert_eq!(cursor.written(), 32); + + assert_eq!(buf.unfilled().written(), 0); + assert_eq!(buf.init_len(), 32); + assert_eq!(buf.filled().len(), 32); + let filled = buf.filled(); + assert_eq!(&filled[..16], [1; 16]); + assert_eq!(&filled[16..], [2; 16]); +} + +#[test] +fn cursor_set_init() { + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowedBuf<'_> = buf.into(); + + unsafe { + rbuf.unfilled().set_init(8); + } + + assert_eq!(rbuf.init_len(), 8); + assert_eq!(rbuf.unfilled().init_ref().len(), 8); + assert_eq!(rbuf.unfilled().init_mut().len(), 8); + assert_eq!(rbuf.unfilled().uninit_mut().len(), 8); + assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 16); + + unsafe { + rbuf.unfilled().advance(4); + } + + unsafe { + rbuf.unfilled().set_init(2); + } + + assert_eq!(rbuf.init_len(), 8); + + unsafe { + rbuf.unfilled().set_init(8); + } + + assert_eq!(rbuf.init_len(), 12); + assert_eq!(rbuf.unfilled().init_ref().len(), 8); + assert_eq!(rbuf.unfilled().init_mut().len(), 8); + assert_eq!(rbuf.unfilled().uninit_mut().len(), 4); + assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 12); +} diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index a1322a185651e..c5c476ec3bfee 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -1,4 +1,4 @@ -use super::{repeat, BorrowBuf, Cursor, SeekFrom}; +use super::{repeat, BorrowedBuf, Cursor, SeekFrom}; use crate::cmp::{self, min}; use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{BufRead, BufReader, Read, Seek, Write}; @@ -160,7 +160,7 @@ fn read_exact_slice() { #[test] fn read_buf_exact() { let buf: &mut [_] = &mut [0; 4]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); let mut c = Cursor::new(&b""[..]); assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); @@ -616,7 +616,7 @@ fn bench_take_read_buf(b: &mut test::Bencher) { b.iter(|| { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 64]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); [255; 128].take(64).read_buf(buf.unfilled()).unwrap(); }); diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 5149926fd519d..7475d71119a76 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -5,7 +5,7 @@ mod tests; use crate::fmt; use crate::io::{ - self, BorrowCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, + self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; /// A reader which is always at EOF. @@ -47,7 +47,7 @@ impl Read for Empty { } #[inline] - fn read_buf(&mut self, _cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { Ok(()) } } @@ -130,7 +130,7 @@ impl Read for Repeat { Ok(buf.len()) } - fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written for slot in unsafe { buf.as_mut() } { slot.write(self.byte); diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index 025173c3f446c..ce5e2c9da1dbf 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,7 +1,7 @@ use crate::cmp::{max, min}; use crate::io::prelude::*; use crate::io::{ - copy, empty, repeat, sink, BorrowBuf, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, + copy, empty, repeat, sink, BorrowedBuf, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, DEFAULT_BUF_SIZE, }; @@ -80,25 +80,25 @@ fn empty_reads() { assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); let buf: &mut [MaybeUninit<_>] = &mut []; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); let buf: &mut [_] = &mut [MaybeUninit::uninit()]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.by_ref().read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index fa9a7fb19e463..51321c51972ac 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -2,7 +2,7 @@ use crate::ffi::{CStr, CString, OsString}; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::io::{self, Error, ErrorKind}; -use crate::io::{IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::os::unix::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sys::cvt; @@ -312,8 +312,8 @@ impl File { false } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - crate::io::default_read_buf(|buf| self.read(buf), buf) + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + crate::io::default_read_buf(|buf| self.read(buf), cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs index a2cbee4dcf07b..0848d3d8f102d 100644 --- a/library/std/src/sys/solid/fs.rs +++ b/library/std/src/sys/solid/fs.rs @@ -2,7 +2,7 @@ use super::{abi, error}; use crate::{ ffi::{CStr, CString, OsStr, OsString}, fmt, - io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}, + io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}, mem::MaybeUninit, os::raw::{c_int, c_short}, os::solid::ffi::OsStrExt, @@ -358,13 +358,13 @@ impl File { } } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { unsafe { - let len = buf.remaining(); + let len = cursor.capacity(); let mut out_num_bytes = MaybeUninit::uninit(); error::SolidError::err_if_negative(abi::SOLID_FS_Read( self.fd.raw(), - buf.unfilled_mut().as_mut_ptr() as *mut u8, + cursor.as_mut().as_mut_ptr() as *mut u8, len, out_num_bytes.as_mut_ptr(), )) @@ -376,9 +376,7 @@ impl File { // Safety: `num_bytes_read` bytes were written to the unfilled // portion of the buffer - buf.assume_init(num_bytes_read); - - buf.add_filled(num_bytes_read); + cursor.advance(num_bytes_read); Ok(()) } diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 6adb734fb0a2f..76a269bb9b59c 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -4,7 +4,7 @@ mod tests; use crate::cmp; -use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -131,7 +131,7 @@ impl FileDesc { } } - pub fn read_buf(&self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let ret = cvt(unsafe { libc::read( self.as_raw_fd(), diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 374f9f72d6d74..5056134544279 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, BorrowCursor, Error, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::path::{Path, PathBuf}; @@ -1031,7 +1031,7 @@ impl File { self.0.read_at(buf, offset) } - pub fn read_buf(&self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.0.read_buf(cursor) } diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index 0e1a6257ed763..41e39ce27cec9 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -1,7 +1,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::unsupported; @@ -214,7 +214,7 @@ impl File { self.0 } - pub fn read_buf(&self, _buf: &mut ReadBuf<'_>) -> io::Result<()> { + pub fn read_buf(&self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.0 } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 6614ae397b57f..b5b5eab1a24ec 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -3,7 +3,7 @@ use super::fd::WasiFd; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::iter; use crate::mem::{self, ManuallyDrop}; use crate::os::raw::c_int; @@ -439,8 +439,8 @@ impl File { true } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - crate::io::default_read_buf(|buf| self.read(buf), buf) + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + crate::io::default_read_buf(|buf| self.read(buf), cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index aed082b3e0abf..bfc2477dff46b 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -2,7 +2,7 @@ use crate::os::windows::prelude::*; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::os::windows::io::{AsHandle, BorrowedHandle}; use crate::path::{Path, PathBuf}; @@ -415,8 +415,8 @@ impl File { self.handle.read_at(buf, offset) } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.handle.read_buf(buf) + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + self.handle.read_buf(cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index e24b09cc96ec8..0ea6876af5b93 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -4,7 +4,7 @@ mod tests; use crate::cmp; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf}; +use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, Read}; use crate::mem; use crate::os::windows::io::{ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, @@ -112,18 +112,16 @@ impl Handle { } } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - let res = unsafe { - self.synchronous_read(buf.unfilled_mut().as_mut_ptr(), buf.remaining(), None) - }; + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + let res = + unsafe { self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), None) }; match res { Ok(read) => { // Safety: `read` bytes were written to the initialized portion of the buffer unsafe { - buf.assume_init(read as usize); + cursor.advance(read as usize); } - buf.add_filled(read as usize); Ok(()) } From ac70aea98509c33ec75208f7b42c8d905c74ebaf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 11 Aug 2022 15:52:29 +0100 Subject: [PATCH 4/4] Address reviewer comments Signed-off-by: Nick Cameron --- library/std/src/fs.rs | 4 +- library/std/src/io/buffered/bufreader.rs | 4 +- .../std/src/io/buffered/bufreader/buffer.rs | 2 +- library/std/src/io/copy.rs | 2 +- library/std/src/io/cursor.rs | 4 +- library/std/src/io/impls.rs | 8 +-- library/std/src/io/mod.rs | 16 ++--- library/std/src/io/readbuf.rs | 65 ++++++++++++------- library/std/src/io/readbuf/tests.rs | 4 +- library/std/src/io/util.rs | 4 +- library/std/src/sys/hermit/fs.rs | 2 +- library/std/src/sys/solid/fs.rs | 2 +- library/std/src/sys/unix/fd.rs | 2 +- library/std/src/sys/unix/fs.rs | 2 +- library/std/src/sys/unsupported/fs.rs | 2 +- library/std/src/sys/wasi/fs.rs | 2 +- library/std/src/sys/windows/fs.rs | 2 +- library/std/src/sys/windows/handle.rs | 2 +- 18 files changed, 74 insertions(+), 55 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 98aa40db32176..e1ab06b0d0f69 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -703,7 +703,7 @@ impl Read for File { self.inner.read_vectored(bufs) } - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.inner.read_buf(cursor) } @@ -755,7 +755,7 @@ impl Read for &File { self.inner.read(buf) } - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.inner.read_buf(cursor) } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index dced922ea572e..88ad92d8a9859 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -266,7 +266,7 @@ impl Read for BufReader { Ok(nread) } - fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. @@ -278,7 +278,7 @@ impl Read for BufReader { let prev = cursor.written(); let mut rem = self.fill_buf()?; - rem.read_buf(cursor.clone())?; + rem.read_buf(cursor.reborrow())?; self.consume(cursor.written() - prev); //slice impl of read_buf known to never unfill buf diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index b122a6c0ccc57..867c22c6041e7 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -93,7 +93,7 @@ impl Buffer { if self.pos >= self.filled { debug_assert!(self.pos == self.filled); - let mut buf: BorrowedBuf<'_> = (&mut *self.buf).into(); + let mut buf = BorrowedBuf::from(&mut *self.buf); // SAFETY: `self.filled` bytes will always have been initialized. unsafe { buf.set_init(self.filled); diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 1efd98b92aa00..38b98afffa168 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -106,7 +106,7 @@ impl BufferedCopySpec for BufWriter { if read_buf.capacity() >= DEFAULT_BUF_SIZE { let mut cursor = read_buf.unfilled(); - match reader.read_buf(cursor.clone()) { + match reader.read_buf(cursor.reborrow()) { Ok(()) => { let bytes_read = cursor.written(); diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index e00577b51073e..d98ab021cadb1 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -323,10 +323,10 @@ where Ok(n) } - fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let prev_written = cursor.written(); - Read::read_buf(&mut self.fill_buf()?, cursor.clone())?; + Read::read_buf(&mut self.fill_buf()?, cursor.reborrow())?; self.pos += (cursor.written() - prev_written) as u64; diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 183c8c660b490..e5048dcc8acd9 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -21,7 +21,7 @@ impl Read for &mut R { } #[inline] - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -125,7 +125,7 @@ impl Read for Box { } #[inline] - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -249,7 +249,7 @@ impl Read for &[u8] { } #[inline] - fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let amt = cmp::min(cursor.capacity(), self.len()); let (a, b) = self.split_at(amt); @@ -427,7 +427,7 @@ impl Read for VecDeque { } #[inline] - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { let (ref mut front, _) = self.as_slices(); let n = cmp::min(cursor.capacity(), front.len()); Read::read_buf(front, cursor)?; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 02f82a7e9957a..8b8ec32bf5b63 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -370,7 +370,7 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec } let mut cursor = read_buf.unfilled(); - match r.read_buf(cursor.clone()) { + match r.read_buf(cursor.reborrow()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), @@ -462,7 +462,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } -pub(crate) fn default_read_buf(read: F, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> +pub(crate) fn default_read_buf(read: F, mut cursor: BorrowedCursor<'_>) -> Result<()> where F: FnOnce(&mut [u8]) -> Result, { @@ -812,7 +812,7 @@ pub trait Read { /// /// The default implementation delegates to `read`. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf(&mut self, buf: BorrowedCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) } @@ -821,10 +821,10 @@ pub trait Read { /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to /// allow use with uninitialized buffers. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> { + fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> { while cursor.capacity() > 0 { let prev_written = cursor.written(); - match self.read_buf(cursor.clone()) { + match self.read_buf(cursor.reborrow()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), @@ -2586,7 +2586,7 @@ impl Read for Take { Ok(n) } - fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> Result<()> { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(()); @@ -2609,7 +2609,7 @@ impl Read for Take { } let mut cursor = sliced_buf.unfilled(); - self.inner.read_buf(cursor.clone())?; + self.inner.read_buf(cursor.reborrow())?; let new_init = cursor.init_ref().len(); let filled = sliced_buf.len(); @@ -2626,7 +2626,7 @@ impl Read for Take { self.limit -= filled as u64; } else { let written = buf.written(); - self.inner.read_buf(buf.clone())?; + self.inner.read_buf(buf.reborrow())?; self.limit -= (buf.written() - written) as u64; } diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index ae3fbcc6a2f14..b1a84095f13fa 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -6,7 +6,7 @@ mod tests; use crate::cmp; use crate::fmt::{self, Debug, Formatter}; use crate::io::{Result, Write}; -use crate::mem::MaybeUninit; +use crate::mem::{self, MaybeUninit}; /// A borrowed byte buffer which is incrementally filled and initialized. /// @@ -23,9 +23,9 @@ use crate::mem::MaybeUninit; /// ``` /// /// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference -/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise -/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor -/// has write-only access to the unfilled portion of the buffer (you can think of it like a +/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but cannot be +/// directly written. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor +/// has write-only access to the unfilled portion of the buffer (you can think of it as a /// write-only iterator). /// /// The lifetime `'data` is a bound on the lifetime of the underlying data. @@ -55,7 +55,7 @@ impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> { let len = slice.len(); BorrowedBuf { - //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf + // SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, filled: 0, init: len, @@ -95,14 +95,21 @@ impl<'data> BorrowedBuf<'data> { /// Returns a shared reference to the filled portion of the buffer. #[inline] pub fn filled(&self) -> &[u8] { - //SAFETY: We only slice the filled part of the buffer, which is always valid + // SAFETY: We only slice the filled part of the buffer, which is always valid unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } } /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { - BorrowedCursor { start: self.filled, buf: self } + pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> { + BorrowedCursor { + start: self.filled, + // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its + // lifetime covariantly is safe. + buf: unsafe { + mem::transmute::<&'this mut BorrowedBuf<'data>, &'this mut BorrowedBuf<'this>>(self) + }, + } } /// Clears the buffer, resetting the filled region to empty. @@ -141,25 +148,37 @@ impl<'data> BorrowedBuf<'data> { /// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks /// the unfilled part of the underlying `BorrowedBuf`. /// -/// The `'buf` lifetime is a bound on the lifetime of the underlying buffer. `'data` is a bound on -/// that buffer's underlying data. +/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound +/// on the data in that buffer by transitivity). #[derive(Debug)] -pub struct BorrowedCursor<'buf, 'data> { +pub struct BorrowedCursor<'a> { /// The underlying buffer. - buf: &'buf mut BorrowedBuf<'data>, + // Safety invariant: we treat the type of buf as covariant in the lifetime of `BorrowedBuf` when + // we create a `BorrowedCursor`. This is only safe if we never replace `buf` by assigning into + // it, so don't do that! + buf: &'a mut BorrowedBuf<'a>, /// The length of the filled portion of the underlying buffer at the time of the cursor's /// creation. start: usize, } -impl<'buf, 'data> BorrowedCursor<'buf, 'data> { - /// Clone this cursor. +impl<'a> BorrowedCursor<'a> { + /// Reborrow this cursor by cloning it with a smaller lifetime. /// - /// Since a cursor maintains unique access to its underlying buffer, the cloned cursor is not - /// accessible while the clone is alive. + /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is + /// not accessible while the new cursor exists. #[inline] - pub fn clone<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { - BorrowedCursor { buf: self.buf, start: self.start } + pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this> { + BorrowedCursor { + // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its + // lifetime covariantly is safe. + buf: unsafe { + mem::transmute::<&'this mut BorrowedBuf<'a>, &'this mut BorrowedBuf<'this>>( + self.buf, + ) + }, + start: self.start, + } } /// Returns the available space in the cursor. @@ -170,8 +189,8 @@ impl<'buf, 'data> BorrowedCursor<'buf, 'data> { /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`. /// - /// Note that if this cursor is a clone of another, then the count returned is the count written - /// via either cursor, not the count since the cursor was cloned. + /// Note that if this cursor is a reborrowed clone of another, then the count returned is the + /// count written via either cursor, not the count since the cursor was reborrowed. #[inline] pub fn written(&self) -> usize { self.buf.filled - self.start @@ -180,14 +199,14 @@ impl<'buf, 'data> BorrowedCursor<'buf, 'data> { /// Returns a shared reference to the initialized portion of the cursor. #[inline] pub fn init_ref(&self) -> &[u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid + // SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.init]) } } /// Returns a mutable reference to the initialized portion of the cursor. #[inline] pub fn init_mut(&mut self) -> &mut [u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid + // SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init]) } @@ -275,7 +294,7 @@ impl<'buf, 'data> BorrowedCursor<'buf, 'data> { } } -impl<'buf, 'data> Write for BorrowedCursor<'buf, 'data> { +impl<'a> Write for BorrowedCursor<'a> { fn write(&mut self, buf: &[u8]) -> Result { self.append(buf); Ok(buf.len()) diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index 8037a95790899..cc1b423f2dd0d 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -117,14 +117,14 @@ fn append() { } #[test] -fn clone_written() { +fn reborrow_written() { let buf: &mut [_] = &mut [MaybeUninit::new(0); 32]; let mut buf: BorrowedBuf<'_> = buf.into(); let mut cursor = buf.unfilled(); cursor.append(&[1; 16]); - let mut cursor2 = cursor.clone(); + let mut cursor2 = cursor.reborrow(); cursor2.append(&[2; 16]); assert_eq!(cursor2.written(), 32); diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 7475d71119a76..f076ee0923c80 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -47,7 +47,7 @@ impl Read for Empty { } #[inline] - fn read_buf(&mut self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { Ok(()) } } @@ -130,7 +130,7 @@ impl Read for Repeat { Ok(buf.len()) } - fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written for slot in unsafe { buf.as_mut() } { slot.write(self.byte); diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index 51321c51972ac..1c5efa94bd36a 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -312,7 +312,7 @@ impl File { false } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { crate::io::default_read_buf(|buf| self.read(buf), cursor) } diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs index 0848d3d8f102d..8e23a7c7d884a 100644 --- a/library/std/src/sys/solid/fs.rs +++ b/library/std/src/sys/solid/fs.rs @@ -358,7 +358,7 @@ impl File { } } - pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { unsafe { let len = cursor.capacity(); let mut out_num_bytes = MaybeUninit::uninit(); diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 76a269bb9b59c..dbaa3c33e2e57 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -131,7 +131,7 @@ impl FileDesc { } } - pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let ret = cvt(unsafe { libc::read( self.as_raw_fd(), diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 5056134544279..b8fc2e8da2b75 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1031,7 +1031,7 @@ impl File { self.0.read_at(buf, offset) } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.0.read_buf(cursor) } diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index 41e39ce27cec9..6ac1b5d2bcfca 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -214,7 +214,7 @@ impl File { self.0 } - pub fn read_buf(&self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { self.0 } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index b5b5eab1a24ec..510cf36b1bf48 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -439,7 +439,7 @@ impl File { true } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { crate::io::default_read_buf(|buf| self.read(buf), cursor) } diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index bfc2477dff46b..9ac7cfebbebe0 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -415,7 +415,7 @@ impl File { self.handle.read_at(buf, offset) } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.handle.read_buf(cursor) } diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 0ea6876af5b93..ae33d48c612ee 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -112,7 +112,7 @@ impl Handle { } } - pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let res = unsafe { self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), None) };