Merge pull request #532 from jsirois/jsirois/issues/499
Add a `fold_ok` utility.
This commit is contained in:
commit
295374e1bd
8 changed files with 103 additions and 75 deletions
|
@ -14,3 +14,6 @@ path = "../libimagstore"
|
||||||
[dependencies.libimagerror]
|
[dependencies.libimagerror]
|
||||||
path = "../libimagerror"
|
path = "../libimagerror"
|
||||||
|
|
||||||
|
[dependencies.libimagutil]
|
||||||
|
path = "../libimagutil"
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))))
|
||||||
|
|
|
@ -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)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
30
libimagutil/src/iter.rs
Normal 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)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue