diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2019-10-24 17:39:38 +0200 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2019-10-26 16:35:31 +0200 |
commit | 0e20b25091a41b0092f127df15cd444fb78853ba (patch) | |
tree | b363c915294cf17a6d30d88ad86748f8d516f180 /lib | |
parent | e7e5d3064585cb5ea0bb6f1ca36df592c2d41949 (diff) |
Add extension traits for handling Result<Option<T>, E> conversion
This extension traits help transforming Result<Option<T>, E> to
Result<T, E> or transforming an iterator over the former type to an
iterator over the latter type.
Should be moved to resiter of course, but we need to implement this
first.
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/core/libimagerror/src/iter.rs | 46 | ||||
-rw-r--r-- | lib/core/libimagerror/src/lib.rs | 1 | ||||
-rw-r--r-- | lib/core/libimagerror/src/result.rs | 38 |
3 files changed, 85 insertions, 0 deletions
diff --git a/lib/core/libimagerror/src/iter.rs b/lib/core/libimagerror/src/iter.rs index 5a288321..1e7dbff9 100644 --- a/lib/core/libimagerror/src/iter.rs +++ b/lib/core/libimagerror/src/iter.rs @@ -128,3 +128,49 @@ impl<I, T> TraceIterator<T> for I where I: Iterator<Item = Result<T, Error>> {} + +/// Extension trait for doing +/// +/// ```ignore +/// Iterator<Item = Result<Option<T>, E>> -> Iterator<Item = Result<T, E>> +/// ``` +/// +pub trait IterInnerOkOrElse<T, E, F> + where T: Sized, + E: Sized, + Self: Iterator<Item = Result<Option<T>, E>> + Sized, + F: Fn() -> E, +{ + fn map_inner_ok_or_else(self, f: F) -> IterInnerOkOrElseImpl<Self, T, E, F>; +} + +pub struct IterInnerOkOrElseImpl<I, T, E, F>(I, F) + where I: Iterator<Item = Result<Option<T>, E>> + Sized, + T: Sized, + E: Sized, + F: Fn() -> E; + +impl<I, T, E, F> IterInnerOkOrElse<T, E, F> for I + where I: Iterator<Item = Result<Option<T>, E>> + Sized, + T: Sized, + E: Sized, + F: Fn() -> E, +{ + fn map_inner_ok_or_else(self, f: F) -> IterInnerOkOrElseImpl<I, T, E, F> { + IterInnerOkOrElseImpl(self, f) + } +} + +impl<I, T, E, F> Iterator for IterInnerOkOrElseImpl<I, T, E, F> + where I: Iterator<Item = Result<Option<T>, E>> + Sized, + T: Sized, + E: Sized, + F: Fn() -> E, +{ + type Item = Result<T, E>; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().map(|e| e.and_then(|opt| opt.ok_or_else(|| (self.1)()))) + } +} + diff --git a/lib/core/libimagerror/src/lib.rs b/lib/core/libimagerror/src/lib.rs index 22391142..9b5e8407 100644 --- a/lib/core/libimagerror/src/lib.rs +++ b/lib/core/libimagerror/src/lib.rs @@ -44,6 +44,7 @@ pub mod errors; pub mod exit; pub mod io; pub mod iter; +pub mod result; pub mod str; pub mod trace; diff --git a/lib/core/libimagerror/src/result.rs b/lib/core/libimagerror/src/result.rs new file mode 100644 index 00000000..0dcb5333 --- /dev/null +++ b/lib/core/libimagerror/src/result.rs @@ -0,0 +1,38 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 the imag 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 +// + +/// Extension trait for doing `Result<Option<T>, E> -> Result<T, E>` +pub trait ResultOptionExt<T, E, F> + where T: Sized, + E: Sized, + F: FnOnce() -> E +{ + fn inner_ok_or_else(self, f: F) -> Result<T, E>; +} + +impl<T, E, F> ResultOptionExt<T, E, F> for Result<Option<T>, E> + where T: Sized, + E: Sized, + F: FnOnce() -> E +{ + fn inner_ok_or_else(self, f: F) -> Result<T, E> { + self.and_then(|opt| opt.ok_or_else(f)) + } +} + |