Merge pull request #1120 from matthiasbeyer/remove-foldresult
Remove FoldResult
This commit is contained in:
commit
ecc8cc4567
8 changed files with 115 additions and 199 deletions
|
@ -54,7 +54,6 @@ use libimagbookmark::collection::BookmarkCollection;
|
|||
use libimagbookmark::link::Link as BookmarkLink;
|
||||
use libimagerror::trace::{MapErrTrace, trace_error, trace_error_exit};
|
||||
use libimagutil::info_result::*;
|
||||
use libimagutil::iter::*;
|
||||
|
||||
mod ui;
|
||||
|
||||
|
@ -88,9 +87,10 @@ fn add(rt: &Runtime) {
|
|||
|
||||
BookmarkCollection::get(rt.store(), &coll)
|
||||
.and_then(|mut collection| {
|
||||
scmd.values_of("urls")
|
||||
.unwrap() // enforced by clap
|
||||
.fold_result(|url| collection.add_link(BookmarkLink::from(url)))
|
||||
for url in scmd.values_of("urls").unwrap() { // unwrap saved by clap
|
||||
let _ = try!(collection.add_link(BookmarkLink::from(url)));
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.map_err_trace()
|
||||
.map_info_str("Ready")
|
||||
|
|
|
@ -145,11 +145,9 @@ impl Configuration {
|
|||
/// If `v` is empty, this is considered to be a successful `override_config()` call.
|
||||
pub fn override_config(&mut self, v: Vec<String>) -> Result<()> {
|
||||
use libimagutil::key_value_split::*;
|
||||
use libimagutil::iter::*;
|
||||
|
||||
use toml_query::read::TomlValueReadExt;
|
||||
|
||||
v.into_iter()
|
||||
let iter = v.into_iter()
|
||||
.map(|s| { debug!("Trying to process '{}'", s); s })
|
||||
.filter_map(|s| match s.into_kv() {
|
||||
Some(kv) => Some(kv.into()),
|
||||
|
@ -166,15 +164,19 @@ impl Configuration {
|
|||
Some(value) => match into_value(value, v) {
|
||||
Some(v) => {
|
||||
info!("Successfully overridden: {} = {}", k, v);
|
||||
Ok(v)
|
||||
Ok(())
|
||||
},
|
||||
None => Err(CE::from_kind(CEK::ConfigOverrideTypeNotMatching)),
|
||||
},
|
||||
None => Err(CE::from_kind(CEK::ConfigOverrideKeyNotAvailable)),
|
||||
})
|
||||
)
|
||||
.fold_result(|i| i)
|
||||
.chain_err(|| CEK::ConfigOverrideError)
|
||||
);
|
||||
|
||||
for elem in iter {
|
||||
let _ = try!(elem.chain_err(|| CEK::ConfigOverrideError));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -617,7 +617,6 @@ pub mod store_check {
|
|||
|
||||
use libimagstore::storeid::StoreId;
|
||||
use libimagstore::iter::get::StoreIdGetIteratorExtension;
|
||||
use libimagutil::iter::FoldResult;
|
||||
use libimagutil::debug_result::DebugResult;
|
||||
|
||||
// Helper data structure to collect incoming and outgoing links for each StoreId
|
||||
|
@ -674,23 +673,21 @@ pub mod store_check {
|
|||
///
|
||||
/// Because why not?
|
||||
let all_collected_storeids_exist = |network: &HashMap<StoreId, Linking>| -> LResult<()> {
|
||||
network
|
||||
.iter()
|
||||
.fold_result(|(id, _)| {
|
||||
if is_match!(self.get(id.clone()), Ok(Some(_))) {
|
||||
debug!("Exists in store: {:?}", id);
|
||||
for (id, _) in network.iter() {
|
||||
if is_match!(self.get(id.clone()), Ok(Some(_))) {
|
||||
debug!("Exists in store: {:?}", id);
|
||||
|
||||
if !try!(id.exists()) {
|
||||
warn!("Does exist in store but not on FS: {:?}", id);
|
||||
Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
warn!("Does not exist in store: {:?}", id);
|
||||
Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
||||
if !try!(id.exists()) {
|
||||
warn!("Does exist in store but not on FS: {:?}", id);
|
||||
return Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
warn!("Does not exist in store: {:?}", id);
|
||||
return Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
/// Helper function to create a SLCECD::OneDirectionalLink error object
|
||||
|
@ -703,46 +700,38 @@ pub mod store_check {
|
|||
/// appear in the _outgoing_ list of the linked entry
|
||||
let incoming_links_exists_as_outgoing_links =
|
||||
|src: &StoreId, linking: &Linking, network: &HashMap<StoreId, Linking>| -> Result<()> {
|
||||
linking
|
||||
.incoming
|
||||
.iter()
|
||||
.fold_result(|link| {
|
||||
for link in linking.incoming.iter() {
|
||||
// Check whether the links which are _incoming_ on _src_ are outgoing
|
||||
// in each of the links in the incoming list.
|
||||
let incoming_consistent = network.get(link)
|
||||
.map(|l| l.outgoing.contains(src))
|
||||
.unwrap_or(false);
|
||||
|
||||
// Check whether the links which are _incoming_ on _src_ are outgoing
|
||||
// in each of the links in the incoming list.
|
||||
let incoming_consistent = network.get(link)
|
||||
.map(|l| l.outgoing.contains(src))
|
||||
.unwrap_or(false);
|
||||
if !incoming_consistent {
|
||||
return Err(mk_one_directional_link_err(src.clone(), link.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
if !incoming_consistent {
|
||||
Err(mk_one_directional_link_err(src.clone(), link.clone()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
Ok(())
|
||||
};
|
||||
|
||||
/// Helper lambda to check whether the _outgoing links of each entry actually also
|
||||
/// appear in the _incoming_ list of the linked entry
|
||||
let outgoing_links_exist_as_incoming_links =
|
||||
|src: &StoreId, linking: &Linking, network: &HashMap<StoreId, Linking>| -> Result<()> {
|
||||
linking
|
||||
.outgoing
|
||||
.iter()
|
||||
.fold_result(|link| {
|
||||
for link in linking.outgoing.iter() {
|
||||
// Check whether the links which are _outgoing_ on _src_ are incoming
|
||||
// in each of the links in the outgoing list.
|
||||
let outgoing_consistent = network.get(link)
|
||||
.map(|l| l.incoming.contains(src))
|
||||
.unwrap_or(false);
|
||||
|
||||
// Check whether the links which are _outgoing_ on _src_ are incoming
|
||||
// in each of the links in the outgoing list.
|
||||
let outgoing_consistent = network.get(link)
|
||||
.map(|l| l.incoming.contains(src))
|
||||
.unwrap_or(false);
|
||||
if !outgoing_consistent {
|
||||
return Err(mk_one_directional_link_err(link.clone(), src.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
if !outgoing_consistent {
|
||||
Err(mk_one_directional_link_err(link.clone(), src.clone()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
Ok(())
|
||||
};
|
||||
|
||||
aggregate_link_network(&self)
|
||||
|
@ -760,11 +749,11 @@ pub mod store_check {
|
|||
.chain_err(|| LEK::LinkHandlingError)
|
||||
})
|
||||
.and_then(|nw| {
|
||||
nw.iter().fold_result(|(id, linking)| {
|
||||
for (id, linking) in nw.iter() {
|
||||
try!(incoming_links_exists_as_outgoing_links(id, linking, &nw));
|
||||
try!(outgoing_links_exist_as_incoming_links(id, linking, &nw));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ use error::Result;
|
|||
use error::ResultExt;
|
||||
|
||||
use libimagstore::store::FileLockEntry;
|
||||
use libimagutil::iter::FoldResult;
|
||||
|
||||
pub struct LineLister<'a> {
|
||||
unknown_output: &'a str,
|
||||
|
@ -46,10 +45,12 @@ impl<'a> Lister for LineLister<'a> {
|
|||
fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {
|
||||
use error::ListErrorKind as LEK;
|
||||
|
||||
entries.fold_result(|entry| {
|
||||
for entry in entries {
|
||||
let s = entry.get_location().to_str().unwrap_or(String::from(self.unknown_output));
|
||||
write!(stdout(), "{:?}\n", s).chain_err(| | LEK::FormatError)
|
||||
})
|
||||
try!(write!(stdout(), "{:?}\n", s).chain_err(|| LEK::FormatError))
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ use error::Result;
|
|||
use error::ResultExt;
|
||||
|
||||
use libimagstore::store::FileLockEntry;
|
||||
use libimagutil::iter::FoldResult;
|
||||
|
||||
pub struct PathLister {
|
||||
absolute: bool,
|
||||
|
@ -46,18 +45,19 @@ impl Lister for PathLister {
|
|||
fn list<'a, I: Iterator<Item = FileLockEntry<'a>>>(&self, entries: I) -> Result<()> {
|
||||
use error::ListErrorKind as LEK;
|
||||
|
||||
entries.fold_result(|entry| {
|
||||
Ok(entry.get_location().clone())
|
||||
.and_then(|pb| pb.into_pathbuf().chain_err(|| LEK::FormatError))
|
||||
.and_then(|pb| {
|
||||
if self.absolute {
|
||||
pb.canonicalize().chain_err(|| LEK::FormatError)
|
||||
} else {
|
||||
Ok(pb.into())
|
||||
}
|
||||
})
|
||||
.and_then(|pb| write!(stdout(), "{:?}\n", pb).chain_err(|| LEK::FormatError))
|
||||
})
|
||||
for entry in entries {
|
||||
let pb = entry.get_location().clone();
|
||||
let pb = try!(pb.into_pathbuf().chain_err(|| LEK::FormatError));
|
||||
let pb = if self.absolute {
|
||||
try!(pb.canonicalize().chain_err(|| LEK::FormatError))
|
||||
} else {
|
||||
pb.into()
|
||||
};
|
||||
|
||||
try!(write!(stdout(), "{:?}\n", pb).chain_err(|| LEK::FormatError))
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ use libimagentryref::flags::RefFlags;
|
|||
use libimagstore::store::Entry;
|
||||
use libimagstore::store::Store;
|
||||
use libimagstore::storeid::StoreId;
|
||||
use libimagutil::iter::FoldResult;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -106,57 +105,57 @@ impl LinkProcessor {
|
|||
pub fn process<'a>(&self, entry: &mut Entry, store: &'a Store) -> Result<()> {
|
||||
let text = entry.to_str();
|
||||
trace!("Processing: {:?}", entry.get_location());
|
||||
extract_links(&text)
|
||||
.into_iter()
|
||||
.fold_result::<_, MarkdownError, _>(|link| {
|
||||
trace!("Processing {:?}", link);
|
||||
match LinkQualification::qualify(&link.link) {
|
||||
LinkQualification::InternalLink => {
|
||||
if !self.process_internal_links {
|
||||
return Ok(());
|
||||
}
|
||||
for link in extract_links(&text).into_iter() {
|
||||
trace!("Processing {:?}", link);
|
||||
match LinkQualification::qualify(&link.link) {
|
||||
LinkQualification::InternalLink => {
|
||||
if !self.process_internal_links {
|
||||
continue
|
||||
}
|
||||
|
||||
let spath = Some(store.path().clone());
|
||||
let id = StoreId::new(spath, PathBuf::from(&link.link))?;
|
||||
let mut target = if self.create_internal_targets {
|
||||
try!(store.retrieve(id))
|
||||
} else {
|
||||
store.get(id.clone())?
|
||||
.ok_or(ME::from_kind(MEK::StoreGetError(id)))?
|
||||
};
|
||||
let spath = Some(store.path().clone());
|
||||
let id = StoreId::new(spath, PathBuf::from(&link.link))?;
|
||||
let mut target = if self.create_internal_targets {
|
||||
try!(store.retrieve(id))
|
||||
} else {
|
||||
store.get(id.clone())?
|
||||
.ok_or(ME::from_kind(MEK::StoreGetError(id)))?
|
||||
};
|
||||
|
||||
entry.add_internal_link(&mut target).map_err(From::from)
|
||||
},
|
||||
LinkQualification::ExternalLink(url) => {
|
||||
if !self.process_external_links {
|
||||
return Ok(());
|
||||
}
|
||||
let _ = entry.add_internal_link(&mut target)?;
|
||||
},
|
||||
LinkQualification::ExternalLink(url) => {
|
||||
if !self.process_external_links {
|
||||
continue
|
||||
}
|
||||
|
||||
entry.add_external_link(store, url).map_err(From::from)
|
||||
},
|
||||
LinkQualification::RefLink(url) => {
|
||||
if !self.process_refs {
|
||||
return Ok(());
|
||||
}
|
||||
entry.add_external_link(store, url)?;
|
||||
},
|
||||
LinkQualification::RefLink(url) => {
|
||||
if !self.process_refs {
|
||||
continue
|
||||
}
|
||||
|
||||
let flags = RefFlags::default()
|
||||
.with_content_hashing(false)
|
||||
.with_permission_tracking(false);
|
||||
trace!("URL = {:?}", url);
|
||||
trace!("URL.path() = {:?}", url.path());
|
||||
trace!("URL.host_str() = {:?}", url.host_str());
|
||||
let path = url.host_str().unwrap_or_else(|| url.path());
|
||||
let path = PathBuf::from(path);
|
||||
let mut target = try!(RefStore::create(store, path, flags));
|
||||
let flags = RefFlags::default()
|
||||
.with_content_hashing(false)
|
||||
.with_permission_tracking(false);
|
||||
trace!("URL = {:?}", url);
|
||||
trace!("URL.path() = {:?}", url.path());
|
||||
trace!("URL.host_str() = {:?}", url.host_str());
|
||||
let path = url.host_str().unwrap_or_else(|| url.path());
|
||||
let path = PathBuf::from(path);
|
||||
let mut target = try!(RefStore::create(store, path, flags));
|
||||
|
||||
entry.add_internal_link(&mut target).map_err(From::from)
|
||||
},
|
||||
LinkQualification::Undecidable(e) => {
|
||||
// error
|
||||
Err(e).chain_err(|| MEK::UndecidableLinkType(link.link.clone()))
|
||||
},
|
||||
}
|
||||
})
|
||||
entry.add_internal_link(&mut target)?;
|
||||
},
|
||||
LinkQualification::Undecidable(e) => {
|
||||
// error
|
||||
return Err(e).chain_err(|| MEK::UndecidableLinkType(link.link.clone()))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,74 +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
|
||||
//
|
||||
|
||||
/// Folds its contents to a result.
|
||||
pub trait FoldResult: Sized {
|
||||
type Item;
|
||||
|
||||
/// Apply a `FnMut(Self::Item) -> Result<R, E>` to each item. If each
|
||||
/// application returns an `Ok(_)`, return `Ok(())`, indicating success.
|
||||
/// Otherwise return the first error.
|
||||
///
|
||||
/// The return type of this function only indicates success with the
|
||||
/// `Ok(())` idiom. To retrieve the values of your application, include an
|
||||
/// accumulator in `func`. This is the intended reason for the permissive
|
||||
/// `FnMut` type.
|
||||
fn fold_result<R, E, F>(self, func: F) -> Result<(), E>
|
||||
where F: FnMut(Self::Item) -> Result<R, E>;
|
||||
|
||||
}
|
||||
|
||||
impl<X, I: Iterator<Item = X>> FoldResult for I {
|
||||
type Item = X;
|
||||
|
||||
fn fold_result<R, E, F>(self, mut func: F) -> Result<(), E>
|
||||
where F: FnMut(Self::Item) -> Result<R, E>
|
||||
{
|
||||
for item in self {
|
||||
try!(func(item));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fold_result_success() {
|
||||
let v = vec![1, 2, 3];
|
||||
let mut accum = vec![];
|
||||
let result: Result<(), &str> = v.iter().fold_result(|item| {
|
||||
accum.push(*item * 2);
|
||||
Ok(*item)
|
||||
});
|
||||
assert_eq!(result, Ok(()));
|
||||
assert_eq!(accum, vec![2, 4, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fold_result_failure() {
|
||||
let v: Vec<usize> = vec![1, 2, 3];
|
||||
let mut accum: Vec<usize> = vec![];
|
||||
let result: Result<(), &str> = v.iter().fold_result(|item| if *item == 2 {
|
||||
Err("failure")
|
||||
} else {
|
||||
accum.push(*item * 2);
|
||||
Ok(*item)
|
||||
});
|
||||
assert_eq!(result, Err("failure"));
|
||||
assert_eq!(accum, vec![2]);
|
||||
}
|
|
@ -45,7 +45,6 @@ pub mod cli_validators;
|
|||
pub mod debug_result;
|
||||
pub mod edit;
|
||||
pub mod info_result;
|
||||
pub mod iter;
|
||||
pub mod key_value_split;
|
||||
pub mod variants;
|
||||
pub mod warn_exit;
|
||||
|
|
Loading…
Reference in a new issue