1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
/* Copyright (c) 2018 Garrett Berg, vitiral@gmail.com
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */
//! **The `expect!` macro**
//!
//! This crate adds the `expect!` macro, which is basically just calling
//! `.expect` on your type but also:
//!
//! - Includes the exact line number of the error
//! - Allows you to specify a custom error message with formatting.
//!
//! This gives you panic messages like this:
//!
//! ```no_compile
//! thread 'example' panicked at '"expect error"', src/lib.rs:5:5
//! ```
//!
//! As opposed to:
//!
//! ```no_compile
//! thread 'example' panicked at 'called `Result::unwrap()` on an `Err` value: "expect error"', libcore/result.rs:945:5
//! ```

/// Unwrap a result or `panic!` with a message.
///
/// Works with [`Result`], [`Option`] and anything else with the `unwrap_or_else` method.
///
/// This macro has two forms:
///
/// - `expect!(result)`: calls `panic!("{:#?}", err)` on any unwrapped `Err`/`None`.
/// - `expect!(result, ...)`: calls `panic!(...)` on any unwrapped `Err`/`None`, allowing you to
///   specify your own error formatting. This is recommened when you are using `expect!` with
///   [`Option`]
///
/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
/// [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html
///
/// # Example
///
/// Without format
///
/// ```rust,should_panic
/// #[macro_use] extern crate expect_macro;
///
/// # fn main() {
/// let result = Err("expect error");
/// expect!(result);
/// # }
///
/// // COMPILER OUTPUT:
/// // thread 'example' panicked at '"expect error"', src/lib.rs:5:5
/// ```
///
/// With format
///
/// ```rust,should_panic
/// #[macro_use] extern crate expect_macro;
///
/// # fn main() {
/// let result = Err("expect error");
/// expect!(result, "Some values: {}, {}", 1, 2);
/// # }
///
/// // COMPILER OUTPUT:
/// // thread 'example' panicked at 'Some values: 1, 2', src/lib.rs:5:5
/// ```
///
///
#[macro_export]
macro_rules! expect {
    [$result:expr, $($rest:tt)*] => {
        $result.unwrap_or_else(|_| {
            panic!($($rest)*)
        })
    };
    [$result:expr] => {
        $result.unwrap_or_else(|e| {
            panic!("{:?}", e)
        })
    };
}

#[test]
#[should_panic]
fn expect_panic_bare() {
    expect!(Err("expect error"));
}

#[test]
#[should_panic]
fn regular_panic_bare() {
    let result: Result<(), &str> = Err("expect error");
    result.unwrap();
}

#[test]
#[should_panic]
fn expect_panic_msg() {
    expect!(Err("expect error"), "Some values: {}, {}", 1, 2);
}