summaryrefslogtreecommitdiffstats
path: root/libimagentrylink
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2016-10-20 18:41:19 +0200
committerGitHub <noreply@github.com>2016-10-20 18:41:19 +0200
commit89af64c27fef706e05a6641fcb736e0e3b85bcfc (patch)
tree4edc0cceae588cb74b990bbd2c15c6b8b6caa810 /libimagentrylink
parent41aaaf9ddc5af54bf853efb98df0add0b08c00d2 (diff)
parente4e5fafce2dfd4084e2847c511b8fc30f90986f8 (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.rs159
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 {