@@ -119,3 +119,84 @@ macro_rules! impl_fn_for_zst {
119
119
) +
120
120
}
121
121
}
122
+
123
+ /// A macro for defining `#[cfg]` if-else statements.
124
+ ///
125
+ /// The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
126
+ /// preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
127
+ /// emitting the implementation which matches first.
128
+ ///
129
+ /// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
130
+ /// without having to rewrite each clause multiple times.
131
+ ///
132
+ /// # Example
133
+ ///
134
+ /// ```
135
+ /// #[macro_use]
136
+ /// extern crate cfg_if;
137
+ ///
138
+ /// cfg_if! {
139
+ /// if #[cfg(unix)] {
140
+ /// fn foo() { /* unix specific functionality */ }
141
+ /// } else if #[cfg(target_pointer_width = "32")] {
142
+ /// fn foo() { /* non-unix, 32-bit functionality */ }
143
+ /// } else {
144
+ /// fn foo() { /* fallback implementation */ }
145
+ /// }
146
+ /// }
147
+ ///
148
+ /// # fn main() {}
149
+ /// ```
150
+ macro_rules! cfg_if {
151
+ // match if/else chains with a final `else`
152
+ ( $(
153
+ if #[ cfg( $( $meta: meta) ,* ) ] { $( $it: item) * }
154
+ ) else * else {
155
+ $( $it2: item) *
156
+ } ) => {
157
+ cfg_if! {
158
+ @__items
159
+ ( ) ;
160
+ $( ( ( $( $meta) ,* ) ( $( $it) * ) ) , ) *
161
+ ( ( ) ( $( $it2) * ) ) ,
162
+ }
163
+ } ;
164
+
165
+ // match if/else chains lacking a final `else`
166
+ (
167
+ if #[ cfg( $( $i_met: meta) ,* ) ] { $( $i_it: item) * }
168
+ $(
169
+ else if #[ cfg( $( $e_met: meta) ,* ) ] { $( $e_it: item) * }
170
+ ) *
171
+ ) => {
172
+ cfg_if! {
173
+ @__items
174
+ ( ) ;
175
+ ( ( $( $i_met) ,* ) ( $( $i_it) * ) ) ,
176
+ $( ( ( $( $e_met) ,* ) ( $( $e_it) * ) ) , ) *
177
+ ( ( ) ( ) ) ,
178
+ }
179
+ } ;
180
+
181
+ // Internal and recursive macro to emit all the items
182
+ //
183
+ // Collects all the negated cfgs in a list at the beginning and after the
184
+ // semicolon is all the remaining items
185
+ ( @__items ( $( $not: meta, ) * ) ; ) => { } ;
186
+ ( @__items ( $( $not: meta, ) * ) ; ( ( $( $m: meta) ,* ) ( $( $it: item) * ) ) , $( $rest: tt) * ) => {
187
+ // Emit all items within one block, applying an approprate #[cfg]. The
188
+ // #[cfg] will require all `$m` matchers specified and must also negate
189
+ // all previous matchers.
190
+ cfg_if! { @__apply cfg( all( $( $m, ) * not( any( $( $not) ,* ) ) ) ) , $( $it) * }
191
+
192
+ // Recurse to emit all other items in `$rest`, and when we do so add all
193
+ // our `$m` matchers to the list of `$not` matchers as future emissions
194
+ // will have to negate everything we just matched as well.
195
+ cfg_if! { @__items ( $( $not, ) * $( $m, ) * ) ; $( $rest) * }
196
+ } ;
197
+
198
+ // Internal macro to Apply a cfg attribute to a list of items
199
+ ( @__apply $m: meta, $( $it: item) * ) => {
200
+ $( #[ $m] $it) *
201
+ } ;
202
+ }
0 commit comments