about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/io/extensions.rs84
1 files changed, 83 insertions, 1 deletions
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<Self>;
+
 }
 
 pub trait ReaderByteConversions {
@@ -337,6 +348,35 @@ impl<T: Reader> ReaderUtil for T {
         }
         return buf;
     }
+
+    fn bytes(self) -> Bytes<T> {
+        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<T> {
+    priv reader: T,
+}
+
+impl<R> Decorator<R> for Bytes<R> {
+    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<u8> for Bytes<R> {
+    #[inline]
+    fn next(&mut self) -> Option<u8> {
+        self.reader.read_byte()
+    }
 }
 
 impl<T: Reader> ReaderByteConversions for T {
@@ -647,6 +687,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]);
         let bytes = reader.read_bytes(4);