From 7f57e5e23400e83102f7fbc830080e53793e959f Mon Sep 17 00:00:00 2001 From: John Sirois Date: Thu, 14 Jul 2016 07:28:50 -0600 Subject: [PATCH] Move from a helper function to a typeclass. This introduces the `FoldResut` trait to move from `func(receiver, ...)` style to `receiver.func(...)` style. Also add a means to pass the default result explicitly. --- libimagentrylist/src/listers/line.rs | 4 +-- libimagentrylist/src/listers/path.rs | 4 +-- libimagstore/src/hook/aspect.rs | 8 +++--- libimagstore/src/store.rs | 38 +++++++++++++--------------- libimagutil/src/iter.rs | 36 +++++++++++++++++++++----- 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/libimagentrylist/src/listers/line.rs b/libimagentrylist/src/listers/line.rs index 241e39d8..a5af428b 100644 --- a/libimagentrylist/src/listers/line.rs +++ b/libimagentrylist/src/listers/line.rs @@ -5,7 +5,7 @@ use lister::Lister; use result::Result; use libimagstore::store::FileLockEntry; -use libimagutil::iter::fold_ok; +use libimagutil::iter::FoldResult; pub struct LineLister<'a> { unknown_output: &'a str, @@ -27,7 +27,7 @@ impl<'a> Lister for LineLister<'a> { use error::ListError as LE; use error::ListErrorKind as LEK; - fold_ok(entries, |entry| { + entries.fold_defresult(|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)))) }) diff --git a/libimagentrylist/src/listers/path.rs b/libimagentrylist/src/listers/path.rs index d08e818d..503b2478 100644 --- a/libimagentrylist/src/listers/path.rs +++ b/libimagentrylist/src/listers/path.rs @@ -5,7 +5,7 @@ use lister::Lister; use result::Result; use libimagstore::store::FileLockEntry; -use libimagutil::iter::fold_ok; +use libimagutil::iter::FoldResult; pub struct PathLister { absolute: bool, @@ -27,7 +27,7 @@ impl Lister for PathLister { use error::ListError as LE; use error::ListErrorKind as LEK; - fold_ok(entries, |entry| { + entries.fold_defresult(|entry| { Ok(entry.get_location().clone()) .and_then(|pb| { if self.absolute { diff --git a/libimagstore/src/hook/aspect.rs b/libimagstore/src/hook/aspect.rs index c58f34fb..bfbd5187 100644 --- a/libimagstore/src/hook/aspect.rs +++ b/libimagstore/src/hook/aspect.rs @@ -1,5 +1,5 @@ use libimagerror::trace::trace_error; -use libimagutil::iter::fold_ok; +use libimagutil::iter::FoldResult; use store::FileLockEntry; use storeid::StoreId; @@ -46,7 +46,7 @@ impl StoreIdAccessor for Aspect { return Err(HE::new(HEK::AccessTypeViolation, None)); } - fold_ok(accessors.iter(), |accessor| { + accessors.iter().fold_defresult(|accessor| { let res = match accessor { &HDA::StoreIdAccess(accessor) => accessor.access(id), _ => unreachable!(), @@ -88,7 +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. - fold_ok(accessors.iter(), |accessor| { + accessors.iter().fold_defresult(|accessor| { let res = match accessor { &HDA::MutableAccess(ref accessor) => accessor.access_mut(fle), &HDA::NonMutableAccess(ref accessor) => accessor.access(fle), @@ -118,7 +118,7 @@ impl NonMutableHookDataAccessor for Aspect { return Err(HE::new(HEK::AccessTypeViolation, None)); } - fold_ok(accessors.iter(), |accessor| { + accessors.iter().fold_defresult(|accessor| { let res = match accessor { &HDA::NonMutableAccess(accessor) => accessor.access(fle), _ => unreachable!(), diff --git a/libimagstore/src/store.rs b/libimagstore/src/store.rs index 7ca8cd37..2ddae130 100644 --- a/libimagstore/src/store.rs +++ b/libimagstore/src/store.rs @@ -37,7 +37,7 @@ use hook::position::HookPosition; use hook::Hook; use libimagerror::into::IntoError; -use libimagutil::iter::fold_ok; +use libimagutil::iter::FoldResult; use self::glob_store_iter::*; @@ -693,16 +693,14 @@ impl Store { id: &StoreId) -> HookResult<()> { - fold_ok( - match aspects.lock() { - Err(_) => return Err(HookErrorKind::HookExecutionError.into()), - Ok(g) => g - }.iter(), - |aspect| { - debug!("[Aspect][exec]: {:?}", aspect); - (aspect as &StoreIdAccessor).access(id) - }).map_err(Box::new) - .map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e)) + match aspects.lock() { + Err(_) => return Err(HookErrorKind::HookExecutionError.into()), + Ok(g) => g + }.iter().fold_defresult(|aspect| { + debug!("[Aspect][exec]: {:?}", aspect); + (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, @@ -710,16 +708,14 @@ impl Store { fle: &mut FileLockEntry) -> HookResult<()> { - fold_ok( - match aspects.lock() { - Err(_) => return Err(HookErrorKind::HookExecutionError.into()), - Ok(g) => g - }.iter(), - |aspect| { - debug!("[Aspect][exec]: {:?}", aspect); - aspect.access_mut(fle) - }).map_err(Box::new) - .map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e)) + match aspects.lock() { + Err(_) => return Err(HookErrorKind::HookExecutionError.into()), + Ok(g) => g + }.iter().fold_defresult(|aspect| { + debug!("[Aspect][exec]: {:?}", aspect); + aspect.access_mut(fle) + }).map_err(Box::new) + .map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e)) } } diff --git a/libimagutil/src/iter.rs b/libimagutil/src/iter.rs index 0f682bff..52d723bf 100644 --- a/libimagutil/src/iter.rs +++ b/libimagutil/src/iter.rs @@ -1,8 +1,30 @@ -/// Processes `iter` returning the last successful result or the first error. -pub fn fold_ok(iter: I, mut func: F) -> Result - where I: Iterator, - R: Default, - F: FnMut(X) -> Result -{ - iter.fold(Ok(R::default()), |acc, item| acc.and_then(|_| func(item))) +/// 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(self, func: F) -> Result + where R: Default, + F: FnMut(Self::Item) + -> Result + { + 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(self, default: R, mut func: F) -> Result + where F: FnMut(Self::Item) -> Result; } + +impl> FoldResult for I { + type Item = X; + + fn fold_result(self, default: R, mut func: F) -> Result + where F: FnMut(Self::Item) -> Result + { + self.fold(Ok(default), |acc, item| acc.and_then(|_| func(item))) + } +} +