devela/code/util/
iif.rs

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
// devela::code::util::iif
//
//! inline if macro.
//

/// *`i`nline `if`* macro.
///
/// A inline alternative for `if` and `if let`.
///
/// # Examples
///
/// Replacing `if`:
/// ```
/// # use devela::iif;
/// // This
/// let s = iif![1 > 0; true; false];
///
/// // Would be equivalent to
/// let s = if 1 > 0 {
///     true
/// } else {
///     false
/// };
/// ```
///
/// Replacing `if let`:
/// ```
/// # use devela::iif;
/// let num = Some(123);
///
/// // This
/// iif![let Some(n) = num ; println!("num:{n}") ; { dbg![num]; }];
///
/// // Would be equivalent to
/// if let Some(n) = num {
///     println!("num:{n}")
/// } else {
///     dbg![num];
/// }
/// ```
///
/// Nested:
/// ```
/// # use devela::iif;
/// let mut s = String::new();
/// let is_premium = Some(true);
///
/// // This
/// iif![let Some(b) = is_premium; iif![b; s += " [premium]"]];
///
/// // Would be equivalent to
/// if let Some(b) = is_premium {
///     if b {
///         s += " [premium]";
///     }
/// }
/// ```
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! iif {
    ($if:expr; $true:expr) => {
        if $if {
            $true
        }
    };
    ($if:expr ; $true:expr ; $($false:expr)?) => {
        // WAIT: [stmt_expr_attributes](https://github.com/rust-lang/rust/issues/15701)
        // #[allow(clippy::redundant_else)]
        if $if {
            $true
        } else {
            $( $false )?
        }
    };

    (let $pat:pat = $if:expr ; $true:expr) => {
        #[allow(clippy::question_mark)]
        if let $pat = $if {
            $true
        }
    };
    (let $pat:pat = $if:expr ; $true:expr ; $($false:expr)? ) => {
        if let $pat = $if {
            $true
        } else {
            $( $false )?
        }
    };
}
#[doc(inline)]
pub use iif;

#[cfg(test)]
mod test_iif {
    use crate::iif;

    #[test]
    fn iif() {
        assert_eq!('a', iif!(true ; 'a' ; 'b'));
        assert_eq!('b', iif!(false ; 'a' ; 'b'));
    }

    #[test]
    fn iif_let() {
        let somea = Some('a');
        let noa: Option<char> = None;

        assert_eq!('a', iif!(let Some(a) = somea; a ; 'b'));
        assert_eq!('b', iif!(let Some(a) = noa; a ; 'b'));
    }
}