diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2016-10-20 18:41:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-20 18:41:19 +0200 |
commit | 89af64c27fef706e05a6641fcb736e0e3b85bcfc (patch) | |
tree | 4edc0cceae588cb74b990bbd2c15c6b8b6caa810 /libimagentrylink | |
parent | 41aaaf9ddc5af54bf853efb98df0add0b08c00d2 (diff) | |
parent | e4e5fafce2dfd4084e2847c511b8fc30f90986f8 (diff) |
Merge pull request #804 from matthiasbeyer/libimagentrylink/iterators
Initial add iterators for link library
Diffstat (limited to 'libimagentrylink')
-rw-r--r-- | libimagentrylink/src/internal.rs | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/libimagentrylink/src/internal.rs b/libimagentrylink/src/internal.rs index 3110ff79..48f5d819 100644 --- a/libimagentrylink/src/internal.rs +++ b/libimagentrylink/src/internal.rs @@ -61,6 +61,9 @@ pub mod iter { use toml::Value; use itertools::Itertools; + use libimagstore::store::Store; + use libimagstore::store::FileLockEntry; + pub struct LinkIter(IntoIter<Link>); impl LinkIter { @@ -69,6 +72,10 @@ pub mod iter { LinkIter(v.into_iter()) } + pub fn into_getter(self, store: &Store) -> GetIter { + GetIter(self.0, store) + } + } impl Iterator for LinkIter { @@ -104,6 +111,158 @@ pub mod iter { } } + /// An Iterator that `Store::get()`s the Entries from the store while consumed + pub struct GetIter<'a>(IntoIter<Link>, &'a Store); + + impl<'a> GetIter<'a> { + pub fn new(i: IntoIter<Link>, store: &'a Store) -> GetIter<'a> { + GetIter(i, store) + } + + /// Turn this iterator into a LinkGcIter, which `Store::delete()`s entries that are not + /// linked to any other entry. + pub fn delete_unlinked(self) -> DeleteUnlinkedIter<'a> { + DeleteUnlinkedIter(self) + } + + /// Turn this iterator into a FilterLinksIter that removes all entries that are not linked + /// to any other entry, by filtering them out the iterator. + /// + /// This does _not_ remove the entries from the store. + pub fn without_unlinked(self) -> FilterLinksIter<'a> { + FilterLinksIter::new(self, Box::new(|links: &[Link]| links.len() > 0)) + } + + /// Turn this iterator into a FilterLinksIter that removes all entries that have less than + /// `n` links to any other entries. + /// + /// This does _not_ remove the entries from the store. + pub fn with_less_than_n_links(self, n: usize) -> FilterLinksIter<'a> { + FilterLinksIter::new(self, Box::new(move |links: &[Link]| links.len() < n)) + } + + /// Turn this iterator into a FilterLinksIter that removes all entries that have more than + /// `n` links to any other entries. + /// + /// This does _not_ remove the entries from the store. + pub fn with_more_than_n_links(self, n: usize) -> FilterLinksIter<'a> { + FilterLinksIter::new(self, Box::new(move |links: &[Link]| links.len() > n)) + } + + /// Turn this iterator into a FilterLinksIter that removes all entries where the predicate + /// `F` returns false + /// + /// This does _not_ remove the entries from the store. + pub fn filtered_for_links(self, f: Box<Fn(&[Link]) -> bool>) -> FilterLinksIter<'a> { + FilterLinksIter::new(self, f) + } + + pub fn store(&self) -> &Store { + self.1 + } + } + + impl<'a> Iterator for GetIter<'a> { + type Item = Result<FileLockEntry<'a>>; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().and_then(|id| match self.1.get(id).map_err_into(LEK::StoreReadError) { + Ok(None) => None, + Ok(Some(x)) => Some(Ok(x)), + Err(e) => Some(Err(e)), + }) + } + + } + + /// An iterator helper that has a function F. + /// + /// If the function F returns `false` for the number of links, the entry is ignored, else it is + /// taken. + pub struct FilterLinksIter<'a>(GetIter<'a>, Box<Fn(&[Link]) -> bool>); + + impl<'a> FilterLinksIter<'a> { + pub fn new(gi: GetIter<'a>, f: Box<Fn(&[Link]) -> bool>) -> FilterLinksIter<'a> { + FilterLinksIter(gi, f) + } + } + + impl<'a> Iterator for FilterLinksIter<'a> { + type Item = Result<FileLockEntry<'a>>; + + fn next(&mut self) -> Option<Self::Item> { + use internal::InternalLinker; + + loop { + match self.0.next() { + Some(Ok(fle)) => { + let links = match fle.get_internal_links().map_err_into(LEK::StoreReadError) + { + Err(e) => return Some(Err(e)), + Ok(links) => links.collect::<Vec<_>>(), + }; + if !(self.1)(&links) { + continue; + } else { + return Some(Ok(fle)); + } + }, + Some(Err(e)) => return Some(Err(e)), + None => break, + } + } + None + } + + } + + /// An iterator that removes all Items from the iterator that are not linked anymore by calling + /// `Store::delete()` on them. + /// + /// It yields only items which are somehow linked to another entry + /// + /// # Warning + /// + /// Deletes entries from the store. + /// + pub struct DeleteUnlinkedIter<'a>(GetIter<'a>); + + impl<'a> Iterator for DeleteUnlinkedIter<'a> { + type Item = Result<FileLockEntry<'a>>; + + fn next(&mut self) -> Option<Self::Item> { + use internal::InternalLinker; + + loop { + match self.0.next() { + Some(Ok(fle)) => { + let links = match fle.get_internal_links().map_err_into(LEK::StoreReadError) + { + Err(e) => return Some(Err(e)), + Ok(links) => links, + }; + if links.count() == 0 { + match self.0 + .store() + .delete(fle.get_location().clone()) + .map_err_into(LEK::StoreWriteError) + { + Ok(x) => x, + Err(e) => return Some(Err(e)), + } + } else { + return Some(Ok(fle)); + } + }, + Some(Err(e)) => return Some(Err(e)), + None => break, + } + } + None + } + + } + } impl InternalLinker for Entry { |