summaryrefslogtreecommitdiffstats
path: root/libimagentrylink
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-08-13 21:48:17 +0000
committerMatthias Beyer <mail@beyermatthias.de>2017-08-27 15:12:09 +0200
commit59a3662ac47b0c657781bd1db34bbf9a5a692326 (patch)
tree709f72c44c8d978a5a76abb9036c6f08744a4aa2 /libimagentrylink
parent31254071e5a4bf2f5db9067c5cdb22c25579ac67 (diff)
Reorganize code in subdirs
Diffstat (limited to 'libimagentrylink')
-rw-r--r--libimagentrylink/Cargo.toml28
l---------libimagentrylink/README.md1
-rw-r--r--libimagentrylink/src/error.rs40
-rw-r--r--libimagentrylink/src/external.rs416
-rw-r--r--libimagentrylink/src/internal.rs1060
-rw-r--r--libimagentrylink/src/lib.rs55
-rw-r--r--libimagentrylink/src/result.rs25
7 files changed, 0 insertions, 1625 deletions
diff --git a/libimagentrylink/Cargo.toml b/libimagentrylink/Cargo.toml
deleted file mode 100644
index 451a0eb9..00000000
--- a/libimagentrylink/Cargo.toml
+++ /dev/null
@@ -1,28 +0,0 @@
-[package]
-name = "libimagentrylink"
-version = "0.4.0"
-authors = ["Matthias Beyer <mail@beyermatthias.de>"]
-
-description = "Library for the imag core distribution"
-
-keywords = ["imag", "PIM", "personal", "information", "management"]
-readme = "../README.md"
-license = "LGPL-2.1"
-
-documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html"
-repository = "https://github.com/matthiasbeyer/imag"
-homepage = "http://imag-pim.org"
-
-[dependencies]
-itertools = "0.5"
-log = "0.3"
-toml = "^0.4"
-semver = "0.5"
-url = "1.2"
-rust-crypto = "0.2"
-env_logger = "0.3"
-is-match = "0.1"
-
-libimagstore = { version = "0.4.0", path = "../libimagstore" }
-libimagerror = { version = "0.4.0", path = "../libimagerror" }
-libimagutil = { version = "0.4.0", path = "../libimagutil" }
diff --git a/libimagentrylink/README.md b/libimagentrylink/README.md
deleted file mode 120000
index d30d8ab6..00000000
--- a/libimagentrylink/README.md
+++ /dev/null
@@ -1 +0,0 @@
-../doc/src/05100-lib-entrylink.md \ No newline at end of file
diff --git a/libimagentrylink/src/error.rs b/libimagentrylink/src/error.rs
deleted file mode 100644
index 10d83f94..00000000
--- a/libimagentrylink/src/error.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-generate_error_module!(
- generate_error_types!(LinkError, LinkErrorKind,
- EntryHeaderReadError => "Error while reading an entry header",
- EntryHeaderWriteError => "Error while writing an entry header",
- ExistingLinkTypeWrong => "Existing link entry has wrong type",
- LinkTargetDoesNotExist => "Link target does not exist in the store",
- LinkParserError => "Link cannot be parsed",
- LinkParserFieldMissingError => "Link cannot be parsed: Field missing",
- LinkParserFieldTypeError => "Link cannot be parsed: Field type wrong",
- InternalConversionError => "Error while converting values internally",
- InvalidUri => "URI is not valid",
- StoreReadError => "Store read error",
- StoreWriteError => "Store write error",
- StoreIdError => "StoreId handling error"
- );
-);
-
-pub use self::error::LinkError;
-pub use self::error::LinkErrorKind;
-pub use self::error::MapErrInto;
-
diff --git a/libimagentrylink/src/external.rs b/libimagentrylink/src/external.rs
deleted file mode 100644
index daed7a12..00000000
--- a/libimagentrylink/src/external.rs
+++ /dev/null
@@ -1,416 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-/// External linking is a complex implementation to be able to serve a clean and easy-to-use
-/// interface.
-///
-/// Internally, there are no such things as "external links" (plural). Each Entry in the store can
-/// only have _one_ external link.
-///
-/// This library does the following therefor: It allows you to have several external links with one
-/// entry, which are internally one file in the store for each link, linked with "internal
-/// linking".
-///
-/// This helps us greatly with deduplication of URLs.
-///
-
-use std::ops::DerefMut;
-use std::collections::BTreeMap;
-use std::fmt::Debug;
-
-use libimagstore::store::Entry;
-use libimagstore::store::FileLockEntry;
-use libimagstore::store::Store;
-use libimagstore::storeid::StoreId;
-use libimagstore::storeid::IntoStoreId;
-use libimagstore::toml_ext::TomlValueExt;
-use libimagutil::debug_result::*;
-
-use error::LinkError as LE;
-use error::LinkErrorKind as LEK;
-use error::MapErrInto;
-use result::Result;
-use internal::InternalLinker;
-use module_path::ModuleEntryPath;
-
-use self::iter::*;
-
-use toml::Value;
-use url::Url;
-use crypto::sha1::Sha1;
-use crypto::digest::Digest;
-
-/// "Link" Type, just an abstraction over `FileLockEntry` to have some convenience internally.
-pub struct Link<'a> {
- link: FileLockEntry<'a>
-}
-
-impl<'a> Link<'a> {
-
- pub fn new(fle: FileLockEntry<'a>) -> Link<'a> {
- Link { link: fle }
- }
-
- /// Get a link Url object from a `FileLockEntry`, ignore errors.
- fn get_link_uri_from_filelockentry(file: &FileLockEntry<'a>) -> Option<Url> {
- file.get_header()
- .read("imag.content.url")
- .ok()
- .and_then(|opt| match opt {
- Some(Value::String(s)) => {
- debug!("Found url, parsing: {:?}", s);
- Url::parse(&s[..]).ok()
- },
- _ => None
- })
- }
-
- pub fn get_url(&self) -> Result<Option<Url>> {
- let opt = self.link
- .get_header()
- .read("imag.content.url");
-
- match opt {
- Ok(Some(Value::String(s))) => {
- Url::parse(&s[..])
- .map(Some)
- .map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e))))
- },
- Ok(None) => Ok(None),
- _ => Err(LE::new(LEK::EntryHeaderReadError, None))
- }
- }
-
-}
-
-pub trait ExternalLinker : InternalLinker {
-
- /// Get the external links from the implementor object
- fn get_external_links<'a>(&self, store: &'a Store) -> Result<UrlIter<'a>>;
-
- /// Set the external links for the implementor object
- fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()>;
-
- /// Add an external link to the implementor object
- fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()>;
-
- /// Remove an external link from the implementor object
- fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()>;
-
-}
-
-pub mod iter {
- //! Iterator helpers for external linking stuff
- //!
- //! Contains also helpers to filter iterators for external/internal links
- //!
- //!
- //! # Warning
- //!
- //! This module uses `internal::Link` as link type, so we operate on _store ids_ here.
- //!
- //! Not to confuse with `external::Link` which is a real `FileLockEntry` under the hood.
- //!
-
- use libimagutil::debug_result::*;
- use libimagstore::store::Store;
-
- use internal::Link;
- use internal::iter::LinkIter;
- use error::LinkErrorKind as LEK;
- use error::MapErrInto;
- use result::Result;
-
- use url::Url;
-
- /// Helper for building `OnlyExternalIter` and `NoExternalIter`
- ///
- /// The boolean value defines, how to interpret the `is_external_link_storeid()` return value
- /// (here as "pred"):
- ///
- /// pred | bool | xor | take?
- /// ---- | ---- | --- | ----
- /// 0 | 0 | 0 | 1
- /// 0 | 1 | 1 | 0
- /// 1 | 0 | 1 | 0
- /// 1 | 1 | 0 | 1
- ///
- /// If `bool` says "take if return value is false", we take the element if the `pred` returns
- /// false... and so on.
- ///
- /// As we can see, the operator between these two operants is `!(a ^ b)`.
- pub struct ExternalFilterIter(LinkIter, bool);
-
- impl Iterator for ExternalFilterIter {
- type Item = Link;
-
- fn next(&mut self) -> Option<Self::Item> {
- use super::is_external_link_storeid;
-
- while let Some(elem) = self.0.next() {
- if !(self.1 ^ is_external_link_storeid(&elem)) {
- return Some(elem);
- }
- }
- None
- }
- }
-
- /// Helper trait to be implemented on `LinkIter` to select or deselect all external links
- ///
- /// # See also
- ///
- /// Also see `OnlyExternalIter` and `NoExternalIter` and the helper traits/functions
- /// `OnlyInteralLinks`/`only_internal_links()` and `OnlyExternalLinks`/`only_external_links()`.
- pub trait SelectExternal {
- fn select_external_links(self, b: bool) -> ExternalFilterIter;
- }
-
- impl SelectExternal for LinkIter {
- fn select_external_links(self, b: bool) -> ExternalFilterIter {
- ExternalFilterIter(self, b)
- }
- }
-
-
- pub struct OnlyExternalIter(ExternalFilterIter);
-
- impl OnlyExternalIter {
- pub fn new(li: LinkIter) -> OnlyExternalIter {
- OnlyExternalIter(ExternalFilterIter(li, true))
- }
-
- pub fn urls<'a>(self, store: &'a Store) -> UrlIter<'a> {
- UrlIter(self, store)
- }
- }
-
- impl Iterator for OnlyExternalIter {
- type Item = Link;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next()
- }
- }
-
- pub struct NoExternalIter(ExternalFilterIter);
-
- impl NoExternalIter {
- pub fn new(li: LinkIter) -> NoExternalIter {
- NoExternalIter(ExternalFilterIter(li, false))
- }
- }
-
- impl Iterator for NoExternalIter {
- type Item = Link;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next()
- }
- }
-
- pub trait OnlyExternalLinks : Sized {
- fn only_external_links(self) -> OnlyExternalIter ;
-
- fn no_internal_links(self) -> OnlyExternalIter {
- self.only_external_links()
- }
- }
-
- impl OnlyExternalLinks for LinkIter {
- fn only_external_links(self) -> OnlyExternalIter {
- OnlyExternalIter::new(self)
- }
- }
-
- pub trait OnlyInternalLinks : Sized {
- fn only_internal_links(self) -> NoExternalIter;
-
- fn no_external_links(self) -> NoExternalIter {
- self.only_internal_links()
- }
- }
-
- impl OnlyInternalLinks for LinkIter {
- fn only_internal_links(self) -> NoExternalIter {
- NoExternalIter::new(self)
- }
- }
-
- pub struct UrlIter<'a>(OnlyExternalIter, &'a Store);
-
- impl<'a> Iterator for UrlIter<'a> {
- type Item = Result<Url>;
-
- fn next(&mut self) -> Option<Self::Item> {
- use super::get_external_link_from_file;
-
- self.0
- .next()
- .map(|id| {
- debug!("Retrieving entry for id: '{:?}'", id);
- self.1
- .retrieve(id.clone())
- .map_err_into(LEK::StoreReadError)
- .map_dbg_err(|_| format!("Retrieving entry for id: '{:?}' failed", id))
- .and_then(|f| {
- debug!("Store::retrieve({:?}) succeeded", id);
- debug!("getting external link from file now");
- get_external_link_from_file(&f)
- .map_dbg_err(|e| format!("URL -> Err = {:?}", e))
- })
- })
- }
-
- }
-
-}
-
-
-/// Check whether the StoreId starts with `/link/external/`
-pub fn is_external_link_storeid<A: AsRef<StoreId> + Debug>(id: A) -> bool {
- debug!("Checking whether this is a 'links/external/': '{:?}'", id);
- id.as_ref().local().starts_with("links/external")
-}
-
-fn get_external_link_from_file(entry: &FileLockEntry) -> Result<Url> {
- Link::get_link_uri_from_filelockentry(entry) // TODO: Do not hide error by using this function
- .ok_or(LE::new(LEK::StoreReadError, None))
-}
-
-/// Implement `ExternalLinker` for `Entry`, hiding the fact that there is no such thing as an external
-/// link in an entry, but internal links to other entries which serve as external links, as one
-/// entry in the store can only have one external link.
-impl ExternalLinker for Entry {
-
- /// Get the external links from the implementor object
- fn get_external_links<'a>(&self, store: &'a Store) -> Result<UrlIter<'a>> {
- // Iterate through all internal links and filter for FileLockEntries which live in
- // /link/external/<SHA> -> load these files and get the external link from their headers,
- // put them into the return vector.
- self.get_internal_links()
- .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
- .map(|iter| {
- debug!("Getting external links");
- iter.only_external_links().urls(store)
- })
- }
-
- /// Set the external links for the implementor object
- fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()> {
- // Take all the links, generate a SHA sum out of each one, filter out the already existing
- // store entries and store the other URIs in the header of one FileLockEntry each, in
- // the path /link/external/<SHA of the URL>
-
- debug!("Iterating {} links = {:?}", links.len(), links);
- for link in links { // for all links
- let hash = {
- let mut s = Sha1::new();
- s.input_str(&link.as_str()[..]);
- s.result_str()
- };
- let file_id = try!(
- ModuleEntryPath::new(format!("external/{}", hash)).into_storeid()
- .map_err_into(LEK::StoreWriteError)
- .map_dbg_err(|_| {
- format!("Failed to build StoreId for this hash '{:?}'", hash)
- })
- );
-
- debug!("Link = '{:?}'", link);
- debug!("Hash = '{:?}'", hash);
- debug!("StoreId = '{:?}'", file_id);
-
- // retrieve the file from the store, which implicitely creates the entry if it does not
- // exist
- let mut file = try!(store
- .retrieve(file_id.clone())
- .map_err_into(LEK::StoreWriteError)
- .map_dbg_err(|_| {
- format!("Failed to create or retrieve an file for this link '{:?}'", link)
- }));
-
- debug!("Generating header content!");
- {
- let mut hdr = file.deref_mut().get_header_mut();
-
- let mut table = match hdr.read("imag.content") {
- Ok(Some(Value::Table(table))) => table,
- Ok(Some(_)) => {
- warn!("There is a value at 'imag.content' which is not a table.");
- warn!("Going to override this value");
- BTreeMap::new()
- },
- Ok(None) => BTreeMap::new(),
- Err(e) => return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e)))),
- };
-
- let v = Value::String(link.into_string());
-
- debug!("setting URL = '{:?}", v);
- table.insert(String::from("url"), v);
-
- if let Err(e) = hdr.set("imag.content", Value::Table(table)) {
- return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
- } else {
- debug!("Setting URL worked");
- }
- }
-
- // then add an internal link to the new file or return an error if this fails
- if let Err(e) = self.add_internal_link(file.deref_mut()) {
- debug!("Error adding internal link");
- return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
- }
- }
- debug!("Ready iterating");
- Ok(())
- }
-
- /// Add an external link to the implementor object
- fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
- // get external links, add this one, save them
- debug!("Getting links");
- self.get_external_links(store)
- .and_then(|links| {
- // TODO: Do not ignore errors here
- let mut links = links.filter_map(Result::ok).collect::<Vec<_>>();
- debug!("Adding link = '{:?}' to links = {:?}", link, links);
- links.push(link);
- debug!("Setting {} links = {:?}", links.len(), links);
- self.set_external_links(store, links)
- })
- }
-
- /// Remove an external link from the implementor object
- fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
- // get external links, remove this one, save them
- self.get_external_links(store)
- .and_then(|links| {
- debug!("Removing link = '{:?}'", link);
- let links = links
- .filter_map(Result::ok)
- .filter(|l| l.as_str() != link.as_str())
- .collect::<Vec<_>>();
- self.set_external_links(store, links)
- })
- }
-
-}
-
diff --git a/libimagentrylink/src/internal.rs b/libimagentrylink/src/internal.rs
deleted file mode 100644
index 62003777..00000000
--- a/libimagentrylink/src/internal.rs
+++ /dev/null
@@ -1,1060 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-use std::collections::BTreeMap;
-#[cfg(test)]
-use std::path::PathBuf;
-
-use libimagstore::storeid::StoreId;
-use libimagstore::storeid::IntoStoreId;
-use libimagstore::store::Entry;
-use libimagstore::store::Result as StoreResult;
-use libimagstore::toml_ext::TomlValueExt;
-use libimagerror::into::IntoError;
-
-use error::LinkErrorKind as LEK;
-use error::MapErrInto;
-use result::Result;
-use self::iter::LinkIter;
-use self::iter::IntoValues;
-
-use toml::Value;
-
-#[derive(Eq, PartialOrd, Ord, Hash, Debug, Clone)]
-pub enum Link {
- Id { link: StoreId },
- Annotated { link: StoreId, annotation: String },
-}
-
-impl Link {
-
- pub fn exists(&self) -> Result<bool> {
- match *self {
- Link::Id { ref link } => link.exists(),
- Link::Annotated { ref link, .. } => link.exists(),
- }
- .map_err_into(LEK::StoreIdError)
- }
-
- pub fn to_str(&self) -> Result<String> {
- match *self {
- Link::Id { ref link } => link.to_str(),
- Link::Annotated { ref link, .. } => link.to_str(),
- }
- .map_err_into(LEK::StoreReadError)
- }
-
-
- fn eq_store_id(&self, id: &StoreId) -> bool {
- match self {
- &Link::Id { link: ref s } => s.eq(id),
- &Link::Annotated { link: ref s, .. } => s.eq(id),
- }
- }
-
- /// Get the StoreId inside the Link, which is always present
- pub fn get_store_id(&self) -> &StoreId {
- match self {
- &Link::Id { link: ref s } => s,
- &Link::Annotated { link: ref s, .. } => s,
- }
- }
-
- /// Helper wrapper around Link for StoreId
- fn without_base(self) -> Link {
- match self {
- Link::Id { link: s } => Link::Id { link: s.without_base() },
- Link::Annotated { link: s, annotation: ann } =>
- Link::Annotated { link: s.without_base(), annotation: ann },
- }
- }
-
- /// Helper wrapper around Link for StoreId
- #[cfg(test)]
- fn with_base(self, pb: PathBuf) -> Link {
- match self {
- Link::Id { link: s } => Link::Id { link: s.with_base(pb) },
- Link::Annotated { link: s, annotation: ann } =>
- Link::Annotated { link: s.with_base(pb), annotation: ann },
- }
- }
-
- fn to_value(&self) -> Result<Value> {
- match self {
- &Link::Id { link: ref s } =>
- s.to_str().map(Value::String).map_err_into(LEK::InternalConversionError),
- &Link::Annotated { ref link, annotation: ref anno } => {
- link.to_str()
- .map(Value::String)
- .map_err_into(LEK::InternalConversionError)
- .map(|link| {
- let mut tab = BTreeMap::new();
-
- tab.insert("link".to_owned(), link);
- tab.insert("annotation".to_owned(), Value::String(anno.clone()));
- Value::Table(tab)
- })
- }
- }
- }
-
-}
-
-impl ::std::cmp::PartialEq for Link {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (&Link::Id { link: ref a }, &Link::Id { link: ref b }) => a.eq(&b),
- (&Link::Annotated { link: ref a, annotation: ref ann1 },
- &Link::Annotated { link: ref b, annotation: ref ann2 }) =>
- (a, ann1).eq(&(b, ann2)),
- _ => false,
- }
- }
-}
-
-impl From<StoreId> for Link {
-
- fn from(s: StoreId) -> Link {
- Link::Id { link: s }
- }
-}
-
-impl Into<StoreId> for Link {
- fn into(self) -> StoreId {
- match self {
- Link::Id { link } => link,
- Link::Annotated { link, .. } => link,
- }
- }
-}
-
-impl IntoStoreId for Link {
- fn into_storeid(self) -> StoreResult<StoreId> {
- match self {
- Link::Id { link } => Ok(link),
- Link::Annotated { link, .. } => Ok(link),
- }
- }
-}
-
-impl AsRef<StoreId> for Link {
- fn as_ref(&self) -> &StoreId {
- match self {
- &Link::Id { ref link } => &link,
- &Link::Annotated { ref link, .. } => &link,
- }
- }
-}
-
-pub trait InternalLinker {
-
- /// Get the internal links from the implementor object
- fn get_internal_links(&self) -> Result<LinkIter>;
-
- /// Set the internal links for the implementor object
- fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<LinkIter>;
-
- /// Add an internal link to the implementor object
- fn add_internal_link(&mut self, link: &mut Entry) -> Result<()>;
-
- /// Remove an internal link from the implementor object
- fn remove_internal_link(&mut self, link: &mut Entry) -> Result<()>;
-
- /// Add internal annotated link
- fn add_internal_annotated_link(&mut self, link: &mut Entry, annotation: String) -> Result<()>;
-}
-
-pub mod iter {
- use std::vec::IntoIter;
- use super::Link;
-
- use error::LinkErrorKind as LEK;
- use error::MapErrInto;
- use result::Result;
-
- use toml::Value;
- use itertools::Itertools;
-
- use libimagstore::store::Store;
- use libimagstore::store::FileLockEntry;
-
- pub struct LinkIter(IntoIter<Link>);
-
- impl LinkIter {
-
- pub fn new(v: Vec<Link>) -> LinkIter {
- LinkIter(v.into_iter())
- }
-
- pub fn into_getter(self, store: &Store) -> GetIter {
- GetIter(self.0, store)
- }
-
- }
-
- impl Iterator for LinkIter {
- type Item = Link;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next()
- }
- }
-
- pub trait IntoValues {
- fn into_values(self) -> Vec<Result<Value>>;
- }
-
- impl<I: Iterator<Item = Link>> IntoValues for I {
- fn into_values(self) -> Vec<Result<Value>> {
- self.map(|s| s.without_base())
- .unique()
- .sorted()
- .into_iter() // Cannot sort toml::Value, hence uglyness here
- .map(|link| link.to_value().map_err_into(LEK::InternalConversionError))
- .collect()
- }
- }
-
- /// 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 {
-
- fn get_internal_links(&self) -> Result<LinkIter> {
- process_rw_result(self.get_header().read("imag.links"))
- }
-
- /// Set the links in a header and return the old links, if any.
- fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<LinkIter> {
- use internal::iter::IntoValues;
-
- let self_location = self.get_location().clone();
- let mut new_links = vec![];
-
- for link in links {
- if let Err(e) = add_foreign_link(link, self_location.clone()) {
- return Err(e);
- }
- new_links.push(link.get_location().clone().into());
- }
-
- let new_links = try!(LinkIter::new(new_links)
- .into_values()
- .into_iter()
- .fold(Ok(vec![]), |acc, elem| {
- acc.and_then(move |mut v| {
- elem.map_err_into(LEK::InternalConversionError)
- .map(|e| {
- v.push(e);
- v
- })
- })
- }));
- process_rw_result(self.get_header_mut().set("imag.links", Value::Array(new_links)))
- }
-
- fn add_internal_link(&mut self, link: &mut Entry) -> Result<()> {
- let location = link.get_location().clone().into();
- add_internal_link_with_instance(self, link, location)
- }
-
<