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 libimagbookmark::link::Link as BookmarkLink;
|
||||||
use libimagerror::trace::{MapErrTrace, trace_error, trace_error_exit};
|
use libimagerror::trace::{MapErrTrace, trace_error, trace_error_exit};
|
||||||
use libimagutil::info_result::*;
|
use libimagutil::info_result::*;
|
||||||
use libimagutil::iter::*;
|
|
||||||
|
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
|
@ -88,9 +87,10 @@ fn add(rt: &Runtime) {
|
||||||
|
|
||||||
BookmarkCollection::get(rt.store(), &coll)
|
BookmarkCollection::get(rt.store(), &coll)
|
||||||
.and_then(|mut collection| {
|
.and_then(|mut collection| {
|
||||||
scmd.values_of("urls")
|
for url in scmd.values_of("urls").unwrap() { // unwrap saved by clap
|
||||||
.unwrap() // enforced by clap
|
let _ = try!(collection.add_link(BookmarkLink::from(url)));
|
||||||
.fold_result(|url| collection.add_link(BookmarkLink::from(url)))
|
}
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
.map_err_trace()
|
.map_err_trace()
|
||||||
.map_info_str("Ready")
|
.map_info_str("Ready")
|
||||||
|
|
|
@ -145,11 +145,9 @@ impl Configuration {
|
||||||
/// If `v` is empty, this is considered to be a successful `override_config()` call.
|
/// If `v` is empty, this is considered to be a successful `override_config()` call.
|
||||||
pub fn override_config(&mut self, v: Vec<String>) -> Result<()> {
|
pub fn override_config(&mut self, v: Vec<String>) -> Result<()> {
|
||||||
use libimagutil::key_value_split::*;
|
use libimagutil::key_value_split::*;
|
||||||
use libimagutil::iter::*;
|
|
||||||
|
|
||||||
use toml_query::read::TomlValueReadExt;
|
use toml_query::read::TomlValueReadExt;
|
||||||
|
|
||||||
v.into_iter()
|
let iter = v.into_iter()
|
||||||
.map(|s| { debug!("Trying to process '{}'", s); s })
|
.map(|s| { debug!("Trying to process '{}'", s); s })
|
||||||
.filter_map(|s| match s.into_kv() {
|
.filter_map(|s| match s.into_kv() {
|
||||||
Some(kv) => Some(kv.into()),
|
Some(kv) => Some(kv.into()),
|
||||||
|
@ -166,15 +164,19 @@ impl Configuration {
|
||||||
Some(value) => match into_value(value, v) {
|
Some(value) => match into_value(value, v) {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
info!("Successfully overridden: {} = {}", k, v);
|
info!("Successfully overridden: {} = {}", k, v);
|
||||||
Ok(v)
|
Ok(())
|
||||||
},
|
},
|
||||||
None => Err(CE::from_kind(CEK::ConfigOverrideTypeNotMatching)),
|
None => Err(CE::from_kind(CEK::ConfigOverrideTypeNotMatching)),
|
||||||
},
|
},
|
||||||
None => Err(CE::from_kind(CEK::ConfigOverrideKeyNotAvailable)),
|
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::storeid::StoreId;
|
||||||
use libimagstore::iter::get::StoreIdGetIteratorExtension;
|
use libimagstore::iter::get::StoreIdGetIteratorExtension;
|
||||||
use libimagutil::iter::FoldResult;
|
|
||||||
use libimagutil::debug_result::DebugResult;
|
use libimagutil::debug_result::DebugResult;
|
||||||
|
|
||||||
// Helper data structure to collect incoming and outgoing links for each StoreId
|
// Helper data structure to collect incoming and outgoing links for each StoreId
|
||||||
|
@ -674,23 +673,21 @@ pub mod store_check {
|
||||||
///
|
///
|
||||||
/// Because why not?
|
/// Because why not?
|
||||||
let all_collected_storeids_exist = |network: &HashMap<StoreId, Linking>| -> LResult<()> {
|
let all_collected_storeids_exist = |network: &HashMap<StoreId, Linking>| -> LResult<()> {
|
||||||
network
|
for (id, _) in network.iter() {
|
||||||
.iter()
|
|
||||||
.fold_result(|(id, _)| {
|
|
||||||
if is_match!(self.get(id.clone()), Ok(Some(_))) {
|
if is_match!(self.get(id.clone()), Ok(Some(_))) {
|
||||||
debug!("Exists in store: {:?}", id);
|
debug!("Exists in store: {:?}", id);
|
||||||
|
|
||||||
if !try!(id.exists()) {
|
if !try!(id.exists()) {
|
||||||
warn!("Does exist in store but not on FS: {:?}", id);
|
warn!("Does exist in store but not on FS: {:?}", id);
|
||||||
Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
return Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!("Does not exist in store: {:?}", id);
|
warn!("Does not exist in store: {:?}", id);
|
||||||
Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
return Err(LE::from_kind(LEK::LinkTargetDoesNotExist))
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Helper function to create a SLCECD::OneDirectionalLink error object
|
/// Helper function to create a SLCECD::OneDirectionalLink error object
|
||||||
|
@ -703,11 +700,7 @@ pub mod store_check {
|
||||||
/// appear in the _outgoing_ list of the linked entry
|
/// appear in the _outgoing_ list of the linked entry
|
||||||
let incoming_links_exists_as_outgoing_links =
|
let incoming_links_exists_as_outgoing_links =
|
||||||
|src: &StoreId, linking: &Linking, network: &HashMap<StoreId, Linking>| -> Result<()> {
|
|src: &StoreId, linking: &Linking, network: &HashMap<StoreId, Linking>| -> Result<()> {
|
||||||
linking
|
for link in linking.incoming.iter() {
|
||||||
.incoming
|
|
||||||
.iter()
|
|
||||||
.fold_result(|link| {
|
|
||||||
|
|
||||||
// Check whether the links which are _incoming_ on _src_ are outgoing
|
// Check whether the links which are _incoming_ on _src_ are outgoing
|
||||||
// in each of the links in the incoming list.
|
// in each of the links in the incoming list.
|
||||||
let incoming_consistent = network.get(link)
|
let incoming_consistent = network.get(link)
|
||||||
|
@ -715,22 +708,18 @@ pub mod store_check {
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if !incoming_consistent {
|
if !incoming_consistent {
|
||||||
Err(mk_one_directional_link_err(src.clone(), link.clone()))
|
return 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
|
/// Helper lambda to check whether the _outgoing links of each entry actually also
|
||||||
/// appear in the _incoming_ list of the linked entry
|
/// appear in the _incoming_ list of the linked entry
|
||||||
let outgoing_links_exist_as_incoming_links =
|
let outgoing_links_exist_as_incoming_links =
|
||||||
|src: &StoreId, linking: &Linking, network: &HashMap<StoreId, Linking>| -> Result<()> {
|
|src: &StoreId, linking: &Linking, network: &HashMap<StoreId, Linking>| -> Result<()> {
|
||||||
linking
|
for link in linking.outgoing.iter() {
|
||||||
.outgoing
|
|
||||||
.iter()
|
|
||||||
.fold_result(|link| {
|
|
||||||
|
|
||||||
// Check whether the links which are _outgoing_ on _src_ are incoming
|
// Check whether the links which are _outgoing_ on _src_ are incoming
|
||||||
// in each of the links in the outgoing list.
|
// in each of the links in the outgoing list.
|
||||||
let outgoing_consistent = network.get(link)
|
let outgoing_consistent = network.get(link)
|
||||||
|
@ -738,11 +727,11 @@ pub mod store_check {
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if !outgoing_consistent {
|
if !outgoing_consistent {
|
||||||
Err(mk_one_directional_link_err(link.clone(), src.clone()))
|
return Err(mk_one_directional_link_err(link.clone(), src.clone()))
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
aggregate_link_network(&self)
|
aggregate_link_network(&self)
|
||||||
|
@ -760,12 +749,12 @@ pub mod store_check {
|
||||||
.chain_err(|| LEK::LinkHandlingError)
|
.chain_err(|| LEK::LinkHandlingError)
|
||||||
})
|
})
|
||||||
.and_then(|nw| {
|
.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!(incoming_links_exists_as_outgoing_links(id, linking, &nw));
|
||||||
try!(outgoing_links_exist_as_incoming_links(id, linking, &nw));
|
try!(outgoing_links_exist_as_incoming_links(id, linking, &nw));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
})
|
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ use error::Result;
|
||||||
use error::ResultExt;
|
use error::ResultExt;
|
||||||
|
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
use libimagutil::iter::FoldResult;
|
|
||||||
|
|
||||||
pub struct LineLister<'a> {
|
pub struct LineLister<'a> {
|
||||||
unknown_output: &'a str,
|
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<()> {
|
fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {
|
||||||
use error::ListErrorKind as LEK;
|
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));
|
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 error::ResultExt;
|
||||||
|
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
use libimagutil::iter::FoldResult;
|
|
||||||
|
|
||||||
pub struct PathLister {
|
pub struct PathLister {
|
||||||
absolute: bool,
|
absolute: bool,
|
||||||
|
@ -46,18 +45,19 @@ impl Lister for PathLister {
|
||||||
fn list<'a, I: Iterator<Item = FileLockEntry<'a>>>(&self, entries: I) -> Result<()> {
|
fn list<'a, I: Iterator<Item = FileLockEntry<'a>>>(&self, entries: I) -> Result<()> {
|
||||||
use error::ListErrorKind as LEK;
|
use error::ListErrorKind as LEK;
|
||||||
|
|
||||||
entries.fold_result(|entry| {
|
for entry in entries {
|
||||||
Ok(entry.get_location().clone())
|
let pb = entry.get_location().clone();
|
||||||
.and_then(|pb| pb.into_pathbuf().chain_err(|| LEK::FormatError))
|
let pb = try!(pb.into_pathbuf().chain_err(|| LEK::FormatError));
|
||||||
.and_then(|pb| {
|
let pb = if self.absolute {
|
||||||
if self.absolute {
|
try!(pb.canonicalize().chain_err(|| LEK::FormatError))
|
||||||
pb.canonicalize().chain_err(|| LEK::FormatError)
|
|
||||||
} else {
|
} else {
|
||||||
Ok(pb.into())
|
pb.into()
|
||||||
|
};
|
||||||
|
|
||||||
|
try!(write!(stdout(), "{:?}\n", pb).chain_err(|| LEK::FormatError))
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.and_then(|pb| write!(stdout(), "{:?}\n", pb).chain_err(|| LEK::FormatError))
|
Ok(())
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ use libimagentryref::flags::RefFlags;
|
||||||
use libimagstore::store::Entry;
|
use libimagstore::store::Entry;
|
||||||
use libimagstore::store::Store;
|
use libimagstore::store::Store;
|
||||||
use libimagstore::storeid::StoreId;
|
use libimagstore::storeid::StoreId;
|
||||||
use libimagutil::iter::FoldResult;
|
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
@ -106,14 +105,12 @@ impl LinkProcessor {
|
||||||
pub fn process<'a>(&self, entry: &mut Entry, store: &'a Store) -> Result<()> {
|
pub fn process<'a>(&self, entry: &mut Entry, store: &'a Store) -> Result<()> {
|
||||||
let text = entry.to_str();
|
let text = entry.to_str();
|
||||||
trace!("Processing: {:?}", entry.get_location());
|
trace!("Processing: {:?}", entry.get_location());
|
||||||
extract_links(&text)
|
for link in extract_links(&text).into_iter() {
|
||||||
.into_iter()
|
|
||||||
.fold_result::<_, MarkdownError, _>(|link| {
|
|
||||||
trace!("Processing {:?}", link);
|
trace!("Processing {:?}", link);
|
||||||
match LinkQualification::qualify(&link.link) {
|
match LinkQualification::qualify(&link.link) {
|
||||||
LinkQualification::InternalLink => {
|
LinkQualification::InternalLink => {
|
||||||
if !self.process_internal_links {
|
if !self.process_internal_links {
|
||||||
return Ok(());
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let spath = Some(store.path().clone());
|
let spath = Some(store.path().clone());
|
||||||
|
@ -125,18 +122,18 @@ impl LinkProcessor {
|
||||||
.ok_or(ME::from_kind(MEK::StoreGetError(id)))?
|
.ok_or(ME::from_kind(MEK::StoreGetError(id)))?
|
||||||
};
|
};
|
||||||
|
|
||||||
entry.add_internal_link(&mut target).map_err(From::from)
|
let _ = entry.add_internal_link(&mut target)?;
|
||||||
},
|
},
|
||||||
LinkQualification::ExternalLink(url) => {
|
LinkQualification::ExternalLink(url) => {
|
||||||
if !self.process_external_links {
|
if !self.process_external_links {
|
||||||
return Ok(());
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.add_external_link(store, url).map_err(From::from)
|
entry.add_external_link(store, url)?;
|
||||||
},
|
},
|
||||||
LinkQualification::RefLink(url) => {
|
LinkQualification::RefLink(url) => {
|
||||||
if !self.process_refs {
|
if !self.process_refs {
|
||||||
return Ok(());
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let flags = RefFlags::default()
|
let flags = RefFlags::default()
|
||||||
|
@ -149,14 +146,16 @@ impl LinkProcessor {
|
||||||
let path = PathBuf::from(path);
|
let path = PathBuf::from(path);
|
||||||
let mut target = try!(RefStore::create(store, path, flags));
|
let mut target = try!(RefStore::create(store, path, flags));
|
||||||
|
|
||||||
entry.add_internal_link(&mut target).map_err(From::from)
|
entry.add_internal_link(&mut target)?;
|
||||||
},
|
},
|
||||||
LinkQualification::Undecidable(e) => {
|
LinkQualification::Undecidable(e) => {
|
||||||
// error
|
// error
|
||||||
Err(e).chain_err(|| MEK::UndecidableLinkType(link.link.clone()))
|
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 debug_result;
|
||||||
pub mod edit;
|
pub mod edit;
|
||||||
pub mod info_result;
|
pub mod info_result;
|
||||||
pub mod iter;
|
|
||||||
pub mod key_value_split;
|
pub mod key_value_split;
|
||||||
pub mod variants;
|
pub mod variants;
|
||||||
pub mod warn_exit;
|
pub mod warn_exit;
|
||||||
|
|
Loading…
Reference in a new issue