trycatch 0.1.0

Throw and catch exceptions in rust.
Documentation
#![allow(clippy::needless_return)]

/// Utility macro simply wrapping `std::panic::panic`.
#[macro_export]
macro_rules! throw {
    ($($arg:tt)*) => {
        panic!($($arg),*)
    };
}

/// Macro for catching exceptions thrown by functions.
///
/// This macro disables the default panic hook during the try block, in order
/// to silence the "thread '...' panicked at ..." messages.
#[macro_export]
macro_rules! try_catch {
    (try $try_block:block catch ($err:ident) $catch_block:block) => {
        let original_hook = std::panic::take_hook();
        std::panic::set_hook(Box::new(|_| {
            // Do nothing
        }));

        match std::panic::catch_unwind(|| $try_block) {
            Err(e) => {
                if let Some(&$err) = e.downcast_ref::<&str>() {
                    $catch_block
                } else {
                    unreachable!();
                }
            }
            Ok(v) => v,
        }

        std::panic::set_hook(original_hook);
    };
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn divide_by_zero() {
        fn divide(x: u32, y: u32) -> u32 {
            if y == 0 {
                throw!("y cannot be zero");
            }
            return x / y;
        }

        try_catch! {
            try {
                let _ = divide(10, 0);
                unreachable!("divide should always throw an exception (panic)");
            } catch (e) {
                assert_eq!(e, "y cannot be zero");
            }
        };
    }
}