diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index e82662c6b0d..0b93a2ad2ca 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]);