Add a fold_ok utility.

Add a utility that folds an iterator into a result and uses it to reduce
boilerplate in the codebase.
This commit is contained in:
John Sirois 2016-07-13 12:37:19 -06:00
parent 3a2010c35b
commit 2c40b8734e
8 changed files with 93 additions and 83 deletions

View file

@ -14,3 +14,6 @@ path = "../libimagstore"
[dependencies.libimagerror]
path = "../libimagerror"
[dependencies.libimagutil]
path = "../libimagutil"

View file

@ -19,6 +19,7 @@ extern crate clap;
extern crate toml;
extern crate libimagstore;
extern crate libimagutil;
#[macro_use] extern crate libimagerror;
pub mod cli;

View file

@ -5,6 +5,7 @@ use lister::Lister;
use result::Result;
use libimagstore::store::FileLockEntry;
use libimagutil::iter::fold_ok;
pub struct LineLister<'a> {
unknown_output: &'a str,
@ -26,13 +27,10 @@ impl<'a> Lister for LineLister<'a> {
use error::ListError as LE;
use error::ListErrorKind as LEK;
entries.fold(Ok(()), |accu, entry| {
accu.and_then(|_| {
write!(stdout(), "{:?}\n",
entry.get_location().to_str().unwrap_or(self.unknown_output))
fold_ok(entries, |entry| {
write!(stdout(), "{:?}\n", entry.get_location().to_str().unwrap_or(self.unknown_output))
.map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))
})
})
}
}

View file

@ -5,6 +5,7 @@ use lister::Lister;
use result::Result;
use libimagstore::store::FileLockEntry;
use libimagutil::iter::fold_ok;
pub struct PathLister {
absolute: bool,
@ -26,8 +27,8 @@ impl Lister for PathLister {
use error::ListError as LE;
use error::ListErrorKind as LEK;
entries.fold(Ok(()), |accu, entry| {
accu.and_then(|_| Ok(entry.get_location().clone()))
fold_ok(entries, |entry| {
Ok(entry.get_location().clone())
.and_then(|pb| {
if self.absolute {
pb.canonicalize().map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))

View file

@ -1,4 +1,5 @@
use libimagerror::trace::trace_error;
use libimagutil::iter::fold_ok;
use store::FileLockEntry;
use storeid::StoreId;
@ -45,10 +46,7 @@ impl StoreIdAccessor for Aspect {
return Err(HE::new(HEK::AccessTypeViolation, None));
}
accessors
.iter()
.fold(Ok(()), |acc, accessor| {
acc.and_then(|_| {
fold_ok(accessors.iter(), |accessor| {
let res = match accessor {
&HDA::StoreIdAccess(accessor) => accessor.access(id),
_ => unreachable!(),
@ -67,7 +65,6 @@ impl StoreIdAccessor for Aspect {
}
}
})
})
}
}
@ -91,8 +88,7 @@ impl MutableHookDataAccessor for Aspect {
// More sophisticated version would check whether there are _chunks_ of
// NonMutableAccess accessors and execute these chunks in parallel. We do not have
// performance concerns yet, so this is okay.
accessors.iter().fold(Ok(()), |acc, accessor| {
acc.and_then(|_| {
fold_ok(accessors.iter(), |accessor| {
let res = match accessor {
&HDA::MutableAccess(ref accessor) => accessor.access_mut(fle),
&HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
@ -112,7 +108,6 @@ impl MutableHookDataAccessor for Aspect {
}
}
})
})
}
}
@ -123,10 +118,7 @@ impl NonMutableHookDataAccessor for Aspect {
return Err(HE::new(HEK::AccessTypeViolation, None));
}
accessors
.iter()
.fold(Ok(()), |acc, accessor| {
acc.and_then(|_| {
fold_ok(accessors.iter(), |accessor| {
let res = match accessor {
&HDA::NonMutableAccess(accessor) => accessor.access(fle),
_ => unreachable!(),
@ -145,7 +137,6 @@ impl NonMutableHookDataAccessor for Aspect {
}
}
})
})
}
}

View file

@ -37,6 +37,7 @@ use hook::position::HookPosition;
use hook::Hook;
use libimagerror::into::IntoError;
use libimagutil::iter::fold_ok;
use self::glob_store_iter::*;
@ -692,13 +693,16 @@ impl Store {
id: &StoreId)
-> HookResult<()>
{
fold_ok(
match aspects.lock() {
Err(_) => return Err(HookErrorKind::HookExecutionError.into()),
Ok(g) => g
}.iter().fold(Ok(()), |acc, aspect| {
}.iter(),
|aspect| {
debug!("[Aspect][exec]: {:?}", aspect);
acc.and_then(|_| (aspect as &StoreIdAccessor).access(id))
}).map_err(Box::new).map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
(aspect as &StoreIdAccessor).access(id)
}).map_err(Box::new)
.map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
}
fn execute_hooks_for_mut_file(&self,
@ -706,13 +710,16 @@ impl Store {
fle: &mut FileLockEntry)
-> HookResult<()>
{
fold_ok(
match aspects.lock() {
Err(_) => return Err(HookErrorKind::HookExecutionError.into()),
Ok(g) => g
}.iter().fold(Ok(()), |acc, aspect| {
}.iter(),
|aspect| {
debug!("[Aspect][exec]: {:?}", aspect);
acc.and_then(|_| aspect.access_mut(fle))
}).map_err(Box::new).map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
aspect.access_mut(fle)
}).map_err(Box::new)
.map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
}
}

8
libimagutil/src/iter.rs Normal file
View file

@ -0,0 +1,8 @@
/// Processes `iter` returning the last successful result or the first error.
pub fn fold_ok<X, I, R, E, F>(iter: I, mut func: F) -> Result<R, E>
where I: Iterator<Item = X>,
R: Default,
F: FnMut(X) -> Result<R, E>
{
iter.fold(Ok(R::default()), |acc, item| acc.and_then(|_| func(item)))
}

View file

@ -18,5 +18,6 @@
extern crate regex;
pub mod ismatch;
pub mod iter;
pub mod key_value_split;
pub mod variants;