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
112
113
#![deny(missing_docs)]
#![doc(html_root_url = "http://docs.rs/cfg-match/0.2.1")]
#![no_std]

//! # cfg_match!
///
/// `cfg_match!` provides a more ergonomic approach to chaining conditionals,
/// like the similar [cfg-if](https://github.com/alexcrichton/cfg-if) crate. In
/// addition to items, `cfg_match!` can also be used for expressions (though a
/// block will require parenthesis wrapping like `=> ({ ... })`).

/// Compile-time conditionals
///
/// The macro stops at the first matching branch, just like a traditional match:
///
/// ```rust
/// # use cfg_match::cfg_match;
///
/// cfg_match! {
///     feature = "foo" => {
///         fn bar() {
///             println!("have foo");
///         }
///     }
///     _ =>
///         fn bar() {
///             println!("no foo :(");
///         }
/// }
/// ```
///
/// Alternatively, the above can be written as:
///
/// ```rust
/// # use cfg_match::cfg_match;
///
/// cfg_match! {
///     #[cfg(feature = "foo")]
///     /// Does a thing because of foo.
///     fn bar() {
///         println!("have foo");
///     }
///
///     #[cfg(_)]
///     fn bar() {
///         println!("no foo :(");
///     }
/// }
/// ```
#[macro_export]
macro_rules! cfg_match {
	(_ => { $($i:item)* }) => {
		$($i)*
	};
	(_ => $(#[$m:meta])+ $i:item) => {
		$(#[$m])*
		$i
	};
	(_ => $e:expr$(,)?) => {
		$e
	};
	(_ => $i:item) => {
		$i
	};
	($cfg:meta => { $($i:item)* } $($t:tt)*) => {
		$(#[cfg($cfg)] $i)*
		#[cfg(not($cfg))] $crate::cfg_match! { $($t)* }
	};
	($cfg:meta => $(#[$m:meta])+ $i:item $($t:tt)*) => {
		#[cfg($cfg)] $(#[$m])* $i
		#[cfg(not($cfg))] $crate::cfg_match! { $($t)* }
	};
	($cfg:meta => $e:expr, $($t:tt)*) => {
		match () {
			#[cfg($cfg)] _ => $e,
			#[cfg(not($cfg))] _ => $crate::cfg_match!($($t)*)
		}
	};
	($cfg:meta => $i:item $($t:tt)*) => {
		#[cfg($cfg)] $i
		#[cfg(not($cfg))] $crate::cfg_match! { $($t)* }
	};
	(#[cfg(_)] $i:item $($t:tt)*) => {
		$i
		$crate::cfg_match! { @not(_) $($t)* }
	};
	(#[cfg($cfg:meta)] $i:item $($t:tt)*) => {
		#[cfg($cfg)] $i
		$crate::cfg_match! { @not($cfg) $($t)* }
	};
	(@not(_) #[cfg('do)] $i:item $($t:tt)*) => {
		$i
		$crate::cfg_match! { @not(_) $($t)* }
	};
	(@not(_) #[cfg(_)] $i:item $($t:tt)*) => {
		$i
		$crate::cfg_match! { @not(_) $($t)* }
	};
	(@not(_)) => { };
	(@not($not:meta)) => {
		#[cfg(not($not))] $crate::cfg_match! { }
	};
	(@not($cfg:meta) #[cfg('do)] $i:item $($t:tt)*) => {
		#[cfg($cfg)] $i
		$crate::cfg_match! { @not($cfg) $($t)* }
	};
	(@not($not:meta) $($t:tt)*) => {
		#[cfg(not($not))] $crate::cfg_match! { $($t)* }
	};
	() => {
		compile_error! { "Unsupported configuration" }
	}
}