unwrap-1.2.1/.gitignore010064400017500000144000000000221311355264400132320ustar0000000000000000target Cargo.lock unwrap-1.2.1/Cargo.toml.orig010064400017500000144000000006251333253105400141350ustar0000000000000000[package] name = "unwrap" version = "1.2.1" authors = ["Andrew Cann "] categories = ["development-tools::debugging", "development-tools::testing"] description = "An unwrap! and an unwrap_err! macro" homepage = "https://github.com/canndrew/unwrap" keywords = ["unwrap", "unwrap_err"] license = "MIT OR BSD-3-Clause" readme = "README.md" repository = "https://github.com/canndrew/unwrap" unwrap-1.2.1/Cargo.toml0000644000000016410000000000000104100ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "unwrap" version = "1.2.1" authors = ["Andrew Cann "] description = "An unwrap! and an unwrap_err! macro" homepage = "https://github.com/canndrew/unwrap" readme = "README.md" keywords = ["unwrap", "unwrap_err"] categories = ["development-tools::debugging", "development-tools::testing"] license = "MIT OR BSD-3-Clause" repository = "https://github.com/canndrew/unwrap" unwrap-1.2.1/README.md010064400017500000144000000075561331506657300125510ustar0000000000000000# An `unwrap!` macro for Rust. The crate provides two macros, `unwrap!` and `unwrap_err!`. The former can be used to unwrap values of type `Result` or `Option` (or any type that implements `VerboseUnwrap`) and is comparable to calling `unwrap()`. The latter can be used to unwrap an error from a `Result` (or any type that implements `VerboseUnwrapErr`) and is comparable to calling `unwrap_err()`. The advantage of using these macros over the `.unwrap()`, `.expect()`, `.unwrap_err()` or `.expect_err()` methods is that, on a panic, they will print the file name, line number, column number, and function name of where the macro was called from. [Documentation](https://docs.rs/unwrap) ## Example This code: ```rust let x: Result<(), u32> = Err(123); let y = unwrap!(x); ``` Panics with the following message: ``` !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! unwrap! called on Result::Err ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! example.rs:2,9 in example_module::example_function Err(123) ``` `unwrap!` can also be called with an optional error message. This is supplied as a format string and arguments. ```rust let x: Option<()> = None; let y = unwrap!(x, "Oh no! {}", 123); ``` Prints: ``` !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! unwrap! called on Option::None ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! example.rs:2,9 in example_module::example_function Oh no! 123 ``` Similarly, for `unwrap_err!` this code: ```rust let x: Result = Ok(456); let y = unwrap_err!(x); ``` Panics with the following message: ``` !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! unwrap_err! called on Result::Ok ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! example.rs:2,9 in example_module::example_function Ok(456) ``` ## Implementation The unwrap crate provides a trait for types which can be unwrapped. ```rust trait VerboseUnwrap { type Wrapped; fn verbose_unwrap(self, message: Option, module_path: &str, file: &str, line_number: u32, column: u32) -> Self::Wrapped; } ``` This is implemented by both `Result` and `Option`. The `unwrap!` macro simply calls this trait method: ```rust 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!()) ); ); ``` Likewise there's a trait for types which can have inner error types unwrapped. ```rust pub trait VerboseUnwrapErr { type Wrapped; fn verbose_unwrap_err(self, message: Option, module_path: &str, file: &str, line_number: u32, column: u32) -> Self::Wrapped; } ``` This is implemented by `Result`, and the `unwrap_err!` macro calls this trait method: ```rust 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!()) ); ); ``` ## Usage Add this to your dependencies in `Cargo.toml` ``` unwrap = "~1.1.0" ``` Then import it using `#[macro_use]` ``` #[macro_use] extern crate unwrap; ``` unwrap-1.2.1/src/lib.rs010064400017500000144000000264701331506657300131710ustar0000000000000000use std::fmt::{format, Debug, Arguments}; /// Types which can be unwrapped and which may want to print a verbose error message when they are /// unwrapped incorrectly. This trait is implemented for `Result` and `Option` as a replacement for /// their inherent `unwrap` methods. This trait is intended to be used via this crate's `unwrap!` /// macro. pub trait VerboseUnwrap { /// The wrapped type. type Wrapped; /// Unwrap the value into its inner type or panics with an error message when the value /// cannot be unwrapped. This method is intended to be called via this crate's `unwrap!` macro. /// /// # Panics /// /// When the value cannot be unwrapped. Eg. on an `Err` or `None` value. /// /// # Arguments /// /// These arguments are used to print a useful diagnostic when the method panics. /// /// * `message`: An optional message, printed alongside the rest of the info. /// * `module_path`: The module path where this method is being called from. Eg. /// `my_crate::my_module::my_function` /// * `file`: The filename where this method is being called from. /// * `line_number`: The line number where this method is being called from. /// * `column`: The column number where this method is being called from fn verbose_unwrap(self, message: Option, module_path: &str, file: &str, line_number: u32, column: u32) -> Self::Wrapped; } impl VerboseUnwrap for Result { type Wrapped = T; fn verbose_unwrap(self, message: Option, module_path: &str, file: &str, line_number: u32, column: u32) -> T { match self { Ok(t) => t, Err(e) => { // TODO(canndrew): As soon as impl specialisation lands specialise this to display // the error and it's chain of causes. /* let mut error_str = String::new(); let mut error: &Error = &e; loop { error_str.push_str(format!("{}\n", error)); error = match error.cause() { Some(e) => e, None => break, } } */ 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 VerboseUnwrap for Option { type Wrapped = T; fn verbose_unwrap(self, message: Option, 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); }, } }, } } } /// A replacement for calling `unwrap()` on a `Result` or `Option`. /// /// This macro is intended to be used in all cases where one would `unwrap` a `Result` or `Option` /// to deliberately panic in case of error, e.g. in test-cases. Such `unwrap`s don't give a precise /// point of failure in the code and instead indicate some line number in the Rust core library. /// This macro provides a precise point of failure and decorates the failure for easy viewing. /// /// # Examples /// /// ``` /// # #[macro_use] /// # extern crate unwrap; /// # fn main() { /// let some_option = Some("Hello".to_string()); /// let string_length = unwrap!(some_option, "This is an optional user-supplied text.").len(); /// assert_eq!(string_length, 5); /// # } /// ``` #[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!()) ); ); /// Types which can be unwrapped into an error type and which may want to print a verbose error /// message when they are unwrapped incorrectly. This trait is implemented for `Result` as a /// replacement for its inherent `unwrap_err`. This trait is intended to be used via this crate's /// `unwrap_err!` macro. pub trait VerboseUnwrapErr { /// The wrapped type. type Wrapped; /// Unwrap the value into its inner error type or panics with an error message when the error /// cannot be unwrapped. This method is intended to be called via this crate's `unwrap_err!` /// macro. /// /// # Panics /// /// When the value cannot be unwrapped to its error type. Eg. on an `Ok` value. /// /// # Arguments /// /// These arguments are used to print a useful diagnostic when the method panics. /// /// * `message`: An optional message, printed alongside the rest of the info. /// * `module_path`: The module path where this method is being called from. Eg. /// `my_crate::my_module::my_function` /// * `file`: The filename where this method is being called from. /// * `line_number`: The line number where this method is being called from. /// * `column`: The column number where this method is being called from fn verbose_unwrap_err(self, message: Option, module_path: &str, file: &str, line_number: u32, column: u32) -> Self::Wrapped; } impl VerboseUnwrapErr for Result { type Wrapped = E; fn verbose_unwrap_err(self, message: Option, 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)); }, 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)); }, } }, } } } /// A replacement for calling `unwrap_err()` on a `Result`. /// /// This macro is intended to be used in all cases where one would `unwrap_err` a `Result` to /// deliberately panic in case of unexpected non-error, e.g. in test-cases. Such `unwrap_err`s don't /// give a precise point of failure in the code and instead indicate some line number in the Rust /// core library. This macro provides a precise point of failure and decorates the failure for easy /// viewing. /// /// # Examples /// /// ``` /// # #[macro_use] /// # extern crate unwrap; /// # fn main() { /// let some_result = Err::("Failed".to_string()); /// let string_length = unwrap_err!(some_result, "This is an optional user-supplied text.").len(); /// assert_eq!(string_length, 6); /// # } /// ``` #[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 = 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 = Err(32); let _ = unwrap!(result, "Here's a message {}", 23); } #[test] #[should_panic] fn unwrap_result_err_message() { let result: Result = Err(32); let _ = unwrap!(result, "Here's a message"); } #[test] #[should_panic] fn unwrap_result_err_no_message() { let result: Result = Err(32); let _ = unwrap!(result); } #[test] fn unwrap_option_some() { let option: Option = 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 = None; let _ = unwrap!(option, "Here's a message"); } #[test] #[should_panic] fn unwrap_option_none_no_message() { let option: Option = None; let _ = unwrap!(option); } #[test] fn unwrap_err_result_err() { let result: Result = 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 = Ok(32); let _ = unwrap_err!(result, "Here's a message {}", 23); } #[test] #[should_panic] fn unwrap_err_result_ok_message() { let result: Result = Ok(32); let _ = unwrap_err!(result, "Here's a message"); } #[test] #[should_panic] fn unwrap_err_result_ok_no_message() { let result: Result = Ok(32); let _ = unwrap_err!(result); } }