Rollup merge of #97015 - nrc:read-buf-cursor, r=Mark-Simulacrum
std::io: migrate ReadBuf to BorrowBuf/BorrowCursor This PR replaces `ReadBuf` (used by the `Read::read_buf` family of methods) with `BorrowBuf` and `BorrowCursor`. The general idea is to split `ReadBuf` because its API is large and confusing. `BorrowBuf` represents a borrowed buffer which is mostly read-only and (other than for construction) deals only with filled vs unfilled segments. a `BorrowCursor` is a mostly write-only view of the unfilled part of a `BorrowBuf` which distinguishes between initialized and uninitialized segments. For `Read::read_buf`, the caller would create a `BorrowBuf`, then pass a `BorrowCursor` to `read_buf`. In addition to the major API split, I've made the following smaller changes: * Removed some methods entirely from the API (mostly the functionality can be replicated with two calls rather than a single one) * Unified naming, e.g., by replacing initialized with init and assume_init with set_init * Added an easy way to get the number of bytes written to a cursor (`written` method) As well as simplifying the API (IMO), this approach has the following advantages: * Since we pass the cursor by value, we remove the 'unsoundness footgun' where a malicious `read_buf` could swap out the `ReadBuf`. * Since `read_buf` cannot write into the filled part of the buffer, we prevent the filled part shrinking or changing which could cause underflow for the caller or unexpected behaviour. ## Outline ```rust pub struct BorrowBuf<'a> impl Debug for BorrowBuf<'_> impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> impl<'a> From<&'a mut [MaybeUninit<u8>]> for BorrowBuf<'a> impl<'a> BorrowBuf<'a> { pub fn capacity(&self) -> usize pub fn len(&self) -> usize pub fn init_len(&self) -> usize pub fn filled(&self) -> &[u8] pub fn unfilled<'this>(&'this mut self) -> BorrowCursor<'this, 'a> pub fn clear(&mut self) -> &mut Self pub unsafe fn set_init(&mut self, n: usize) -> &mut Self } pub struct BorrowCursor<'buf, 'data> impl<'buf, 'data> BorrowCursor<'buf, 'data> { pub fn clone<'this>(&'this mut self) -> BorrowCursor<'this, 'data> pub fn capacity(&self) -> usize pub fn written(&self) -> usize pub fn init_ref(&self) -> &[u8] pub fn init_mut(&mut self) -> &mut [u8] pub fn uninit_mut(&mut self) -> &mut [MaybeUninit<u8>] pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] pub unsafe fn advance(&mut self, n: usize) -> &mut Self pub fn ensure_init(&mut self) -> &mut Self pub unsafe fn set_init(&mut self, n: usize) -> &mut Self pub fn append(&mut self, buf: &[u8]) } ``` ## TODO * ~~Migrate non-unix libs and tests~~ * ~~Naming~~ * ~~`BorrowBuf` or `BorrowedBuf` or `SliceBuf`? (We might want an owned equivalent for the async IO traits)~~ * ~~Should we rename the `readbuf` module? We might keep the name indicate it includes both the buf and cursor variations and someday the owned version too. Or we could change it. It is not publicly exposed, so it is not that important~~. * ~~`read_buf` method: we read into the cursor now, so the `_buf` suffix is a bit weird.~~ * ~~Documentation~~ * Tests are incomplete (I adjusted existing tests, but did not add new ones). cc https://github.com/rust-lang/rust/issues/78485, https://github.com/rust-lang/rust/issues/94741 supersedes: https://github.com/rust-lang/rust/pull/95770, https://github.com/rust-lang/rust/pull/93359 fixes #93305
This commit is contained in:
commit
b9306c231a
21 changed files with 508 additions and 454 deletions
|
@ -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, 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,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: BorrowedCursor<'_>) -> 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: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.inner.read_buf(cursor)
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
|
|
|
@ -2,7 +2,7 @@ mod buffer;
|
|||
|
||||
use crate::fmt;
|
||||
use crate::io::{
|
||||
self, BufRead, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE,
|
||||
self, BorrowedCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE,
|
||||
};
|
||||
use buffer::Buffer;
|
||||
|
||||
|
@ -266,21 +266,21 @@ impl<R: Read> Read for BufReader<R> {
|
|||
Ok(nread)
|
||||
}
|
||||
|
||||
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> 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.
|
||||
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.reborrow())?;
|
||||
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -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::from(&mut *self.buf);
|
||||
// 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())
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::io::prelude::*;
|
||||
use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, ReadBuf, 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};
|
||||
|
@ -61,48 +63,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: BorrowedBuf<'_> = 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: BorrowedBuf<'_> = 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: BorrowedBuf<'_> = 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: BorrowedBuf<'_> = 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]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{BufWriter, ErrorKind, Read, ReadBuf, 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,37 +97,39 @@ impl<I: Write> BufferedCopySpec for BufWriter<I> {
|
|||
|
||||
loop {
|
||||
let buf = writer.buffer_mut();
|
||||
let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
|
||||
let mut read_buf: BorrowedBuf<'_> = 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.reborrow()) {
|
||||
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;
|
||||
|
||||
// SAFETY: ReadBuf guarantees all of its filled bytes are init
|
||||
unsafe { buf.set_len(buf.len() + bytes_read) };
|
||||
init = read_buf.init_len() - bytes_read;
|
||||
len += bytes_read as u64;
|
||||
|
||||
// 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
|
||||
// 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<R: Read + ?Sized, W: Write + ?Sized>(
|
|||
reader: &mut R,
|
||||
writer: &mut W,
|
||||
) -> Result<u64> {
|
||||
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: BorrowedBuf<'_> = 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),
|
||||
|
|
|
@ -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, BorrowedCursor, 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: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
let prev_written = cursor.written();
|
||||
|
||||
Read::read_buf(&mut self.fill_buf()?, buf)?;
|
||||
Read::read_buf(&mut self.fill_buf()?, cursor.reborrow())?;
|
||||
|
||||
self.pos += (buf.filled_len() - prev_filled) as u64;
|
||||
self.pos += (cursor.written() - prev_written) as u64;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -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, BorrowedCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write,
|
||||
};
|
||||
use crate::mem;
|
||||
|
||||
|
@ -21,8 +21,8 @@ impl<R: Read + ?Sized> 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: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
(**self).read_buf(cursor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -125,8 +125,8 @@ impl<R: Read + ?Sized> Read for Box<R> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||
(**self).read_buf(buf)
|
||||
fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> 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: BorrowedCursor<'_>) -> 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(())
|
||||
|
@ -427,10 +427,10 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
|
|||
}
|
||||
|
||||
#[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(())
|
||||
}
|
||||
|
|
|
@ -278,7 +278,7 @@ pub use self::{
|
|||
};
|
||||
|
||||
#[unstable(feature = "read_buf", issue = "78485")]
|
||||
pub use self::readbuf::ReadBuf;
|
||||
pub use self::readbuf::{BorrowedBuf, BorrowedCursor};
|
||||
pub(crate) use error::const_io_error;
|
||||
|
||||
mod buffered;
|
||||
|
@ -362,29 +362,30 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>
|
|||
buf.reserve(32); // buf is full, need more space
|
||||
}
|
||||
|
||||
let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
|
||||
let mut read_buf: BorrowedBuf<'_> = 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.reborrow()) {
|
||||
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: BorrowedBuf'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<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn default_read_buf<F>(read: F, buf: &mut ReadBuf<'_>) -> Result<()>
|
||||
pub(crate) fn default_read_buf<F>(read: F, mut cursor: BorrowedCursor<'_>) -> Result<()>
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> Result<usize>,
|
||||
{
|
||||
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(())
|
||||
}
|
||||
|
||||
|
@ -803,30 +807,30 @@ pub trait Read {
|
|||
|
||||
/// 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 [`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: &mut ReadBuf<'_>) -> 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 `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 [`BorrowedCursor`] 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: BorrowedCursor<'_>) -> Result<()> {
|
||||
while cursor.capacity() > 0 {
|
||||
let prev_written = cursor.written();
|
||||
match self.read_buf(cursor.reborrow()) {
|
||||
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 +2586,48 @@ impl<T: Read> Read for Take<T> {
|
|||
Ok(n)
|
||||
}
|
||||
|
||||
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> 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(());
|
||||
}
|
||||
|
||||
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: BorrowedBuf<'_> = 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.reborrow())?;
|
||||
|
||||
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.reborrow())?;
|
||||
self.limit -= (buf.written() - written) as u64;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -5,9 +5,10 @@ mod tests;
|
|||
|
||||
use crate::cmp;
|
||||
use crate::fmt::{self, Debug, Formatter};
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::io::{Result, Write};
|
||||
use crate::mem::{self, MaybeUninit};
|
||||
|
||||
/// 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
|
||||
|
@ -20,146 +21,95 @@ use crate::mem::MaybeUninit;
|
|||
/// [ filled | unfilled ]
|
||||
/// [ initialized | uninitialized ]
|
||||
/// ```
|
||||
pub struct ReadBuf<'a> {
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
///
|
||||
/// 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 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.
|
||||
pub struct BorrowedBuf<'data> {
|
||||
/// The buffer's underlying data.
|
||||
buf: &'data mut [MaybeUninit<u8>],
|
||||
/// The length of `self.buf` which is known to be filled.
|
||||
filled: usize,
|
||||
initialized: usize,
|
||||
/// The length of `self.buf` which is known to be initialized.
|
||||
init: usize,
|
||||
}
|
||||
|
||||
impl Debug for ReadBuf<'_> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ReadBuf<'a> {
|
||||
/// Creates a new `ReadBuf` from a fully initialized buffer.
|
||||
/// Create a new `BorrowedBuf` from a fully initialized slice.
|
||||
impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> {
|
||||
let len = buf.len();
|
||||
fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> {
|
||||
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() },
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `ReadBuf` from a fully uninitialized buffer.
|
||||
///
|
||||
/// Use `assume_init` if part of the buffer is known to be already initialized.
|
||||
/// Create a new `BorrowedBuf` from an uninitialized buffer.
|
||||
///
|
||||
/// Use `set_init` if part of the buffer is known to be already initialized.
|
||||
impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> {
|
||||
#[inline]
|
||||
pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> {
|
||||
ReadBuf { buf, filled: 0, initialized: 0 }
|
||||
fn from(buf: &'data mut [MaybeUninit<u8>]) -> BorrowedBuf<'data> {
|
||||
BorrowedBuf { buf, filled: 0, init: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'data> BorrowedBuf<'data> {
|
||||
/// 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.init
|
||||
}
|
||||
|
||||
/// 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 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]) }
|
||||
}
|
||||
|
||||
/// Returns a shared reference to the initialized portion of the buffer.
|
||||
///
|
||||
/// This includes the filled portion.
|
||||
#[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]) }
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the initialized portion of the buffer.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must not de-initialize portions of the buffer that have already been initialized.
|
||||
#[inline]
|
||||
pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
&mut self.buf[self.filled..]
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the uninitialized part of the buffer.
|
||||
///
|
||||
/// It is safe to uninitialize any of these bytes.
|
||||
#[inline]
|
||||
pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
&mut self.buf[self.initialized..]
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn initialize_unfilled(&mut self) -> &mut [u8] {
|
||||
// should optimize out the assertion
|
||||
self.initialize_unfilled_to(self.remaining())
|
||||
}
|
||||
|
||||
/// 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`.
|
||||
#[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);
|
||||
}
|
||||
|
||||
// SAFETY: we just initialized uninit bytes, and the previous bytes were already init
|
||||
unsafe {
|
||||
self.assume_init(n);
|
||||
}
|
||||
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)
|
||||
},
|
||||
}
|
||||
|
||||
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.
|
||||
#[inline]
|
||||
pub fn remaining(&self) -> usize {
|
||||
self.capacity() - self.filled
|
||||
}
|
||||
|
||||
/// Clears the buffer, resetting the filled region to empty.
|
||||
|
@ -167,83 +117,190 @@ impl<'a> ReadBuf<'a> {
|
|||
/// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
|
||||
#[inline]
|
||||
pub fn clear(&mut self) -> &mut Self {
|
||||
self.set_filled(0) // The assertion in `set_filled` is optimized out
|
||||
}
|
||||
|
||||
/// Increases the size of the filled region of the buffer.
|
||||
///
|
||||
/// The number of initialized bytes is not changed.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the filled region of the buffer would become larger than the initialized region.
|
||||
#[inline]
|
||||
pub fn add_filled(&mut self, n: usize) -> &mut Self {
|
||||
self.set_filled(self.filled + n)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn set_filled(&mut self, n: usize) -> &mut Self {
|
||||
assert!(n <= self.initialized);
|
||||
|
||||
self.filled = n;
|
||||
self.filled = 0;
|
||||
self
|
||||
}
|
||||
|
||||
/// Asserts that the first `n` unfilled bytes of the buffer are initialized.
|
||||
/// Asserts that the first `n` bytes of the buffer are initialized.
|
||||
///
|
||||
/// `ReadBuf` 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
|
||||
///
|
||||
/// The caller must ensure that the first `n` unfilled 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.init = cmp::max(self.init, n);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A writeable view of the unfilled portion of a [`BorrowedBuf`](BorrowedBuf).
|
||||
///
|
||||
/// 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`](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
|
||||
/// `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 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<'a> {
|
||||
/// The underlying buffer.
|
||||
// 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<'a> BorrowedCursor<'a> {
|
||||
/// Reborrow this cursor by cloning it with a smaller lifetime.
|
||||
///
|
||||
/// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is
|
||||
/// not accessible while the new cursor exists.
|
||||
#[inline]
|
||||
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.
|
||||
#[inline]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.buf.capacity() - self.buf.filled
|
||||
}
|
||||
|
||||
/// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`.
|
||||
///
|
||||
/// 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
|
||||
}
|
||||
|
||||
/// 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
|
||||
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
|
||||
unsafe {
|
||||
MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init])
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the uninitialized part of the cursor.
|
||||
///
|
||||
/// It is safe to uninitialize any of these bytes.
|
||||
#[inline]
|
||||
pub fn uninit_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
&mut self.buf.buf[self.buf.init..]
|
||||
}
|
||||
|
||||
/// 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<u8>] {
|
||||
&mut self.buf.buf[self.buf.filled..]
|
||||
}
|
||||
|
||||
/// 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` bytes of the cursor have been properly
|
||||
/// initialised.
|
||||
#[inline]
|
||||
pub unsafe fn advance(&mut self, n: usize) -> &mut Self {
|
||||
self.buf.filled += n;
|
||||
self.buf.init = cmp::max(self.buf.init, self.buf.filled);
|
||||
self
|
||||
}
|
||||
|
||||
/// Appends data to the buffer, advancing the written position and possibly also the initialized position.
|
||||
/// Initializes all bytes in the cursor.
|
||||
#[inline]
|
||||
pub fn ensure_init(&mut self) -> &mut Self {
|
||||
for byte in self.uninit_mut() {
|
||||
byte.write(0);
|
||||
}
|
||||
self.buf.init = self.buf.capacity();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Asserts that the first `n` unfilled bytes of the cursor are initialized.
|
||||
///
|
||||
/// `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
|
||||
///
|
||||
/// 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.init = cmp::max(self.buf.init, self.buf.filled + n);
|
||||
self
|
||||
}
|
||||
|
||||
/// Appends data to the cursor, advancing 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.set_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.buf.filled += buf.len();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for BorrowedCursor<'a> {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||
self.append(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,181 +1,175 @@
|
|||
use super::ReadBuf;
|
||||
use super::BorrowedBuf;
|
||||
use crate::mem::MaybeUninit;
|
||||
|
||||
/// Test that ReadBuf has the correct numbers when created with new
|
||||
/// Test that BorrowedBuf 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: BorrowedBuf<'_> = 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 BorrowedBuf 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: BorrowedBuf<'_> = 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: BorrowedBuf<'_> = buf.into();
|
||||
|
||||
rbuf.initialize_unfilled();
|
||||
rbuf.unfilled().ensure_init();
|
||||
|
||||
assert_eq!(rbuf.initialized_len(), 16);
|
||||
assert_eq!(rbuf.init_len(), 16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initialize_unfilled_to() {
|
||||
let mut buf = [MaybeUninit::uninit(); 16];
|
||||
let mut rbuf = ReadBuf::uninit(&mut buf);
|
||||
fn addvance_filled() {
|
||||
let buf: &mut [_] = &mut [0; 16];
|
||||
let mut rbuf: BorrowedBuf<'_> = buf.into();
|
||||
|
||||
rbuf.initialize_unfilled_to(8);
|
||||
unsafe {
|
||||
rbuf.unfilled().advance(1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[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);
|
||||
|
||||
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: BorrowedBuf<'_> = 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: BorrowedBuf<'_> = buf.into();
|
||||
|
||||
unsafe {
|
||||
rbuf.assume_init(8);
|
||||
rbuf.set_init(8);
|
||||
}
|
||||
|
||||
assert_eq!(rbuf.initialized_len(), 8);
|
||||
|
||||
rbuf.add_filled(4);
|
||||
assert_eq!(rbuf.init_len(), 8);
|
||||
|
||||
unsafe {
|
||||
rbuf.assume_init(2);
|
||||
rbuf.unfilled().advance(4);
|
||||
}
|
||||
|
||||
assert_eq!(rbuf.initialized_len(), 8);
|
||||
|
||||
unsafe {
|
||||
rbuf.assume_init(8);
|
||||
rbuf.set_init(2);
|
||||
}
|
||||
|
||||
assert_eq!(rbuf.initialized_len(), 12);
|
||||
assert_eq!(rbuf.init_len(), 8);
|
||||
|
||||
unsafe {
|
||||
rbuf.set_init(8);
|
||||
}
|
||||
|
||||
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: BorrowedBuf<'_> = 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);
|
||||
fn reborrow_written() {
|
||||
let buf: &mut [_] = &mut [MaybeUninit::new(0); 32];
|
||||
let mut buf: BorrowedBuf<'_> = buf.into();
|
||||
|
||||
rbuf.add_filled(8);
|
||||
let mut cursor = buf.unfilled();
|
||||
cursor.append(&[1; 16]);
|
||||
|
||||
let filled = rbuf.filled().to_vec();
|
||||
let mut cursor2 = cursor.reborrow();
|
||||
cursor2.append(&[2; 16]);
|
||||
|
||||
assert_eq!(&*filled, &*rbuf.filled_mut());
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{repeat, Cursor, ReadBuf, 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};
|
||||
|
@ -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: BorrowedBuf<'_> = 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]
|
||||
|
@ -615,10 +615,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: BorrowedBuf<'_> = buf.into();
|
||||
|
||||
[255; 128].take(64).read_buf(&mut rbuf).unwrap();
|
||||
[255; 128].take(64).read_buf(buf.unfilled()).unwrap();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ mod tests;
|
|||
|
||||
use crate::fmt;
|
||||
use crate::io::{
|
||||
self, BufRead, IoSlice, IoSliceMut, Read, ReadBuf, 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, _buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||
fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> 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: BorrowedCursor<'_>) -> 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(())
|
||||
}
|
||||
|
||||
|
|
|
@ -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, BorrowedBuf, 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 buf: &mut [MaybeUninit<_>] = &mut [];
|
||||
let mut buf: BorrowedBuf<'_> = buf.into();
|
||||
e.read_buf(buf.unfilled()).unwrap();
|
||||
assert_eq!(buf.len(), 0);
|
||||
assert_eq!(buf.init_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 buf: &mut [_] = &mut [MaybeUninit::uninit()];
|
||||
let mut buf: BorrowedBuf<'_> = buf.into();
|
||||
e.read_buf(buf.unfilled()).unwrap();
|
||||
assert_eq!(buf.len(), 0);
|
||||
assert_eq!(buf.init_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 buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024];
|
||||
let mut buf: BorrowedBuf<'_> = buf.into();
|
||||
e.read_buf(buf.unfilled()).unwrap();
|
||||
assert_eq!(buf.len(), 0);
|
||||
assert_eq!(buf.init_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 [_] = &mut [MaybeUninit::uninit(); 1024];
|
||||
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);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -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<usize> {
|
||||
|
|
|
@ -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,
|
||||
|
@ -366,13 +366,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(),
|
||||
))
|
||||
|
@ -384,9 +384,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(())
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
mod tests;
|
||||
|
||||
use crate::cmp;
|
||||
use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf};
|
||||
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,20 +131,19 @@ impl FileDesc {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||
pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> 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(())
|
||||
}
|
||||
|
||||
|
|
|
@ -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, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::mem;
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
|
||||
use crate::path::{Path, PathBuf};
|
||||
|
@ -1037,8 +1037,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: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0.read_buf(cursor)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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<usize> {
|
||||
|
|
|
@ -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<usize> {
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue