From d4dd4c68f82baf4d307012da1b4d6b91d26fb12f Mon Sep 17 00:00:00 2001 From: Palmer Cox Date: Thu, 13 Feb 2014 23:27:53 -0500 Subject: [PATCH 1/2] Create RefReader and RefWriter adaptor structs RefReader and RefWriter allow a caller to pass a Reader or Writer instance by reference to generic functions that are expecting arguments by value. --- src/libstd/io/mod.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 24b3d1cc4de70..c99fe587fc0d0 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -779,6 +779,13 @@ pub trait Reader { self.read_byte().map(|i| i as i8) } + /// Creates a wrapper around a mutable reference to the reader. + /// + /// This is useful to allow applying adaptors while still + /// retaining ownership of the original value. + fn by_ref<'a>(&'a mut self) -> RefReader<'a, Self> { + RefReader { inner: self } + } } impl Reader for ~Reader { @@ -789,6 +796,14 @@ impl<'a> Reader for &'a mut Reader { fn read(&mut self, buf: &mut [u8]) -> IoResult { self.read(buf) } } +pub struct RefReader<'a, R> { + priv inner: &'a mut R +} + +impl<'a, R: Reader> Reader for RefReader<'a, R> { + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.read(buf) } +} + fn extend_sign(val: u64, nbytes: uint) -> i64 { let shift = (8 - nbytes) * 8; (val << shift) as i64 >> shift @@ -969,6 +984,14 @@ pub trait Writer { fn write_i8(&mut self, n: i8) -> IoResult<()> { self.write([n as u8]) } + + /// Creates a wrapper around a mutable reference to the writer. + /// + /// This is useful to allow applying wrappers while still + /// retaining ownership of the original value. + fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self> { + RefWriter { inner: self } + } } impl Writer for ~Writer { @@ -981,6 +1004,16 @@ impl<'a> Writer for &'a mut Writer { fn flush(&mut self) -> IoResult<()> { self.flush() } } +pub struct RefWriter<'a, W> { + inner: &'a mut W +} + +impl<'a, W: Writer> Writer for RefWriter<'a, W> { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.inner.write(buf) } + fn flush(&mut self) -> IoResult<()> { self.inner.flush() } +} + + pub trait Stream: Reader + Writer { } impl Stream for T {} From 4c233d1c73edae4fb2609100528d3c952723453f Mon Sep 17 00:00:00 2001 From: Palmer Cox Date: Thu, 13 Feb 2014 23:28:11 -0500 Subject: [PATCH 2/2] Update LimitReader to take the Reader to wrap by value --- src/libstd/io/util.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index c4d92b36ecfa6..2e12fc0b9f290 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -14,19 +14,20 @@ use io; use vec::bytes::MutableByteVector; /// Wraps a `Reader`, limiting the number of bytes that can be read from it. -pub struct LimitReader<'a, R> { +pub struct LimitReader { priv limit: uint, - priv inner: &'a mut R + priv inner: R } -impl<'a, R: Reader> LimitReader<'a, R> { +impl LimitReader { /// Creates a new `LimitReader` - pub fn new<'a>(r: &'a mut R, limit: uint) -> LimitReader<'a, R> { + pub fn new(r: R, limit: uint) -> LimitReader { LimitReader { limit: limit, inner: r } } + pub fn unwrap(self) -> R { self.inner } } -impl<'a, R: Reader> Reader for LimitReader<'a, R> { +impl Reader for LimitReader { fn read(&mut self, buf: &mut [u8]) -> io::IoResult { if self.limit == 0 { return Err(io::standard_error(io::EndOfFile)); @@ -192,7 +193,7 @@ mod test { fn test_bounded_reader_unlimited() { let mut r = MemReader::new(~[0, 1, 2]); { - let mut r = LimitReader::new(&mut r, 4); + let mut r = LimitReader::new(r.by_ref(), 4); assert_eq!(~[0, 1, 2], r.read_to_end().unwrap()); } } @@ -201,7 +202,7 @@ mod test { fn test_bound_reader_limited() { let mut r = MemReader::new(~[0, 1, 2]); { - let mut r = LimitReader::new(&mut r, 2); + let mut r = LimitReader::new(r.by_ref(), 2); assert_eq!(~[0, 1], r.read_to_end().unwrap()); } assert_eq!(~[2], r.read_to_end().unwrap());