From 0dfa9978cc57efc8eb51485fc3a333eafd1aa392 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Mar 2015 14:49:03 -0800 Subject: std: Stabilize portions of the `io` module The new `io` module has had some time to bake and this commit stabilizes some of the utilities associated with it. This commit also deprecates a number of `std::old_io::util` functions and structures. These items are now `#[stable]` * `Cursor` * `Cursor::{new, into_inner, get_ref, get_mut, position, set_position}` * Implementations of I/O traits for `Cursor` * Delegating implementations of I/O traits for references and `Box` pointers * Implementations of I/O traits for primitives like slices and `Vec` * `ReadExt::bytes` * `Bytes` (and impls) * `ReadExt::chain` * `Chain` (and impls) * `ReadExt::take` (and impls) * `BufReadExt::lines` * `Lines` (and impls) * `io::copy` * `io::{empty, Empty}` (and impls) * `io::{sink, Sink}` (and impls) * `io::{repeat, Repeat}` (and impls) These items remain `#[unstable]` * Core I/O traits. These may want a little bit more time to bake along with the commonly used methods like `read_to_end`. * `BufReadExt::split` - this function may be renamed to not conflict with `SliceExt::split`. * `Error` - there are a number of questions about its representation, `ErrorKind`, and usability. These items are now `#[deprecated]` in `old_io` * `LimitReader` - use `take` instead * `NullWriter` - use `io::sink` instead * `ZeroReader` - use `io::repeat` instead * `NullReader` - use `io::empty` instead * `MultiWriter` - use `broadcast` instead * `ChainedReader` - use `chain` instead * `TeeReader` - use `tee` instead * `copy` - use `io::copy` instead [breaking-change] --- src/libstd/io/cursor.rs | 20 ++++++++++++++-- src/libstd/io/impls.rs | 64 +++++++++++++++++++++++++++++++++++++------------ src/libstd/io/mod.rs | 32 +++++++++++++++++++++++++ src/libstd/io/util.rs | 17 ++++++++++++- 4 files changed, 115 insertions(+), 18 deletions(-) (limited to 'src/libstd/io') diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index b1779587528..78f9222bde7 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(missing_copy_implementations)] - use prelude::v1::*; use io::prelude::*; @@ -32,6 +30,7 @@ use slice; /// Implementations of the I/O traits for `Cursor` are not currently generic /// over `T` itself. Instead, specific implementations are provided for various /// in-memory buffer types like `Vec` and `&[u8]`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Cursor { inner: T, pos: u64, @@ -39,26 +38,32 @@ pub struct Cursor { impl Cursor { /// Create a new cursor wrapping the provided underlying I/O object. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: T) -> Cursor { Cursor { pos: 0, inner: inner } } /// Consume this cursor, returning the underlying value. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> T { self.inner } /// Get a reference to the underlying value in this cursor. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &T { &self.inner } /// Get a mutable reference to the underlying value in this cursor. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying value as it may corrupt this cursor's position. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut T { &mut self.inner } /// Returns the current value of this cursor + #[stable(feature = "rust1", since = "1.0.0")] pub fn position(&self) -> u64 { self.pos } /// Sets the value of this cursor + #[stable(feature = "rust1", since = "1.0.0")] pub fn set_position(&mut self, pos: u64) { self.pos = pos; } } @@ -83,8 +88,11 @@ macro_rules! seek { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> io::Seek for Cursor<&'a [u8]> { seek!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> io::Seek for Cursor<&'a mut [u8]> { seek!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl io::Seek for Cursor> { seek!(); } macro_rules! read { @@ -97,8 +105,11 @@ macro_rules! read { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for Cursor<&'a [u8]> { read!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for Cursor<&'a mut [u8]> { read!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Cursor> { read!(); } macro_rules! buffer { @@ -111,10 +122,14 @@ macro_rules! buffer { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor<&'a [u8]> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor<&'a mut [u8]> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for Cursor<&'a mut [u8]> { fn write(&mut self, data: &[u8]) -> io::Result { let pos = cmp::min(self.pos, self.inner.len() as u64); @@ -125,6 +140,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Cursor> { fn write(&mut self, buf: &[u8]) -> io::Result { // Make sure the internal buffer is as least as big as where we diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 82b69ddebff..c968415d3ef 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -22,57 +22,88 @@ use vec::Vec; // ============================================================================= // Forwarding implementations +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, R: Read + ?Sized> Read for &'a mut R { - fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result<()> { (**self).read_to_end(buf) } - + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result<()> { + (**self).read_to_end(buf) + } fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_to_string(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, W: Write + ?Sized> Write for &'a mut W { fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } - - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_all(buf) } - - fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { (**self).write_fmt(fmt) } - fn flush(&mut self) -> io::Result<()> { (**self).flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, S: Seek + ?Sized> Seek for &'a mut S { fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] 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) -> io::Result<()> { (**self).read_until(byte, buf) } - - fn read_line(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_line(buf) } + fn read_line(&mut self, buf: &mut String) -> io::Result<()> { + (**self).read_line(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Box { - fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result<()> { + (**self).read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> { + (**self).read_to_string(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Box { fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } fn flush(&mut self) -> io::Result<()> { (**self).flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Seek for Box { fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Box { 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) -> io::Result<()> { + (**self).read_until(byte, buf) + } + fn read_line(&mut self, buf: &mut String) -> io::Result<()> { + (**self).read_line(buf) + } } // ============================================================================= // In-memory buffer implementations +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a [u8] { fn read(&mut self, buf: &mut [u8]) -> io::Result { let amt = cmp::min(buf.len(), self.len()); @@ -83,11 +114,13 @@ impl<'a> Read for &'a [u8] { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for &'a [u8] { fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } fn consume(&mut self, amt: usize) { *self = &self[amt..]; } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a mut [u8] { fn write(&mut self, data: &[u8]) -> io::Result { let amt = cmp::min(data.len(), self.len()); @@ -108,6 +141,7 @@ impl<'a> Write for &'a mut [u8] { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Vec { fn write(&mut self, buf: &[u8]) -> io::Result { self.push_all(buf); @@ -115,7 +149,7 @@ impl Write for Vec { } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - try!(self.write(buf)); + self.push_all(buf); Ok(()) } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 5510c0203e6..a91ab57c7e9 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -237,11 +237,13 @@ pub trait Read { /// 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 } /// Transform this `Read` instance to an `Iterator` over its bytes. @@ -250,6 +252,7 @@ pub trait ReadExt: Read + Sized { /// R::Err>`. 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. + #[stable(feature = "rust1", since = "1.0.0")] fn bytes(self) -> Bytes { Bytes { inner: self } } @@ -264,6 +267,9 @@ pub trait ReadExt: Read + Sized { /// /// Currently this adaptor will discard intermediate data read, and should /// be avoided if this is not desired. + #[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 { Chars { inner: self } } @@ -273,6 +279,7 @@ pub trait ReadExt: Read + Sized { /// The returned `Read` instance will first read all bytes from this object /// until EOF is encountered. Afterwards the output is equivalent to the /// output of `next`. + #[stable(feature = "rust1", since = "1.0.0")] fn chain(self, next: R) -> Chain { Chain { first: self, second: next, done_first: false } } @@ -283,6 +290,7 @@ pub trait ReadExt: Read + Sized { /// `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. + #[stable(feature = "rust1", since = "1.0.0")] fn take(self, limit: u64) -> Take { Take { inner: self, limit: limit } } @@ -293,6 +301,9 @@ pub trait ReadExt: Read + Sized { /// Whenever the returned `Read` instance is read it will write the read /// data to `out`. The current semantics of this implementation imply that /// a `write` error will not report how much data was initially read. + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] fn tee(self, out: W) -> Tee { Tee { reader: self, writer: out } } @@ -415,11 +426,13 @@ pub trait Write { /// 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 } /// Creates a new writer which will write all data to both this writer and @@ -430,11 +443,15 @@ pub trait WriteExt: Write + Sized { /// implementation do not precisely track where errors happen. For example /// an error on the second call to `write` will not report that the first /// call to `write` succeeded. + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] fn broadcast(self, other: W) -> Broadcast { Broadcast { first: self, second: other } } } +#[stable(feature = "rust1", since = "1.0.0")] impl WriteExt for T {} /// An object implementing `Seek` internally has some form of cursor which can @@ -592,6 +609,8 @@ pub trait BufReadExt: BufRead + Sized { /// /// This function will yield errors whenever `read_until` would have also /// yielded an error. + #[unstable(feature = "io", reason = "may be renamed to not conflict with \ + SliceExt::split")] fn split(self, byte: u8) -> Split { Split { buf: self, delim: byte } } @@ -604,11 +623,13 @@ 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 { Lines { buf: self } } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufReadExt for T {} /// A `Write` adaptor which will write data to multiple locations. @@ -635,12 +656,14 @@ impl Write for Broadcast { /// Adaptor to chain together two instances of `Read`. /// /// For more information, see `ReadExt::chain`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Chain { first: T, second: U, done_first: bool, } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { if !self.done_first { @@ -656,11 +679,13 @@ impl Read for Chain { /// Reader adaptor which limits the bytes read from an underlying reader. /// /// For more information, see `ReadExt::take`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Take { inner: T, limit: u64, } +#[stable(feature = "rust1", since = "1.0.0")] impl Take { /// Returns the number of bytes that can be read before this instance will /// return EOF. @@ -669,9 +694,11 @@ impl Take { /// /// This instance may reach EOF after reading fewer bytes than indicated by /// this method if the underlying `Read` instance reaches EOF. + #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Take { fn read(&mut self, buf: &mut [u8]) -> Result { // Don't call into inner reader at all at EOF because it may still block @@ -686,6 +713,7 @@ impl Read for Take { } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Take { fn fill_buf(&mut self) -> Result<&[u8]> { let buf = try!(self.inner.fill_buf()); @@ -721,10 +749,12 @@ impl Read for Tee { /// A bridge from implementations of `Read` to an `Iterator` of `u8`. /// /// See `ReadExt::bytes` for more information. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Bytes { inner: R, } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Bytes { type Item = Result; @@ -845,10 +875,12 @@ impl Iterator for Split { /// byte. /// /// See `BufReadExt::lines` for more information. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Lines { buf: B, } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Lines { type Item = Result; diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 3d342137c62..20426025257 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -12,7 +12,7 @@ use prelude::v1::*; -use io::{self, Read, Write, ErrorKind}; +use io::{self, Read, Write, ErrorKind, BufRead}; /// Copies the entire contents of a reader into a writer. /// @@ -27,6 +27,7 @@ use io::{self, Read, Write, ErrorKind}; /// This function will return an error immediately if any call to `read` or /// `write` returns an error. All instances of `ErrorKind::Interrupted` are /// handled by this function and the underlying operation is retried. +#[stable(feature = "rust1", since = "1.0.0")] pub fn copy(r: &mut R, w: &mut W) -> io::Result { let mut buf = [0; super::DEFAULT_BUF_SIZE]; let mut written = 0; @@ -43,26 +44,37 @@ pub fn copy(r: &mut R, w: &mut W) -> io::Result { } /// A reader which is always at EOF. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Empty { _priv: () } /// Creates an instance of an empty reader. /// /// All reads from the returned reader will return `Ok(0)`. +#[stable(feature = "rust1", since = "1.0.0")] pub fn empty() -> Empty { Empty { _priv: () } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Empty { fn read(&mut self, _buf: &mut [u8]) -> io::Result { Ok(0) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl BufRead for Empty { + fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } + fn consume(&mut self, _n: usize) {} +} /// A reader which infinitely yields one byte. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Repeat { byte: u8 } /// Creates an instance of a reader that infinitely repeats one byte. /// /// All reads from this reader will succeed by filling the specified buffer with /// the given byte. +#[stable(feature = "rust1", since = "1.0.0")] pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Repeat { fn read(&mut self, buf: &mut [u8]) -> io::Result { for slot in buf.iter_mut() { @@ -73,14 +85,17 @@ impl Read for Repeat { } /// A writer which will move data into the void. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Sink { _priv: () } /// Creates an instance of a writer which will successfully consume all data. /// /// All calls to `write` on the returned instance will return `Ok(buf.len())` /// and the contents of the buffer will not be inspected. +#[stable(feature = "rust1", since = "1.0.0")] pub fn sink() -> Sink { Sink { _priv: () } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Sink { fn write(&mut self, buf: &[u8]) -> io::Result { Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } -- cgit 1.4.1-3-g733a5