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
105
106
107
108
109
110
111
//! This crate provides the `if_chain!` macro -- a macro for composing
//! long chains of if-else if-else statements.
//!
//! It is intended to provide an alternative to writing if chains with `match`,
//! such as:
//!
//! ```ignore
//! match () {
//!     _ if some_condition => ...,
//!     _ if some_other_condition => ...,
//!     _ if some_third_condition => ...,
//!     _ => ...,
//! }
//! ```
//!
//! # Example usage
//!
//! While it is mainly intended for long chains, `if_chain!` can be used
//! for simple if-else situations, such as:
//!
//! ```ignore
//! if_chain! {
//! | some_condition => (/* some_condition is true */),
//! | _ => (/* the else branch */)
//! }
//! ```
//!
//! The earlier `match` example can be rewritten as:
//!
//! ```ignore
//! if_chain! {
//! | some_condition => ...,
//! | some_other_condition => ...,
//! | some_third_condition => ...,
//! }
//! ```
//!
//! Note that the `else` branch is not required, since `if_chain!` simply gets
//! expanded into:
//!
//! ```ignore
//! if some_condition {
//!     ...
//! } else if some_other_condition }
//!     ...
//! } else if some_third_condition {
//!     ...
//! }
//! ```

#![cfg_attr(not(test), no_std)]

/// A macro for writing if chains
#[macro_export]
macro_rules! if_chain {
    (| $cond:expr => $branch:expr
     $(, | $cond_alt:expr => $branch_alt:expr )*
     $(, | _ => $fallback:expr)? $(,)? ) => {
        if $cond {
            $branch
        }

        $(
            else if $cond_alt {
                $branch_alt
            }
        )*

        $(
            else {
                $fallback
            }
        )?
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn single() {
        if_chain! {
        | 'c' != 'd' => (),
        }
    }

    #[test]
    fn multiple() {
        let x = 2;

        if_chain! {
        | x == 1 => {
            todo!()
        },
        | x == 1 => unreachable!(),
        | _ => println!("idk what x is.."),
        }
    }

    #[test]
    #[should_panic]
    fn test_with_panic() {
        let x = 9;

        if_chain! {
        | x % 2 == 0 => {
            (/* x is even */)
        },
        | _ => panic!("x is odd")
        }
    }
}