devela/code/util/
iif.rs

1// devela::code::util::iif
2//
3//! inline if macro.
4//
5
6/// *`i`nline `if`* macro.
7///
8/// A inline alternative for `if` and `if let`.
9///
10/// # Examples
11///
12/// Replacing `if`:
13/// ```
14/// # use devela::iif;
15/// // This
16/// let s = iif![1 > 0; true; false];
17///
18/// // Would be equivalent to
19/// let s = if 1 > 0 {
20///     true
21/// } else {
22///     false
23/// };
24/// ```
25///
26/// Replacing `if let`:
27/// ```
28/// # use devela::iif;
29/// let num = Some(123);
30///
31/// // This
32/// iif![let Some(n) = num ; println!("num:{n}") ; { dbg![num]; }];
33///
34/// // Would be equivalent to
35/// if let Some(n) = num {
36///     println!("num:{n}")
37/// } else {
38///     dbg![num];
39/// }
40/// ```
41///
42/// Nested:
43/// ```
44/// # use devela::iif;
45/// let mut s = String::new();
46/// let is_premium = Some(true);
47///
48/// // This
49/// iif![let Some(b) = is_premium; iif![b; s += " [premium]"]];
50///
51/// // Would be equivalent to
52/// if let Some(b) = is_premium {
53///     if b {
54///         s += " [premium]";
55///     }
56/// }
57/// ```
58#[macro_export]
59#[cfg_attr(cargo_primary_package, doc(hidden))]
60macro_rules! iif {
61    ($if:expr; $true:expr) => {
62        if $if {
63            $true
64        }
65    };
66    ($if:expr ; $true:expr ; $($false:expr)?) => {
67        // WAIT: [stmt_expr_attributes](https://github.com/rust-lang/rust/issues/15701)
68        // #[allow(clippy::redundant_else)]
69        if $if {
70            $true
71        } else {
72            $( $false )?
73        }
74    };
75
76    (let $pat:pat = $if:expr ; $true:expr) => {
77        #[allow(clippy::question_mark)]
78        if let $pat = $if {
79            $true
80        }
81    };
82    (let $pat:pat = $if:expr ; $true:expr ; $($false:expr)? ) => {
83        if let $pat = $if {
84            $true
85        } else {
86            $( $false )?
87        }
88    };
89}
90#[doc(inline)]
91pub use iif;
92
93#[cfg(test)]
94mod test_iif {
95    use crate::iif;
96
97    #[test]
98    fn iif() {
99        assert_eq!('a', iif!(true ; 'a' ; 'b'));
100        assert_eq!('b', iif!(false ; 'a' ; 'b'));
101    }
102
103    #[test]
104    fn iif_let() {
105        let somea = Some('a');
106        let noa: Option<char> = None;
107
108        assert_eq!('a', iif!(let Some(a) = somea; a ; 'b'));
109        assert_eq!('b', iif!(let Some(a) = noa; a ; 'b'));
110    }
111}