1b12ac153Sopenharmony_ci//! A macro for defining `#[cfg]` if-else statements. 2b12ac153Sopenharmony_ci//! 3b12ac153Sopenharmony_ci//! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C 4b12ac153Sopenharmony_ci//! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases, 5b12ac153Sopenharmony_ci//! emitting the implementation which matches first. 6b12ac153Sopenharmony_ci//! 7b12ac153Sopenharmony_ci//! This allows you to conveniently provide a long list `#[cfg]`'d blocks of code 8b12ac153Sopenharmony_ci//! without having to rewrite each clause multiple times. 9b12ac153Sopenharmony_ci//! 10b12ac153Sopenharmony_ci//! # Example 11b12ac153Sopenharmony_ci//! 12b12ac153Sopenharmony_ci//! ``` 13b12ac153Sopenharmony_ci//! cfg_if::cfg_if! { 14b12ac153Sopenharmony_ci//! if #[cfg(unix)] { 15b12ac153Sopenharmony_ci//! fn foo() { /* unix specific functionality */ } 16b12ac153Sopenharmony_ci//! } else if #[cfg(target_pointer_width = "32")] { 17b12ac153Sopenharmony_ci//! fn foo() { /* non-unix, 32-bit functionality */ } 18b12ac153Sopenharmony_ci//! } else { 19b12ac153Sopenharmony_ci//! fn foo() { /* fallback implementation */ } 20b12ac153Sopenharmony_ci//! } 21b12ac153Sopenharmony_ci//! } 22b12ac153Sopenharmony_ci//! 23b12ac153Sopenharmony_ci//! # fn main() {} 24b12ac153Sopenharmony_ci//! ``` 25b12ac153Sopenharmony_ci 26b12ac153Sopenharmony_ci#![no_std] 27b12ac153Sopenharmony_ci#![doc(html_root_url = "https://docs.rs/cfg-if")] 28b12ac153Sopenharmony_ci#![deny(missing_docs)] 29b12ac153Sopenharmony_ci#![cfg_attr(test, deny(warnings))] 30b12ac153Sopenharmony_ci 31b12ac153Sopenharmony_ci/// The main macro provided by this crate. See crate documentation for more 32b12ac153Sopenharmony_ci/// information. 33b12ac153Sopenharmony_ci#[macro_export] 34b12ac153Sopenharmony_cimacro_rules! cfg_if { 35b12ac153Sopenharmony_ci // match if/else chains with a final `else` 36b12ac153Sopenharmony_ci ($( 37b12ac153Sopenharmony_ci if #[cfg($meta:meta)] { $($tokens:tt)* } 38b12ac153Sopenharmony_ci ) else * else { 39b12ac153Sopenharmony_ci $($tokens2:tt)* 40b12ac153Sopenharmony_ci }) => { 41b12ac153Sopenharmony_ci $crate::cfg_if! { 42b12ac153Sopenharmony_ci @__items 43b12ac153Sopenharmony_ci () ; 44b12ac153Sopenharmony_ci $( ( ($meta) ($($tokens)*) ), )* 45b12ac153Sopenharmony_ci ( () ($($tokens2)*) ), 46b12ac153Sopenharmony_ci } 47b12ac153Sopenharmony_ci }; 48b12ac153Sopenharmony_ci 49b12ac153Sopenharmony_ci // match if/else chains lacking a final `else` 50b12ac153Sopenharmony_ci ( 51b12ac153Sopenharmony_ci if #[cfg($i_met:meta)] { $($i_tokens:tt)* } 52b12ac153Sopenharmony_ci $( 53b12ac153Sopenharmony_ci else if #[cfg($e_met:meta)] { $($e_tokens:tt)* } 54b12ac153Sopenharmony_ci )* 55b12ac153Sopenharmony_ci ) => { 56b12ac153Sopenharmony_ci $crate::cfg_if! { 57b12ac153Sopenharmony_ci @__items 58b12ac153Sopenharmony_ci () ; 59b12ac153Sopenharmony_ci ( ($i_met) ($($i_tokens)*) ), 60b12ac153Sopenharmony_ci $( ( ($e_met) ($($e_tokens)*) ), )* 61b12ac153Sopenharmony_ci ( () () ), 62b12ac153Sopenharmony_ci } 63b12ac153Sopenharmony_ci }; 64b12ac153Sopenharmony_ci 65b12ac153Sopenharmony_ci // Internal and recursive macro to emit all the items 66b12ac153Sopenharmony_ci // 67b12ac153Sopenharmony_ci // Collects all the negated cfgs in a list at the beginning and after the 68b12ac153Sopenharmony_ci // semicolon is all the remaining items 69b12ac153Sopenharmony_ci (@__items ($($not:meta,)*) ; ) => {}; 70b12ac153Sopenharmony_ci (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($tokens:tt)*) ), $($rest:tt)*) => { 71b12ac153Sopenharmony_ci // Emit all items within one block, applying an appropriate #[cfg]. The 72b12ac153Sopenharmony_ci // #[cfg] will require all `$m` matchers specified and must also negate 73b12ac153Sopenharmony_ci // all previous matchers. 74b12ac153Sopenharmony_ci #[cfg(all($($m,)* not(any($($not),*))))] $crate::cfg_if! { @__identity $($tokens)* } 75b12ac153Sopenharmony_ci 76b12ac153Sopenharmony_ci // Recurse to emit all other items in `$rest`, and when we do so add all 77b12ac153Sopenharmony_ci // our `$m` matchers to the list of `$not` matchers as future emissions 78b12ac153Sopenharmony_ci // will have to negate everything we just matched as well. 79b12ac153Sopenharmony_ci $crate::cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } 80b12ac153Sopenharmony_ci }; 81b12ac153Sopenharmony_ci 82b12ac153Sopenharmony_ci // Internal macro to make __apply work out right for different match types, 83b12ac153Sopenharmony_ci // because of how macros matching/expand stuff. 84b12ac153Sopenharmony_ci (@__identity $($tokens:tt)*) => { 85b12ac153Sopenharmony_ci $($tokens)* 86b12ac153Sopenharmony_ci }; 87b12ac153Sopenharmony_ci} 88b12ac153Sopenharmony_ci 89b12ac153Sopenharmony_ci#[cfg(test)] 90b12ac153Sopenharmony_cimod tests { 91b12ac153Sopenharmony_ci cfg_if! { 92b12ac153Sopenharmony_ci if #[cfg(test)] { 93b12ac153Sopenharmony_ci use core::option::Option as Option2; 94b12ac153Sopenharmony_ci fn works1() -> Option2<u32> { Some(1) } 95b12ac153Sopenharmony_ci } else { 96b12ac153Sopenharmony_ci fn works1() -> Option<u32> { None } 97b12ac153Sopenharmony_ci } 98b12ac153Sopenharmony_ci } 99b12ac153Sopenharmony_ci 100b12ac153Sopenharmony_ci cfg_if! { 101b12ac153Sopenharmony_ci if #[cfg(foo)] { 102b12ac153Sopenharmony_ci fn works2() -> bool { false } 103b12ac153Sopenharmony_ci } else if #[cfg(test)] { 104b12ac153Sopenharmony_ci fn works2() -> bool { true } 105b12ac153Sopenharmony_ci } else { 106b12ac153Sopenharmony_ci fn works2() -> bool { false } 107b12ac153Sopenharmony_ci } 108b12ac153Sopenharmony_ci } 109b12ac153Sopenharmony_ci 110b12ac153Sopenharmony_ci cfg_if! { 111b12ac153Sopenharmony_ci if #[cfg(foo)] { 112b12ac153Sopenharmony_ci fn works3() -> bool { false } 113b12ac153Sopenharmony_ci } else { 114b12ac153Sopenharmony_ci fn works3() -> bool { true } 115b12ac153Sopenharmony_ci } 116b12ac153Sopenharmony_ci } 117b12ac153Sopenharmony_ci 118b12ac153Sopenharmony_ci cfg_if! { 119b12ac153Sopenharmony_ci if #[cfg(test)] { 120b12ac153Sopenharmony_ci use core::option::Option as Option3; 121b12ac153Sopenharmony_ci fn works4() -> Option3<u32> { Some(1) } 122b12ac153Sopenharmony_ci } 123b12ac153Sopenharmony_ci } 124b12ac153Sopenharmony_ci 125b12ac153Sopenharmony_ci cfg_if! { 126b12ac153Sopenharmony_ci if #[cfg(foo)] { 127b12ac153Sopenharmony_ci fn works5() -> bool { false } 128b12ac153Sopenharmony_ci } else if #[cfg(test)] { 129b12ac153Sopenharmony_ci fn works5() -> bool { true } 130b12ac153Sopenharmony_ci } 131b12ac153Sopenharmony_ci } 132b12ac153Sopenharmony_ci 133b12ac153Sopenharmony_ci #[test] 134b12ac153Sopenharmony_ci fn it_works() { 135b12ac153Sopenharmony_ci assert!(works1().is_some()); 136b12ac153Sopenharmony_ci assert!(works2()); 137b12ac153Sopenharmony_ci assert!(works3()); 138b12ac153Sopenharmony_ci assert!(works4().is_some()); 139b12ac153Sopenharmony_ci assert!(works5()); 140b12ac153Sopenharmony_ci } 141b12ac153Sopenharmony_ci 142b12ac153Sopenharmony_ci #[test] 143b12ac153Sopenharmony_ci #[allow(clippy::assertions_on_constants)] 144b12ac153Sopenharmony_ci fn test_usage_within_a_function() { 145b12ac153Sopenharmony_ci cfg_if! {if #[cfg(debug_assertions)] { 146b12ac153Sopenharmony_ci // we want to put more than one thing here to make sure that they 147b12ac153Sopenharmony_ci // all get configured properly. 148b12ac153Sopenharmony_ci assert!(cfg!(debug_assertions)); 149b12ac153Sopenharmony_ci assert_eq!(4, 2+2); 150b12ac153Sopenharmony_ci } else { 151b12ac153Sopenharmony_ci assert!(works1().is_some()); 152b12ac153Sopenharmony_ci assert_eq!(10, 5+5); 153b12ac153Sopenharmony_ci }} 154b12ac153Sopenharmony_ci } 155b12ac153Sopenharmony_ci 156b12ac153Sopenharmony_ci trait Trait { 157b12ac153Sopenharmony_ci fn blah(&self); 158b12ac153Sopenharmony_ci } 159b12ac153Sopenharmony_ci 160b12ac153Sopenharmony_ci #[allow(dead_code)] 161b12ac153Sopenharmony_ci struct Struct; 162b12ac153Sopenharmony_ci 163b12ac153Sopenharmony_ci impl Trait for Struct { 164b12ac153Sopenharmony_ci cfg_if! { 165b12ac153Sopenharmony_ci if #[cfg(feature = "blah")] { 166b12ac153Sopenharmony_ci fn blah(&self) { 167b12ac153Sopenharmony_ci unimplemented!(); 168b12ac153Sopenharmony_ci } 169b12ac153Sopenharmony_ci } else { 170b12ac153Sopenharmony_ci fn blah(&self) { 171b12ac153Sopenharmony_ci unimplemented!(); 172b12ac153Sopenharmony_ci } 173b12ac153Sopenharmony_ci } 174b12ac153Sopenharmony_ci } 175b12ac153Sopenharmony_ci } 176b12ac153Sopenharmony_ci} 177