From 61026ae621ffbc6d7538cfb0add49b8fc5638e86 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 2 Sep 2013 01:30:21 +0200 Subject: [PATCH 1/2] rt::io: Add Bytes iterator for Reader An iterator that simply calls `.read_bytes()` each iteration. I think choosing to own the Reader value and implementing Decorator to allow extracting it is the most generically useful. The Reader type variable can of course be some kind of reference type that implements Reader. --- src/libstd/rt/io/extensions.rs | 84 +++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index e82662c6b0d2f..0b93a2ad2ca50 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -15,8 +15,9 @@ use uint; use int; +use iterator::Iterator; use vec; -use rt::io::{Reader, Writer}; +use rt::io::{Reader, Writer, Decorator}; use rt::io::{read_error, standard_error, EndOfFile, DEFAULT_BUF_SIZE}; use option::{Option, Some, None}; use unstable::finally::Finally; @@ -62,6 +63,16 @@ pub trait ReaderUtil { /// Raises the same conditions as the `read` method. fn read_to_end(&mut self) -> ~[u8]; + /// Create an iterator that reads a single byte on + /// each iteration, until EOF. + /// + /// # Failure + /// + /// Raises the same conditions as the `read` method, for + /// each call to its `.next()` method. + /// Ends the iteration if the condition is handled. + fn bytes(self) -> Bytes; + } pub trait ReaderByteConversions { @@ -337,6 +348,35 @@ impl ReaderUtil for T { } return buf; } + + fn bytes(self) -> Bytes { + Bytes{reader: self} + } +} + +/// An iterator that reads a single byte on each iteration, +/// until EOF. +/// +/// # Failure +/// +/// Raises the same conditions as the `read` method, for +/// each call to its `.next()` method. +/// Ends the iteration if the condition is handled. +pub struct Bytes { + priv reader: T, +} + +impl Decorator for Bytes { + fn inner(self) -> R { self.reader } + fn inner_ref<'a>(&'a self) -> &'a R { &self.reader } + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { &mut self.reader } +} + +impl<'self, R: Reader> Iterator for Bytes { + #[inline] + fn next(&mut self) -> Option { + self.reader.read_byte() + } } impl ReaderByteConversions for T { @@ -646,6 +686,48 @@ mod test { } } + #[test] + fn bytes_0_bytes() { + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + Some(0) + } else { + buf[0] = 10; + Some(1) + } + } + }; + let byte = reader.bytes().next(); + assert!(byte == Some(10)); + } + + #[test] + fn bytes_eof() { + let mut reader = MockReader::new(); + reader.read = |_| None; + let byte = reader.bytes().next(); + assert!(byte == None); + } + + #[test] + fn bytes_error() { + let mut reader = MockReader::new(); + reader.read = |_| { + read_error::cond.raise(placeholder_error()); + None + }; + let mut it = reader.bytes(); + do read_error::cond.trap(|_| ()).inside { + let byte = it.next(); + assert!(byte == None); + } + } + + #[test] fn read_bytes() { let mut reader = MemReader::new(~[10, 11, 12, 13]); From 913d1b48ad4e2dd909009aab93837cd596a235b2 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 3 Sep 2013 20:00:32 +0200 Subject: [PATCH 2/2] rt::io: Rename Bytes to ByteIterator and add note about iteration --- src/libstd/rt/io/extensions.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index 0b93a2ad2ca50..15ac6544dee0e 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -71,7 +71,7 @@ pub trait ReaderUtil { /// Raises the same conditions as the `read` method, for /// each call to its `.next()` method. /// Ends the iteration if the condition is handled. - fn bytes(self) -> Bytes; + fn bytes(self) -> ByteIterator; } @@ -349,30 +349,36 @@ impl ReaderUtil for T { return buf; } - fn bytes(self) -> Bytes { - Bytes{reader: self} + fn bytes(self) -> ByteIterator { + ByteIterator{reader: self} } } /// An iterator that reads a single byte on each iteration, -/// until EOF. +/// until `.read_byte()` returns `None`. +/// +/// # Notes about the Iteration Protocol +/// +/// The `ByteIterator` may yield `None` and thus terminate +/// an iteration, but continue to yield elements if iteration +/// is attempted again. /// /// # Failure /// /// Raises the same conditions as the `read` method, for /// each call to its `.next()` method. -/// Ends the iteration if the condition is handled. -pub struct Bytes { +/// Yields `None` if the condition is handled. +pub struct ByteIterator { priv reader: T, } -impl Decorator for Bytes { +impl Decorator for ByteIterator { fn inner(self) -> R { self.reader } fn inner_ref<'a>(&'a self) -> &'a R { &self.reader } fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { &mut self.reader } } -impl<'self, R: Reader> Iterator for Bytes { +impl<'self, R: Reader> Iterator for ByteIterator { #[inline] fn next(&mut self) -> Option { self.reader.read_byte()