Rewrite Store::entries()

This patch rewrites the Store::entries() function to not be collecting
the iterator.

It therefore introduces a new, internal, iterator type which creates the
StoreId objects from the pathes the PathIterator yields internally.

With this patch, the Store iterator interface changes, as the iterators
now yield `Result<StoreId, StoreError>` instead of `StoreId`.
This is necessary, as the internal conversion errors shouldn't be
hidden.

Of course, the iterator types (like the StoreGetIterator and so on)
should hold a Result<StoreId> internally as well, and also yield
appropritely. This was changed in this commit, too.
This commit is contained in:
Matthias Beyer 2018-04-30 15:46:39 +02:00
parent f4556f3983
commit a2ff298e67
5 changed files with 47 additions and 29 deletions

View file

@ -20,6 +20,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use error::Result; use error::Result;
use storeid::StoreId;
/// A wrapper for an iterator over `PathBuf`s /// A wrapper for an iterator over `PathBuf`s
pub struct PathIterator(Box<Iterator<Item = Result<PathBuf>>>); pub struct PathIterator(Box<Iterator<Item = Result<PathBuf>>>);
@ -30,6 +31,10 @@ impl PathIterator {
PathIterator(iter) PathIterator(iter)
} }
pub fn store_id_constructing(self, storepath: PathBuf) -> StoreIdConstructingIterator {
StoreIdConstructingIterator(self, storepath)
}
} }
impl Iterator for PathIterator { impl Iterator for PathIterator {
@ -41,3 +46,29 @@ impl Iterator for PathIterator {
} }
/// Helper type for constructing StoreIds from a PathIterator.
///
/// Automatically ignores non-files.
pub struct StoreIdConstructingIterator(PathIterator, PathBuf);
impl Iterator for StoreIdConstructingIterator {
type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(next) = self.0.next() {
match next {
Err(e) => return Some(Err(e)),
Ok(next) => if next.is_file() {
return Some(StoreId::from_full_path(&self.1, next))
} else {
continue
}
}
}
None
}
}

View file

@ -27,7 +27,7 @@ use storeid::StoreId;
mod fs; mod fs;
mod inmemory; mod inmemory;
mod iter; pub(crate) mod iter;
pub use self::fs::FSFileAbstraction; pub use self::fs::FSFileAbstraction;
pub use self::fs::FSFileAbstractionInstance; pub use self::fs::FSFileAbstractionInstance;

View file

@ -32,10 +32,10 @@ macro_rules! mk_iterator {
use store::Store; use store::Store;
use error::Result; use error::Result;
pub struct $itername<'a>(Box<Iterator<Item = StoreId> + 'a>, &'a Store); pub struct $itername<'a>(Box<Iterator<Item = Result<StoreId>> + 'a>, &'a Store);
impl<'a> $itername<'a> { impl<'a> $itername<'a> {
pub fn new(inner: Box<Iterator<Item = StoreId> + 'a>, store: &'a Store) -> Self { pub fn new(inner: Box<Iterator<Item = Result<StoreId>> + 'a>, store: &'a Store) -> Self {
$itername(inner, store) $itername(inner, store)
} }
} }
@ -44,7 +44,7 @@ macro_rules! mk_iterator {
type Item = Result<$yield>; type Item = Result<$yield>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|id| $fun(id, self.1)) self.0.next().map(|id| $fun(id?, self.1))
} }
} }
@ -53,7 +53,7 @@ macro_rules! mk_iterator {
} }
impl<'a, I> $extname<'a> for I impl<'a, I> $extname<'a> for I
where I: Iterator<Item = StoreId> + 'a where I: Iterator<Item = Result<StoreId>> + 'a
{ {
fn $extfnname(self, store: &'a Store) -> $itername<'a> { fn $extfnname(self, store: &'a Store) -> $itername<'a> {
$itername(Box::new(self), store) $itername(Box::new(self), store)

View file

@ -741,25 +741,12 @@ impl Store {
} }
/// Get _all_ entries in the store (by id as iterator) /// Get _all_ entries in the store (by id as iterator)
pub fn entries<'a>(&'a self) -> Result<StoreIdIteratorWithStore<'a>> { pub fn entries(&self) -> Result<StoreIdIteratorWithStore> {
self.backend self.backend
.pathes_recursively(self.path().clone()) .pathes_recursively(self.path().clone())
.and_then(|iter| { .map(|i| i.store_id_constructing(self.path().clone()))
let mut elems = vec![]; .map(Box::new)
for element in iter { .map(|it| StoreIdIteratorWithStore::new(it, self))
let is_file = {
let mut base = self.path().clone();
base.push(element.clone());
self.backend.is_file(&base)?
};
if is_file {
let sid = StoreId::from_full_path(self.path(), element)?;
elems.push(sid);
}
}
Ok(StoreIdIteratorWithStore::new(Box::new(elems.into_iter()), self))
})
} }
/// Gets the path where this store is on the disk /// Gets the path where this store is on the disk

View file

@ -241,7 +241,7 @@ macro_rules! module_entry_path_mod {
} }
pub struct StoreIdIterator { pub struct StoreIdIterator {
iter: Box<Iterator<Item = StoreId>>, iter: Box<Iterator<Item = Result<StoreId>>>,
} }
impl Debug for StoreIdIterator { impl Debug for StoreIdIterator {
@ -254,16 +254,16 @@ impl Debug for StoreIdIterator {
impl StoreIdIterator { impl StoreIdIterator {
pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator { pub fn new(iter: Box<Iterator<Item = Result<StoreId>>>) -> StoreIdIterator {
StoreIdIterator { iter } StoreIdIterator { iter }
} }
} }
impl Iterator for StoreIdIterator { impl Iterator for StoreIdIterator {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<StoreId> { fn next(&mut self) -> Option<Self::Item> {
self.iter.next() self.iter.next()
} }
@ -280,16 +280,16 @@ impl<'a> Deref for StoreIdIteratorWithStore<'a> {
} }
impl<'a> Iterator for StoreIdIteratorWithStore<'a> { impl<'a> Iterator for StoreIdIteratorWithStore<'a> {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<StoreId> { fn next(&mut self) -> Option<Self::Item> {
self.0.next() self.0.next()
} }
} }
impl<'a> StoreIdIteratorWithStore<'a> { impl<'a> StoreIdIteratorWithStore<'a> {
pub fn new(iter: Box<Iterator<Item = StoreId>>, store: &'a Store) -> Self { pub fn new(iter: Box<Iterator<Item = Result<StoreId>>>, store: &'a Store) -> Self {
StoreIdIteratorWithStore(StoreIdIterator::new(iter), store) StoreIdIteratorWithStore(StoreIdIterator::new(iter), store)
} }