Remove FoldResult

This commit is contained in:
Matthias Beyer 2017-09-28 23:08:07 +02:00
parent d8055b4553
commit 169107d569
8 changed files with 115 additions and 199 deletions

View File

@ -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")

View File

@ -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(())
} }
} }

View File

@ -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(|_| ())
} }
} }

View File

@ -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(())
} }
} }

View File

@ -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(())
})
} }
} }

View File

@ -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(())
} }
} }

View File

@ -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]);
}

View File

@ -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;