use std::{
fmt::Debug,
ops::{ControlFlow, Try},
};
pub trait Extract<T>
where
Self: Try<Output = T> + Sized,
{
fn output(self) -> Option<T> {
match self.branch() {
ControlFlow::Continue(val) => Some(val),
ControlFlow::Break(_) => None,
}
}
fn unwrap(self) -> T
where
Self::Residual: Debug,
{
match self.branch() {
ControlFlow::Continue(v) => v,
#[cfg(not(panic = "immediate-abort"))]
ControlFlow::Break(r) => panic!("called `unwrap()` on a residual: {r:?}"),
#[cfg(panic = "immediate-abort")]
ControlFlow::Break(_) => panic!(),
}
}
fn expect(self, msg: &str) -> T
where
Self::Residual: Debug,
{
match self.branch() {
ControlFlow::Continue(v) => v,
#[cfg(not(panic = "immediate-abort"))]
ControlFlow::Break(r) => panic!("{msg}: {r:?}"),
#[cfg(panic = "immediate-abort")]
ControlFlow::Break(_) => panic!(),
}
}
fn unwrap_or(self, default: T) -> T {
match self.branch() {
ControlFlow::Continue(v) => v,
ControlFlow::Break(_) => default,
}
}
fn unwrap_or_default(self) -> T
where
T: Default,
{
match self.branch() {
ControlFlow::Continue(v) => v,
ControlFlow::Break(_) => Default::default(),
}
}
fn unwrap_or_else<F>(self, f: F) -> T
where
F: FnOnce() -> T,
{
match self.branch() {
ControlFlow::Continue(v) => v,
ControlFlow::Break(_) => f(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
impl<T> Extract<T> for Option<T> {}
impl<T, E> Extract<T> for Result<T, E> {}
mod output {
use super::*;
#[test]
fn ok() {
let ok_5: Result<_, ()> = Ok(5);
let stdlib = ok_5.ok();
let custom = ok_5.output();
assert_eq!(stdlib, custom);
}
}
}