~matthiasbeyer/imag

eb675b44bc62fbe2984c8a2831b14a7feb7e2d18 — Matthias Beyer 1 year, 1 month ago 7ba3b2f
Add iterator extension for reporting from iterator

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
1 files changed, 56 insertions(+), 0 deletions(-)

M lib/core/libimagrt/src/runtime.rs
M lib/core/libimagrt/src/runtime.rs => lib/core/libimagrt/src/runtime.rs +56 -0
@@ 577,6 577,62 @@ impl<'a> Runtime<'a> {
    }
}

pub trait IntoTouchIterator<E, F>
    where Self: Iterator<Item = E> + Sized,
          E: Sized,
          F: Fn(&E) -> Option<StoreId>
{
    fn report_entries_touched<'a>(self, rt: &'a Runtime<'a>, func: F) -> TouchIterator<'a, Self, E, F> {
        TouchIterator {
            inner: self,
            rt,
            func
        }
    }
}

impl<I, E, F> IntoTouchIterator<E, F> for I
    where I: Iterator<Item = E>,
          E: Sized,
          F: Fn(&E) -> Option<StoreId>
{
    // default implementation
}

pub struct TouchIterator<'a, I, E, F>
    where I: Iterator<Item = E>,
          E: Sized,
          F: Fn(&E) -> Option<StoreId>
{
    inner: I,
    rt: &'a Runtime<'a>,
    func: F
}

impl<'a, I, E, F> Iterator for TouchIterator<'a, I, E, F>
    where I: Iterator<Item = E>,
          E: Sized,
          F: Fn(&E) -> Option<StoreId>
{
    type Item = Result<E>;

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(next) = self.inner.next() {
            match (self.func)(&next) {
                Some(id) => if let Err(e) = self.rt.report_touched(&id) {
                    return Some(Err(e))
                } else {
                    return Some(Ok(next))
                },

                None => continue,
            }
        }

        None
    }
}

/// A trait for providing ids from clap argument matches
///
/// This trait can be implement on a type so that it can provide IDs when given a ArgMatches