//! // read a line into buffer
//! reader.read_line(&mut buffer)?;
//!
-//! println!("{}", buffer);
+//! println!("{buffer}");
//! Ok(())
//! }
//! ```
//!
//! [`File`]: crate::fs::File
//! [`TcpStream`]: crate::net::TcpStream
-//! [`Vec<T>`]: Vec
//! [`io::stdout`]: stdout
//! [`io::Result`]: self::Result
//! [`?` operator]: ../../book/appendix-02-operators.html
mod tests;
use crate::cmp;
+use crate::convert::TryInto;
use crate::fmt;
-use crate::memchr;
+use crate::mem::replace;
use crate::ops::{Deref, DerefMut};
-use crate::ptr;
use crate::slice;
use crate::str;
use crate::sys;
+use crate::sys_common::memchr;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::buffered::IntoInnerError;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::buffered::{BufReader, BufWriter, LineWriter};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::cursor::Cursor;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::error::{Error, ErrorKind, Result};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
+pub use self::buffered::WriterPanicked;
+#[unstable(feature = "internal_output_capture", issue = "none")]
+#[doc(no_inline, hidden)]
+pub use self::stdio::set_output_capture;
#[unstable(feature = "print_internals", issue = "none")]
pub use self::stdio::{_eprint, _print};
-#[unstable(feature = "libstd_io_internals", issue = "42788")]
-#[doc(no_inline, hidden)]
-pub use self::stdio::{set_panic, set_print};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::util::{copy, empty, repeat, sink, Empty, Repeat, Sink};
+pub use self::{
+ buffered::{BufReader, BufWriter, IntoInnerError, LineWriter},
+ copy::copy,
+ cursor::Cursor,
+ error::{Error, ErrorKind, Result},
+ stdio::{stderr, stdin, stdout, Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock},
+ util::{empty, repeat, sink, Empty, Repeat, Sink},
+};
+
+#[unstable(feature = "read_buf", issue = "78485")]
+pub use self::readbuf::ReadBuf;
+pub(crate) use error::const_io_error;
mod buffered;
+pub(crate) mod copy;
mod cursor;
mod error;
mod impls;
pub mod prelude;
+mod readbuf;
mod stdio;
mod util;
const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
+pub(crate) use stdio::cleanup;
+
struct Guard<'a> {
buf: &'a mut Vec<u8>,
len: usize,
}
}
-// A few methods below (read_to_string, read_line) will append data into a
-// `String` buffer, but we need to be pretty careful when doing this. The
-// implementation will just call `.as_mut_vec()` and then delegate to a
-// byte-oriented reading method, but we must ensure that when returning we never
-// leave `buf` in a state such that it contains invalid UTF-8 in its bounds.
+// Several `read_to_string` and `read_line` methods in the standard library will
+// append data into a `String` buffer, but we need to be pretty careful when
+// doing this. The implementation will just call `.as_mut_vec()` and then
+// delegate to a byte-oriented reading method, but we must ensure that when
+// returning we never leave `buf` in a state such that it contains invalid UTF-8
+// in its bounds.
//
// To this end, we use an RAII guard (to protect against panics) which updates
// the length of the string when it is dropped. This guard initially truncates
// 2. We're passing a raw buffer to the function `f`, and it is expected that
// the function only *appends* bytes to the buffer. We'll get undefined
// behavior if existing bytes are overwritten to have non-UTF-8 data.
-fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
+pub(crate) unsafe fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
where
F: FnOnce(&mut Vec<u8>) -> Result<usize>,
{
- unsafe {
- let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
- let ret = f(g.buf);
- if str::from_utf8(&g.buf[g.len..]).is_err() {
- ret.and_then(|_| {
- Err(Error::new(ErrorKind::InvalidData, "stream did not contain valid UTF-8"))
- })
- } else {
- g.len = g.buf.len();
- ret
- }
+ let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
+ let ret = f(g.buf);
+ if str::from_utf8(&g.buf[g.len..]).is_err() {
+ ret.and_then(|_| {
+ Err(error::const_io_error!(
+ ErrorKind::InvalidData,
+ "stream did not contain valid UTF-8"
+ ))
+ })
+ } else {
+ g.len = g.buf.len();
+ ret
}
}
// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
// time is 4,500 times (!) slower than a default reservation size of 32 if the
// reader has a very small amount of data to return.
-//
-// 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.
-fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
- read_to_end_with_reservation(r, buf, |_| 32)
-}
-
-fn read_to_end_with_reservation<R, F>(
- r: &mut R,
- buf: &mut Vec<u8>,
- mut reservation_size: F,
-) -> Result<usize>
-where
- R: Read + ?Sized,
- F: FnMut(&R) -> 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 mut g = Guard { len: buf.len(), buf };
- let ret;
+ let start_cap = buf.capacity();
+
+ let mut initialized = 0; // Extra initialized bytes from previous loop iteration
loop {
- if g.len == g.buf.len() {
- 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;
- g.buf.reserve(reservation_size(r));
- let capacity = g.buf.capacity();
- g.buf.set_len(capacity);
- r.initializer().initialize(&mut g.buf[g.len..]);
- }
+ if buf.len() == buf.capacity() {
+ buf.reserve(32); // buf is full, need more space
}
- match r.read(&mut g.buf[g.len..]) {
- Ok(0) => {
- ret = Ok(g.len - start_len);
- break;
- }
- Ok(n) => g.len += n,
- Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
- Err(e) => {
- ret = Err(e);
- break;
+ let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
+
+ // SAFETY: These bytes were initialized but not filled in the previous loop
+ unsafe {
+ read_buf.assume_init(initialized);
+ }
+
+ match r.read_buf(&mut read_buf) {
+ Ok(()) => {}
+ Err(e) if e.kind() == ErrorKind::Interrupted => continue,
+ Err(e) => return Err(e),
+ }
+
+ if read_buf.filled_len() == 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();
+
+ // SAFETY: ReadBuf's invariants mean this much memory is init
+ unsafe {
+ buf.set_len(new_len);
+ }
+
+ if buf.len() == buf.capacity() && 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];
+
+ loop {
+ match r.read(&mut probe) {
+ Ok(0) => return Ok(buf.len() - start_len),
+ Ok(n) => {
+ buf.extend_from_slice(&probe[..n]);
+ break;
+ }
+ Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
+ Err(e) => return Err(e),
+ }
}
}
}
+}
- ret
+pub(crate) fn default_read_to_string<R: Read + ?Sized>(
+ r: &mut R,
+ buf: &mut String,
+) -> Result<usize> {
+ // Note that we do *not* call `r.read_to_end()` here. We are passing
+ // `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end`
+ // method to fill it up. An arbitrary implementation could overwrite the
+ // entire contents of the vector, not just append to it (which is what
+ // we are expecting).
+ //
+ // To prevent extraneously checking the UTF-8-ness of the entire buffer
+ // we pass it to our hardcoded `default_read_to_end` implementation which
+ // we know is guaranteed to only read data into the end of the buffer.
+ unsafe { append_to_string(buf, |b| default_read_to_end(r, b)) }
}
pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
write(buf)
}
+pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
+ while !buf.is_empty() {
+ match this.read(buf) {
+ Ok(0) => break,
+ Ok(n) => {
+ let tmp = buf;
+ buf = &mut tmp[n..];
+ }
+ Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+ Err(e) => return Err(e),
+ }
+ }
+ if !buf.is_empty() {
+ Err(error::const_io_error!(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
+ } else {
+ Ok(())
+ }
+}
+
+pub(crate) fn default_read_buf<F>(read: F, buf: &mut ReadBuf<'_>) -> Result<()>
+where
+ F: FnOnce(&mut [u8]) -> Result<usize>,
+{
+ let n = read(buf.initialize_unfilled())?;
+ buf.add_filled(n);
+ Ok(())
+}
+
/// The `Read` trait allows for reading bytes from a source.
///
/// Implementors of the `Read` trait are called 'readers'.
/// }
/// ```
///
-/// Read from [`&str`] because [`&[u8]`][slice] implements `Read`:
+/// Read from [`&str`] because [`&[u8]`][prim@slice] implements `Read`:
///
/// ```no_run
/// # use std::io;
/// [`&str`]: prim@str
/// [`std::io`]: self
/// [`File`]: crate::fs::File
-/// [slice]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(spotlight)]
+#[doc(notable_trait)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "IoRead")]
pub trait Read {
/// Pull some bytes from this source into the specified buffer, returning
/// how many bytes were read.
/// waiting for data, but if an object needs to block for a read and cannot,
/// it will typically signal this via an [`Err`] return value.
///
- /// If the return value of this method is [`Ok(n)`], then it must be
- /// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates
+ /// If the return value of this method is [`Ok(n)`], then implementations must
+ /// guarantee that `0 <= n <= buf.len()`. A nonzero `n` value indicates
/// that the buffer `buf` has been filled in with `n` bytes of data from this
/// source. If `n` is `0`, then it can indicate one of two scenarios:
///
/// 1. This reader has reached its "end of file" and will likely no longer
/// be able to produce bytes. Note that this does not mean that the
- /// reader will *always* no longer be able to produce bytes.
+ /// reader will *always* no longer be able to produce bytes. As an example,
+ /// on Linux, this method will call the `recv` syscall for a [`TcpStream`],
+ /// where returning zero indicates the connection was shut down correctly. While
+ /// for [`File`], it is possible to reach the end of file and get zero as result,
+ /// but if more data is appended to the file, future calls to `read` will return
+ /// more data.
/// 2. The buffer specified was 0 bytes in length.
///
/// It is not an error if the returned value `n` is smaller than the buffer size,
/// This may happen for example because fewer bytes are actually available right now
/// (e. g. being close to end-of-file) or because read() was interrupted by a signal.
///
+ /// As this trait is safe to implement, callers cannot rely on `n <= buf.len()` for safety.
+ /// Extra care needs to be taken when `unsafe` functions are used to access the read bytes.
+ /// Callers have to ensure that no unchecked out-of-bounds accesses are possible even if
+ /// `n > buf.len()`.
+ ///
/// No guarantees are provided about the contents of `buf` when this
/// function is called, implementations cannot rely on any property of the
/// contents of `buf` being true. It is recommended that *implementations*
/// only write data to `buf` instead of reading its contents.
///
- /// Correspondingly, however, *callers* of this method may not assume any guarantees
+ /// Correspondingly, however, *callers* of this method must not assume any guarantees
/// about how the implementation uses `buf`. The trait is safe to implement,
/// so it is possible that the code that's supposed to write to the buffer might also read
/// from it. It is your responsibility to make sure that `buf` is initialized
///
/// [`Ok(n)`]: Ok
/// [`File`]: crate::fs::File
+ /// [`TcpStream`]: crate::net::TcpStream
///
/// ```no_run
/// use std::io;
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
/// [`std::fs::read`]: crate::fs::read
#[stable(feature = "rust1", since = "1.0.0")]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
- read_to_end(self, buf)
+ default_read_to_end(self, buf)
}
/// Read all bytes until EOF in this source, appending them to `buf`.
/// [`std::fs::read_to_string`]: crate::fs::read_to_string
#[stable(feature = "rust1", since = "1.0.0")]
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
- // Note that we do *not* call `.read_to_end()` here. We are passing
- // `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end`
- // method to fill it up. An arbitrary implementation could overwrite the
- // entire contents of the vector, not just append to it (which is what
- // we are expecting).
- //
- // To prevent extraneously checking the UTF-8-ness of the entire buffer
- // we pass it to our hardcoded `read_to_end` implementation which we
- // know is guaranteed to only read data into the end of the buffer.
- append_to_string(buf, |b| read_to_end(self, b))
+ default_read_to_string(self, buf)
}
/// Read the exact number of bytes required to fill `buf`.
/// }
/// ```
#[stable(feature = "read_exact", since = "1.6.0")]
- fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
- while !buf.is_empty() {
- match self.read(buf) {
- Ok(0) => break,
- Ok(n) => {
- let tmp = buf;
- buf = &mut tmp[n..];
- }
- Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+ fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
+ default_read_exact(self, buf)
+ }
+
+ /// 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<()> {
+ default_read_buf(|b| self.read(b), buf)
+ }
+
+ /// 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"));
+ }
}
- if !buf.is_empty() {
- Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
- } else {
- Ok(())
- }
+
+ Ok(())
}
/// Creates a "by reference" adaptor for this instance of `Read`.
///
- /// The returned adaptor also implements `Read` and will simply borrow this
+ /// The returned adapter also implements `Read` and will simply borrow this
/// current reader.
///
/// # Examples
/// Transforms this `Read` instance to an [`Iterator`] over its bytes.
///
- /// The returned type implements [`Iterator`] where the `Item` is
- /// [`Result`]`<`[`u8`]`, `[`io::Error`]`>`.
+ /// The returned type implements [`Iterator`] where the [`Item`] is
+ /// <code>[Result]<[u8], [io::Error]></code>.
/// The yielded item is [`Ok`] if a byte was successfully read and [`Err`]
/// otherwise. EOF is mapped to returning [`None`] from this iterator.
///
///
/// [`File`]s implement `Read`:
///
- /// [`File`]: crate::fs::File
- /// [`Result`]: crate::result::Result
- /// [`io::Error`]: self::Error
+ /// [`Item`]: Iterator::Item
+ /// [`File`]: crate::fs::File "fs::File"
+ /// [Result]: crate::result::Result "Result"
+ /// [io::Error]: self::Error "io::Error"
///
/// ```no_run
/// use std::io;
Bytes { inner: self }
}
- /// Creates an adaptor which will chain this stream with another.
+ /// Creates an adapter which will chain this stream with another.
///
/// The returned `Read` instance will first read all bytes from this object
/// until EOF is encountered. Afterwards the output is equivalent to the
Chain { first: self, second: next, done_first: false }
}
- /// Creates an adaptor which will read at most `limit` bytes from it.
+ /// Creates an adapter which will read at most `limit` bytes from it.
///
/// This function returns a new instance of `Read` which will read at most
/// `limit` bytes, after which it will always return EOF ([`Ok(0)`]). Any
}
}
+/// Read all bytes from a [reader][Read] into a new [`String`].
+///
+/// This is a convenience function for [`Read::read_to_string`]. Using this
+/// function avoids having to create a variable first and provides more type
+/// safety since you can only get the buffer out if there were no errors. (If you
+/// use [`Read::read_to_string`] you have to remember to check whether the read
+/// succeeded because otherwise your buffer will be empty or only partially full.)
+///
+/// # Performance
+///
+/// The downside of this function's increased ease of use and type safety is
+/// that it gives you less control over performance. For example, you can't
+/// pre-allocate memory like you can using [`String::with_capacity`] and
+/// [`Read::read_to_string`]. Also, you can't re-use the buffer if an error
+/// occurs while reading.
+///
+/// In many cases, this function's performance will be adequate and the ease of use
+/// and type safety tradeoffs will be worth it. However, there are cases where you
+/// need more control over performance, and in those cases you should definitely use
+/// [`Read::read_to_string`] directly.
+///
+/// Note that in some special cases, such as when reading files, this function will
+/// pre-allocate memory based on the size of the input it is reading. In those
+/// cases, the performance should be as good as if you had used
+/// [`Read::read_to_string`] with a manually pre-allocated buffer.
+///
+/// # Errors
+///
+/// This function forces you to handle errors because the output (the `String`)
+/// is wrapped in a [`Result`]. See [`Read::read_to_string`] for the errors
+/// that can occur. If any error occurs, you will get an [`Err`], so you
+/// don't have to worry about your buffer being empty or partially full.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(io_read_to_string)]
+///
+/// # use std::io;
+/// fn main() -> io::Result<()> {
+/// let stdin = io::read_to_string(io::stdin())?;
+/// println!("Stdin was:");
+/// println!("{stdin}");
+/// Ok(())
+/// }
+/// ```
+#[unstable(feature = "io_read_to_string", issue = "80218")]
+pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
+ let mut buf = String::new();
+ reader.read_to_string(&mut buf)?;
+ Ok(buf)
+}
+
/// A buffer type used with `Read::read_vectored`.
///
/// It is semantically a wrapper around an `&mut [u8]`, but is guaranteed to be
/// Advance the internal cursor of the slice.
///
+ /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of
+ /// multiple buffers.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(io_slice_advance)]
+ ///
+ /// use std::io::IoSliceMut;
+ /// use std::ops::Deref;
+ ///
+ /// let mut data = [1; 8];
+ /// let mut buf = IoSliceMut::new(&mut data);
+ ///
+ /// // Mark 3 bytes as read.
+ /// buf.advance(3);
+ /// assert_eq!(buf.deref(), [1; 5].as_ref());
+ /// ```
+ #[unstable(feature = "io_slice_advance", issue = "62726")]
+ #[inline]
+ pub fn advance(&mut self, n: usize) {
+ self.0.advance(n)
+ }
+
+ /// Advance the internal cursor of the slices.
+ ///
/// # Notes
///
/// Elements in the slice may be modified if the cursor is not advanced to
/// ][..];
///
/// // Mark 10 bytes as read.
- /// bufs = IoSliceMut::advance(bufs, 10);
+ /// IoSliceMut::advance_slices(&mut bufs, 10);
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
/// ```
#[unstable(feature = "io_slice_advance", issue = "62726")]
#[inline]
- pub fn advance<'b>(bufs: &'b mut [IoSliceMut<'a>], n: usize) -> &'b mut [IoSliceMut<'a>] {
+ pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
// Number of buffers to remove.
let mut remove = 0;
// Total length of all the to be removed buffers.
}
}
- let bufs = &mut bufs[remove..];
+ *bufs = &mut replace(bufs, &mut [])[remove..];
if !bufs.is_empty() {
- bufs[0].0.advance(n - accumulated_len)
+ bufs[0].advance(n - accumulated_len)
}
- bufs
}
}
/// A buffer type used with `Write::write_vectored`.
///
-/// It is semantically a wrapper around an `&[u8]`, but is guaranteed to be
+/// It is semantically a wrapper around a `&[u8]`, but is guaranteed to be
/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
/// Windows.
#[stable(feature = "iovec", since = "1.36.0")]
///
/// Panics on Windows if the slice is larger than 4GB.
#[stable(feature = "iovec", since = "1.36.0")]
+ #[must_use]
#[inline]
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
IoSlice(sys::io::IoSlice::new(buf))
/// Advance the internal cursor of the slice.
///
+ /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple
+ /// buffers.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(io_slice_advance)]
+ ///
+ /// use std::io::IoSlice;
+ /// use std::ops::Deref;
+ ///
+ /// let mut data = [1; 8];
+ /// let mut buf = IoSlice::new(&mut data);
+ ///
+ /// // Mark 3 bytes as read.
+ /// buf.advance(3);
+ /// assert_eq!(buf.deref(), [1; 5].as_ref());
+ /// ```
+ #[unstable(feature = "io_slice_advance", issue = "62726")]
+ #[inline]
+ pub fn advance(&mut self, n: usize) {
+ self.0.advance(n)
+ }
+
+ /// Advance the internal cursor of the slices.
+ ///
/// # Notes
///
/// Elements in the slice may be modified if the cursor is not advanced to
/// ][..];
///
/// // Mark 10 bytes as written.
- /// bufs = IoSlice::advance(bufs, 10);
+ /// IoSlice::advance_slices(&mut bufs, 10);
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
#[unstable(feature = "io_slice_advance", issue = "62726")]
#[inline]
- pub fn advance<'b>(bufs: &'b mut [IoSlice<'a>], n: usize) -> &'b mut [IoSlice<'a>] {
+ pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
// Number of buffers to remove.
let mut remove = 0;
// Total length of all the to be removed buffers.
}
}
- let bufs = &mut bufs[remove..];
+ *bufs = &mut replace(bufs, &mut [])[remove..];
if !bufs.is_empty() {
- bufs[0].0.advance(n - accumulated_len)
+ bufs[0].advance(n - accumulated_len)
}
- bufs
}
}
}
}
-/// 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")]
- #[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")]
- #[inline]
- pub unsafe fn nop() -> Initializer {
- Initializer(false)
- }
-
- /// Indicates if a buffer should be initialized.
- #[unstable(feature = "read_initializer", issue = "42788")]
- #[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'.
/// * The [`write`] method will attempt to write some data into the object,
/// returning how many bytes were successfully written.
///
-/// * The [`flush`] method is useful for adaptors and explicit buffers
+/// * The [`flush`] method is useful for adapters and explicit buffers
/// themselves for ensuring that all buffered data has been pushed out to the
/// 'true sink'.
///
///
/// [`write_all`]: Write::write_all
#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(spotlight)]
+#[doc(notable_trait)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "IoWrite")]
pub trait Write {
/// Write a buffer into this writer, returning how many bytes were written.
///
/// This function will attempt to write the entire contents of `buf`, but
- /// the entire write may not succeed, or the write may also generate an
+ /// the entire write might not succeed, or the write may also generate an
/// error. A call to `write` represents *at most one* attempt to write to
/// any wrapped object.
///
/// The default implementation calls [`write`] with either the first nonempty
/// buffer provided, or an empty one if none exists.
///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::IoSlice;
+ /// use std::io::prelude::*;
+ /// use std::fs::File;
+ ///
+ /// fn main() -> std::io::Result<()> {
+ /// let mut data1 = [1; 8];
+ /// let mut data2 = [15; 8];
+ /// let io_slice1 = IoSlice::new(&mut data1);
+ /// let io_slice2 = IoSlice::new(&mut data2);
+ ///
+ /// let mut buffer = File::create("foo.txt")?;
+ ///
+ /// // Writes some prefix of the byte string, not necessarily all of it.
+ /// buffer.write_vectored(&[io_slice1, io_slice2])?;
+ /// Ok(())
+ /// }
+ /// ```
+ ///
/// [`write`]: Write::write
#[stable(feature = "iovec", since = "1.36.0")]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
default_write_vectored(|b| self.write(b), bufs)
}
- /// Determines if this `Write`er has an efficient [`write_vectored`]
+ /// Determines if this `Write`r has an efficient [`write_vectored`]
/// implementation.
///
- /// If a `Write`er does not override the default [`write_vectored`]
+ /// If a `Write`r does not override the default [`write_vectored`]
/// implementation, code using it may want to avoid the method all together
/// and coalesce writes into a single buffer for higher performance.
///
while !buf.is_empty() {
match self.write(buf) {
Ok(0) => {
- return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"));
+ return Err(error::const_io_error!(
+ ErrorKind::WriteZero,
+ "failed to write whole buffer",
+ ));
}
Ok(n) => buf = &buf[n..],
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> {
// Guarantee that bufs is empty if it contains no data,
// to avoid calling write_vectored if there is no data to be written.
- bufs = IoSlice::advance(bufs, 0);
+ IoSlice::advance_slices(&mut bufs, 0);
while !bufs.is_empty() {
match self.write_vectored(bufs) {
Ok(0) => {
- return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"));
+ return Err(error::const_io_error!(
+ ErrorKind::WriteZero,
+ "failed to write whole buffer",
+ ));
}
- Ok(n) => bufs = IoSlice::advance(bufs, n),
+ Ok(n) => IoSlice::advance_slices(&mut bufs, n),
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
/// encountered.
///
/// This method is primarily used to interface with the
- /// [`format_args!()`] macro, but it is rare that this should
+ /// [`format_args!()`] macro, and it is rare that this should
/// explicitly be called. The [`write!()`] macro should be favored to
/// invoke this method instead.
///
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
// Create a shim which translates a Write to a fmt::Write and saves
// off I/O errors. instead of discarding them
- struct Adaptor<'a, T: ?Sized + 'a> {
+ struct Adapter<'a, T: ?Sized + 'a> {
inner: &'a mut T,
error: Result<()>,
}
- impl<T: Write + ?Sized> fmt::Write for Adaptor<'_, T> {
+ impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write_all(s.as_bytes()) {
Ok(()) => Ok(()),
}
}
- let mut output = Adaptor { inner: self, error: Ok(()) };
+ let mut output = Adapter { inner: self, error: Ok(()) };
match fmt::write(&mut output, fmt) {
Ok(()) => Ok(()),
Err(..) => {
if output.error.is_err() {
output.error
} else {
- Err(Error::new(ErrorKind::Other, "formatter error"))
+ Err(error::const_io_error!(ErrorKind::Uncategorized, "formatter error"))
}
}
}
}
- /// Creates a "by reference" adaptor for this instance of `Write`.
+ /// Creates a "by reference" adapter for this instance of `Write`.
///
- /// The returned adaptor also implements `Write` and will simply borrow this
+ /// The returned adapter also implements `Write` and will simply borrow this
/// current writer.
///
/// # Examples
///
/// # Errors
///
+ /// Seeking can fail, for example because it might involve flushing a buffer.
+ ///
/// Seeking to a negative offset is considered an error.
#[stable(feature = "rust1", since = "1.0.0")]
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
+ /// Rewind to the beginning of a stream.
+ ///
+ /// This is a convenience method, equivalent to `seek(SeekFrom::Start(0))`.
+ ///
+ /// # Errors
+ ///
+ /// Rewinding can fail, for example because it might involve flushing a buffer.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use std::io::{Read, Seek, Write};
+ /// use std::fs::OpenOptions;
+ ///
+ /// let mut f = OpenOptions::new()
+ /// .write(true)
+ /// .read(true)
+ /// .create(true)
+ /// .open("foo.txt").unwrap();
+ ///
+ /// let hello = "Hello!\n";
+ /// write!(f, "{hello}").unwrap();
+ /// f.rewind().unwrap();
+ ///
+ /// let mut buf = String::new();
+ /// f.read_to_string(&mut buf).unwrap();
+ /// assert_eq!(&buf, hello);
+ /// ```
+ #[stable(feature = "seek_rewind", since = "1.55.0")]
+ fn rewind(&mut self) -> Result<()> {
+ self.seek(SeekFrom::Start(0))?;
+ Ok(())
+ }
+
/// Returns the length of this stream (in bytes).
///
/// This method is implemented using up to three seek operations. If this
/// # Example
///
/// ```no_run
- /// #![feature(seek_convenience)]
+ /// #![feature(seek_stream_len)]
/// use std::{
/// io::{self, Seek},
/// fs::File,
/// let mut f = File::open("foo.txt")?;
///
/// let len = f.stream_len()?;
- /// println!("The file is currently {} bytes long", len);
+ /// println!("The file is currently {len} bytes long");
/// Ok(())
/// }
/// ```
- #[unstable(feature = "seek_convenience", issue = "59359")]
+ #[unstable(feature = "seek_stream_len", issue = "59359")]
fn stream_len(&mut self) -> Result<u64> {
let old_pos = self.stream_position()?;
let len = self.seek(SeekFrom::End(0))?;
/// # Example
///
/// ```no_run
- /// #![feature(seek_convenience)]
/// use std::{
/// io::{self, BufRead, BufReader, Seek},
/// fs::File,
/// Ok(())
/// }
/// ```
- #[unstable(feature = "seek_convenience", issue = "59359")]
+ #[stable(feature = "seek_convenience", since = "1.51.0")]
fn stream_position(&mut self) -> Result<u64> {
self.seek(SeekFrom::Current(0))
}
/// let buffer = stdin.fill_buf().unwrap();
///
/// // work with buffer
- /// println!("{:?}", buffer);
+ /// println!("{buffer:?}");
///
/// // ensure the bytes we worked with aren't returned again later
/// let length = buffer.len();
#[stable(feature = "rust1", since = "1.0.0")]
fn consume(&mut self, amt: usize);
+ /// Check if the underlying `Read` has any data left to be read.
+ ///
+ /// This function may fill the buffer to check for data,
+ /// so this functions returns `Result<bool>`, not `bool`.
+ ///
+ /// Default implementation calls `fill_buf` and checks that
+ /// returned slice is empty (which means that there is no data left,
+ /// since EOF is reached).
+ ///
+ /// Examples
+ ///
+ /// ```
+ /// #![feature(buf_read_has_data_left)]
+ /// use std::io;
+ /// use std::io::prelude::*;
+ ///
+ /// let stdin = io::stdin();
+ /// let mut stdin = stdin.lock();
+ ///
+ /// while stdin.has_data_left().unwrap() {
+ /// let mut line = String::new();
+ /// stdin.read_line(&mut line).unwrap();
+ /// // work with line
+ /// println!("{line:?}");
+ /// }
+ /// ```
+ #[unstable(feature = "buf_read_has_data_left", reason = "recently added", issue = "86423")]
+ fn has_data_left(&mut self) -> Result<bool> {
+ self.fill_buf().map(|b| !b.is_empty())
+ }
+
/// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
///
/// This function will read bytes from the underlying stream until the
}
/// Read all bytes until a newline (the `0xA` byte) is reached, and append
- /// them to the provided buffer.
+ /// them to the provided buffer. You do not need to clear the buffer before
+ /// appending.
///
/// This function will read bytes from the underlying stream until the
/// newline delimiter (the `0xA` byte) or EOF is found. Once found, all bytes
// Note that we are not calling the `.read_until` method here, but
// rather our hardcoded implementation. For more details as to why, see
// the comments in `read_to_end`.
- append_to_string(buf, |b| read_until(self, b'\n', b))
+ unsafe { append_to_string(buf, |b| read_until(self, b'\n', b)) }
}
/// Returns an iterator over the contents of this reader split on the byte
/// `byte`.
///
/// The iterator returned from this function will return instances of
- /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
+ /// <code>[io::Result]<[Vec]\<u8>></code>. Each vector returned will *not* have
/// the delimiter byte at the end.
///
/// This function will yield errors whenever [`read_until`] would have
/// also yielded an error.
///
- /// [`io::Result`]: self::Result
- /// [`Vec<u8>`]: Vec
+ /// [io::Result]: self::Result "io::Result"
/// [`read_until`]: BufRead::read_until
///
/// # Examples
/// Returns an iterator over the lines of this reader.
///
/// The iterator returned from this function will yield instances of
- /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
+ /// <code>[io::Result]<[String]></code>. Each string returned will *not* have a newline
/// byte (the `0xA` byte) or `CRLF` (`0xD`, `0xA` bytes) at the end.
///
- /// [`io::Result`]: self::Result
+ /// [io::Result]: self::Result "io::Result"
///
/// # Examples
///
}
}
-/// Adaptor to chain together two readers.
+/// Adapter to chain together two readers.
///
/// This struct is generally created by calling [`chain`] on a reader.
/// Please see the documentation of [`chain`] for more details.
///
/// [`chain`]: Read::chain
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
pub struct Chain<T, U> {
first: T,
second: U,
}
}
-#[stable(feature = "std_debug", since = "1.16.0")]
-impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Chain").field("t", &self.first).field("u", &self.second).finish()
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Read, U: Read> Read for Chain<T, U> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
}
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")]
}
}
-/// Reader adaptor which limits the bytes read from an underlying reader.
+impl<T, U> SizeHint for Chain<T, U> {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second)
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ match (SizeHint::upper_bound(&self.first), SizeHint::upper_bound(&self.second)) {
+ (Some(first), Some(second)) => first.checked_add(second),
+ _ => None,
+ }
+ }
+}
+
+/// Reader adapter which limits the bytes read from an underlying reader.
///
/// This struct is generally created by calling [`take`] on a reader.
/// Please see the documentation of [`take`] for more details.
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(());
+ }
- fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
- // Pass in a reservation_size closure that respects the current value
- // of limit for each read. If we hit the read limit, this prevents the
- // final zero-byte read from allocating again.
- read_to_end_with_reservation(self, buf, |self_| cmp::min(self_.limit, 32) as usize)
+ let prev_filled = buf.filled_len();
+
+ if self.limit <= buf.remaining() 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());
+
+ // SAFETY: no uninit data is written to ibuf
+ let ibuf = unsafe { &mut buf.unfilled_mut()[..limit] };
+
+ let mut sliced_buf = ReadBuf::uninit(ibuf);
+
+ // SAFETY: extra_init bytes of ibuf are known to be initialized
+ 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
+
+ // SAFETY: new_init bytes of buf's unfilled buffer have been initialized
+ 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(())
}
}
}
}
+impl<T> SizeHint for Take<T> {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ cmp::min(SizeHint::lower_bound(&self.inner) as u64, self.limit) as usize
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ match SizeHint::upper_bound(&self.inner) {
+ Some(upper_bound) => Some(cmp::min(upper_bound as u64, self.limit) as usize),
+ None => self.limit.try_into().ok(),
+ }
+ }
+}
+
/// An iterator over `u8` values of a reader.
///
/// This struct is generally created by calling [`bytes`] on a reader.
};
}
}
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ SizeHint::size_hint(&self.inner)
+ }
+}
+
+trait SizeHint {
+ fn lower_bound(&self) -> usize;
+
+ fn upper_bound(&self) -> Option<usize>;
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.lower_bound(), self.upper_bound())
+ }
+}
+
+impl<T> SizeHint for T {
+ #[inline]
+ default fn lower_bound(&self) -> usize {
+ 0
+ }
+
+ #[inline]
+ default fn upper_bound(&self) -> Option<usize> {
+ None
+ }
+}
+
+impl<T> SizeHint for &mut T {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ SizeHint::lower_bound(*self)
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ SizeHint::upper_bound(*self)
+ }
+}
+
+impl<T> SizeHint for Box<T> {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ SizeHint::lower_bound(&**self)
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ SizeHint::upper_bound(&**self)
+ }
+}
+
+impl SizeHint for &[u8] {
+ #[inline]
+ fn lower_bound(&self) -> usize {
+ self.len()
+ }
+
+ #[inline]
+ fn upper_bound(&self) -> Option<usize> {
+ Some(self.len())
+ }
}
/// An iterator over the contents of an instance of `BufRead` split on a