summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2019-10-24 17:39:38 +0200
committerMatthias Beyer <mail@beyermatthias.de>2019-10-26 16:35:31 +0200
commit0e20b25091a41b0092f127df15cd444fb78853ba (patch)
treeb363c915294cf17a6d30d88ad86748f8d516f180 /lib
parente7e5d3064585cb5ea0bb6f1ca36df592c2d41949 (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.rs46
-rw-r--r--lib/core/libimagerror/src/lib.rs1
-rw-r--r--lib/core/libimagerror/src/result.rs38
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))
+ }
+}
+