Merge pull request #532 from jsirois/jsirois/issues/499

Add a `fold_ok` utility.
This commit is contained in:
Matthias Beyer 2016-07-14 18:29:32 +02:00 committed by GitHub
commit 295374e1bd
8 changed files with 103 additions and 75 deletions

View file

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

View file

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

View file

@ -5,6 +5,7 @@ use lister::Lister;
use result::Result; use result::Result;
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,
@ -26,13 +27,10 @@ impl<'a> Lister for LineLister<'a> {
use error::ListError as LE; use error::ListError as LE;
use error::ListErrorKind as LEK; use error::ListErrorKind as LEK;
entries.fold(Ok(()), |accu, entry| { entries.fold_defresult(|entry| {
accu.and_then(|_| { write!(stdout(), "{:?}\n", entry.get_location().to_str().unwrap_or(self.unknown_output))
write!(stdout(), "{:?}\n", .map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))
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 result::Result;
use libimagstore::store::FileLockEntry; use libimagstore::store::FileLockEntry;
use libimagutil::iter::FoldResult;
pub struct PathLister { pub struct PathLister {
absolute: bool, absolute: bool,
@ -26,8 +27,8 @@ impl Lister for PathLister {
use error::ListError as LE; use error::ListError as LE;
use error::ListErrorKind as LEK; use error::ListErrorKind as LEK;
entries.fold(Ok(()), |accu, entry| { entries.fold_defresult(|entry| {
accu.and_then(|_| Ok(entry.get_location().clone())) Ok(entry.get_location().clone())
.and_then(|pb| { .and_then(|pb| {
if self.absolute { if self.absolute {
pb.canonicalize().map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) 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 libimagerror::trace::trace_error;
use libimagutil::iter::FoldResult;
use store::FileLockEntry; use store::FileLockEntry;
use storeid::StoreId; use storeid::StoreId;
@ -45,29 +46,25 @@ impl StoreIdAccessor for Aspect {
return Err(HE::new(HEK::AccessTypeViolation, None)); return Err(HE::new(HEK::AccessTypeViolation, None));
} }
accessors accessors.iter().fold_defresult(|accessor| {
.iter() let res = match accessor {
.fold(Ok(()), |acc, accessor| { &HDA::StoreIdAccess(accessor) => accessor.access(id),
acc.and_then(|_| { _ => unreachable!(),
let res = match accessor { };
&HDA::StoreIdAccess(accessor) => accessor.access(id),
_ => unreachable!(),
};
match res { match res {
Ok(res) => Ok(res), Ok(res) => Ok(res),
Err(e) => { Err(e) => {
if !e.is_aborting() { if !e.is_aborting() {
trace_error(&e); trace_error(&e);
// ignore error if it is not aborting, as we printed it already // ignore error if it is not aborting, as we printed it already
Ok(()) Ok(())
} else { } else {
Err(e) Err(e)
}
}
} }
}) }
}) }
})
} }
} }
@ -91,27 +88,25 @@ impl MutableHookDataAccessor for Aspect {
// More sophisticated version would check whether there are _chunks_ of // More sophisticated version would check whether there are _chunks_ of
// NonMutableAccess accessors and execute these chunks in parallel. We do not have // NonMutableAccess accessors and execute these chunks in parallel. We do not have
// performance concerns yet, so this is okay. // performance concerns yet, so this is okay.
accessors.iter().fold(Ok(()), |acc, accessor| { accessors.iter().fold_defresult(|accessor| {
acc.and_then(|_| { let res = match accessor {
let res = match accessor { &HDA::MutableAccess(ref accessor) => accessor.access_mut(fle),
&HDA::MutableAccess(ref accessor) => accessor.access_mut(fle), &HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
&HDA::NonMutableAccess(ref accessor) => accessor.access(fle), _ => unreachable!(),
_ => unreachable!(), };
};
match res { match res {
Ok(res) => Ok(res), Ok(res) => Ok(res),
Err(e) => { Err(e) => {
if !e.is_aborting() { if !e.is_aborting() {
trace_error(&e); trace_error(&e);
// ignore error if it is not aborting, as we printed it already // ignore error if it is not aborting, as we printed it already
Ok(()) Ok(())
} else { } else {
Err(e) Err(e)
}
} }
} }
}) }
}) })
} }
} }
@ -123,29 +118,25 @@ impl NonMutableHookDataAccessor for Aspect {
return Err(HE::new(HEK::AccessTypeViolation, None)); return Err(HE::new(HEK::AccessTypeViolation, None));
} }
accessors accessors.iter().fold_defresult(|accessor| {
.iter() let res = match accessor {
.fold(Ok(()), |acc, accessor| { &HDA::NonMutableAccess(accessor) => accessor.access(fle),
acc.and_then(|_| { _ => unreachable!(),
let res = match accessor { };
&HDA::NonMutableAccess(accessor) => accessor.access(fle),
_ => unreachable!(),
};
match res { match res {
Ok(res) => Ok(res), Ok(res) => Ok(res),
Err(e) => { Err(e) => {
if !e.is_aborting() { if !e.is_aborting() {
trace_error(&e); trace_error(&e);
// ignore error if it is not aborting, as we printed it already // ignore error if it is not aborting, as we printed it already
Ok(()) Ok(())
} else { } else {
Err(e) Err(e)
}
}
} }
}) }
}) }
})
} }
} }

View file

@ -37,6 +37,7 @@ use hook::position::HookPosition;
use hook::Hook; use hook::Hook;
use libimagerror::into::IntoError; use libimagerror::into::IntoError;
use libimagutil::iter::FoldResult;
use self::glob_store_iter::*; use self::glob_store_iter::*;
@ -695,10 +696,11 @@ impl Store {
match aspects.lock() { match aspects.lock() {
Err(_) => return Err(HookErrorKind::HookExecutionError.into()), Err(_) => return Err(HookErrorKind::HookExecutionError.into()),
Ok(g) => g Ok(g) => g
}.iter().fold(Ok(()), |acc, aspect| { }.iter().fold_defresult(|aspect| {
debug!("[Aspect][exec]: {:?}", aspect); debug!("[Aspect][exec]: {:?}", aspect);
acc.and_then(|_| (aspect as &StoreIdAccessor).access(id)) (aspect as &StoreIdAccessor).access(id)
}).map_err(Box::new).map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e)) }).map_err(Box::new)
.map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
} }
fn execute_hooks_for_mut_file(&self, fn execute_hooks_for_mut_file(&self,
@ -709,10 +711,11 @@ impl Store {
match aspects.lock() { match aspects.lock() {
Err(_) => return Err(HookErrorKind::HookExecutionError.into()), Err(_) => return Err(HookErrorKind::HookExecutionError.into()),
Ok(g) => g Ok(g) => g
}.iter().fold(Ok(()), |acc, aspect| { }.iter().fold_defresult(|aspect| {
debug!("[Aspect][exec]: {:?}", aspect); debug!("[Aspect][exec]: {:?}", aspect);
acc.and_then(|_| aspect.access_mut(fle)) aspect.access_mut(fle)
}).map_err(Box::new).map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e)) }).map_err(Box::new)
.map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
} }
} }

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

@ -0,0 +1,30 @@
/// Folds its contents to a result.
pub trait FoldResult: Sized {
type Item;
/// Processes all contained items returning the last successful result or the first error.
/// If there are no items, returns `Ok(R::default())`.
fn fold_defresult<R, E, F>(self, func: F) -> Result<R, E>
where R: Default,
F: FnMut(Self::Item)
-> Result<R, E>
{
self.fold_result(R::default(), func)
}
/// Processes all contained items returning the last successful result or the first error.
/// If there are no items, returns `Ok(default)`.
fn fold_result<R, E, F>(self, default: R, mut func: F) -> Result<R, 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, default: R, mut func: F) -> Result<R, E>
where F: FnMut(Self::Item) -> Result<R, E>
{
self.fold(Ok(default), |acc, item| acc.and_then(|_| func(item)))
}
}

View file

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