summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2019-10-24 18:08:52 +0200
committerMatthias Beyer <mail@beyermatthias.de>2019-10-25 17:21:25 +0200
commit823e294947ca52f0bdcbd48affd7ad2317bc9c62 (patch)
tree23a59d958cb5598dcb09e6096145da0b66cabfd5
parent4d457fa79a9bd37ccdfd45ce4fcca1d20d649f31 (diff)
Add ok-or-else extension
Extracted from imag, where the source is LGPL2.0, but I am the author and hereby relicense this piece of code with MPL 2.0 for the resiter crate repository. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--src/lib.rs2
-rw-r--r--src/ok_or_else.rs72
2 files changed, 74 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index ff4ecc3..e9ba2f3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -201,6 +201,7 @@ pub mod filter_map;
pub mod flat_map;
pub mod flatten;
pub mod map;
+pub mod ok_or_else;
pub mod oks;
pub mod onerr;
pub mod onok;
@@ -216,6 +217,7 @@ pub use filter_map::FilterMap;
pub use flat_map::FlatMap;
pub use flatten::Flatten;
pub use map::Map;
+pub use ok_or_else::{ResultOptionExt, IterInnerOkOrElse};
pub use oks::GetOks;
pub use onerr::OnErrDo;
pub use onok::OnOkDo;
diff --git a/src/ok_or_else.rs b/src/ok_or_else.rs
new file mode 100644
index 0000000..c071af9
--- /dev/null
+++ b/src/ok_or_else.rs
@@ -0,0 +1,72 @@
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+/// 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))
+ }
+}
+
+
+
+/// 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)())))
+ }
+}
+