Add module external::iter
This commit is contained in:
parent
3567606008
commit
378951a16b
1 changed files with 139 additions and 0 deletions
|
@ -111,6 +111,145 @@ pub trait ExternalLinker : InternalLinker {
|
|||
|
||||
}
|
||||
|
||||
pub mod iter {
|
||||
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 | 1 | 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)`.
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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(id: &StoreId) -> bool {
|
||||
debug!("Checking whether this is a 'links/external/': '{:?}'", id);
|
||||
|
|
Loading…
Reference in a new issue