From 23be3f4885688e5e0011005e2295c75168854c0a Mon Sep 17 00:00:00 2001 From: Fenrir Date: Sun, 21 Jan 2018 14:06:28 -0700 Subject: Recreate ctr-std from latest nightly --- ctr-std/src/io/mod.rs | 708 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 534 insertions(+), 174 deletions(-) (limited to 'ctr-std/src/io/mod.rs') diff --git a/ctr-std/src/io/mod.rs b/ctr-std/src/io/mod.rs index 58788cd..33d11eb 100644 --- a/ctr-std/src/io/mod.rs +++ b/ctr-std/src/io/mod.rs @@ -21,7 +21,8 @@ //! of other types, and you can implement them for your types too. As such, //! you'll see a few different types of I/O throughout the documentation in //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec`]s. For -//! example, [`Read`] adds a [`read()`] method, which we can use on `File`s: +//! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on +//! [`File`]s: //! //! ``` //! use std::io; @@ -106,7 +107,7 @@ //! ``` //! //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call -//! to [`write()`]: +//! to [`write`][`Write::write`]: //! //! ``` //! use std::io; @@ -145,6 +146,18 @@ //! # } //! ``` //! +//! Note that you cannot use the [`?` operator] in functions that do not return +//! a [`Result`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`] +//! or `match` on the return value to catch any possible errors: +//! +//! ``` +//! use std::io; +//! +//! let mut input = String::new(); +//! +//! io::stdin().read_line(&mut input).unwrap(); +//! ``` +//! //! And a very common source of output is standard output: //! //! ``` @@ -157,7 +170,7 @@ //! # } //! ``` //! -//! Of course, using [`io::stdout()`] directly is less common than something like +//! Of course, using [`io::stdout`] directly is less common than something like //! [`println!`]. //! //! ## Iterator types @@ -245,13 +258,15 @@ //! [`Vec`]: ../vec/struct.Vec.html //! [`BufReader`]: struct.BufReader.html //! [`BufWriter`]: struct.BufWriter.html -//! [`write()`]: trait.Write.html#tymethod.write -//! [`io::stdout()`]: fn.stdout.html +//! [`Write::write`]: trait.Write.html#tymethod.write +//! [`io::stdout`]: fn.stdout.html //! [`println!`]: ../macro.println.html //! [`Lines`]: struct.Lines.html //! [`io::Result`]: type.Result.html -//! [`?` operator]: ../../book/syntax-index.html -//! [`read()`]: trait.Read.html#tymethod.read +//! [`?` operator]: ../../book/first-edition/syntax-index.html +//! [`Read::read`]: trait.Read.html#tymethod.read +//! [`Result`]: ../result/enum.Result.html +//! [`.unwrap()`]: ../result/enum.Result.html#method.unwrap #![stable(feature = "rust1", since = "1.0.0")] @@ -262,6 +277,7 @@ use fmt; use result; use str; use memchr; +use ptr; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::{BufReader, BufWriter, LineWriter}; @@ -274,10 +290,12 @@ pub use self::error::{Result, Error, ErrorKind}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr}; +pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::stdio::{StdoutLock, StderrLock, StdinLock}; -#[unstable(feature = "libstd_io_internals", issue = "0")] +#[unstable(feature = "print_internals", issue = "0")] +pub use self::stdio::{_print, _eprint}; +#[unstable(feature = "libstd_io_internals", issue = "42788")] #[doc(no_inline, hidden)] pub use self::stdio::{set_panic, set_print}; @@ -292,6 +310,14 @@ mod stdio; const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; +struct Guard<'a> { buf: &'a mut Vec, len: usize } + +impl<'a> Drop for Guard<'a> { + fn drop(&mut self) { + unsafe { self.buf.set_len(self.len); } + } +} + // 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 @@ -313,23 +339,16 @@ const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; fn append_to_string(buf: &mut String, f: F) -> Result where F: FnOnce(&mut Vec) -> Result { - struct Guard<'a> { s: &'a mut Vec, len: usize } - impl<'a> Drop for Guard<'a> { - fn drop(&mut self) { - unsafe { self.s.set_len(self.len); } - } - } - unsafe { - let mut g = Guard { len: buf.len(), s: buf.as_mut_vec() }; - let ret = f(g.s); - if str::from_utf8(&g.s[g.len..]).is_err() { + 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.s.len(); + g.len = g.buf.len(); ret } } @@ -341,25 +360,29 @@ fn append_to_string(buf: &mut String, f: F) -> Result // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every // time is 4,500 times (!) slower than this 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: &mut R, buf: &mut Vec) -> Result { let start_len = buf.len(); - let mut len = start_len; - let mut new_write_size = 16; + let mut g = Guard { len: buf.len(), buf: buf }; let ret; loop { - if len == buf.len() { - if new_write_size < DEFAULT_BUF_SIZE { - new_write_size *= 2; + if g.len == g.buf.len() { + unsafe { + g.buf.reserve(32); + let capacity = g.buf.capacity(); + g.buf.set_len(capacity); + r.initializer().initialize(&mut g.buf[g.len..]); } - buf.resize(len + new_write_size, 0); } - match r.read(&mut buf[len..]) { + match r.read(&mut g.buf[g.len..]) { Ok(0) => { - ret = Ok(len - start_len); + ret = Ok(g.len - start_len); break; } - Ok(n) => len += n, + Ok(n) => g.len += n, Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => { ret = Err(e); @@ -368,39 +391,33 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result } } - buf.truncate(len); ret } /// The `Read` trait allows for reading bytes from a source. /// -/// Implementors of the `Read` trait are sometimes called 'readers'. +/// Implementors of the `Read` trait are called 'readers'. /// -/// Readers are defined by one required method, `read()`. Each call to `read` +/// Readers are defined by one required method, [`read()`]. Each call to [`read()`] /// will attempt to pull bytes from this source into a provided buffer. A -/// number of other methods are implemented in terms of `read()`, giving +/// number of other methods are implemented in terms of [`read()`], giving /// implementors a number of ways to read bytes while only needing to implement /// a single method. /// /// Readers are intended to be composable with one another. Many implementors -/// throughout `std::io` take and provide types which implement the `Read` +/// throughout [`std::io`] take and provide types which implement the `Read` /// trait. /// -/// Please note that each call to `read` may involve a system call, and -/// therefore, using something that implements [`BufRead`][bufread], such as -/// [`BufReader`][bufreader], will be more efficient. -/// -/// [bufread]: trait.BufRead.html -/// [bufreader]: struct.BufReader.html +/// Please note that each call to [`read()`] may involve a system call, and +/// therefore, using something that implements [`BufRead`], such as +/// [`BufReader`], will be more efficient. /// /// # Examples /// -/// [`File`][file]s implement `Read`: -/// -/// [file]: ../fs/struct.File.html +/// [`File`]s implement `Read`: /// /// ``` -/// use std::io; +/// # use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// @@ -423,16 +440,43 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result /// # Ok(()) /// # } /// ``` +/// +/// Read from [`&str`] because [`&[u8]`][slice] implements `Read`: +/// +/// ``` +/// # use std::io; +/// use std::io::prelude::*; +/// +/// # fn foo() -> io::Result<()> { +/// let mut b = "This string will be read".as_bytes(); +/// let mut buffer = [0; 10]; +/// +/// // read up to 10 bytes +/// b.read(&mut buffer)?; +/// +/// // etc... it works exactly as a File does! +/// # Ok(()) +/// # } +/// ``` +/// +/// [`read()`]: trait.Read.html#tymethod.read +/// [`std::io`]: ../../std/io/index.html +/// [`File`]: ../fs/struct.File.html +/// [`BufRead`]: trait.BufRead.html +/// [`BufReader`]: struct.BufReader.html +/// [`&str`]: ../../std/primitive.str.html +/// [slice]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] +#[doc(spotlight)] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. /// /// This function does not provide any guarantees about whether it blocks /// waiting for data, but if an object needs to block for a read but cannot - /// it will typically signal this via an `Err` return value. + /// it will typically signal this via an [`Err`] return value. /// - /// If the return value of this method is `Ok(n)`, then it must be + /// 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 /// 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: @@ -453,11 +497,17 @@ pub trait Read { /// variant will be returned. If an error is returned then it must be /// guaranteed that no bytes were read. /// + /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read + /// operation should be retried if there is nothing else to do. + /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`File`]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -468,7 +518,7 @@ pub trait Read { /// let mut f = File::open("foo.txt")?; /// let mut buffer = [0; 10]; /// - /// // read 10 bytes + /// // read up to 10 bytes /// f.read(&mut buffer[..])?; /// # Ok(()) /// # } @@ -476,19 +526,47 @@ pub trait Read { #[stable(feature = "rust1", since = "1.0.0")] fn read(&mut self, buf: &mut [u8]) -> Result; + /// 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. + /// + /// [`Initializer::nop()`]: ../../std/io/struct.Initializer.html#method.nop + /// [`Initializer`]: ../../std/io/struct.Initializer.html + #[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 - /// `buf`. This function will continuously call `read` to append more data to - /// `buf` until `read` returns either `Ok(0)` or an error of - /// non-`ErrorKind::Interrupted` kind. + /// `buf`. This function will continuously call [`read()`] to append more data to + /// `buf` until [`read()`] returns either [`Ok(0)`] or an error of + /// non-[`ErrorKind::Interrupted`] kind. /// /// If successful, this function will return the total number of bytes read. /// /// # Errors /// /// If this function encounters an error of the kind - /// `ErrorKind::Interrupted` then the error is ignored and the operation + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation /// will continue. /// /// If any other read error is encountered then this function immediately @@ -497,9 +575,12 @@ pub trait Read { /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`read()`]: trait.Read.html#tymethod.read + /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`File`]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -520,7 +601,7 @@ pub trait Read { read_to_end(self, buf) } - /// Read all bytes until EOF in this source, placing them into `buf`. + /// Read all bytes until EOF in this source, appending them to `buf`. /// /// If successful, this function returns the number of bytes which were read /// and appended to `buf`. @@ -530,7 +611,7 @@ pub trait Read { /// If the data in this stream is *not* valid UTF-8 then an error is /// returned and `buf` is unchanged. /// - /// See [`read_to_end()`][readtoend] for other error semantics. + /// See [`read_to_end`][readtoend] for other error semantics. /// /// [readtoend]: #method.read_to_end /// @@ -580,11 +661,11 @@ pub trait Read { /// # Errors /// /// If this function encounters an error of the kind - /// `ErrorKind::Interrupted` then the error is ignored and the operation + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation /// will continue. /// /// If this function encounters an "end of file" before completely filling - /// the buffer, it returns an error of the kind `ErrorKind::UnexpectedEof`. + /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. /// The contents of `buf` are unspecified in this case. /// /// If any other read error is encountered then this function immediately @@ -596,9 +677,11 @@ pub trait Read { /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`File`]: ../fs/struct.File.html + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof /// /// ``` /// use std::io; @@ -669,18 +752,25 @@ pub trait Read { #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } - /// Transforms this `Read` instance to an `Iterator` over its bytes. + /// Transforms this `Read` instance to an [`Iterator`] over its bytes. /// - /// The returned type implements `Iterator` where the `Item` is `Result`. The yielded item is `Ok` if a byte was successfully read and - /// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from - /// this iterator. + /// The returned type implements [`Iterator`] where the `Item` is + /// [`Result`]`<`[`u8`]`, `[`io::Error`]`>`. + /// The yielded item is [`Ok`] if a byte was successfully read and [`Err`] + /// otherwise. EOF is mapped to returning [`None`] from this iterator. /// /// # Examples /// /// [`File`][file]s implement `Read`: /// /// [file]: ../fs/struct.File.html + /// [`Iterator`]: ../../std/iter/trait.Iterator.html + /// [`Result`]: ../../std/result/enum.Result.html + /// [`io::Error`]: ../../std/io/struct.Error.html + /// [`u8`]: ../../std/primitive.u8.html + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// ``` /// use std::io; @@ -701,12 +791,12 @@ pub trait Read { Bytes { inner: self } } - /// Transforms this `Read` instance to an `Iterator` over `char`s. + /// Transforms this `Read` instance to an [`Iterator`] over [`char`]s. /// /// This adaptor will attempt to interpret this reader as a UTF-8 encoded - /// sequence of characters. The returned iterator will return `None` once + /// sequence of characters. The returned iterator will return [`None`] once /// EOF is reached for this reader. Otherwise each element yielded will be a - /// `Result` where `E` may contain information about what I/O error + /// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error /// occurred or where decoding failed. /// /// Currently this adaptor will discard intermediate data read, and should @@ -714,9 +804,13 @@ pub trait Read { /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`File`]: ../fs/struct.File.html + /// [`Iterator`]: ../../std/iter/trait.Iterator.html + /// [`Result`]: ../../std/result/enum.Result.html + /// [`char`]: ../../std/primitive.char.html + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// ``` /// #![feature(io)] @@ -779,15 +873,17 @@ pub trait Read { /// Creates an adaptor 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 + /// `limit` bytes, after which it will always return EOF ([`Ok(0)`]). Any /// read errors will not count towards the number of bytes read and future - /// calls to `read` may succeed. + /// calls to [`read()`] may succeed. /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`File`]: ../fs/struct.File.html + /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`read()`]: trait.Read.html#tymethod.read /// /// ``` /// use std::io; @@ -811,16 +907,60 @@ pub trait Read { } } +/// 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'. /// -/// Writers are defined by two required methods, [`write()`] and [`flush()`]: +/// Writers are defined by two required methods, [`write`] and [`flush`]: /// -/// * The [`write()`] method will attempt to write some data into the object, +/// * 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 adaptors and explicit buffers /// themselves for ensuring that all buffered data has been pushed out to the /// 'true sink'. /// @@ -828,8 +968,8 @@ pub trait Read { /// throughout [`std::io`] take and provide types which implement the `Write` /// trait. /// -/// [`write()`]: #tymethod.write -/// [`flush()`]: #tymethod.flush +/// [`write`]: #tymethod.write +/// [`flush`]: #tymethod.flush /// [`std::io`]: index.html /// /// # Examples @@ -846,6 +986,7 @@ pub trait Read { /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[doc(spotlight)] pub trait Write { /// Write a buffer into this object, returning how many bytes were written. /// @@ -856,9 +997,9 @@ pub trait Write { /// /// Calls to `write` are not guaranteed to block waiting for data to be /// written, and a write which would otherwise block can be indicated through - /// an `Err` variant. + /// an [`Err`] variant. /// - /// If the return value is `Ok(n)` then it must be guaranteed that + /// If the return value is [`Ok(n)`] then it must be guaranteed that /// `0 <= n <= buf.len()`. A return value of `0` typically means that the /// underlying object is no longer able to accept bytes and will likely not /// be able to in the future as well, or that the buffer provided is empty. @@ -872,6 +1013,13 @@ pub trait Write { /// It is **not** considered an error if the entire buffer could not be /// written to this writer. /// + /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the + /// write operation should be retried if there is nothing else to do. + /// + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// /// # Examples /// /// ``` @@ -881,6 +1029,7 @@ pub trait Write { /// # fn foo() -> std::io::Result<()> { /// let mut buffer = File::create("foo.txt")?; /// + /// // Writes some prefix of the byte string, not necessarily all of it. /// buffer.write(b"some bytes")?; /// # Ok(()) /// # } @@ -916,14 +1065,20 @@ pub trait Write { /// Attempts to write an entire buffer into this write. /// - /// This method will continuously call `write` while there is more data to - /// write. This method will not return until the entire buffer has been - /// successfully written or an error occurs. The first error generated from - /// this method will be returned. + /// This method will continuously call [`write`] until there is no more data + /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is + /// returned. This method will not return until the entire buffer has been + /// successfully written or such an error occurs. The first error that is + /// not of [`ErrorKind::Interrupted`] kind generated from this method will be + /// returned. /// /// # Errors /// - /// This function will return the first error that `write` returns. + /// This function will return the first error of + /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns. + /// + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`write`]: #tymethod.write /// /// # Examples /// @@ -1159,7 +1314,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// For example, reading line-by-line is inefficient without using a buffer, so /// if you want to read by line, you'll need `BufRead`, which includes a -/// [`read_line()`] method as well as a [`lines()`] iterator. +/// [`read_line`] method as well as a [`lines`] iterator. /// /// # Examples /// @@ -1183,8 +1338,8 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// [`BufReader`]: struct.BufReader.html /// [`File`]: ../fs/struct.File.html -/// [`read_line()`]: #method.read_line -/// [`lines()`]: #method.lines +/// [`read_line`]: #method.read_line +/// [`lines`]: #method.lines /// [`Read`]: trait.Read.html /// /// ``` @@ -1209,13 +1364,13 @@ pub trait BufRead: Read { /// Fills the internal buffer of this object, returning the buffer contents. /// /// This function is a lower-level call. It needs to be paired with the - /// [`consume()`] method to function properly. When calling this + /// [`consume`] method to function properly. When calling this /// method, none of the contents will be "read" in the sense that later - /// calling `read` may return the same contents. As such, [`consume()`] must + /// calling `read` may return the same contents. As such, [`consume`] must /// be called with the number of bytes that are consumed from this buffer to /// ensure that the bytes are never returned twice. /// - /// [`consume()`]: #tymethod.consume + /// [`consume`]: #tymethod.consume /// /// An empty buffer returned indicates that the stream has reached EOF. /// @@ -1256,21 +1411,21 @@ pub trait BufRead: Read { /// so they should no longer be returned in calls to `read`. /// /// This function is a lower-level call. It needs to be paired with the - /// [`fill_buf()`] method to function properly. This function does + /// [`fill_buf`] method to function properly. This function does /// not perform any I/O, it simply informs this object that some amount of - /// its buffer, returned from [`fill_buf()`], has been consumed and should + /// its buffer, returned from [`fill_buf`], has been consumed and should /// no longer be returned. As such, this function may do odd things if - /// [`fill_buf()`] isn't called before calling it. + /// [`fill_buf`] isn't called before calling it. /// /// The `amt` must be `<=` the number of bytes in the buffer returned by - /// [`fill_buf()`]. + /// [`fill_buf`]. /// /// # Examples /// - /// Since `consume()` is meant to be used with [`fill_buf()`], + /// Since `consume()` is meant to be used with [`fill_buf`], /// that method's example includes an example of `consume()`. /// - /// [`fill_buf()`]: #tymethod.fill_buf + /// [`fill_buf`]: #tymethod.fill_buf #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); @@ -1282,36 +1437,52 @@ pub trait BufRead: Read { /// /// If successful, this function will return the total number of bytes read. /// + /// An empty buffer returned indicates that the stream has reached EOF. + /// /// # Errors /// /// This function will ignore all instances of [`ErrorKind::Interrupted`] and - /// will otherwise return any errors returned by [`fill_buf()`]. + /// will otherwise return any errors returned by [`fill_buf`]. /// /// If an I/O error is encountered then all bytes read so far will be /// present in `buf` and its length will have been adjusted appropriately. /// - /// # Examples - /// - /// A locked standard input implements `BufRead`. In this example, we'll - /// read from standard input until we see an `a` byte. - /// - /// [`fill_buf()`]: #tymethod.fill_buf + /// [`fill_buf`]: #tymethod.fill_buf /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted /// - /// ``` - /// use std::io; - /// use std::io::prelude::*; + /// # Examples /// - /// fn foo() -> io::Result<()> { - /// let stdin = io::stdin(); - /// let mut stdin = stdin.lock(); - /// let mut buffer = Vec::new(); + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to read all the bytes in a byte slice + /// in hyphen delimited segments: /// - /// stdin.read_until(b'a', &mut buffer)?; + /// [`Cursor`]: struct.Cursor.html /// - /// println!("{:?}", buffer); - /// # Ok(()) - /// # } + /// ``` + /// use std::io::{self, BufRead}; + /// + /// let mut cursor = io::Cursor::new(b"lorem-ipsum"); + /// let mut buf = vec![]; + /// + /// // cursor is at 'l' + /// let num_bytes = cursor.read_until(b'-', &mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 6); + /// assert_eq!(buf, b"lorem-"); + /// buf.clear(); + /// + /// // cursor is at 'i' + /// let num_bytes = cursor.read_until(b'-', &mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 5); + /// assert_eq!(buf, b"ipsum"); + /// buf.clear(); + /// + /// // cursor is at EOF + /// let num_bytes = cursor.read_until(b'-', &mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 0); + /// assert_eq!(buf, b""); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_until(&mut self, byte: u8, buf: &mut Vec) -> Result { @@ -1328,37 +1499,47 @@ pub trait BufRead: Read { /// /// If successful, this function will return the total number of bytes read. /// + /// An empty buffer returned indicates that the stream has reached EOF. + /// /// # Errors /// - /// This function has the same error semantics as [`read_until()`] and will + /// This function has the same error semantics as [`read_until`] and will /// also return an error if the read bytes are not valid UTF-8. If an I/O /// error is encountered then `buf` may contain some bytes already read in /// the event that all data read so far was valid UTF-8. /// /// # Examples /// - /// A locked standard input implements `BufRead`. In this example, we'll - /// read all of the lines from standard input. If we were to do this in - /// an actual project, the [`lines()`] method would be easier, of - /// course. + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to read all the lines in a byte slice: /// - /// [`lines()`]: #method.lines - /// [`read_until()`]: #method.read_until + /// [`Cursor`]: struct.Cursor.html /// /// ``` - /// use std::io; - /// use std::io::prelude::*; - /// - /// let stdin = io::stdin(); - /// let mut stdin = stdin.lock(); - /// let mut buffer = String::new(); - /// - /// while stdin.read_line(&mut buffer).unwrap() > 0 { - /// // work with buffer - /// println!("{:?}", buffer); - /// - /// buffer.clear(); - /// } + /// use std::io::{self, BufRead}; + /// + /// let mut cursor = io::Cursor::new(b"foo\nbar"); + /// let mut buf = String::new(); + /// + /// // cursor is at 'f' + /// let num_bytes = cursor.read_line(&mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 4); + /// assert_eq!(buf, "foo\n"); + /// buf.clear(); + /// + /// // cursor is at 'b' + /// let num_bytes = cursor.read_line(&mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 3); + /// assert_eq!(buf, "bar"); + /// buf.clear(); + /// + /// // cursor is at EOF + /// let num_bytes = cursor.read_line(&mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 0); + /// assert_eq!(buf, ""); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_line(&mut self, buf: &mut String) -> Result { @@ -1375,27 +1556,31 @@ pub trait BufRead: Read { /// [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have /// the delimiter byte at the end. /// - /// This function will yield errors whenever [`read_until()`] would have + /// This function will yield errors whenever [`read_until`] would have /// also yielded an error. /// + /// [`io::Result`]: type.Result.html + /// [`Vec`]: ../vec/struct.Vec.html + /// [`read_until`]: #method.read_until + /// /// # Examples /// - /// A locked standard input implements `BufRead`. In this example, we'll - /// read some input from standard input, splitting on commas. + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to iterate over all hyphen delimited + /// segments in a byte slice /// - /// [`io::Result`]: type.Result.html - /// [`Vec`]: ../vec/struct.Vec.html - /// [`read_until()`]: #method.read_until + /// [`Cursor`]: struct.Cursor.html /// /// ``` - /// use std::io; - /// use std::io::prelude::*; + /// use std::io::{self, BufRead}; /// - /// let stdin = io::stdin(); + /// let cursor = io::Cursor::new(b"lorem-ipsum-dolor"); /// - /// for content in stdin.lock().split(b',') { - /// println!("{:?}", content.unwrap()); - /// } + /// let mut split_iter = cursor.split(b'-').map(|l| l.unwrap()); + /// assert_eq!(split_iter.next(), Some(b"lorem".to_vec())); + /// assert_eq!(split_iter.next(), Some(b"ipsum".to_vec())); + /// assert_eq!(split_iter.next(), Some(b"dolor".to_vec())); + /// assert_eq!(split_iter.next(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn split(self, byte: u8) -> Split where Self: Sized { @@ -1413,24 +1598,29 @@ pub trait BufRead: Read { /// /// # Examples /// - /// A locked standard input implements `BufRead`: + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to iterate over all the lines in a byte + /// slice. + /// + /// [`Cursor`]: struct.Cursor.html /// /// ``` - /// use std::io; - /// use std::io::prelude::*; + /// use std::io::{self, BufRead}; /// - /// let stdin = io::stdin(); + /// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor"); /// - /// for line in stdin.lock().lines() { - /// println!("{}", line.unwrap()); - /// } + /// let mut lines_iter = cursor.lines().map(|l| l.unwrap()); + /// assert_eq!(lines_iter.next(), Some(String::from("lorem"))); + /// assert_eq!(lines_iter.next(), Some(String::from("ipsum"))); + /// assert_eq!(lines_iter.next(), Some(String::from("dolor"))); + /// assert_eq!(lines_iter.next(), None); /// ``` /// /// # Errors /// - /// Each line of the iterator has the same error semantics as [`BufRead::read_line()`]. + /// Each line of the iterator has the same error semantics as [`BufRead::read_line`]. /// - /// [`BufRead::read_line()`]: trait.BufRead.html#method.read_line + /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line #[stable(feature = "rust1", since = "1.0.0")] fn lines(self) -> Lines where Self: Sized { Lines { buf: self } @@ -1439,10 +1629,10 @@ pub trait BufRead: Read { /// Adaptor 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. +/// This struct is generally created by calling [`chain`] on a reader. +/// Please see the documentation of [`chain`] for more details. /// -/// [`chain()`]: trait.Read.html#method.chain +/// [`chain`]: trait.Read.html#method.chain #[stable(feature = "rust1", since = "1.0.0")] pub struct Chain { first: T, @@ -1450,6 +1640,81 @@ pub struct Chain { done_first: bool, } +impl Chain { + /// Consumes the `Chain`, returning the wrapped readers. + /// + /// # Examples + /// + /// ``` + /// # use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.into_inner(); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn into_inner(self) -> (T, U) { + (self.first, self.second) + } + + /// Gets references to the underlying readers in this `Chain`. + /// + /// # Examples + /// + /// ``` + /// # use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_ref(); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_ref(&self) -> (&T, &U) { + (&self.first, &self.second) + } + + /// Gets mutable references to the underlying readers in this `Chain`. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + /// + /// # Examples + /// + /// ``` + /// # use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let mut chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_mut(); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_mut(&mut self) -> (&mut T, &mut U) { + (&mut self.first, &mut self.second) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1471,6 +1736,15 @@ impl Read for Chain { } self.second.read(buf) } + + 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")] @@ -1496,10 +1770,10 @@ impl BufRead for Chain { /// Reader adaptor 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. +/// This struct is generally created by calling [`take`] on a reader. +/// Please see the documentation of [`take`] for more details. /// -/// [`take()`]: trait.Read.html#method.take +/// [`take`]: trait.Read.html#method.take #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Take { @@ -1538,6 +1812,35 @@ impl Take { #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } + /// Sets the number of bytes that can be read before this instance will + /// return EOF. This is the same as constructing a new `Take` instance, so + /// the amount of bytes read and the previous limit value don't matter when + /// calling this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(take_set_limit)] + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let f = File::open("foo.txt")?; + /// + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); + /// + /// assert_eq!(handle.limit(), 10); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "take_set_limit", issue = "42781")] + pub fn set_limit(&mut self, limit: u64) { + self.limit = limit; + } + /// Consumes the `Take`, returning the wrapped reader. /// /// # Examples @@ -1562,6 +1865,60 @@ impl Take { pub fn into_inner(self) -> T { self.inner } + + /// Gets a reference to the underlying reader. + /// + /// # Examples + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_ref(); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying reader. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying reader as doing so may corrupt the internal limit of this + /// `Take`. + /// + /// # Examples + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_mut(); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1577,6 +1934,10 @@ impl Read for Take { self.limit -= n as u64; Ok(n) } + + unsafe fn initializer(&self) -> Initializer { + self.inner.initializer() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1614,10 +1975,10 @@ fn read_one_byte(reader: &mut Read) -> Option> { /// An iterator over `u8` values of a reader. /// -/// This struct is generally created by calling [`bytes()`] on a reader. -/// Please see the documentation of [`bytes()`] for more details. +/// This struct is generally created by calling [`bytes`] on a reader. +/// Please see the documentation of [`bytes`] for more details. /// -/// [`bytes()`]: trait.Read.html#method.bytes +/// [`bytes`]: trait.Read.html#method.bytes #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Bytes { @@ -1635,7 +1996,7 @@ impl Iterator for Bytes { /// An iterator over the `char`s of a reader. /// -/// This struct is generally created by calling [`chars()`][chars] on a reader. +/// This struct is generally created by calling [`chars`][chars] on a reader. /// Please see the documentation of `chars()` for more details. /// /// [chars]: trait.Read.html#method.chars @@ -1666,10 +2027,9 @@ impl Iterator for Chars { type Item = result::Result; fn next(&mut self) -> Option> { - let first_byte = match read_one_byte(&mut self.inner) { - None => return None, - Some(Ok(b)) => b, - Some(Err(e)) => return Some(Err(CharsError::Other(e))), + let first_byte = match read_one_byte(&mut self.inner)? { + Ok(b) => b, + Err(e) => return Some(Err(CharsError::Other(e))), }; let width = core_str::utf8_char_width(first_byte); if width == 1 { return Some(Ok(first_byte as char)) } @@ -1726,7 +2086,7 @@ impl fmt::Display for CharsError { /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// -/// This struct is generally created by calling [`split()`][split] on a +/// This struct is generally created by calling [`split`][split] on a /// `BufRead`. Please see the documentation of `split()` for more details. /// /// [split]: trait.BufRead.html#method.split @@ -1758,7 +2118,7 @@ impl Iterator for Split { /// An iterator over the lines of an instance of `BufRead`. /// -/// This struct is generally created by calling [`lines()`][lines] on a +/// This struct is generally created by calling [`lines`][lines] on a /// `BufRead`. Please see the documentation of `lines()` for more details. /// /// [lines]: trait.BufRead.html#method.lines -- cgit v1.2.3