pub trait ExtractOption<T> {
fn extract(self) -> Option<T>;
}
impl<T> ExtractOption<T> for Option<T> {
fn extract(self) -> Option<T> {
self
}
}
pub trait FallibleMapExt<T, E> {
fn try_map<F, U>(self, f: F) -> Result<Option<U>, E>
where
F: FnOnce(T) -> Result<U, E>;
fn try_unwrap_or<F>(self, f: F) -> Result<T, E>
where
F: FnOnce() -> Result<T, E>;
fn try_and_then<F, U>(self, f: F) -> Result<Option<U>, E>
where
F: FnOnce(T) -> Result<Option<U>, E>;
}
impl<C, T, E> FallibleMapExt<T, E> for C
where
C: ExtractOption<T>,
{
fn try_map<F, U>(self, f: F) -> Result<Option<U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
match self.extract() {
Some(x) => f(x).map(Some),
None => Ok(None),
}
}
fn try_unwrap_or<F>(self, f: F) -> Result<T, E>
where
F: FnOnce() -> Result<T, E>,
{
match self.extract() {
Some(x) => Ok(x),
None => f(),
}
}
fn try_and_then<F, U>(self, f: F) -> Result<Option<U>, E>
where
F: FnOnce(T) -> Result<Option<U>, E>,
{
match self.extract() {
Some(x) => f(x),
None => Ok(None),
}
}
}
pub struct FallibleMapIterator<I, F, B, E> {
iter: I,
f: F,
_marker: std::marker::PhantomData<(B, E)>,
}
impl<I, F, B, E> FallibleMapIterator<I, F, B, E> {
pub fn new(iter: I, f: F) -> Self {
FallibleMapIterator {
iter,
f,
_marker: std::marker::PhantomData,
}
}
}
impl<I, F, B, E> Iterator for FallibleMapIterator<I, F, B, E>
where
I: Iterator,
F: FnMut(I::Item) -> Result<B, E>,
{
type Item = Result<B, E>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(&mut self.f)
}
}
pub trait FallibleMapIteratorExt: Iterator {
fn try_map<B, F, E>(self, f: F) -> FallibleMapIterator<Self, F, B, E>
where
Self: Sized,
F: FnMut(Self::Item) -> Result<B, E>;
}
impl<I> FallibleMapIteratorExt for I
where
I: Iterator,
{
fn try_map<B, F, E>(self, f: F) -> FallibleMapIterator<Self, F, B, E>
where
Self: Sized,
F: FnMut(Self::Item) -> Result<B, E>,
{
FallibleMapIterator::new(self, f)
}
}