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();
}
}