dirx 0.1.0

Creates an in-memory index of all the files in a directory tree, and allows efficient scanning of only those files that have been modified since the index got created
Documentation
use crate::index::DirIndex;
use crate::index::IndexedFile;
use crate::index::IndexedMeta;
use std::iter::FusedIterator;
use std::path::Path;
use std::path::PathBuf;

macro_rules! impl_iterator {
    (
        $( #[ $meta:meta ] )*
        $vis:vis struct $name:ident < $( $generics:tt ),* > {
            type Item = $item:ty ;
            type Inner = $inner:ty ;
            fn new = | $new_arg:ident : $new_arg_ty:ty | $new:expr ;
            fn transform = | ( $( $transform_arg:ident ),* ) : $transform_arg_ty:ty | $transform:expr ;
        }
        $( $rest:tt )*
    ) => {
        $(#[$meta])*
        $vis struct $name<$($generics),*> {
            inner: $inner,
        }

        impl<$($generics),*> $name<$($generics),*> {
            pub fn new($new_arg: $new_arg_ty) -> Self {
                Self { inner: $new }
            }

            #[allow(unused_parens)]
            fn transform(($($transform_arg),*): $transform_arg_ty) -> <Self as Iterator>::Item {
                $transform
            }
        }

        impl<$($generics),*> Iterator for $name<$($generics),*> {
            type Item = $item;

            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                self.inner.next().map(Self::transform)
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                self.inner.size_hint()
            }

            #[inline]
            fn count(self) -> usize {
                self.inner.count()
            }

            #[inline]
            fn nth(&mut self, n: usize) -> Option<Self::Item> {
                self.inner.nth(n).map(Self::transform)
            }

            #[inline]
            fn last(self) -> Option<Self::Item> {
                self.inner.last().map(Self::transform)
            }
        }

        impl<$($generics),*> DoubleEndedIterator for $name<$($generics),*> {
            #[inline]
            fn next_back(&mut self) -> Option<Self::Item> {
                self.inner.next_back().map(Self::transform)
            }

            #[inline]
            fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
                self.inner.nth_back(n).map(Self::transform)
            }
        }

        impl<$($generics),*> ExactSizeIterator for $name<$($generics),*> {
            #[inline]
            fn len(&self) -> usize {
                self.inner.len()
            }
        }

        impl<$($generics),*> FusedIterator for $name<$($generics),*> {}

        impl_iterator! { $($rest)* }
    };
    () => {};
}

impl_iterator! {
    #[derive(Clone, Debug)]
    pub struct Iter<'i, T> {
        type Item = (&'i Path, &'i T);
        type Inner = indexmap::map::Iter<'i, PathBuf, IndexedFile<T>>;
        fn new = |index: &'i DirIndex<T>| index.entries.iter();
        fn transform = |(path, entry): (&'i PathBuf, &'i IndexedFile<T>)|
            (path.as_ref(), &entry.data);
    }

    #[derive(Debug)]
    pub struct IterMut<'i, T> {
        type Item = (&'i Path, &'i mut T);
        type Inner = indexmap::map::IterMut<'i, PathBuf, IndexedFile<T>>;
        fn new = |index: &'i mut DirIndex<T>| index.entries.iter_mut();
        fn transform = |(path, entry): (&'i PathBuf, &'i mut IndexedFile<T>)|
            (path.as_ref(), &mut entry.data);
    }

    #[derive(Debug)]
    pub struct IntoIter<T> {
        type Item = (PathBuf, T);
        type Inner = indexmap::map::IntoIter<PathBuf, IndexedFile<T>>;
        fn new = |index: DirIndex<T>| index.entries.into_iter();
        fn transform = |(path, entry): (PathBuf, IndexedFile<T>)| (path, entry.data);
    }

    #[derive(Clone, Debug)]
    pub struct IterWithMeta<'i, T> {
        type Item = (&'i Path, &'i IndexedMeta, &'i T);
        type Inner = indexmap::map::Iter<'i, PathBuf, IndexedFile<T>>;
        fn new = |index: &'i DirIndex<T>| index.entries.iter();
        fn transform = |(path, entry): (&'i PathBuf, &'i IndexedFile<T>)|
            (path.as_ref(), &entry.meta, &entry.data);
    }

    #[derive(Debug)]
    pub struct IterWithMetaMut<'i, T> {
        type Item = (&'i Path, &'i mut IndexedMeta, &'i mut T);
        type Inner = indexmap::map::IterMut<'i, PathBuf, IndexedFile<T>>;
        fn new = |index: &'i mut DirIndex<T>| index.entries.iter_mut();
        fn transform = |(path, entry): (&'i PathBuf, &'i mut IndexedFile<T>)|
            (path.as_ref(), &mut entry.meta, &mut entry.data);
    }

    #[derive(Debug)]
    pub struct IntoIterWithMeta<T> {
        type Item = (PathBuf, IndexedMeta, T);
        type Inner = indexmap::map::IntoIter<PathBuf, IndexedFile<T>>;
        fn new = |index: DirIndex<T>| index.entries.into_iter();
        fn transform = |(path, entry): (PathBuf, IndexedFile<T>)|
            (path, entry.meta, entry.data);
    }

    #[derive(Clone, Debug)]
    pub struct Paths<'i, T> {
        type Item = &'i Path;
        type Inner = indexmap::map::Keys<'i, PathBuf, IndexedFile<T>>;
        fn new = |index: &'i DirIndex<T>| index.entries.keys();
        fn transform = |(path): (&'i PathBuf)| path.as_ref();
    }
}