read_buf
This commit is contained in:
parent
3802025f40
commit
98c6200b16
@ -13,7 +13,7 @@ mod tests;
|
|||||||
|
|
||||||
use crate::ffi::OsString;
|
use crate::ffi::OsString;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
use crate::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||||
use crate::path::{Path, PathBuf};
|
use crate::path::{Path, PathBuf};
|
||||||
use crate::sys::fs as fs_imp;
|
use crate::sys::fs as fs_imp;
|
||||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||||
@ -629,12 +629,6 @@ impl Read for File {
|
|||||||
self.inner.is_read_vectored()
|
self.inner.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
|
||||||
unsafe { Initializer::nop() }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserves space in the buffer based on the file size when available.
|
// Reserves space in the buffer based on the file size when available.
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
buf.reserve(buffer_capacity_required(self));
|
buf.reserve(buffer_capacity_required(self));
|
||||||
@ -687,12 +681,6 @@ impl Read for &File {
|
|||||||
self.inner.is_read_vectored()
|
self.inner.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
|
||||||
unsafe { Initializer::nop() }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserves space in the buffer based on the file size when available.
|
// Reserves space in the buffer based on the file size when available.
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
buf.reserve(buffer_capacity_required(self));
|
buf.reserve(buffer_capacity_required(self));
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::cmp;
|
use crate::cmp;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{
|
use crate::io::{
|
||||||
self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE,
|
self, BufRead, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE,
|
||||||
};
|
};
|
||||||
|
use crate::mem::MaybeUninit;
|
||||||
|
|
||||||
/// The `BufReader<R>` struct adds buffering to any reader.
|
/// The `BufReader<R>` struct adds buffering to any reader.
|
||||||
///
|
///
|
||||||
@ -47,9 +48,10 @@ use crate::io::{
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct BufReader<R> {
|
pub struct BufReader<R> {
|
||||||
inner: R,
|
inner: R,
|
||||||
buf: Box<[u8]>,
|
buf: Box<[MaybeUninit<u8>]>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
cap: usize,
|
cap: usize,
|
||||||
|
init: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read> BufReader<R> {
|
impl<R: Read> BufReader<R> {
|
||||||
@ -91,11 +93,8 @@ impl<R: Read> BufReader<R> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
|
pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
|
||||||
unsafe {
|
let buf = Box::new_uninit_slice(capacity);
|
||||||
let mut buf = Box::new_uninit_slice(capacity).assume_init();
|
BufReader { inner, buf, pos: 0, cap: 0, init: 0 }
|
||||||
inner.initializer().initialize(&mut buf);
|
|
||||||
BufReader { inner, buf, pos: 0, cap: 0 }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +170,7 @@ impl<R> BufReader<R> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "bufreader_buffer", since = "1.37.0")]
|
#[stable(feature = "bufreader_buffer", since = "1.37.0")]
|
||||||
pub fn buffer(&self) -> &[u8] {
|
pub fn buffer(&self) -> &[u8] {
|
||||||
&self.buf[self.pos..self.cap]
|
unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[self.pos..self.cap]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of bytes the internal buffer can hold at once.
|
/// Returns the number of bytes the internal buffer can hold at once.
|
||||||
@ -271,6 +270,25 @@ impl<R: Read> Read for BufReader<R> {
|
|||||||
Ok(nread)
|
Ok(nread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> 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.pos == self.cap && buf.remaining() >= self.buf.len() {
|
||||||
|
self.discard_buffer();
|
||||||
|
return self.inner.read_buf(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
let prev = buf.filled_len();
|
||||||
|
|
||||||
|
let mut rem = self.fill_buf()?;
|
||||||
|
rem.read_buf(buf)?;
|
||||||
|
|
||||||
|
self.consume(buf.filled_len() - prev); //slice impl of read_buf known to never unfill buf
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Small read_exacts from a BufReader are extremely common when used with a deserializer.
|
// Small read_exacts from a BufReader are extremely common when used with a deserializer.
|
||||||
// The default implementation calls read in a loop, which results in surprisingly poor code
|
// The default implementation calls read in a loop, which results in surprisingly poor code
|
||||||
// generation for the common path where the buffer has enough bytes to fill the passed-in
|
// generation for the common path where the buffer has enough bytes to fill the passed-in
|
||||||
@ -303,16 +321,11 @@ impl<R: Read> Read for BufReader<R> {
|
|||||||
self.inner.is_read_vectored()
|
self.inner.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can't skip unconditionally because of the large buffer case in read.
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
self.inner.initializer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// The inner reader might have an optimized `read_to_end`. Drain our buffer and then
|
// The inner reader might have an optimized `read_to_end`. Drain our buffer and then
|
||||||
// delegate to the inner implementation.
|
// delegate to the inner implementation.
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
let nread = self.cap - self.pos;
|
let nread = self.cap - self.pos;
|
||||||
buf.extend_from_slice(&self.buf[self.pos..self.cap]);
|
buf.extend_from_slice(&self.buffer());
|
||||||
self.discard_buffer();
|
self.discard_buffer();
|
||||||
Ok(nread + self.inner.read_to_end(buf)?)
|
Ok(nread + self.inner.read_to_end(buf)?)
|
||||||
}
|
}
|
||||||
@ -363,10 +376,24 @@ impl<R: Read> BufRead for BufReader<R> {
|
|||||||
// to tell the compiler that the pos..cap slice is always valid.
|
// to tell the compiler that the pos..cap slice is always valid.
|
||||||
if self.pos >= self.cap {
|
if self.pos >= self.cap {
|
||||||
debug_assert!(self.pos == self.cap);
|
debug_assert!(self.pos == self.cap);
|
||||||
self.cap = self.inner.read(&mut self.buf)?;
|
|
||||||
|
let mut readbuf = ReadBuf::uninit(&mut self.buf);
|
||||||
|
|
||||||
|
// SAFETY: `self.init` is either 0 set to `readbuf.initialized_len()`
|
||||||
|
// from the last time this function was called
|
||||||
|
unsafe {
|
||||||
|
readbuf.assume_init(self.init);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inner.read_buf(&mut readbuf)?;
|
||||||
|
|
||||||
|
self.cap = readbuf.filled_len();
|
||||||
|
self.init = readbuf.initialized_len();
|
||||||
|
|
||||||
self.pos = 0;
|
self.pos = 0;
|
||||||
}
|
}
|
||||||
Ok(&self.buf[self.pos..self.cap])
|
// SAFETY: self.cap is always <= self.init, so self.buf[self.pos..self.cap] is always init
|
||||||
|
unsafe { Ok(MaybeUninit::slice_assume_init_ref(&self.buf[self.pos..self.cap])) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consume(&mut self, amt: usize) {
|
fn consume(&mut self, amt: usize) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::io::prelude::*;
|
use crate::io::prelude::*;
|
||||||
use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom};
|
use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, ReadBuf, SeekFrom};
|
||||||
|
use crate::mem::MaybeUninit;
|
||||||
use crate::panic;
|
use crate::panic;
|
||||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use crate::thread;
|
use crate::thread;
|
||||||
@ -55,6 +56,55 @@ fn test_buffered_reader() {
|
|||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
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);
|
||||||
|
|
||||||
|
reader.read_buf(&mut buf).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);
|
||||||
|
|
||||||
|
reader.read_buf(&mut buf).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(buf.filled(), [0, 1]);
|
||||||
|
assert_eq!(reader.buffer(), []);
|
||||||
|
|
||||||
|
let mut buf = [MaybeUninit::uninit(); 1];
|
||||||
|
let mut buf = ReadBuf::uninit(&mut buf);
|
||||||
|
|
||||||
|
reader.read_buf(&mut buf).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(buf.filled(), [2]);
|
||||||
|
assert_eq!(reader.buffer(), [3]);
|
||||||
|
|
||||||
|
let mut buf = [MaybeUninit::uninit(); 3];
|
||||||
|
let mut buf = ReadBuf::uninit(&mut buf);
|
||||||
|
|
||||||
|
reader.read_buf(&mut buf).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(buf.filled(), [3]);
|
||||||
|
assert_eq!(reader.buffer(), []);
|
||||||
|
|
||||||
|
reader.read_buf(&mut buf).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(buf.filled(), [3, 4]);
|
||||||
|
assert_eq!(reader.buffer(), []);
|
||||||
|
|
||||||
|
buf.clear();
|
||||||
|
|
||||||
|
reader.read_buf(&mut buf).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(buf.filled_len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_buffered_reader_seek() {
|
fn test_buffered_reader_seek() {
|
||||||
let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
|
let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use super::{BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE};
|
use super::{BufWriter, ErrorKind, Read, ReadBuf, Result, Write, DEFAULT_BUF_SIZE};
|
||||||
use crate::mem::MaybeUninit;
|
use crate::mem::MaybeUninit;
|
||||||
|
|
||||||
/// Copies the entire contents of a reader into a writer.
|
/// Copies the entire contents of a reader into a writer.
|
||||||
@ -82,33 +82,23 @@ impl<I: Write> BufferedCopySpec for BufWriter<I> {
|
|||||||
return stack_buffer_copy(reader, writer);
|
return stack_buffer_copy(reader, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: #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;
|
|
||||||
unsafe {
|
|
||||||
let spare_cap = writer.buffer_mut().spare_capacity_mut();
|
|
||||||
reader.initializer().initialize(MaybeUninit::slice_assume_init_mut(spare_cap));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let buf = writer.buffer_mut();
|
let buf = writer.buffer_mut();
|
||||||
let spare_cap = buf.spare_capacity_mut();
|
let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
|
||||||
|
|
||||||
if spare_cap.len() >= DEFAULT_BUF_SIZE {
|
if read_buf.capacity() >= DEFAULT_BUF_SIZE {
|
||||||
match reader.read(unsafe { MaybeUninit::slice_assume_init_mut(spare_cap) }) {
|
match reader.read_buf(&mut read_buf) {
|
||||||
Ok(0) => return Ok(len), // EOF reached
|
//Ok(0) => return Ok(len), // EOF reached
|
||||||
Ok(bytes_read) => {
|
Ok(()) => {
|
||||||
assert!(bytes_read <= spare_cap.len());
|
let bytes_read = read_buf.filled_len();
|
||||||
// SAFETY: The initializer contract guarantees that either it or `read`
|
|
||||||
// will have initialized these bytes. And we just checked that the number
|
if bytes_read == 0 {
|
||||||
// of bytes is within the buffer capacity.
|
return Ok(len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: ReadBuf guarantees all of its filled bytes are init
|
||||||
unsafe { buf.set_len(buf.len() + bytes_read) };
|
unsafe { buf.set_len(buf.len() + bytes_read) };
|
||||||
len += bytes_read as u64;
|
len += bytes_read as u64;
|
||||||
// Read again if the buffer still has enough capacity, as BufWriter itself would do
|
// Read again if the buffer still has enough capacity, as BufWriter itself would do
|
||||||
@ -129,28 +119,26 @@ fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
|
|||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
writer: &mut W,
|
writer: &mut W,
|
||||||
) -> Result<u64> {
|
) -> Result<u64> {
|
||||||
let mut buf = MaybeUninit::<[u8; DEFAULT_BUF_SIZE]>::uninit();
|
let mut buf = [MaybeUninit::uninit(); DEFAULT_BUF_SIZE];
|
||||||
// FIXME: #42788
|
let mut buf = ReadBuf::uninit(&mut buf);
|
||||||
//
|
|
||||||
// - This creates a (mut) reference to a slice of
|
let mut len = 0;
|
||||||
// _uninitialized_ integers, which is **undefined behavior**
|
|
||||||
//
|
|
||||||
// - Only the standard library gets to soundly "ignore" this,
|
|
||||||
// based on its privileged knowledge of unstable rustc
|
|
||||||
// internals;
|
|
||||||
unsafe {
|
|
||||||
reader.initializer().initialize(buf.assume_init_mut());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut written = 0;
|
|
||||||
loop {
|
loop {
|
||||||
let len = match reader.read(unsafe { buf.assume_init_mut() }) {
|
match reader.read_buf(&mut buf) {
|
||||||
Ok(0) => return Ok(written),
|
Ok(()) => {}
|
||||||
Ok(len) => len,
|
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
|
||||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
|
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
writer.write_all(unsafe { &buf.assume_init_ref()[..len] })?;
|
|
||||||
written += len as u64;
|
if buf.filled().is_empty() {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
len += buf.filled().len() as u64;
|
||||||
|
writer.write_all(buf.filled())?;
|
||||||
|
buf.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(len)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ mod tests;
|
|||||||
use crate::io::prelude::*;
|
use crate::io::prelude::*;
|
||||||
|
|
||||||
use crate::cmp;
|
use crate::cmp;
|
||||||
use crate::io::{self, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, SeekFrom};
|
use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
|
||||||
|
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
|
||||||
@ -324,6 +324,16 @@ where
|
|||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||||
|
let prev_filled = buf.filled_len();
|
||||||
|
|
||||||
|
Read::read_buf(&mut self.fill_buf()?, buf)?;
|
||||||
|
|
||||||
|
self.pos += (buf.filled_len() - prev_filled) as u64;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
let mut nread = 0;
|
let mut nread = 0;
|
||||||
for buf in bufs {
|
for buf in bufs {
|
||||||
@ -346,11 +356,6 @@ where
|
|||||||
self.pos += n as u64;
|
self.pos += n as u64;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -5,7 +5,7 @@ use crate::alloc::Allocator;
|
|||||||
use crate::cmp;
|
use crate::cmp;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{
|
use crate::io::{
|
||||||
self, BufRead, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write,
|
self, BufRead, Error, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write,
|
||||||
};
|
};
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
|
||||||
@ -19,6 +19,11 @@ impl<R: Read + ?Sized> Read for &mut R {
|
|||||||
(**self).read(buf)
|
(**self).read(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||||
|
(**self).read_buf(buf)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
(**self).read_vectored(bufs)
|
(**self).read_vectored(bufs)
|
||||||
@ -29,11 +34,6 @@ impl<R: Read + ?Sized> Read for &mut R {
|
|||||||
(**self).is_read_vectored()
|
(**self).is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
(**self).initializer()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
(**self).read_to_end(buf)
|
(**self).read_to_end(buf)
|
||||||
@ -123,6 +123,11 @@ impl<R: Read + ?Sized> Read for Box<R> {
|
|||||||
(**self).read(buf)
|
(**self).read(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||||
|
(**self).read_buf(buf)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
(**self).read_vectored(bufs)
|
(**self).read_vectored(bufs)
|
||||||
@ -133,11 +138,6 @@ impl<R: Read + ?Sized> Read for Box<R> {
|
|||||||
(**self).is_read_vectored()
|
(**self).is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
(**self).initializer()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
(**self).read_to_end(buf)
|
(**self).read_to_end(buf)
|
||||||
@ -247,6 +247,17 @@ impl Read for &[u8] {
|
|||||||
Ok(amt)
|
Ok(amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||||
|
let amt = cmp::min(buf.remaining(), self.len());
|
||||||
|
let (a, b) = self.split_at(amt);
|
||||||
|
|
||||||
|
buf.append(a);
|
||||||
|
|
||||||
|
*self = b;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
let mut nread = 0;
|
let mut nread = 0;
|
||||||
@ -265,11 +276,6 @@ impl Read for &[u8] {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||||
if buf.len() > self.len() {
|
if buf.len() > self.len() {
|
||||||
|
@ -256,7 +256,6 @@ use crate::convert::TryInto;
|
|||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::mem::replace;
|
use crate::mem::replace;
|
||||||
use crate::ops::{Deref, DerefMut};
|
use crate::ops::{Deref, DerefMut};
|
||||||
use crate::ptr;
|
|
||||||
use crate::slice;
|
use crate::slice;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
use crate::sys;
|
use crate::sys;
|
||||||
@ -288,12 +287,16 @@ pub use self::stdio::{_eprint, _print};
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::util::{empty, repeat, sink, Empty, Repeat, Sink};
|
pub use self::util::{empty, repeat, sink, Empty, Repeat, Sink};
|
||||||
|
|
||||||
|
#[unstable(feature = "read_buf", issue = "78485")]
|
||||||
|
pub use self::readbuf::ReadBuf;
|
||||||
|
|
||||||
mod buffered;
|
mod buffered;
|
||||||
pub(crate) mod copy;
|
pub(crate) mod copy;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod error;
|
mod error;
|
||||||
mod impls;
|
mod impls;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
mod readbuf;
|
||||||
mod stdio;
|
mod stdio;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
@ -359,68 +362,39 @@ where
|
|||||||
// Because we're extending the buffer with uninitialized data for trusted
|
// 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.
|
// 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> {
|
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 initial_len = buf.len(); // need to know so we can return how many bytes we read
|
||||||
let start_cap = buf.capacity();
|
|
||||||
let mut g = Guard { len: buf.len(), buf };
|
let mut initialized = 0; // Extra initalized bytes from previous loop iteration
|
||||||
loop {
|
loop {
|
||||||
// If we've read all the way up to the capacity, reserve more space.
|
if buf.len() == buf.capacity() {
|
||||||
if g.len == g.buf.capacity() {
|
buf.reserve(32); // buf is full, need more space
|
||||||
g.buf.reserve(32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize any excess capacity and adjust the length so we can write
|
let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
|
||||||
// to it.
|
|
||||||
if g.buf.len() < g.buf.capacity() {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// FIXME(danielhenrymantilla): #42788
|
// add back extra initalized bytes, we don't want to reinitalize initalized bytes
|
||||||
//
|
read_buf.assume_init(initialized);
|
||||||
// - 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 buf = &mut g.buf[g.len..];
|
match r.read_buf(&mut read_buf) {
|
||||||
match r.read(buf) {
|
Ok(()) => {}
|
||||||
Ok(0) => return Ok(g.len - start_len),
|
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
|
||||||
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,
|
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.len == g.buf.capacity() && g.buf.capacity() == start_cap {
|
if read_buf.filled_len() == 0 {
|
||||||
// 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];
|
|
||||||
|
|
||||||
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;
|
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>(
|
pub(crate) fn default_read_to_string<R: Read + ?Sized>(
|
||||||
@ -656,31 +630,6 @@ pub trait Read {
|
|||||||
false
|
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`.
|
/// 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
|
/// 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)
|
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
|
/// The returned adapter also implements `Read` and will simply borrow this
|
||||||
/// current reader.
|
/// 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.
|
/// A trait for objects which are byte-oriented sinks.
|
||||||
///
|
///
|
||||||
/// Implementors of the `Write` trait are sometimes called 'writers'.
|
/// 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)
|
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")]
|
#[stable(feature = "chain_bufread", since = "1.9.0")]
|
||||||
@ -2610,8 +2542,46 @@ impl<T: Read> Read for Take<T> {
|
|||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> {
|
||||||
self.inner.initializer()
|
// 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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
245
library/std/src/io/readbuf.rs
Normal file
245
library/std/src/io/readbuf.rs
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
#![unstable(feature = "read_buf", issue = "78485")]
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
use crate::cmp;
|
||||||
|
use crate::fmt::{self, Debug, Formatter};
|
||||||
|
use crate::mem::MaybeUninit;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet
|
||||||
|
/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a
|
||||||
|
/// subset of the initialized region.
|
||||||
|
///
|
||||||
|
/// In summary, the contents of the buffer can be visualized as:
|
||||||
|
/// ```not_rust
|
||||||
|
/// [ capacity ]
|
||||||
|
/// [ filled | unfilled ]
|
||||||
|
/// [ initialized | uninitialized ]
|
||||||
|
/// ```
|
||||||
|
pub struct ReadBuf<'a> {
|
||||||
|
buf: &'a mut [MaybeUninit<u8>],
|
||||||
|
filled: usize,
|
||||||
|
initialized: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ReadBuf<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("ReadBuf")
|
||||||
|
.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.
|
||||||
|
#[inline]
|
||||||
|
pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> {
|
||||||
|
let len = buf.len();
|
||||||
|
|
||||||
|
ReadBuf {
|
||||||
|
//SAFETY: inintialized data never becoming uninitialized is an invariant of ReadBuf
|
||||||
|
buf: unsafe { (buf 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 inintialized.
|
||||||
|
#[inline]
|
||||||
|
pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> {
|
||||||
|
ReadBuf { buf, filled: 0, initialized: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the total capacity of the buffer.
|
||||||
|
#[inline]
|
||||||
|
pub fn capacity(&self) -> usize {
|
||||||
|
self.buf.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the filled portion 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);
|
||||||
|
|
||||||
|
//dont try to do any zeroing if we already have enough initialized
|
||||||
|
if n > (self.initialized - self.filled) {
|
||||||
|
let uninit = (n + self.filled) - self.initialized;
|
||||||
|
|
||||||
|
let unfilled = &mut self.uninitialized_mut()[0..uninit];
|
||||||
|
|
||||||
|
for byte in unfilled.iter_mut() {
|
||||||
|
byte.write(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: we just inintialized uninit bytes, and the previous bytes were already init
|
||||||
|
unsafe {
|
||||||
|
self.assume_init(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
///
|
||||||
|
/// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
|
||||||
|
#[inline]
|
||||||
|
pub fn clear(&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) {
|
||||||
|
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) {
|
||||||
|
assert!(n <= self.initialized);
|
||||||
|
|
||||||
|
self.filled = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asserts that the first `n` unfilled bytes of the buffer are initialized.
|
||||||
|
///
|
||||||
|
/// `ReadBuf` 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) {
|
||||||
|
self.initialized = cmp::max(self.initialized, self.filled + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Appends data to the buffer, advancing the written position and possibly also the initialized position.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `self.remaining()` is less than `buf.len()`.
|
||||||
|
#[inline]
|
||||||
|
pub fn append(&mut self, buf: &[u8]) {
|
||||||
|
assert!(self.remaining() >= 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
169
library/std/src/io/readbuf/tests.rs
Normal file
169
library/std/src/io/readbuf/tests.rs
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
use super::ReadBuf;
|
||||||
|
use crate::mem::MaybeUninit;
|
||||||
|
|
||||||
|
/// Test that ReadBuf has the correct numbers when created with new
|
||||||
|
#[test]
|
||||||
|
fn new() {
|
||||||
|
let mut buf = [0; 16];
|
||||||
|
let rbuf = ReadBuf::new(&mut buf);
|
||||||
|
|
||||||
|
assert_eq!(rbuf.filled_len(), 0);
|
||||||
|
assert_eq!(rbuf.initialized_len(), 16);
|
||||||
|
assert_eq!(rbuf.capacity(), 16);
|
||||||
|
assert_eq!(rbuf.remaining(), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that ReadBuf has the correct numbers when created with uninit
|
||||||
|
#[test]
|
||||||
|
fn uninit() {
|
||||||
|
let mut buf = [MaybeUninit::uninit(); 16];
|
||||||
|
let rbuf = ReadBuf::uninit(&mut buf);
|
||||||
|
|
||||||
|
assert_eq!(rbuf.filled_len(), 0);
|
||||||
|
assert_eq!(rbuf.initialized_len(), 0);
|
||||||
|
assert_eq!(rbuf.capacity(), 16);
|
||||||
|
assert_eq!(rbuf.remaining(), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn initialize_unfilled() {
|
||||||
|
let mut buf = [MaybeUninit::uninit(); 16];
|
||||||
|
let mut rbuf = ReadBuf::uninit(&mut buf);
|
||||||
|
|
||||||
|
rbuf.initialize_unfilled();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn clear() {
|
||||||
|
let mut buf = [255; 16];
|
||||||
|
let mut rbuf = ReadBuf::new(&mut buf);
|
||||||
|
|
||||||
|
rbuf.set_filled(16);
|
||||||
|
|
||||||
|
assert_eq!(rbuf.filled_len(), 16);
|
||||||
|
assert_eq!(rbuf.remaining(), 0);
|
||||||
|
|
||||||
|
rbuf.clear();
|
||||||
|
|
||||||
|
assert_eq!(rbuf.filled_len(), 0);
|
||||||
|
assert_eq!(rbuf.remaining(), 16);
|
||||||
|
|
||||||
|
assert_eq!(rbuf.initialized(), [255; 16]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assume_init() {
|
||||||
|
let mut buf = [MaybeUninit::uninit(); 16];
|
||||||
|
let mut rbuf = ReadBuf::uninit(&mut buf);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
rbuf.assume_init(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(rbuf.initialized_len(), 8);
|
||||||
|
|
||||||
|
rbuf.add_filled(4);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
rbuf.assume_init(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(rbuf.initialized_len(), 8);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
rbuf.assume_init(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(rbuf.initialized_len(), 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn append() {
|
||||||
|
let mut buf = [MaybeUninit::new(255); 16];
|
||||||
|
let mut rbuf = ReadBuf::uninit(&mut buf);
|
||||||
|
|
||||||
|
rbuf.append(&[0; 8]);
|
||||||
|
|
||||||
|
assert_eq!(rbuf.initialized_len(), 8);
|
||||||
|
assert_eq!(rbuf.filled_len(), 8);
|
||||||
|
assert_eq!(rbuf.filled(), [0; 8]);
|
||||||
|
|
||||||
|
rbuf.clear();
|
||||||
|
|
||||||
|
rbuf.append(&[1; 16]);
|
||||||
|
|
||||||
|
assert_eq!(rbuf.initialized_len(), 16);
|
||||||
|
assert_eq!(rbuf.filled_len(), 16);
|
||||||
|
assert_eq!(rbuf.filled(), [1; 16]);
|
||||||
|
}
|
@ -7,7 +7,7 @@ use crate::io::prelude::*;
|
|||||||
|
|
||||||
use crate::cell::{Cell, RefCell};
|
use crate::cell::{Cell, RefCell};
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter, Lines, Split};
|
use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, Split};
|
||||||
use crate::lazy::SyncOnceCell;
|
use crate::lazy::SyncOnceCell;
|
||||||
use crate::pin::Pin;
|
use crate::pin::Pin;
|
||||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||||
@ -108,11 +108,6 @@ impl Read for StdinRaw {
|
|||||||
self.0.is_read_vectored()
|
self.0.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
handle_ebadf(self.0.read_to_end(buf), 0)
|
handle_ebadf(self.0.read_to_end(buf), 0)
|
||||||
}
|
}
|
||||||
@ -514,10 +509,6 @@ impl Read for Stdin {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
self.lock().is_read_vectored()
|
self.lock().is_read_vectored()
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
self.lock().read_to_end(buf)
|
self.lock().read_to_end(buf)
|
||||||
}
|
}
|
||||||
@ -552,11 +543,6 @@ impl Read for StdinLock<'_> {
|
|||||||
self.inner.is_read_vectored()
|
self.inner.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
self.inner.read_to_end(buf)
|
self.inner.read_to_end(buf)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use super::{repeat, Cursor, SeekFrom};
|
use super::{repeat, Cursor, ReadBuf, SeekFrom};
|
||||||
use crate::cmp::{self, min};
|
use crate::cmp::{self, min};
|
||||||
use crate::io::{self, IoSlice, IoSliceMut};
|
use crate::io::{self, IoSlice, IoSliceMut};
|
||||||
use crate::io::{BufRead, BufReader, Read, Seek, Write};
|
use crate::io::{BufRead, BufReader, Read, Seek, Write};
|
||||||
|
use crate::mem::MaybeUninit;
|
||||||
use crate::ops::Deref;
|
use crate::ops::Deref;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -156,6 +157,28 @@ fn read_exact_slice() {
|
|||||||
assert_eq!(c, b"9");
|
assert_eq!(c, b"9");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn read_buf_exact() {
|
||||||
|
let mut buf = [0; 4];
|
||||||
|
let mut buf = ReadBuf::new(&mut buf);
|
||||||
|
|
||||||
|
let mut c = Cursor::new(&b""[..]);
|
||||||
|
assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
|
||||||
|
|
||||||
|
let mut c = Cursor::new(&b"123456789"[..]);
|
||||||
|
c.read_buf_exact(&mut buf).unwrap();
|
||||||
|
assert_eq!(buf.filled(), b"1234");
|
||||||
|
|
||||||
|
buf.clear();
|
||||||
|
|
||||||
|
c.read_buf_exact(&mut buf).unwrap();
|
||||||
|
assert_eq!(buf.filled(), b"5678");
|
||||||
|
|
||||||
|
buf.clear();
|
||||||
|
|
||||||
|
assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn take_eof() {
|
fn take_eof() {
|
||||||
struct R;
|
struct R;
|
||||||
@ -559,3 +582,23 @@ fn test_write_all_vectored() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_take_read(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut buf = [0; 64];
|
||||||
|
|
||||||
|
[255; 128].take(64).read(&mut buf).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_take_read_buf(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut buf = [MaybeUninit::uninit(); 64];
|
||||||
|
|
||||||
|
let mut rbuf = ReadBuf::uninit(&mut buf);
|
||||||
|
|
||||||
|
[255; 128].take(64).read_buf(&mut rbuf).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ mod tests;
|
|||||||
|
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{
|
use crate::io::{
|
||||||
self, BufRead, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write,
|
self, BufRead, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, Write,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A reader which is always at EOF.
|
/// A reader which is always at EOF.
|
||||||
@ -47,8 +47,8 @@ impl Read for Empty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
fn read_buf(&mut self, _buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||||
Initializer::nop()
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -130,6 +130,22 @@ impl Read for Repeat {
|
|||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
|
||||||
|
for slot in unsafe { buf.unfilled_mut() } {
|
||||||
|
slot.write(self.byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
let remaining = buf.remaining();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
buf.assume_init(remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.add_filled(remaining);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
let mut nwritten = 0;
|
let mut nwritten = 0;
|
||||||
@ -143,11 +159,6 @@ impl Read for Repeat {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeHint for Repeat {
|
impl SizeHint for Repeat {
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use crate::cmp::{max, min};
|
use crate::cmp::{max, min};
|
||||||
use crate::io::prelude::*;
|
use crate::io::prelude::*;
|
||||||
use crate::io::{
|
use crate::io::{
|
||||||
copy, empty, repeat, sink, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, DEFAULT_BUF_SIZE,
|
copy, empty, repeat, sink, BufWriter, Empty, ReadBuf, Repeat, Result, SeekFrom, Sink,
|
||||||
|
DEFAULT_BUF_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::mem::MaybeUninit;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn copy_copies() {
|
fn copy_copies() {
|
||||||
let mut r = repeat(0).take(4);
|
let mut r = repeat(0).take(4);
|
||||||
@ -75,6 +78,30 @@ fn empty_reads() {
|
|||||||
assert_eq!(e.read(&mut [0]).unwrap(), 0);
|
assert_eq!(e.read(&mut [0]).unwrap(), 0);
|
||||||
assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
|
assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
|
||||||
assert_eq!(e.by_ref().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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -306,6 +306,7 @@
|
|||||||
#![feature(maybe_uninit_extra)]
|
#![feature(maybe_uninit_extra)]
|
||||||
#![feature(maybe_uninit_slice)]
|
#![feature(maybe_uninit_slice)]
|
||||||
#![feature(maybe_uninit_uninit_array)]
|
#![feature(maybe_uninit_uninit_array)]
|
||||||
|
#![feature(maybe_uninit_write_slice)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(mixed_integer_ops)]
|
#![feature(mixed_integer_ops)]
|
||||||
#![feature(must_not_suspend)]
|
#![feature(must_not_suspend)]
|
||||||
@ -321,6 +322,7 @@
|
|||||||
#![feature(panic_unwind)]
|
#![feature(panic_unwind)]
|
||||||
#![feature(pin_static_ref)]
|
#![feature(pin_static_ref)]
|
||||||
#![feature(prelude_import)]
|
#![feature(prelude_import)]
|
||||||
|
#![feature(ptr_as_uninit)]
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
|
@ -6,7 +6,7 @@ mod tests;
|
|||||||
use crate::io::prelude::*;
|
use crate::io::prelude::*;
|
||||||
|
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, Initializer, IoSlice, IoSliceMut};
|
use crate::io::{self, IoSlice, IoSliceMut};
|
||||||
use crate::net::{Shutdown, SocketAddr, ToSocketAddrs};
|
use crate::net::{Shutdown, SocketAddr, ToSocketAddrs};
|
||||||
use crate::sys_common::net as net_imp;
|
use crate::sys_common::net as net_imp;
|
||||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||||
@ -626,12 +626,6 @@ impl Read for TcpStream {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
self.0.is_read_vectored()
|
self.0.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
|
||||||
unsafe { Initializer::nop() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Write for TcpStream {
|
impl Write for TcpStream {
|
||||||
@ -666,12 +660,6 @@ impl Read for &TcpStream {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
self.0.is_read_vectored()
|
self.0.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
|
||||||
unsafe { Initializer::nop() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Write for &TcpStream {
|
impl Write for &TcpStream {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
|
use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
|
||||||
use super::{sockaddr_un, SocketAddr};
|
use super::{sockaddr_un, SocketAddr};
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, Initializer, IoSlice, IoSliceMut};
|
use crate::io::{self, IoSlice, IoSliceMut};
|
||||||
use crate::net::Shutdown;
|
use crate::net::Shutdown;
|
||||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
@ -624,11 +624,6 @@ impl io::Read for UnixStream {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
io::Read::is_read_vectored(&&*self)
|
io::Read::is_read_vectored(&&*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||||
@ -645,11 +640,6 @@ impl<'a> io::Read for &'a UnixStream {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
self.0.is_read_vectored()
|
self.0.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||||
|
@ -109,7 +109,7 @@ use crate::io::prelude::*;
|
|||||||
use crate::ffi::OsStr;
|
use crate::ffi::OsStr;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::fs;
|
use crate::fs;
|
||||||
use crate::io::{self, Initializer, IoSlice, IoSliceMut};
|
use crate::io::{self, IoSlice, IoSliceMut};
|
||||||
use crate::num::NonZeroI32;
|
use crate::num::NonZeroI32;
|
||||||
use crate::path::Path;
|
use crate::path::Path;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
@ -361,12 +361,6 @@ impl Read for ChildStdout {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
self.inner.is_read_vectored()
|
self.inner.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
|
||||||
unsafe { Initializer::nop() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsInner<AnonPipe> for ChildStdout {
|
impl AsInner<AnonPipe> for ChildStdout {
|
||||||
@ -428,12 +422,6 @@ impl Read for ChildStderr {
|
|||||||
fn is_read_vectored(&self) -> bool {
|
fn is_read_vectored(&self) -> bool {
|
||||||
self.inner.is_read_vectored()
|
self.inner.is_read_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
|
||||||
unsafe { Initializer::nop() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsInner<AnonPipe> for ChildStderr {
|
impl AsInner<AnonPipe> for ChildStderr {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::cmp;
|
use crate::cmp;
|
||||||
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
|
use crate::io::{self, IoSlice, IoSliceMut, Read};
|
||||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||||
use crate::sys::cvt;
|
use crate::sys::cvt;
|
||||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||||
@ -289,11 +289,6 @@ impl<'a> Read for &'a FileDesc {
|
|||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
(**self).read(buf)
|
(**self).read(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsInner<OwnedFd> for FileDesc {
|
impl AsInner<OwnedFd> for FileDesc {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user