diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2019-10-24 18:08:52 +0200 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2019-10-25 17:21:25 +0200 |
commit | 823e294947ca52f0bdcbd48affd7ad2317bc9c62 (patch) | |
tree | 23a59d958cb5598dcb09e6096145da0b66cabfd5 | |
parent | 4d457fa79a9bd37ccdfd45ce4fcca1d20d649f31 (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.rs | 2 | ||||
-rw-r--r-- | src/ok_or_else.rs | 72 |
2 files changed, 74 insertions, 0 deletions
@@ -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)()))) + } +} + |