| |
| |
| |
| |
| |
| use std::io::BufRead; |
|
|
| pub struct ResultShunt<I, E> { |
| iter: I, |
| error: Option<E>, |
| } |
|
|
| impl<I, T, E> ResultShunt<I, E> |
| where |
| I: Iterator<Item = Result<T, E>>, |
| { |
| |
| |
| |
| pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E> |
| 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 } |
| } |
|
|
| |
| |
| |
| fn reconstruct<U>(self, val: U) -> Result<U, E> { |
| match self.error { |
| None => Ok(val), |
| Some(e) => Err(e), |
| } |
| } |
| } |
|
|
| impl<I, T, E> Iterator for ResultShunt<I, E> |
| where |
| I: Iterator<Item = Result<T, E>>, |
| { |
| type Item = T; |
|
|
| fn next(&mut self) -> Option<Self::Item> { |
| match self.iter.next() { |
| Some(Ok(v)) => Some(v), |
| Some(Err(e)) => { |
| self.error = Some(e); |
| None |
| } |
| None => None, |
| } |
| } |
| } |
|
|
| |
| #[derive(Debug)] |
| pub struct Lines<B> { |
| buf: B, |
| } |
|
|
| pub trait LinesWithEnding<B> { |
| fn lines_with_ending(self) -> Lines<B>; |
| } |
|
|
| impl<B> LinesWithEnding<B> for B |
| where |
| B: BufRead, |
| { |
| fn lines_with_ending(self) -> Lines<B> { |
| Lines::<B> { buf: self } |
| } |
| } |
| impl<B: BufRead> Iterator for Lines<B> { |
| type Item = std::io::Result<String>; |
|
|
| fn next(&mut self) -> Option<Self::Item> { |
| let mut buf = String::new(); |
| match self.buf.read_line(&mut buf) { |
| Ok(0) => None, |
| Ok(_n) => { |
| |
| |
| |
| |
| |
| |
| Some(Ok(buf)) |
| } |
| Err(e) => Some(Err(e)), |
| } |
| } |
| } |
|
|