Unwrap Or Macro

/// Helper to support control flow with unwrapping
///
/// Usage:
///
/// ```
/// for val in &[None, Some(13)] {
///     let val = unwrap_or!(val, continue);
///     println!("{}", val);
/// }
/// ```
/// 
/// For non Some / Ok variants, the error can be captured with a second 
/// argument. For Options this variable will always be bound to the `()`:
///
/// ```
/// for val in &[None, Some(13)] {
///     let val = unwrap_or!(val, err, { 
///         println!("Got {}", err); 
///        continue;
///     });
///     println!("{}", val);
/// }
/// ``` 
///
#[macro_export]
macro_rules! unwrap_or {
    ($obj:expr, $or:expr) => {
        match $crate::TryOp::into_result($obj) {
            Ok(obj) => obj,
            Err(_) => $or,
        }
    };
    ($obj:expr, $err:ident, $or:expr) => {
        match $crate::TryOp::into_result($obj) {
            Ok(obj) => obj,
            Err($err) => $or,
        }
    };
}

trait TryOp {
    type Ok;
    type Error;
    fn into_result(self) -> std::result::Result<Self::Ok, Self::Error>; 
}

impl<T> TryOp for std::option::Option<T> {
    type Ok = T;
    type Error = ();

    fn into_result(self) -> std::result::Result<T, ()> {
        self.ok_or(())
    }
}

impl<T, E> TryOp for std::result::Result<T, E> {
    type Ok = T;
    type Error = E;

    fn into_result(self) -> std::result::Result<T, E> {
        self
    }
}