std: Stabilize the io
module
The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
This commit is contained in:
parent
79dd393a4f
commit
d54bd9f29a
8 changed files with 212 additions and 105 deletions
|
@ -16,8 +16,7 @@ use prelude::v1::*;
|
|||
use io::prelude::*;
|
||||
|
||||
use cmp;
|
||||
use error::Error as StdError;
|
||||
use error::FromError;
|
||||
use error::{self, FromError};
|
||||
use fmt;
|
||||
use io::{self, Cursor, DEFAULT_BUF_SIZE, Error, ErrorKind};
|
||||
use ptr;
|
||||
|
@ -28,6 +27,7 @@ use ptr;
|
|||
/// For example, every call to `read` on `TcpStream` results in a system call.
|
||||
/// A `BufReader` performs large, infrequent reads on the underlying `Read`
|
||||
/// and maintains an in-memory buffer of the results.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BufReader<R> {
|
||||
inner: R,
|
||||
buf: Cursor<Vec<u8>>,
|
||||
|
@ -35,11 +35,13 @@ pub struct BufReader<R> {
|
|||
|
||||
impl<R: Read> BufReader<R> {
|
||||
/// Creates a new `BufReader` with a default buffer capacity
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(inner: R) -> BufReader<R> {
|
||||
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `BufReader` with the specified buffer capacity
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
|
||||
BufReader {
|
||||
inner: inner,
|
||||
|
@ -48,6 +50,7 @@ impl<R: Read> BufReader<R> {
|
|||
}
|
||||
|
||||
/// Gets a reference to the underlying reader.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &R { &self.inner }
|
||||
|
||||
/// Gets a mutable reference to the underlying reader.
|
||||
|
@ -55,14 +58,17 @@ impl<R: Read> BufReader<R> {
|
|||
/// # Warning
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying reader.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
|
||||
|
||||
/// Unwraps this `BufReader`, returning the underlying reader.
|
||||
///
|
||||
/// Note that any leftover data in the internal buffer is lost.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> R { self.inner }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Read> Read for BufReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
// If we don't have any buffered data and we're doing a massive read
|
||||
|
@ -77,6 +83,7 @@ impl<R: Read> Read for BufReader<R> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Read> BufRead for BufReader<R> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
// If we've reached the end of our internal buffer then we need to fetch
|
||||
|
@ -112,6 +119,7 @@ impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug {
|
|||
/// underlying `Write` in large, infrequent batches.
|
||||
///
|
||||
/// This writer will be flushed when it is dropped.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BufWriter<W> {
|
||||
inner: Option<W>,
|
||||
buf: Vec<u8>,
|
||||
|
@ -120,15 +128,18 @@ pub struct BufWriter<W> {
|
|||
/// An error returned by `into_inner` which indicates whether a flush error
|
||||
/// happened or not.
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoInnerError<W>(W, Error);
|
||||
|
||||
impl<W: Write> BufWriter<W> {
|
||||
/// Creates a new `BufWriter` with a default buffer capacity
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(inner: W) -> BufWriter<W> {
|
||||
BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `BufWriter` with the specified buffer capacity
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacity(cap: usize, inner: W) -> BufWriter<W> {
|
||||
BufWriter {
|
||||
inner: Some(inner),
|
||||
|
@ -165,6 +176,7 @@ impl<W: Write> BufWriter<W> {
|
|||
}
|
||||
|
||||
/// Gets a reference to the underlying writer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() }
|
||||
|
||||
/// Gets a mutable reference to the underlying write.
|
||||
|
@ -172,11 +184,13 @@ impl<W: Write> BufWriter<W> {
|
|||
/// # Warning
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying writer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() }
|
||||
|
||||
/// Unwraps this `BufWriter`, returning the underlying writer.
|
||||
///
|
||||
/// The buffer is flushed before returning the writer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
|
||||
match self.flush_buf() {
|
||||
Err(e) => Err(IntoInnerError(self, e)),
|
||||
|
@ -185,6 +199,7 @@ impl<W: Write> BufWriter<W> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Write for BufWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
if self.buf.len() + buf.len() > self.buf.capacity() {
|
||||
|
@ -224,23 +239,30 @@ impl<W> IntoInnerError<W> {
|
|||
/// Returns the error which caused the call to `into_inner` to fail.
|
||||
///
|
||||
/// This error was returned when attempting to flush the internal buffer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn error(&self) -> &Error { &self.1 }
|
||||
|
||||
/// Returns the underlying `BufWriter` instance which generated the error.
|
||||
///
|
||||
/// The returned object can be used to retry a flush or re-inspect the
|
||||
/// buffer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> W { self.0 }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W> FromError<IntoInnerError<W>> for Error {
|
||||
fn from_error(iie: IntoInnerError<W>) -> Error { iie.1 }
|
||||
}
|
||||
|
||||
impl<W> StdError for IntoInnerError<W> {
|
||||
fn description(&self) -> &str { self.error().description() }
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W> error::Error for IntoInnerError<W> {
|
||||
fn description(&self) -> &str {
|
||||
error::Error::description(self.error())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W> fmt::Display for IntoInnerError<W> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.error().fmt(f)
|
||||
|
@ -251,26 +273,41 @@ impl<W> fmt::Display for IntoInnerError<W> {
|
|||
/// (`0x0a`, `'\n'`) is detected.
|
||||
///
|
||||
/// This writer will be flushed when it is dropped.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct LineWriter<W> {
|
||||
inner: BufWriter<W>,
|
||||
}
|
||||
|
||||
impl<W: Write> LineWriter<W> {
|
||||
/// Creates a new `LineWriter`
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(inner: W) -> LineWriter<W> {
|
||||
// Lines typically aren't that long, don't use a giant buffer
|
||||
LineWriter { inner: BufWriter::with_capacity(1024, inner) }
|
||||
LineWriter::with_capacity(1024, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `LineWriter` with a specified capacity for the internal
|
||||
/// buffer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
|
||||
LineWriter { inner: BufWriter::with_capacity(cap, inner) }
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying writer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &W { self.inner.get_ref() }
|
||||
|
||||
/// Gets a mutable reference to the underlying writer.
|
||||
///
|
||||
/// This type does not expose the ability to get a mutable reference to the
|
||||
/// underlying reader because that could possibly corrupt the buffer.
|
||||
pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() }
|
||||
/// Caution must be taken when calling methods on the mutable reference
|
||||
/// returned as extra writes could corrupt the output stream.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() }
|
||||
|
||||
/// Unwraps this `LineWriter`, returning the underlying writer.
|
||||
///
|
||||
/// The internal buffer is flushed before returning the writer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
|
||||
self.inner.into_inner().map_err(|IntoInnerError(buf, e)| {
|
||||
IntoInnerError(LineWriter { inner: buf }, e)
|
||||
|
@ -278,6 +315,7 @@ impl<W: Write> LineWriter<W> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Write for LineWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match buf.rposition_elem(&b'\n') {
|
||||
|
@ -320,12 +358,13 @@ impl<W: Read> Read for InternalBufWriter<W> {
|
|||
|
||||
/// Wraps a Stream and buffers input and output to and from it.
|
||||
///
|
||||
/// It can be excessively inefficient to work directly with a `Stream`. For
|
||||
/// It can be excessively inefficient to work directly with a `Read+Write`. For
|
||||
/// example, every call to `read` or `write` on `TcpStream` results in a system
|
||||
/// call. A `BufStream` keeps in memory buffers of data, making large,
|
||||
/// infrequent calls to `read` and `write` on the underlying `Stream`.
|
||||
/// infrequent calls to `read` and `write` on the underlying `Read+Write`.
|
||||
///
|
||||
/// The output half will be flushed when this stream is dropped.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BufStream<S> {
|
||||
inner: BufReader<InternalBufWriter<S>>
|
||||
}
|
||||
|
@ -333,6 +372,7 @@ pub struct BufStream<S> {
|
|||
impl<S: Read + Write> BufStream<S> {
|
||||
/// Creates a new buffered stream with explicitly listed capacities for the
|
||||
/// reader/writer buffer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacities(reader_cap: usize, writer_cap: usize, inner: S)
|
||||
-> BufStream<S> {
|
||||
let writer = BufWriter::with_capacity(writer_cap, inner);
|
||||
|
@ -343,11 +383,13 @@ impl<S: Read + Write> BufStream<S> {
|
|||
|
||||
/// Creates a new buffered stream with the default reader/writer buffer
|
||||
/// capacities.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(inner: S) -> BufStream<S> {
|
||||
BufStream::with_capacities(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE, inner)
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying stream.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &S {
|
||||
let InternalBufWriter(ref w) = self.inner.inner;
|
||||
w.get_ref()
|
||||
|
@ -359,6 +401,7 @@ impl<S: Read + Write> BufStream<S> {
|
|||
///
|
||||
/// It is inadvisable to read directly from or write directly to the
|
||||
/// underlying stream.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut S {
|
||||
let InternalBufWriter(ref mut w) = self.inner.inner;
|
||||
w.get_mut()
|
||||
|
@ -368,6 +411,7 @@ impl<S: Read + Write> BufStream<S> {
|
|||
///
|
||||
/// The internal buffer is flushed before returning the stream. Any leftover
|
||||
/// data in the read buffer is lost.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> Result<S, IntoInnerError<BufStream<S>>> {
|
||||
let BufReader { inner: InternalBufWriter(w), buf } = self.inner;
|
||||
w.into_inner().map_err(|IntoInnerError(w, e)| {
|
||||
|
@ -378,17 +422,20 @@ impl<S: Read + Write> BufStream<S> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<S: Read + Write> BufRead for BufStream<S> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
|
||||
fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<S: Read + Write> Read for BufStream<S> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<S: Read + Write> Write for BufStream<S> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.inner.get_mut().write(buf)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use boxed::Box;
|
||||
use clone::Clone;
|
||||
use error::Error as StdError;
|
||||
use error;
|
||||
use fmt;
|
||||
use option::Option::{self, Some, None};
|
||||
use result;
|
||||
|
@ -22,6 +22,7 @@ use sys;
|
|||
///
|
||||
/// This typedef is generally used to avoid writing out `io::Error` directly and
|
||||
/// is otherwise a direct mapping to `std::result::Result`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
/// The error type for I/O operations of the `Read`, `Write`, `Seek`, and
|
||||
|
@ -31,6 +32,7 @@ pub type Result<T> = result::Result<T, Error>;
|
|||
/// `Error` can be created with crafted error messages and a particular value of
|
||||
/// `ErrorKind`.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Error {
|
||||
repr: Repr,
|
||||
}
|
||||
|
@ -50,6 +52,10 @@ struct Custom {
|
|||
|
||||
/// A list specifying general categories of I/O error.
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||
#[unstable(feature = "io",
|
||||
reason = "the interaction between OS error codes and how they map to \
|
||||
these names (as well as the names themselves) has not \
|
||||
been thoroughly thought out")]
|
||||
pub enum ErrorKind {
|
||||
/// The file was not found.
|
||||
FileNotFound,
|
||||
|
@ -96,6 +102,9 @@ pub enum ErrorKind {
|
|||
|
||||
impl Error {
|
||||
/// Creates a new custom error from a specified kind/description/detail.
|
||||
#[unstable(feature = "io", reason = "the exact makeup of an Error may
|
||||
change to include `Box<Error>` for \
|
||||
example")]
|
||||
pub fn new(kind: ErrorKind,
|
||||
description: &'static str,
|
||||
detail: Option<String>) -> Error {
|
||||
|
@ -113,16 +122,20 @@ impl Error {
|
|||
/// This function reads the value of `errno` for the target platform (e.g.
|
||||
/// `GetLastError` on Windows) and will return a corresponding instance of
|
||||
/// `Error` for the error code.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn last_os_error() -> Error {
|
||||
Error::from_os_error(sys::os::errno() as i32)
|
||||
}
|
||||
|
||||
/// Creates a new instance of an `Error` from a particular OS error code.
|
||||
#[unstable(feature = "io",
|
||||
reason = "unclear whether this function is necessary")]
|
||||
pub fn from_os_error(code: i32) -> Error {
|
||||
Error { repr: Repr::Os(code) }
|
||||
}
|
||||
|
||||
/// Return the corresponding `ErrorKind` for this error.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn kind(&self) -> ErrorKind {
|
||||
match self.repr {
|
||||
Repr::Os(code) => sys::decode_error_kind(code),
|
||||
|
@ -131,6 +144,9 @@ impl Error {
|
|||
}
|
||||
|
||||
/// Returns a short description for this error message
|
||||
#[unstable(feature = "io")]
|
||||
#[deprecated(since = "1.0.0", reason = "use the Error trait's description \
|
||||
method instead")]
|
||||
pub fn description(&self) -> &str {
|
||||
match self.repr {
|
||||
Repr::Os(..) => "os error",
|
||||
|
@ -139,6 +155,8 @@ impl Error {
|
|||
}
|
||||
|
||||
/// Returns a detailed error message for this error (if one is available)
|
||||
#[unstable(feature = "io")]
|
||||
#[deprecated(since = "1.0.0", reason = "use the to_string() method instead")]
|
||||
pub fn detail(&self) -> Option<String> {
|
||||
match self.repr {
|
||||
Repr::Os(code) => Some(sys::os::error_string(code)),
|
||||
|
@ -147,6 +165,7 @@ impl Error {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.repr {
|
||||
|
@ -173,7 +192,8 @@ impl fmt::Display for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl StdError for Error {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
match self.repr {
|
||||
Repr::Os(..) => "os error",
|
||||
|
|
|
@ -27,10 +27,10 @@ impl<'a, R: Read + ?Sized> Read for &'a mut R {
|
|||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
(**self).read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
(**self).read_to_end(buf)
|
||||
}
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
(**self).read_to_string(buf)
|
||||
}
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
|
|||
impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
|
||||
fn consume(&mut self, amt: usize) { (**self).consume(amt) }
|
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
(**self).read_until(byte, buf)
|
||||
}
|
||||
fn read_line(&mut self, buf: &mut String) -> io::Result<()> {
|
||||
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
(**self).read_line(buf)
|
||||
}
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ impl<R: Read + ?Sized> Read for Box<R> {
|
|||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
(**self).read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
(**self).read_to_end(buf)
|
||||
}
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
(**self).read_to_string(buf)
|
||||
}
|
||||
}
|
||||
|
@ -92,10 +92,10 @@ impl<S: Seek + ?Sized> Seek for Box<S> {
|
|||
impl<B: BufRead + ?Sized> BufRead for Box<B> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
|
||||
fn consume(&mut self, amt: usize) { (**self).consume(amt) }
|
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
(**self).read_until(byte, buf)
|
||||
}
|
||||
fn read_line(&mut self, buf: &mut String) -> io::Result<()> {
|
||||
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
(**self).read_line(buf)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,11 @@
|
|||
//! > development. At this time it is still recommended to use the `old_io`
|
||||
//! > module while the details of this module shake out.
|
||||
|
||||
#![unstable(feature = "io",
|
||||
reason = "this new I/O module is still under active development and \
|
||||
APIs are subject to tweaks fairly regularly")]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use cmp;
|
||||
use unicode::str as core_str;
|
||||
use error::Error as StdError;
|
||||
use error as std_error;
|
||||
use fmt;
|
||||
use iter::Iterator;
|
||||
use marker::Sized;
|
||||
|
@ -111,8 +109,8 @@ fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> Result<usize>
|
|||
// 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<()>
|
||||
where F: FnOnce(&mut Vec<u8>) -> Result<()>
|
||||
fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
|
||||
where F: FnOnce(&mut Vec<u8>) -> Result<usize>
|
||||
{
|
||||
struct Guard<'a> { s: &'a mut Vec<u8>, len: usize }
|
||||
#[unsafe_destructor]
|
||||
|
@ -126,7 +124,7 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<()>
|
|||
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() {
|
||||
ret.and_then(|()| {
|
||||
ret.and_then(|_| {
|
||||
Err(Error::new(ErrorKind::InvalidInput,
|
||||
"stream did not contain valid UTF-8", None))
|
||||
})
|
||||
|
@ -137,14 +135,15 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<()>
|
|||
}
|
||||
}
|
||||
|
||||
fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<()> {
|
||||
fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
|
||||
let mut read = 0;
|
||||
loop {
|
||||
if buf.capacity() == buf.len() {
|
||||
buf.reserve(DEFAULT_BUF_SIZE);
|
||||
}
|
||||
match with_end_to_cap(buf, |b| r.read(b)) {
|
||||
Ok(0) => return Ok(()),
|
||||
Ok(_) => {}
|
||||
Ok(0) => return Ok(read),
|
||||
Ok(n) => read += n,
|
||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
@ -159,6 +158,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<()> {
|
|||
/// Readers are intended to be composable with one another. Many objects
|
||||
/// throughout the I/O and related libraries take and provide types which
|
||||
/// implement the `Read` trait.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Read {
|
||||
/// Pull some bytes from this source into the specified buffer, returning
|
||||
/// how many bytes were read.
|
||||
|
@ -187,6 +187,7 @@ pub trait Read {
|
|||
/// If this function encounters any form of I/O or other error, an error
|
||||
/// variant will be returned. If an error is returned then it must be
|
||||
/// guaranteed that no bytes were read.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
|
||||
|
||||
/// Read all bytes until EOF in this source, placing them into `buf`.
|
||||
|
@ -198,7 +199,8 @@ pub trait Read {
|
|||
/// 2. Returns an error which is not of the kind `ErrorKind::Interrupted`.
|
||||
///
|
||||
/// Until one of these conditions is met the function will continuously
|
||||
/// invoke `read` to append more data to `buf`.
|
||||
/// invoke `read` to append more data to `buf`. If successful, this function
|
||||
/// will return the total number of bytes read.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -209,19 +211,24 @@ pub trait Read {
|
|||
/// If any other read error is encountered then this function immediately
|
||||
/// returns. Any bytes which have already been read will be appended to
|
||||
/// `buf`.
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<()> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
|
||||
read_to_end(self, buf)
|
||||
}
|
||||
|
||||
/// Read all bytes until EOF in this source, placing them into `buf`.
|
||||
///
|
||||
/// If successful, this function returns the number of bytes which were read
|
||||
/// and appended to `buf`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the data in this stream is *not* valid UTF-8 then an error is
|
||||
/// returned and `buf` is unchanged.
|
||||
///
|
||||
/// See `read_to_end` for other error semantics.
|
||||
fn read_to_string(&mut self, buf: &mut String) -> Result<()> {
|
||||
#[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
|
||||
|
@ -233,18 +240,13 @@ pub trait Read {
|
|||
// know is guaranteed to only read data into the end of the buffer.
|
||||
append_to_string(buf, |b| read_to_end(self, b))
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for all instances of `Read`, typically imported through
|
||||
/// `std::io::prelude::*`.
|
||||
#[unstable(feature = "io", reason = "may merge into the Read trait")]
|
||||
pub trait ReadExt: Read + Sized {
|
||||
/// Create a "by reference" adaptor for this instance of `Read`.
|
||||
///
|
||||
/// The returned adaptor also implements `Read` and will simply borrow this
|
||||
/// current reader.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn by_ref(&mut self) -> &mut Self { self }
|
||||
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
|
||||
|
||||
/// Transform this `Read` instance to an `Iterator` over its bytes.
|
||||
///
|
||||
|
@ -253,7 +255,7 @@ pub trait ReadExt: Read + Sized {
|
|||
/// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from
|
||||
/// this iterator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn bytes(self) -> Bytes<Self> {
|
||||
fn bytes(self) -> Bytes<Self> where Self: Sized {
|
||||
Bytes { inner: self }
|
||||
}
|
||||
|
||||
|
@ -270,7 +272,7 @@ pub trait ReadExt: Read + Sized {
|
|||
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
|
||||
of where errors happen is currently \
|
||||
unclear and may change")]
|
||||
fn chars(self) -> Chars<Self> {
|
||||
fn chars(self) -> Chars<Self> where Self: Sized {
|
||||
Chars { inner: self }
|
||||
}
|
||||
|
||||
|
@ -280,7 +282,7 @@ pub trait ReadExt: Read + Sized {
|
|||
/// until EOF is encountered. Afterwards the output is equivalent to the
|
||||
/// output of `next`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn chain<R: Read>(self, next: R) -> Chain<Self, R> {
|
||||
fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized {
|
||||
Chain { first: self, second: next, done_first: false }
|
||||
}
|
||||
|
||||
|
@ -291,7 +293,7 @@ pub trait ReadExt: Read + Sized {
|
|||
/// read errors will not count towards the number of bytes read and future
|
||||
/// calls to `read` may succeed.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn take(self, limit: u64) -> Take<Self> {
|
||||
fn take(self, limit: u64) -> Take<Self> where Self: Sized {
|
||||
Take { inner: self, limit: limit }
|
||||
}
|
||||
|
||||
|
@ -304,13 +306,11 @@ pub trait ReadExt: Read + Sized {
|
|||
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
|
||||
of where errors happen is currently \
|
||||
unclear and may change")]
|
||||
fn tee<W: Write>(self, out: W) -> Tee<Self, W> {
|
||||
fn tee<W: Write>(self, out: W) -> Tee<Self, W> where Self: Sized {
|
||||
Tee { reader: self, writer: out }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read> ReadExt for T {}
|
||||
|
||||
/// A trait for objects which are byte-oriented sinks.
|
||||
///
|
||||
/// The `write` method will attempt to write some data into the object,
|
||||
|
@ -322,6 +322,7 @@ impl<T: Read> ReadExt for T {}
|
|||
/// Writers are intended to be composable with one another. Many objects
|
||||
/// throughout the I/O and related libraries take and provide types which
|
||||
/// implement the `Write` trait.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Write {
|
||||
/// Write a buffer into this object, returning how many bytes were written.
|
||||
///
|
||||
|
@ -347,6 +348,7 @@ pub trait Write {
|
|||
///
|
||||
/// It is **not** considered an error if the entire buffer could not be
|
||||
/// written to this writer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize>;
|
||||
|
||||
/// Flush this output stream, ensuring that all intermediately buffered
|
||||
|
@ -356,6 +358,7 @@ pub trait Write {
|
|||
///
|
||||
/// It is considered an error if not all bytes could be written due to
|
||||
/// I/O errors or EOF being reached.
|
||||
#[unstable(feature = "io", reason = "waiting for RFC 950")]
|
||||
fn flush(&mut self) -> Result<()>;
|
||||
|
||||
/// Attempts to write an entire buffer into this write.
|
||||
|
@ -368,6 +371,7 @@ pub trait Write {
|
|||
/// # Errors
|
||||
///
|
||||
/// This function will return the first error that `write` returns.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
|
||||
while buf.len() > 0 {
|
||||
match self.write(buf) {
|
||||
|
@ -396,6 +400,7 @@ pub trait Write {
|
|||
/// # Errors
|
||||
///
|
||||
/// This function will return any I/O error reported while formatting.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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
|
||||
|
@ -422,18 +427,13 @@ pub trait Write {
|
|||
Err(..) => output.error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for all instances of `Write`, typically imported through
|
||||
/// `std::io::prelude::*`.
|
||||
#[unstable(feature = "io", reason = "may merge into the Read trait")]
|
||||
pub trait WriteExt: Write + Sized {
|
||||
/// Create a "by reference" adaptor for this instance of `Write`.
|
||||
///
|
||||
/// The returned adaptor also implements `Write` and will simply borrow this
|
||||
/// current writer.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn by_ref(&mut self) -> &mut Self { self }
|
||||
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
|
||||
|
||||
/// Creates a new writer which will write all data to both this writer and
|
||||
/// another writer.
|
||||
|
@ -446,19 +446,21 @@ pub trait WriteExt: Write + Sized {
|
|||
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
|
||||
of where errors happen is currently \
|
||||
unclear and may change")]
|
||||
fn broadcast<W: Write>(self, other: W) -> Broadcast<Self, W> {
|
||||
fn broadcast<W: Write>(self, other: W) -> Broadcast<Self, W>
|
||||
where Self: Sized
|
||||
{
|
||||
Broadcast { first: self, second: other }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Write> WriteExt for T {}
|
||||
|
||||
/// An object implementing `Seek` internally has some form of cursor which can
|
||||
/// be moved within a stream of bytes.
|
||||
///
|
||||
/// The stream typically has a fixed size, allowing seeking relative to either
|
||||
/// end or the current offset.
|
||||
#[unstable(feature = "io", reason = "the central `seek` method may be split \
|
||||
into multiple methods instead of taking \
|
||||
an enum as an argument")]
|
||||
pub trait Seek {
|
||||
/// Seek to an offset, in bytes, in a stream
|
||||
///
|
||||
|
@ -479,6 +481,7 @@ pub trait Seek {
|
|||
|
||||
/// Enumeration of possible methods to seek within an I/O object.
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||
#[unstable(feature = "io", reason = "awaiting the stability of Seek")]
|
||||
pub enum SeekFrom {
|
||||
/// Set the offset to the provided number of bytes.
|
||||
Start(u64),
|
||||
|
@ -499,7 +502,8 @@ pub enum SeekFrom {
|
|||
}
|
||||
|
||||
fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
|
||||
-> Result<()> {
|
||||
-> Result<usize> {
|
||||
let mut read = 0;
|
||||
loop {
|
||||
let (done, used) = {
|
||||
let available = match r.fill_buf() {
|
||||
|
@ -519,8 +523,9 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
|
|||
}
|
||||
};
|
||||
r.consume(used);
|
||||
read += used;
|
||||
if done || used == 0 {
|
||||
return Ok(());
|
||||
return Ok(read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -530,6 +535,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
|
|||
///
|
||||
/// This type extends the `Read` trait with a few methods that are not
|
||||
/// possible to reasonably implement with purely a read interface.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait BufRead: Read {
|
||||
/// Fills the internal buffer of this object, returning the buffer contents.
|
||||
///
|
||||
|
@ -546,10 +552,16 @@ pub trait BufRead: Read {
|
|||
///
|
||||
/// This function will return an I/O error if the underlying reader was
|
||||
/// read, but returned an error.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fill_buf(&mut self) -> Result<&[u8]>;
|
||||
|
||||
/// Tells this buffer that `amt` bytes have been consumed from the buffer,
|
||||
/// so they should no longer be returned in calls to `read`.
|
||||
///
|
||||
/// 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 no longer be returned.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn consume(&mut self, amt: usize);
|
||||
|
||||
/// Read all bytes until the delimiter `byte` is reached.
|
||||
|
@ -560,7 +572,8 @@ pub trait BufRead: Read {
|
|||
/// `buf`.
|
||||
///
|
||||
/// If this buffered reader is currently at EOF, then this function will not
|
||||
/// place any more bytes into `buf` and will return `Ok(())`.
|
||||
/// place any more bytes into `buf` and will return `Ok(n)` where `n` is the
|
||||
/// number of bytes which were read.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -569,7 +582,8 @@ pub trait BufRead: Read {
|
|||
///
|
||||
/// 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.
|
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<()> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
|
||||
read_until(self, byte, buf)
|
||||
}
|
||||
|
||||
|
@ -581,7 +595,8 @@ pub trait BufRead: Read {
|
|||
/// found) will be appended to `buf`.
|
||||
///
|
||||
/// If this reader is currently at EOF then this function will not modify
|
||||
/// `buf` and will return `Ok(())`.
|
||||
/// `buf` and will return `Ok(n)` where `n` is the number of bytes which
|
||||
/// were read.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -589,17 +604,14 @@ pub trait BufRead: Read {
|
|||
/// 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.
|
||||
fn read_line(&mut self, buf: &mut String) -> Result<()> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn read_line(&mut self, buf: &mut String) -> Result<usize> {
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for all instances of `BufRead`, typically imported through
|
||||
/// `std::io::prelude::*`.
|
||||
pub trait BufReadExt: BufRead + Sized {
|
||||
/// Returns an iterator over the contents of this reader split on the byte
|
||||
/// `byte`.
|
||||
///
|
||||
|
@ -611,7 +623,7 @@ pub trait BufReadExt: BufRead + Sized {
|
|||
/// yielded an error.
|
||||
#[unstable(feature = "io", reason = "may be renamed to not conflict with \
|
||||
SliceExt::split")]
|
||||
fn split(self, byte: u8) -> Split<Self> {
|
||||
fn split(self, byte: u8) -> Split<Self> where Self: Sized {
|
||||
Split { buf: self, delim: byte }
|
||||
}
|
||||
|
||||
|
@ -624,22 +636,21 @@ pub trait BufReadExt: BufRead + Sized {
|
|||
/// This function will yield errors whenever `read_string` would have also
|
||||
/// yielded an error.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn lines(self) -> Lines<Self> {
|
||||
fn lines(self) -> Lines<Self> where Self: Sized {
|
||||
Lines { buf: self }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: BufRead> BufReadExt for T {}
|
||||
|
||||
/// A `Write` adaptor which will write data to multiple locations.
|
||||
///
|
||||
/// For more information, see `WriteExt::broadcast`.
|
||||
#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")]
|
||||
pub struct Broadcast<T, U> {
|
||||
first: T,
|
||||
second: U,
|
||||
}
|
||||
|
||||
#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")]
|
||||
impl<T: Write, U: Write> Write for Broadcast<T, U> {
|
||||
fn write(&mut self, data: &[u8]) -> Result<usize> {
|
||||
let n = try!(self.first.write(data));
|
||||
|
@ -732,11 +743,13 @@ impl<T: BufRead> BufRead for Take<T> {
|
|||
/// An adaptor which will emit all read data to a specified writer as well.
|
||||
///
|
||||
/// For more information see `ReadExt::tee`
|
||||
#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")]
|
||||
pub struct Tee<R, W> {
|
||||
reader: R,
|
||||
writer: W,
|
||||
}
|
||||
|
||||
#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")]
|
||||
impl<R: Read, W: Write> Read for Tee<R, W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
let n = try!(self.reader.read(buf));
|
||||
|
@ -771,6 +784,7 @@ impl<R: Read> Iterator for Bytes<R> {
|
|||
/// A bridge from implementations of `Read` to an `Iterator` of `char`.
|
||||
///
|
||||
/// See `ReadExt::chars` for more information.
|
||||
#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
|
||||
pub struct Chars<R> {
|
||||
inner: R,
|
||||
}
|
||||
|
@ -778,6 +792,7 @@ pub struct Chars<R> {
|
|||
/// An enumeration of possible errors that can be generated from the `Chars`
|
||||
/// adapter.
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
|
||||
pub enum CharsError {
|
||||
/// Variant representing that the underlying stream was read successfully
|
||||
/// but it did not contain valid utf8 data.
|
||||
|
@ -787,6 +802,7 @@ pub enum CharsError {
|
|||
Other(Error),
|
||||
}
|
||||
|
||||
#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
|
||||
impl<R: Read> Iterator for Chars<R> {
|
||||
type Item = result::Result<char, CharsError>;
|
||||
|
||||
|
@ -818,14 +834,15 @@ impl<R: Read> Iterator for Chars<R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl StdError for CharsError {
|
||||
#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
|
||||
impl std_error::Error for CharsError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
CharsError::NotUtf8 => "invalid utf8 encoding",
|
||||
CharsError::Other(ref e) => e.description(),
|
||||
CharsError::Other(ref e) => std_error::Error::description(e),
|
||||
}
|
||||
}
|
||||
fn cause(&self) -> Option<&StdError> {
|
||||
fn cause(&self) -> Option<&std_error::Error> {
|
||||
match *self {
|
||||
CharsError::NotUtf8 => None,
|
||||
CharsError::Other(ref e) => e.cause(),
|
||||
|
@ -833,6 +850,7 @@ impl StdError for CharsError {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
|
||||
impl fmt::Display for CharsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -848,19 +866,21 @@ impl fmt::Display for CharsError {
|
|||
/// particular byte.
|
||||
///
|
||||
/// See `BufReadExt::split` for more information.
|
||||
#[unstable(feature = "io", reason = "awaiting stability of BufReadExt::split")]
|
||||
pub struct Split<B> {
|
||||
buf: B,
|
||||
delim: u8,
|
||||
}
|
||||
|
||||
#[unstable(feature = "io", reason = "awaiting stability of BufReadExt::split")]
|
||||
impl<B: BufRead> Iterator for Split<B> {
|
||||
type Item = Result<Vec<u8>>;
|
||||
|
||||
fn next(&mut self) -> Option<Result<Vec<u8>>> {
|
||||
let mut buf = Vec::new();
|
||||
match self.buf.read_until(self.delim, &mut buf) {
|
||||
Ok(()) if buf.len() == 0 => None,
|
||||
Ok(()) => {
|
||||
Ok(0) => None,
|
||||
Ok(_n) => {
|
||||
if buf[buf.len() - 1] == self.delim {
|
||||
buf.pop();
|
||||
}
|
||||
|
@ -887,8 +907,8 @@ impl<B: BufRead> Iterator for Lines<B> {
|
|||
fn next(&mut self) -> Option<Result<String>> {
|
||||
let mut buf = String::new();
|
||||
match self.buf.read_line(&mut buf) {
|
||||
Ok(()) if buf.len() == 0 => None,
|
||||
Ok(()) => {
|
||||
Ok(0) => None,
|
||||
Ok(_n) => {
|
||||
if buf.ends_with("\n") {
|
||||
buf.pop();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
//! `Write`, `ReadExt`, and `WriteExt`. Structures and functions are not
|
||||
//! contained in this module.
|
||||
|
||||
pub use super::{Read, ReadExt, Write, WriteExt, BufRead, BufReadExt};
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
pub use super::{Read, Write, BufRead};
|
||||
pub use fs::PathExt;
|
||||
|
||||
// FIXME: pub use as `Seek` when the name isn't in the actual prelude any more
|
||||
|
|
|
@ -86,6 +86,7 @@ impl Write for StderrRaw {
|
|||
///
|
||||
/// This handle implements the `Read` trait, but beware that concurrent reads
|
||||
/// of `Stdin` must be executed with care.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Stdin {
|
||||
inner: Arc<Mutex<BufReader<StdinRaw>>>,
|
||||
}
|
||||
|
@ -94,6 +95,7 @@ pub struct Stdin {
|
|||
///
|
||||
/// This handle implements both the `Read` and `BufRead` traits and is
|
||||
/// constructed via the `lock` method on `Stdin`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct StdinLock<'a> {
|
||||
inner: MutexGuard<'a, BufReader<StdinRaw>>,
|
||||
}
|
||||
|
@ -110,6 +112,7 @@ pub struct StdinLock<'a> {
|
|||
///
|
||||
/// To avoid locking and buffering altogether, it is recommended to use the
|
||||
/// `stdin_raw` constructor.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn stdin() -> Stdin {
|
||||
static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init);
|
||||
return Stdin {
|
||||
|
@ -136,30 +139,41 @@ impl Stdin {
|
|||
/// The lock is released when the returned lock goes out of scope. The
|
||||
/// returned guard also implements the `Read` and `BufRead` traits for
|
||||
/// accessing the underlying data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn lock(&self) -> StdinLock {
|
||||
StdinLock { inner: self.inner.lock().unwrap() }
|
||||
}
|
||||
|
||||
/// Locks this handle and reads a line of input into the specified buffer.
|
||||
///
|
||||
/// For detailed semantics of this method, see the documentation on
|
||||
/// `BufRead::read_line`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
self.lock().read_line(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.lock().read(buf)
|
||||
}
|
||||
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.lock().read_to_end(buf)
|
||||
}
|
||||
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
self.lock().read_to_string(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a> Read for StdinLock<'a> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a> BufRead for StdinLock<'a> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
|
||||
fn consume(&mut self, n: usize) { self.inner.consume(n) }
|
||||
|
@ -186,6 +200,7 @@ const OUT_MAX: usize = ::usize::MAX;
|
|||
/// Each handle shares a global buffer of data to be written to the standard
|
||||
/// output stream. Access is also synchronized via a lock and explicit control
|
||||
/// over locking is available via the `lock` method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Stdout {
|
||||
// FIXME: this should be LineWriter or BufWriter depending on the state of
|
||||
// stdout (tty or not). Note that if this is not line buffered it
|
||||
|
@ -197,6 +212,7 @@ pub struct Stdout {
|
|||
///
|
||||
/// This handle implements the `Write` trait and is constructed via the `lock`
|
||||
/// method on `Stdout`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct StdoutLock<'a> {
|
||||
inner: MutexGuard<'a, LineWriter<StdoutRaw>>,
|
||||
}
|
||||
|
@ -211,6 +227,7 @@ pub struct StdoutLock<'a> {
|
|||
///
|
||||
/// To avoid locking and buffering altogether, it is recommended to use the
|
||||
/// `stdout_raw` constructor.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn stdout() -> Stdout {
|
||||
static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init);
|
||||
return Stdout {
|
||||
|
@ -228,11 +245,13 @@ impl Stdout {
|
|||
///
|
||||
/// The lock is released when the returned lock goes out of scope. The
|
||||
/// returned guard also implements the `Write` trait for writing data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn lock(&self) -> StdoutLock {
|
||||
StdoutLock { inner: self.inner.lock().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.lock().write(buf)
|
||||
|
@ -247,6 +266,7 @@ impl Write for Stdout {
|
|||
self.lock().write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a> Write for StdoutLock<'a> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
|
||||
|
@ -257,6 +277,7 @@ impl<'a> Write for StdoutLock<'a> {
|
|||
/// A handle to the standard error stream of a process.
|
||||
///
|
||||
/// For more information, see `stderr`
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Stderr {
|
||||
inner: Arc<Mutex<StderrRaw>>,
|
||||
}
|
||||
|
@ -265,6 +286,7 @@ pub struct Stderr {
|
|||
///
|
||||
/// This handle implements the `Write` trait and is constructed via the `lock`
|
||||
/// method on `Stderr`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct StderrLock<'a> {
|
||||
inner: MutexGuard<'a, StderrRaw>,
|
||||
}
|
||||
|
@ -278,6 +300,7 @@ pub struct StderrLock<'a> {
|
|||
///
|
||||
/// To avoid locking altogether, it is recommended to use the `stderr_raw`
|
||||
/// constructor.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn stderr() -> Stderr {
|
||||
static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init);
|
||||
return Stderr {
|
||||
|
@ -295,11 +318,13 @@ impl Stderr {
|
|||
///
|
||||
/// The lock is released when the returned lock goes out of scope. The
|
||||
/// returned guard also implements the `Write` trait for writing data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn lock(&self) -> StderrLock {
|
||||
StderrLock { inner: self.inner.lock().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.lock().write(buf)
|
||||
|
@ -314,6 +339,7 @@ impl Write for Stderr {
|
|||
self.lock().write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a> Write for StderrLock<'a> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
|
||||
|
|
|
@ -242,6 +242,9 @@
|
|||
#![deny(unused_must_use)]
|
||||
#![allow(deprecated)] // seriously this is all deprecated
|
||||
#![allow(unused_imports)]
|
||||
#![deprecated(since = "1.0.0",
|
||||
reasons = "APIs have been replaced with new I/O modules such as \
|
||||
std::{io, fs, net, process}")]
|
||||
|
||||
pub use self::SeekStyle::*;
|
||||
pub use self::FileMode::*;
|
||||
|
|
|
@ -148,7 +148,6 @@ use cell::UnsafeCell;
|
|||
use fmt;
|
||||
use io;
|
||||
use marker::PhantomData;
|
||||
use old_io::stdio;
|
||||
use rt::{self, unwind};
|
||||
use sync::{Mutex, Condvar, Arc};
|
||||
use thunk::Thunk;
|
||||
|
@ -165,10 +164,6 @@ pub struct Builder {
|
|||
name: Option<String>,
|
||||
// The size of the stack for the spawned thread
|
||||
stack_size: Option<usize>,
|
||||
// Thread-local stdout
|
||||
stdout: Option<Box<Writer + Send + 'static>>,
|
||||
// Thread-local stderr
|
||||
stderr: Option<Box<Writer + Send + 'static>>,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
|
@ -179,8 +174,6 @@ impl Builder {
|
|||
Builder {
|
||||
name: None,
|
||||
stack_size: None,
|
||||
stdout: None,
|
||||
stderr: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,16 +195,22 @@ impl Builder {
|
|||
/// Redirect thread-local stdout.
|
||||
#[unstable(feature = "std_misc",
|
||||
reason = "Will likely go away after proc removal")]
|
||||
pub fn stdout(mut self, stdout: Box<Writer + Send + 'static>) -> Builder {
|
||||
self.stdout = Some(stdout);
|
||||
#[deprecated(since = "1.0.0",
|
||||
reason = "the old I/O module is deprecated and this function \
|
||||
will be removed with no replacement")]
|
||||
#[allow(deprecated)]
|
||||
pub fn stdout(self, _stdout: Box<Writer + Send + 'static>) -> Builder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Redirect thread-local stderr.
|
||||
#[unstable(feature = "std_misc",
|
||||
reason = "Will likely go away after proc removal")]
|
||||
pub fn stderr(mut self, stderr: Box<Writer + Send + 'static>) -> Builder {
|
||||
self.stderr = Some(stderr);
|
||||
#[deprecated(since = "1.0.0",
|
||||
reason = "the old I/O module is deprecated and this function \
|
||||
will be removed with no replacement")]
|
||||
#[allow(deprecated)]
|
||||
pub fn stderr(self, _stderr: Box<Writer + Send + 'static>) -> Builder {
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -259,7 +258,7 @@ impl Builder {
|
|||
}
|
||||
|
||||
fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
|
||||
let Builder { name, stack_size, stdout, stderr } = self;
|
||||
let Builder { name, stack_size } = self;
|
||||
|
||||
let stack_size = stack_size.unwrap_or(rt::min_stack());
|
||||
|
||||
|
@ -290,16 +289,6 @@ impl Builder {
|
|||
}
|
||||
|
||||
let mut output = None;
|
||||
let f: Thunk<(), T> = if stdout.is_some() || stderr.is_some() {
|
||||
Thunk::new(move || {
|
||||
let _ = stdout.map(stdio::set_stdout);
|
||||
let _ = stderr.map(stdio::set_stderr);
|
||||
f.invoke(())
|
||||
})
|
||||
} else {
|
||||
f
|
||||
};
|
||||
|
||||
let try_result = {
|
||||
let ptr = &mut output;
|
||||
|
||||
|
|
Loading…
Reference in a new issue