Implement Show for types in std::io::{buffered,util}

A derived implementation would not be appropriate for the Buffered types
since the buffer is both huge (64k by default) and full of uninitialized
memory. Instead of printing the whole thing, we display how full it is.

I also altered MultiWriter to make it generic over Writers instead of
taking Box<Writer> trait objects. Box<Writer> implements Writer so
existing use cases should continue to work, and this enables a more
useful Show implementation in applicable cases.

The change to MultiWriter may break code that uses it, but any fixes
should be easy.

[breaking-change]
This commit is contained in:
Steven Fackler 2015-01-10 17:32:54 -08:00
parent 099b411e08
commit b4fae2fba9
2 changed files with 46 additions and 10 deletions

View File

@ -13,6 +13,7 @@
//! Buffering wrappers for I/O traits
use cmp;
use fmt;
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
use iter::{IteratorExt, ExactSizeIterator};
use ops::Drop;
@ -51,6 +52,13 @@ pub struct BufferedReader<R> {
cap: uint,
}
impl<R> fmt::Show for BufferedReader<R> where R: fmt::Show {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "BufferedReader {{ reader: {:?}, buffer: {}/{} }}",
self.inner, self.cap - self.pos, self.buf.len())
}
}
impl<R: Reader> BufferedReader<R> {
/// Creates a new `BufferedReader` with the specified buffer capacity
pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> {
@ -148,6 +156,13 @@ pub struct BufferedWriter<W> {
pos: uint
}
impl<W> fmt::Show for BufferedWriter<W> where W: fmt::Show {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
self.inner.as_ref().unwrap(), self.pos, self.buf.len())
}
}
impl<W: Writer> BufferedWriter<W> {
/// Creates a new `BufferedWriter` with the specified buffer capacity
pub fn with_capacity(cap: uint, inner: W) -> BufferedWriter<W> {
@ -235,6 +250,13 @@ pub struct LineBufferedWriter<W> {
inner: BufferedWriter<W>,
}
impl<W> fmt::Show for LineBufferedWriter<W> where W: fmt::Show {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
self.inner.inner, self.inner.pos, self.inner.buf.len())
}
}
impl<W: Writer> LineBufferedWriter<W> {
/// Creates a new `LineBufferedWriter`
pub fn new(inner: W) -> LineBufferedWriter<W> {
@ -318,6 +340,17 @@ pub struct BufferedStream<S> {
inner: BufferedReader<InternalBufferedWriter<S>>
}
impl<S> fmt::Show for BufferedStream<S> where S: fmt::Show {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let reader = &self.inner;
let writer = &self.inner.inner.0;
write!(fmt, "BufferedStream {{ stream: {:?}, write_buffer: {}/{}, read_buffer: {}/{} }}",
writer.inner,
writer.pos, writer.buf.len(),
reader.cap - reader.pos, reader.buf.len())
}
}
impl<S: Stream> BufferedStream<S> {
/// Creates a new buffered stream with explicitly listed capacities for the
/// reader/writer buffer.

View File

@ -16,6 +16,7 @@ use io;
use slice::bytes::MutableByteVector;
/// Wraps a `Reader`, limiting the number of bytes that can be read from it.
#[derive(Show)]
pub struct LimitReader<R> {
limit: uint,
inner: R
@ -77,7 +78,7 @@ impl<R: Buffer> Buffer for LimitReader<R> {
}
/// A `Writer` which ignores bytes written to it, like /dev/null.
#[derive(Copy)]
#[derive(Copy, Show)]
pub struct NullWriter;
impl Writer for NullWriter {
@ -86,7 +87,7 @@ impl Writer for NullWriter {
}
/// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
#[derive(Copy)]
#[derive(Copy, Show)]
pub struct ZeroReader;
impl Reader for ZeroReader {
@ -107,7 +108,7 @@ impl Buffer for ZeroReader {
}
/// A `Reader` which is always at EOF, like /dev/null.
#[derive(Copy)]
#[derive(Copy, Show)]
pub struct NullReader;
impl Reader for NullReader {
@ -128,18 +129,19 @@ impl Buffer for NullReader {
///
/// The `Writer`s are delegated to in order. If any `Writer` returns an error,
/// that error is returned immediately and remaining `Writer`s are not called.
pub struct MultiWriter {
writers: Vec<Box<Writer+'static>>
#[derive(Show)]
pub struct MultiWriter<W> {
writers: Vec<W>
}
impl MultiWriter {
impl<W> MultiWriter<W> where W: Writer {
/// Creates a new `MultiWriter`
pub fn new(writers: Vec<Box<Writer+'static>>) -> MultiWriter {
pub fn new(writers: Vec<W>) -> MultiWriter<W> {
MultiWriter { writers: writers }
}
}
impl Writer for MultiWriter {
impl<W> Writer for MultiWriter<W> where W: Writer {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
for writer in self.writers.iter_mut() {
@ -159,7 +161,7 @@ impl Writer for MultiWriter {
/// A `Reader` which chains input from multiple `Reader`s, reading each to
/// completion before moving onto the next.
#[derive(Clone)]
#[derive(Clone, Show)]
pub struct ChainedReader<I, R> {
readers: I,
cur_reader: Option<R>,
@ -198,6 +200,7 @@ impl<R: Reader, I: Iterator<Item=R>> Reader for ChainedReader<I, R> {
/// A `Reader` which forwards input from another `Reader`, passing it along to
/// a `Writer` as well. Similar to the `tee(1)` command.
#[derive(Show)]
pub struct TeeReader<R, W> {
reader: R,
writer: W,
@ -239,7 +242,7 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
}
/// An adaptor converting an `Iterator<u8>` to a `Reader`.
#[derive(Clone)]
#[derive(Clone, Show)]
pub struct IterReader<T> {
iter: T,
}