const_if/
lib.rs

1/// All magic happens there
2#[macro_export]
3macro_rules! __hidden_handling_cases {
4    // hide this case from the API
5    (else $e: expr) => {$e};
6
7    ($cond : expr => $if_true: expr;
8        $(elif $cond2: expr => $if_t2:expr;)*
9        else $if_false:expr
10    ) => {
11        [__hidden_handling_cases!($($cond2 => $if_t2; )elif * else $if_false), $if_true][$cond as bool as usize]
12    };
13}
14
15#[macro_export]
16macro_rules! const_if {
17    ($cond: expr => $if_true:expr;$if_false: expr) => {
18        [$if_false, $if_true][(!!$cond)  as usize]
19    };
20
21    // delegate to private macro
22    ($cond : expr => $if_true: expr;
23        $(elif $cond2: expr => $if_t2:expr;)*
24        else $if_false:expr
25    ) => {
26        __hidden_handling_cases!($cond => $if_true; $(elif $cond2 => $if_t2;)* else $if_false)
27    };
28}
29
30mod tests {
31    const fn min(x: i32, y: i32) -> i32 {
32        const_if!(x < y => x;y)
33    }
34
35    #[test]
36    fn test_min() {
37        assert_eq!(min(2, 3), 2);
38    }
39
40
41    const fn is_zero(i: i32) -> &'static str {
42        const_if!(
43            i == 0 => "Yes";
44            else "No"
45        )
46    }
47
48    const fn compare_to_42(i: i32) -> &'static str {
49        const_if!(
50            i < 42 => "Lesser";
51            elif i == 42 => "Equals";
52            else "Bigger"
53        )
54    }
55
56    const fn int_to_str(i: i32) -> &'static str {
57        const_if!(
58            i == 0 => "Zero";
59            elif i == 1 => "One";
60            elif i == 2 => "Two";
61            elif i == 3 => "Three";
62            elif i == 4 => "Four";
63            elif i == 5 => "Five";
64            elif i == 6 => "Six";
65            elif i == 7 => "Seven";
66            elif i == 8 => "Eight";
67            elif i == 9 => "Nine";
68            elif i == 10 => "Ten";
69            else "Unknown"
70        )
71    }
72
73    #[test]
74    fn test_multiple_elif() {
75        assert_eq!(int_to_str(0), "Zero");
76        assert_eq!(int_to_str(5), "Five");
77        assert_eq!(int_to_str(10), "Ten");
78        assert_eq!(int_to_str(11), "Unknown");
79    }
80
81    #[test]
82    fn test_if_else() {
83        assert_eq!(is_zero(0), "Yes");
84        assert_eq!(is_zero(42), "No");
85    }
86
87    #[test]
88    fn test_if_elif_else() {
89        assert_eq!(compare_to_42(0), "Lesser");
90        assert_eq!(compare_to_42(42), "Equals");
91        assert_eq!(compare_to_42(1337), "Bigger");
92    }
93
94    #[test]
95    fn test_expanded() {
96        let i = 6;
97        assert_eq!(
98            [
99                [
100                    [
101                        [
102                            [
103                                [
104                                    [
105                                        [
106                                            [
107                                                [["Unknown", "Ten"][(i == 10) as usize], "Nine"]
108                                                    [(i == 9) as usize],
109                                                "Eight",
110                                            ][(i == 8) as usize],
111                                            "Seven",
112                                        ][(i == 7) as usize],
113                                        "Six",
114                                    ][(i == 6) as usize],
115                                    "Five",
116                                ][(i == 5) as usize],
117                                "Four",
118                            ][(i == 4) as usize],
119                            "Three",
120                        ][(i == 3) as usize],
121                        "Two",
122                    ][(i == 2) as usize],
123                    "One",
124                ][(i == 1) as usize],
125                "Zero",
126            ][(i == 0) as usize],
127            "Six"
128        );
129    }
130}