1
Fork 0
This commit is contained in:
DrMeepster 2021-01-17 22:28:18 -08:00
parent 3802025f40
commit 98c6200b16
18 changed files with 772 additions and 294 deletions

View file

@ -256,7 +256,6 @@ use crate::convert::TryInto;
use crate::fmt;
use crate::mem::replace;
use crate::ops::{Deref, DerefMut};
use crate::ptr;
use crate::slice;
use crate::str;
use crate::sys;
@ -288,12 +287,16 @@ pub use self::stdio::{_eprint, _print};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::util::{empty, repeat, sink, Empty, Repeat, Sink};
#[unstable(feature = "read_buf", issue = "78485")]
pub use self::readbuf::ReadBuf;
mod buffered;
pub(crate) mod copy;
mod cursor;
mod error;
mod impls;
pub mod prelude;
mod readbuf;
mod stdio;
mod util;
@ -359,68 +362,39 @@ where
// Because we're extending the buffer with uninitialized data for trusted
// readers, we need to make sure to truncate that if any of this panics.
pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
let start_len = buf.len();
let start_cap = buf.capacity();
let mut g = Guard { len: buf.len(), buf };
let initial_len = buf.len(); // need to know so we can return how many bytes we read
let mut initialized = 0; // Extra initalized bytes from previous loop iteration
loop {
// If we've read all the way up to the capacity, reserve more space.
if g.len == g.buf.capacity() {
g.buf.reserve(32);
if buf.len() == buf.capacity() {
buf.reserve(32); // buf is full, need more space
}
// Initialize any excess capacity and adjust the length so we can write
// to it.
if g.buf.len() < g.buf.capacity() {
unsafe {
// FIXME(danielhenrymantilla): #42788
//
// - This creates a (mut) reference to a slice of
// _uninitialized_ integers, which is **undefined behavior**
//
// - Only the standard library gets to soundly "ignore" this,
// based on its privileged knowledge of unstable rustc
// internals;
let capacity = g.buf.capacity();
g.buf.set_len(capacity);
r.initializer().initialize(&mut g.buf[g.len..]);
}
let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
unsafe {
// add back extra initalized bytes, we don't want to reinitalize initalized bytes
read_buf.assume_init(initialized);
}
let buf = &mut g.buf[g.len..];
match r.read(buf) {
Ok(0) => return Ok(g.len - start_len),
Ok(n) => {
// We can't allow bogus values from read. If it is too large, the returned vec could have its length
// set past its capacity, or if it overflows the vec could be shortened which could create an invalid
// string if this is called via read_to_string.
assert!(n <= buf.len());
g.len += n;
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
match r.read_buf(&mut read_buf) {
Ok(()) => {}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
if g.len == g.buf.capacity() && g.buf.capacity() == start_cap {
// The buffer might be an exact fit. Let's read into a probe buffer
// and see if it returns `Ok(0)`. If so, we've avoided an
// unnecessary doubling of the capacity. But if not, append the
// probe buffer to the primary buffer and let its capacity grow.
let mut probe = [0u8; 32];
if read_buf.filled_len() == 0 {
break;
}
loop {
match r.read(&mut probe) {
Ok(0) => return Ok(g.len - start_len),
Ok(n) => {
g.buf.extend_from_slice(&probe[..n]);
g.len += n;
break;
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
}
// 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();
unsafe {
buf.set_len(new_len);
}
}
Ok(buf.len() - initial_len)
}
pub(crate) fn default_read_to_string<R: Read + ?Sized>(
@ -656,31 +630,6 @@ pub trait Read {
false
}
/// Determines if this `Read`er can work with buffers of uninitialized
/// memory.
///
/// The default implementation returns an initializer which will zero
/// buffers.
///
/// If a `Read`er guarantees that it can work properly with uninitialized
/// memory, it should call [`Initializer::nop()`]. See the documentation for
/// [`Initializer`] for details.
///
/// The behavior of this method must be independent of the state of the
/// `Read`er - the method only takes `&self` so that it can be used through
/// trait objects.
///
/// # Safety
///
/// This method is unsafe because a `Read`er could otherwise return a
/// non-zeroing `Initializer` from another `Read` type without an `unsafe`
/// block.
#[unstable(feature = "read_initializer", issue = "42788")]
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::zeroing()
}
/// Read all bytes until EOF in this source, placing them into `buf`.
///
/// All bytes read from this source will be appended to the specified buffer
@ -830,7 +779,42 @@ pub trait Read {
default_read_exact(self, buf)
}
/// Creates a "by reference" adapter for this instance of `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
/// 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<()> {
let n = self.read(buf.initialize_unfilled())?;
buf.add_filled(n);
Ok(())
}
/// Read the exact number of bytes required to fill `buf`.
///
/// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`ReadBuf`] 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) {
Ok(()) => {}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
if buf.filled().len() == prev_filled {
return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer"));
}
}
Ok(())
}
/// Creates a "by reference" adaptor for this instance of `Read`.
///
/// The returned adapter also implements `Read` and will simply borrow this
/// current reader.
@ -1300,53 +1284,6 @@ impl<'a> Deref for IoSlice<'a> {
}
}
/// A type used to conditionally initialize buffers passed to `Read` methods.
#[unstable(feature = "read_initializer", issue = "42788")]
#[derive(Debug)]
pub struct Initializer(bool);
impl Initializer {
/// Returns a new `Initializer` which will zero out buffers.
#[unstable(feature = "read_initializer", issue = "42788")]
#[must_use]
#[inline]
pub fn zeroing() -> Initializer {
Initializer(true)
}
/// Returns a new `Initializer` which will not zero out buffers.
///
/// # Safety
///
/// This may only be called by `Read`ers which guarantee that they will not
/// read from buffers passed to `Read` methods, and that the return value of
/// the method accurately reflects the number of bytes that have been
/// written to the head of the buffer.
#[unstable(feature = "read_initializer", issue = "42788")]
#[must_use]
#[inline]
pub unsafe fn nop() -> Initializer {
Initializer(false)
}
/// Indicates if a buffer should be initialized.
#[unstable(feature = "read_initializer", issue = "42788")]
#[must_use]
#[inline]
pub fn should_initialize(&self) -> bool {
self.0
}
/// Initializes a buffer if necessary.
#[unstable(feature = "read_initializer", issue = "42788")]
#[inline]
pub fn initialize(&self, buf: &mut [u8]) {
if self.should_initialize() {
unsafe { ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) }
}
}
}
/// A trait for objects which are byte-oriented sinks.
///
/// Implementors of the `Write` trait are sometimes called 'writers'.
@ -2403,11 +2340,6 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
}
self.second.read_vectored(bufs)
}
unsafe fn initializer(&self) -> Initializer {
let initializer = self.first.initializer();
if initializer.should_initialize() { initializer } else { self.second.initializer() }
}
}
#[stable(feature = "chain_bufread", since = "1.9.0")]
@ -2610,8 +2542,46 @@ impl<T: Read> Read for Take<T> {
Ok(n)
}
unsafe fn initializer(&self) -> Initializer {
self.inner.initializer()
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> 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 {
let extra_init = buf.initialized_len() - buf.filled_len();
let ibuf = unsafe { &mut buf.unfilled_mut()[..self.limit as usize] };
let mut sliced_buf = ReadBuf::uninit(ibuf);
unsafe {
sliced_buf.assume_init(extra_init);
}
self.inner.read_buf(&mut sliced_buf)?;
let new_init = sliced_buf.initialized_len();
let filled = sliced_buf.filled_len();
// sliced_buf / ibuf must drop here
unsafe {
buf.assume_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;
}
Ok(())
}
}