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.
This commit is contained in:
blake2-ppc 2013-09-02 01:30:21 +02:00
parent 1f4aba8cbf
commit 61026ae621

View File

@ -15,8 +15,9 @@
use uint; use uint;
use int; use int;
use iterator::Iterator;
use vec; 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 rt::io::{read_error, standard_error, EndOfFile, DEFAULT_BUF_SIZE};
use option::{Option, Some, None}; use option::{Option, Some, None};
use unstable::finally::Finally; use unstable::finally::Finally;
@ -62,6 +63,16 @@ pub trait ReaderUtil {
/// Raises the same conditions as the `read` method. /// Raises the same conditions as the `read` method.
fn read_to_end(&mut self) -> ~[u8]; 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 { pub trait ReaderByteConversions {
@ -337,6 +348,35 @@ impl<T: Reader> ReaderUtil for T {
} }
return buf; 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 { impl<T: Reader> 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] #[test]
fn read_bytes() { fn read_bytes() {
let mut reader = MemReader::new(~[10, 11, 12, 13]); let mut reader = MemReader::new(~[10, 11, 12, 13]);