diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 256f9d325f3..a48403f19a4 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -552,6 +552,16 @@ mod test { assert_eq!(reader.read_char(), Ok('ß')); } + #[test] + fn test_chars() { + let buf = [195u8, 159u8, 'a' as u8]; + let mut reader = BufferedReader::with_capacity(1, BufReader::new(buf)); + let mut it = reader.chars(); + assert_eq!(it.next(), Some('ß')); + assert_eq!(it.next(), Some('a')); + assert_eq!(it.next(), None); + } + #[bench] fn bench_buffered_reader(bh: &mut Harness) { bh.iter(|| { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 4d28143c75a..1c1df691a52 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1001,6 +1001,30 @@ impl<'r, T: Buffer> Iterator<~str> for Lines<'r, T> { } } +/// An iterator that reads a utf8-encoded character on each iteration, +/// until `.read_char()` returns `None`. +/// +/// # Notes about the Iteration Protocol +/// +/// The `Chars` may yield `None` and thus terminate +/// an iteration, but continue to yield elements if iteration +/// is attempted again. +/// +/// # Error +/// +/// This iterator will swallow all I/O errors, transforming `Err` values to +/// `None`. If errors need to be handled, it is recommended to use the +/// `read_char` method directly. +pub struct Chars<'r, T> { + priv buffer: &'r mut T +} + +impl<'r, T: Buffer> Iterator for Chars<'r, T> { + fn next(&mut self) -> Option { + self.buffer.read_char().ok() + } +} + /// A Buffer is a type of reader which has some form of internal buffering to /// allow certain kinds of reading operations to be more optimized than others. /// This type extends the `Reader` trait with a few methods that are not @@ -1146,6 +1170,17 @@ pub trait Buffer: Reader { None => Err(standard_error(InvalidInput)) } } + + /// Create an iterator that reads a utf8-encoded character on each iteration until EOF. + /// + /// # Error + /// + /// This iterator will transform all error values to `None`, discarding the + /// cause of the error. If this is undesirable, it is recommended to call + /// `read_char` directly. + fn chars<'r>(&'r mut self) -> Chars<'r, Self> { + Chars { buffer: self } + } } pub enum SeekStyle {