use std::fmt::{format, Debug, Arguments};
pub trait VerboseUnwrap {
type Wrapped;
fn verbose_unwrap(self, message: Option<Arguments>, module_path: &str, file: &str, line_number: u32, column: u32) -> Self::Wrapped;
}
impl<T, E: Debug> VerboseUnwrap for Result<T, E> {
type Wrapped = T;
fn verbose_unwrap(self, message: Option<Arguments>, module_path: &str, file: &str, line_number: u32, column: u32) -> T {
match self {
Ok(t) => t,
Err(e) => {
match message {
Some(args) => {
let msg = format(args);
panic!("\n\
\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
! unwrap! called on Result::Err !\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
{}:{},{} in {}\n\
{}\n\
\n\
{:?}\n\
\n", file, line_number, column, module_path, msg, Err::<(), E>(e));
},
None => {
panic!("\n\
\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
! unwrap! called on Result::Err !\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
{}:{},{} in {}\n\
\n\
{:?}\n\
\n", file, line_number, column, module_path, Err::<(), E>(e));
},
}
},
}
}
}
impl<T> VerboseUnwrap for Option<T> {
type Wrapped = T;
fn verbose_unwrap(self, message: Option<Arguments>, module_path: &str, file: &str, line_number: u32, column: u32) -> T {
match self {
Some(t) => t,
None => {
match message {
Some(args) => {
let msg = format(args);
panic!("\n\
\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
! unwrap! called on Option::None !\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
{}:{},{} in {}\n\
{}\n\
\n", file, line_number, column, module_path, msg);
},
None => {
panic!("\n\
\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
! unwrap! called on Option::None !\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
{}:{},{} in {}\n\
\n", file, line_number, column, module_path);
},
}
},
}
}
}
#[macro_export]
macro_rules! unwrap(
($e:expr) => (
$crate::VerboseUnwrap::verbose_unwrap($e, None, module_path!(), file!(), line!(), column!())
);
($e:expr, $($arg:tt)*) => (
$crate::VerboseUnwrap::verbose_unwrap($e, Some(format_args!($($arg)*)), module_path!(), file!(), line!(), column!())
);
);
pub trait VerboseUnwrapErr {
type Wrapped;
fn verbose_unwrap_err(self, message: Option<Arguments>, module_path: &str, file: &str, line_number: u32, column: u32) -> Self::Wrapped;
}
impl<T: Debug, E> VerboseUnwrapErr for Result<T, E> {
type Wrapped = E;
fn verbose_unwrap_err(self, message: Option<Arguments>, module_path: &str, file: &str, line_number: u32, column: u32) -> E {
match self {
Err(e) => e,
Ok(t) => {
match message {
Some(args) => {
let msg = format(args);
panic!("\n\
\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
! unwrap_err! called on Result::Ok !\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
{}:{},{} in {}\n\
{}\n\
\n\
{:?}\n\
\n", file, line_number, column, module_path, msg, Ok::<T, ()>(t));
},
None => {
panic!("\n\
\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
! unwrap_err! called on Result::Ok !\n\
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\
{}:{},{} in {}\n\
\n\
{:?}\n\
\n", file, line_number, column, module_path, Ok::<T, ()>(t));
},
}
},
}
}
}
#[macro_export]
macro_rules! unwrap_err(
($e:expr) => (
$crate::VerboseUnwrapErr::verbose_unwrap_err($e, None, module_path!(), file!(), line!(), column!())
);
($e:expr, $($arg:tt)*) => (
$crate::VerboseUnwrapErr::verbose_unwrap_err($e, Some(format_args!($($arg)*)), module_path!(), file!(), line!(), column!())
);
);
#[cfg(test)]
mod tests {
#[test]
fn unwrap_result_ok() {
let result: Result<u32, u32> = Ok(32);
let x = unwrap!(result);
let y = unwrap!(result, "Here's a message");
assert_eq!(x, 32);
assert_eq!(y, 32);
}
#[test]
#[should_panic]
fn unwrap_result_err_message_args() {
let result: Result<u32, u32> = Err(32);
let _ = unwrap!(result, "Here's a message {}", 23);
}
#[test]
#[should_panic]
fn unwrap_result_err_message() {
let result: Result<u32, u32> = Err(32);
let _ = unwrap!(result, "Here's a message");
}
#[test]
#[should_panic]
fn unwrap_result_err_no_message() {
let result: Result<u32, u32> = Err(32);
let _ = unwrap!(result);
}
#[test]
fn unwrap_option_some() {
let option: Option<u32> = Some(32);
let x = unwrap!(option);
let y = unwrap!(option, "Here's a message");
assert_eq!(x, 32);
assert_eq!(y, 32);
}
#[test]
#[should_panic]
fn unwrap_option_none_message() {
let option: Option<u32> = None;
let _ = unwrap!(option, "Here's a message");
}
#[test]
#[should_panic]
fn unwrap_option_none_no_message() {
let option: Option<u32> = None;
let _ = unwrap!(option);
}
#[test]
fn unwrap_err_result_err() {
let result: Result<u32, u32> = Err(32);
let x = unwrap_err!(result);
let y = unwrap_err!(result, "Here's a message");
assert_eq!(x, 32);
assert_eq!(y, 32);
}
#[test]
#[should_panic]
fn unwrap_err_result_ok_message_args() {
let result: Result<u32, u32> = Ok(32);
let _ = unwrap_err!(result, "Here's a message {}", 23);
}
#[test]
#[should_panic]
fn unwrap_err_result_ok_message() {
let result: Result<u32, u32> = Ok(32);
let _ = unwrap_err!(result, "Here's a message");
}
#[test]
#[should_panic]
fn unwrap_err_result_ok_no_message() {
let result: Result<u32, u32> = Ok(32);
let _ = unwrap_err!(result);
}
}