Skip to main content

cfg_elif/
expr.rs

1//! Conditional compilation at expression positions.
2
3pub use crate::{expr_cfg as cfg, expr_feature as feature};
4
5/// Compiles expressions conditionally on features.
6///
7/// # Examples
8///
9/// ```rust
10/// use cfg_elif::expr::feature;
11///
12/// assert_eq!(
13///     feature!(if ("foo") {
14///         0
15///     } else if ("bar" && "baz") {
16///         1
17///     } else if ("bar" || "baz") {
18///         2
19///     } else if (("bar" || "baz") && ("foo" || "baz")) {
20///         3
21///     } else if (!"bar") {
22///         42
23///     } else {
24///         4
25///     }),
26///     42
27/// );
28/// ```
29#[macro_export]
30macro_rules! expr_feature {
31    (if ($name:literal) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {
32        {
33            #[cfg(feature = $name)]
34            $then1
35            #[cfg(not(feature = $name))]
36            { $crate::expr_feature!($(if $condition $then2 else)* $else) }
37        }
38    };
39    (if (!$name:literal) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {
40        {
41            #[cfg(not(feature = $name))]
42            $then1
43            #[cfg(feature = $name)]
44            { $crate::expr_feature!($(if $condition $then2 else)* $else) }
45        }
46    };
47    (if ($left:tt && $right:tt) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {
48        $crate::expr_feature!(if ($left) {
49            $crate::expr_feature!(if ($right) $then1 else {
50                $crate::expr_feature!($(if $condition $then2 else)* $else)
51            })
52        } else {
53            $crate::expr_feature!($(if $condition $then2 else)* $else)
54        })
55    };
56    (if ($left:tt || $right:tt) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {
57        $crate::expr_feature!(if ($left) $then1 else if ($right) $then1 else {
58            $crate::expr_feature!($(if $condition $then2 else)* $else)
59        })
60    };
61    (if ($inner:tt) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {
62        $crate::expr_feature!(if $inner $then1 else {
63            $crate::expr_feature!($(if $condition $then2 else)* $else)
64        })
65    };
66    ($else:block) => {
67        $else
68    };
69}
70
71/// Compiles expressions conditionally on compile configurations.
72///
73/// # Examples
74///
75/// ```rust
76/// use cfg_elif::expr::cfg;
77///
78/// assert_eq!(
79///     cfg!(if (feature == "foo") {
80///         0
81///     } else if (target_pointer_width != "64") {
82///         1
83///     } else if ((target_family == "unix") && (feature == "bar")) {
84///         2
85///     } else if ((feature == "baz") || (target_os == "freebsd")) {
86///         3
87///     } else if (!(panic == "unwind")) {
88///         4
89///     } else {
90///         42
91///     }),
92///     42
93/// );
94/// ```
95#[macro_export]
96macro_rules! expr_cfg {
97    (if ($key:ident) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {{
98        #[cfg($key)]
99        $then1
100        #[cfg(not($key))]
101        { $crate::expr_cfg!($(if $condition $then2 else)* $else) }
102    }};
103    (if ($key:ident == $value:literal) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {{
104        #[cfg($key = $value)]
105        $then1
106        #[cfg(not($key = $value))]
107        { $crate::expr_cfg!($(if $condition $then2 else)* $else) }
108    }};
109    (if ($key:ident != $value:literal) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {{
110        #[cfg(not($key = $value))]
111        $then1
112        #[cfg($key = $value)]
113        { $crate::expr_cfg!($(if $condition $then2 else)* $else) }
114    }};
115    (if ($left:tt && $right:tt) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {{
116        $crate::expr_cfg!(if $left {
117            $crate::expr_cfg!(if $right $then1 else {
118                $crate::expr_cfg!($(if $condition $then2 else)* $else)
119            })
120        } else {
121            $crate::expr_cfg!($(if $condition $then2 else)* $else)
122        })
123    }};
124    (if ($left:tt || $right:tt) $then1:block else $(if $condition:tt $then2:block else)* $else:block) => {{
125        $crate::expr_cfg!(if $left $then1 else if $right $then1 else {
126            $crate::expr_cfg!($(if $condition $then2 else)* $else)
127        })
128    }};
129    (if (!$condition1:tt) $then1:block else $(if $condition2:tt $then2:block else)* $else:block) => {{
130        $crate::expr_cfg!(if $condition1 {
131            $crate::expr_cfg!($(if $condition2 $then2 else)* $else)
132        } else $then1)
133    }};
134    ($else:block) => {
135        $else
136    };
137}