Merge pull request #1120 from matthiasbeyer/remove-foldresult

Remove FoldResult
This commit is contained in:
Matthias Beyer 2017-09-30 11:21:09 +02:00 committed by GitHub
commit ecc8cc4567
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 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")

View file

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

View file

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

View file

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

View file

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

View file

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

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 edit;
pub mod info_result;
pub mod iter;
pub mod key_value_split;
pub mod variants;
pub mod warn_exit;