//! This comes from the Rust libcore and is duplicated here because it is not exported //! (cf ) //! We are now using the version from //! because the one from the libcore seems to cause overflowing stacks in some cases //! It also contains a lines_with_ending that copies std::io::BufRead but keeps line endings. use std::io::BufRead; pub struct ResultShunt { iter: I, error: Option, } impl ResultShunt where I: Iterator>, { /// Process the given iterator as if it yielded a `T` instead of a /// `Result`. Any errors will stop the inner iterator and /// the overall result will be an error. pub fn process(iter: I, mut f: F) -> Result where F: FnMut(&mut Self) -> U, { let mut shunt = ResultShunt::new(iter); let value = f(shunt.by_ref()); shunt.reconstruct(value) } fn new(iter: I) -> Self { ResultShunt { iter, error: None } } /// Consume the adapter and rebuild a `Result` value. This should /// *always* be called, otherwise any potential error would be /// lost. fn reconstruct(self, val: U) -> Result { match self.error { None => Ok(val), Some(e) => Err(e), } } } impl Iterator for ResultShunt where I: Iterator>, { type Item = T; fn next(&mut self) -> Option { match self.iter.next() { Some(Ok(v)) => Some(v), Some(Err(e)) => { self.error = Some(e); None } None => None, } } } /// Copied from std::io::BufRead but keep newline characters. #[derive(Debug)] pub struct Lines { buf: B, } pub trait LinesWithEnding { fn lines_with_ending(self) -> Lines; } impl LinesWithEnding for B where B: BufRead, { fn lines_with_ending(self) -> Lines { Lines:: { buf: self } } } impl Iterator for Lines { type Item = std::io::Result; fn next(&mut self) -> Option { let mut buf = String::new(); match self.buf.read_line(&mut buf) { Ok(0) => None, Ok(_n) => { // if buf.ends_with('\n') { // buf.pop(); // if buf.ends_with('\r') { // buf.pop(); // } // } Some(Ok(buf)) } Err(e) => Some(Err(e)), } } }