Skip to main content

chainable_if/
lib.rs

1//! This crate provides the `if_chain!` macro -- a macro for composing
2//! long chains of if-else if-else statements.
3//!
4//! It is intended to provide an alternative to writing if chains with `match`,
5//! such as:
6//!
7//! ```ignore
8//! match () {
9//!     _ if some_condition => ...,
10//!     _ if some_other_condition => ...,
11//!     _ if some_third_condition => ...,
12//!     _ => ...,
13//! }
14//! ```
15//!
16//! # Example usage
17//!
18//! While it is mainly intended for long chains, `if_chain!` can be used
19//! for simple if-else situations, such as:
20//!
21//! ```ignore
22//! if_chain! {
23//! | some_condition => (/* some_condition is true */),
24//! | _ => (/* the else branch */)
25//! }
26//! ```
27//!
28//! The earlier `match` example can be rewritten as:
29//!
30//! ```ignore
31//! if_chain! {
32//! | some_condition => ...,
33//! | some_other_condition => ...,
34//! | some_third_condition => ...,
35//! }
36//! ```
37//!
38//! Note that the `else` branch is not required, since `if_chain!` simply gets
39//! expanded into:
40//!
41//! ```ignore
42//! if some_condition {
43//!     ...
44//! } else if some_other_condition }
45//!     ...
46//! } else if some_third_condition {
47//!     ...
48//! }
49//! ```
50
51#![cfg_attr(not(test), no_std)]
52
53/// A macro for writing if chains
54#[macro_export]
55macro_rules! if_chain {
56    (| $cond:expr => $branch:expr
57     $(, | $cond_alt:expr => $branch_alt:expr )*
58     $(, | _ => $fallback:expr)? $(,)? ) => {
59        if $cond {
60            $branch
61        }
62
63        $(
64            else if $cond_alt {
65                $branch_alt
66            }
67        )*
68
69        $(
70            else {
71                $fallback
72            }
73        )?
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    #[test]
80    fn single() {
81        if_chain! {
82        | 'c' != 'd' => (),
83        }
84    }
85
86    #[test]
87    fn multiple() {
88        let x = 2;
89
90        if_chain! {
91        | x == 1 => {
92            todo!()
93        },
94        | x == 1 => unreachable!(),
95        | _ => println!("idk what x is.."),
96        }
97    }
98
99    #[test]
100    #[should_panic]
101    fn test_with_panic() {
102        let x = 9;
103
104        if_chain! {
105        | x % 2 == 0 => {
106            (/* x is even */)
107        },
108        | _ => panic!("x is odd")
109        }
110    }
111}