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, U, E> {
fn try_map<F>(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>(self, f: F) -> Result<Option<U>, E>
where
F: FnOnce(T) -> Result<Option<U>, E>;
}
impl<C, T, U, E> FallibleMapExt<T, U, E> for C
where
C: ExtractOption<T>,
{
fn try_map<F>(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>(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 trait TryMapIteratorExt: Iterator {
fn try_map<B, F, E>(self, f: F) -> Result<Vec<B>, E>
where
Self: Sized,
F: FnMut(Self::Item) -> Result<B, E>;
}
impl<I> TryMapIteratorExt for I
where
I: Iterator,
{
fn try_map<B, F, E>(mut self, mut f: F) -> Result<Vec<B>, E>
where
Self: Sized,
F: FnMut(Self::Item) -> Result<B, E>,
{
self.try_fold(Vec::new(), |mut results, item| {
results.push(f(item)?);
Ok(results)
})
}
}