summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cfg_aliases/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/cfg_aliases/src
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/cfg_aliases/src')
-rw-r--r--third_party/rust/cfg_aliases/src/lib.rs372
1 files changed, 372 insertions, 0 deletions
diff --git a/third_party/rust/cfg_aliases/src/lib.rs b/third_party/rust/cfg_aliases/src/lib.rs
new file mode 100644
index 0000000000..860a4f0044
--- /dev/null
+++ b/third_party/rust/cfg_aliases/src/lib.rs
@@ -0,0 +1,372 @@
+//! # CFG Aliases
+//!
+//! CFG Aliases is a tiny utility to help save you a lot of effort with long winded `#[cfg()]` checks. This crate provides a single [`cfg_aliases!`] macro that doesn't have any dependencies and specifically avoids pulling in `syn` or `quote` so that the impact on your comile times should be negligible.
+//!
+//! You use the the [`cfg_aliases!`] macro in your `build.rs` script to define aliases such as `x11` that could then be used in the `cfg` attribute or macro for conditional compilation: `#[cfg(x11)]`.
+//!
+//! ## Example
+//!
+//! **Cargo.toml:**
+//!
+//! ```toml
+//! [build-dependencies]
+//! cfg_aliases = "0.1.0"
+//! ```
+//!
+//! **build.rs:**
+//!
+//! ```rust
+//! use cfg_aliases::cfg_aliases;
+//!
+//! fn main() {
+//! // Setup cfg aliases
+//! cfg_aliases! {
+//! // Platforms
+//! wasm: { target_arch = "wasm32" },
+//! android: { target_os = "android" },
+//! macos: { target_os = "macos" },
+//! linux: { target_os = "linux" },
+//! // Backends
+//! surfman: { all(unix, feature = "surfman", not(wasm)) },
+//! glutin: { all(feature = "glutin", not(wasm)) },
+//! wgl: { all(windows, feature = "wgl", not(wasm)) },
+//! dummy: { not(any(wasm, glutin, wgl, surfman)) },
+//! }
+//! }
+//! ```
+//!
+//! Now that we have our aliases setup we can use them just like you would expect:
+//!
+//! ```rust
+//! #[cfg(wasm)]
+//! println!("This is running in WASM");
+//!
+//! #[cfg(surfman)]
+//! {
+//! // Do stuff related to surfman
+//! }
+//!
+//! #[cfg(dummy)]
+//! println!("We're in dummy mode, specify another feature if you want a smarter app!");
+//! ```
+//!
+//! This greatly improves what would otherwise look like this without the aliases:
+//!
+//! ```rust
+//! #[cfg(target_arch = "wasm32")]
+//! println!("We're running in WASM");
+//!
+//! #[cfg(all(unix, feature = "surfman", not(target_arch = "22")))]
+//! {
+//! // Do stuff related to surfman
+//! }
+//!
+//! #[cfg(not(any(
+//! target_arch = "wasm32",
+//! all(unix, feature = "surfman", not(target_arch = "wasm32")),
+//! all(windows, feature = "wgl", not(target_arch = "wasm32")),
+//! all(feature = "glutin", not(target_arch = "wasm32")),
+//! )))]
+//! println!("We're in dummy mode, specify another feature if you want a smarter app!");
+//! ```
+//!
+//! You can also use the `cfg!` macro or combine your aliases with other checks using `all()`, `not()`, and `any()`. Your aliases are genuine `cfg` flags now!
+//!
+//! ```rust
+//! if cfg!(glutin) {
+//! // use glutin
+//! } else {
+//! // Do something else
+//! }
+//!
+//! #[cfg(all(glutin, surfman))]
+//! compile_error!("You cannot specify both `glutin` and `surfman` features");
+//! ```
+//!
+//! ## Syntax and Error Messages
+//!
+//! The aliase names are restricted to the same rules as rust identifiers which, for one, means that they cannot have dashes ( `-` ) in them. Additionally, if you get certain syntax elements wrong, such as the alias name, the macro will error saying that the recursion limit was reached instead of giving a clear indication of what actually went wrong. This is due to a nuance with the macro parser and it might be fixed in a later release of this crate. It is also possible that aliases with dashes in the name might be supported in a later release. Open an issue if that is something that you would like implemented.
+//!
+//! Finally, you can also induce an infinite recursion by having rules that both reference each-other, but this isn't a real limitation because that doesn't make logical sense anyway:
+//!
+//! ```rust,ignore
+//! // This causes an error!
+//! cfg_aliases! {
+//! test1: { not(test2) },
+//! test2: { not(test1) },
+//! }
+//! ```
+//!
+//! ## Attribution and Thanks
+//!
+//! - Thanks to my God and Father who led me through figuring this out and to whome I owe everything.
+//! - Thanks to @Yandros on the Rust forum for [showing me][sm] some crazy macro hacks!
+//! - Thanks to @sfackler for [pointing out][po] the way to make cargo add the cfg flags.
+//! - Thanks to the authors of the [`tectonic_cfg_support::target_cfg`] macro from which most of the cfg attribute parsing logic is taken from. Also thanks to @ratmice for [bringing it up][bip] on the Rust forum.
+//!
+//! [`tectonic_cfg_support::target_cfg`]: https://docs.rs/tectonic_cfg_support/0.0.1/src/tectonic_cfg_support/lib.rs.html#166-298
+//! [po]: https://users.rust-lang.org/t/any-such-thing-as-cfg-aliases/40100/2
+//! [bip]: https://users.rust-lang.org/t/any-such-thing-as-cfg-aliases/40100/13
+//! [sm]: https://users.rust-lang.org/t/any-such-thing-as-cfg-aliases/40100/3
+
+#![allow(clippy::needless_doctest_main)]
+
+// In the `cfg_aliases!` macro below, all of the rules that start with @parser were derived from
+// the `target_cfg!` macro here:
+//
+// https://docs.rs/tectonic_cfg_support/0.0.1/src/tectonic_cfg_support/lib.rs.html#166-298.
+//
+// The `target_cfg!` macro is excellently commented while the one below is not very well commented
+// yet, so if you need some help understanding it you might benefit by reading that implementation.
+// Also check out this forum topic for more history on the macro development:
+//
+// https://users.rust-lang.org/t/any-such-thing-as-cfg-aliases/40100?u=zicklag
+
+/// Create `cfg` aliases
+///
+/// **build.rs:**
+///
+/// ```rust
+/// # use cfg_aliases::cfg_aliases;
+/// // Setup cfg aliases
+/// cfg_aliases! {
+/// // Platforms
+/// wasm: { target_arch = "wasm32" },
+/// android: { target_os = "android" },
+/// macos: { target_os = "macos" },
+/// linux: { target_os = "linux" },
+/// // Backends
+/// surfman: { all(unix, feature = "surfman", not(wasm)) },
+/// glutin: { all(feature = "glutin", not(wasm)) },
+/// wgl: { all(windows, feature = "wgl", not(wasm)) },
+/// dummy: { not(any(wasm, glutin, wgl, surfman)) },
+/// }
+/// ```
+///
+/// After you put this in your build script you can then check for those conditions like so:
+///
+/// ```rust
+/// #[cfg(surfman)]
+/// {
+/// // Do stuff related to surfman
+/// }
+///
+/// #[cfg(dummy)]
+/// println!("We're in dummy mode, specify another feature if you want a smarter app!");
+/// ```
+///
+/// This greatly improves what would otherwise look like this without the aliases:
+///
+/// ```rust
+/// #[cfg(all(unix, feature = "surfman", not(target_arch = "wasm32")))]
+/// {
+/// // Do stuff related to surfman
+/// }
+///
+/// #[cfg(not(any(
+/// target_arch = "wasm32",
+/// all(unix, feature = "surfman", not(target_arch = "wasm32")),
+/// all(windows, feature = "wgl", not(target_arch = "wasm32")),
+/// all(feature = "glutin", not(target_arch = "wasm32")),
+/// )))]
+/// println!("We're in dummy mode, specify another feature if you want a smarter app!");
+/// ```
+#[macro_export]
+macro_rules! cfg_aliases {
+ // Helper that just checks whether the CFG environment variable is set
+ (@cfg_is_set $cfgname:ident) => {
+ std::env::var(
+ format!(
+ "CARGO_CFG_{}",
+ &stringify!($cfgname).to_uppercase().replace("-", "_")
+ )
+ ).is_ok()
+ };
+ // Helper to check for the presense of a feature
+ (@cfg_has_feature $feature:expr) => {
+ {
+ std::env::var(
+ format!(
+ "CARGO_FEATURE_{}",
+ &stringify!($feature).to_uppercase().replace("-", "_").replace('"', "")
+ )
+ ).map(|x| x == "1").unwrap_or(false)
+ }
+ };
+
+ // Helper that checks whether a CFG environment contains the given value
+ (@cfg_contains $cfgname:ident = $cfgvalue:expr) => {
+ std::env::var(
+ format!(
+ "CARGO_CFG_{}",
+ &stringify!($cfgname).to_uppercase().replace("-", "_")
+ )
+ ).unwrap_or("".to_string()).split(",").find(|x| x == &$cfgvalue).is_some()
+ };
+
+ // Emitting `any(clause1,clause2,...)`: convert to `$crate::cfg_aliases!(clause1) && $crate::cfg_aliases!(clause2) && ...`
+ (
+ @parser_emit
+ all
+ $({$($grouped:tt)+})+
+ ) => {
+ ($(
+ ($crate::cfg_aliases!(@parser $($grouped)+))
+ )&&+)
+ };
+
+ // Likewise for `all(clause1,clause2,...)`.
+ (
+ @parser_emit
+ any
+ $({$($grouped:tt)+})+
+ ) => {
+ ($(
+ ($crate::cfg_aliases!(@parser $($grouped)+))
+ )||+)
+ };
+
+ // "@clause" rules are used to parse the comma-separated lists. They munch
+ // their inputs token-by-token and finally invoke an "@emit" rule when the
+ // list is all grouped. The general pattern for recording the parser state
+ // is:
+ //
+ // ```
+ // $crate::cfg_aliases!(
+ // @clause $operation
+ // [{grouped-clause-1} {grouped-clause-2...}]
+ // [not-yet-parsed-tokens...]
+ // current-clause-tokens...
+ // )
+ // ```
+
+ // This rule must come first in this section. It fires when the next token
+ // to parse is a comma. When this happens, we take the tokens in the
+ // current clause and add them to the list of grouped clauses, adding
+ // delimeters so that the grouping can be easily extracted again in the
+ // emission stage.
+ (
+ @parser_clause
+ $op:ident
+ [$({$($grouped:tt)+})*]
+ [, $($rest:tt)*]
+ $($current:tt)+
+ ) => {
+ $crate::cfg_aliases!(@parser_clause $op [
+ $(
+ {$($grouped)+}
+ )*
+ {$($current)+}
+ ] [
+ $($rest)*
+ ]);
+ };
+
+ // This rule comes next. It fires when the next un-parsed token is *not* a
+ // comma. In this case, we add that token to the list of tokens in the
+ // current clause, then move on to the next one.
+ (
+ @parser_clause
+ $op:ident
+ [$({$($grouped:tt)+})*]
+ [$tok:tt $($rest:tt)*]
+ $($current:tt)*
+ ) => {
+ $crate::cfg_aliases!(@parser_clause $op [
+ $(
+ {$($grouped)+}
+ )*
+ ] [
+ $($rest)*
+ ] $($current)* $tok);
+ };
+
+ // This rule fires when there are no more tokens to parse in this list. We
+ // finish off the "current" token group, then delegate to the emission
+ // rule.
+ (
+ @parser_clause
+ $op:ident
+ [$({$($grouped:tt)+})*]
+ []
+ $($current:tt)+
+ ) => {
+ $crate::cfg_aliases!(@parser_emit $op
+ $(
+ {$($grouped)+}
+ )*
+ {$($current)+}
+ );
+ };
+
+
+ // `all(clause1, clause2...)` : we must parse this comma-separated list and
+ // partner with `@emit all` to output a bunch of && terms.
+ (
+ @parser
+ all($($tokens:tt)+)
+ ) => {
+ $crate::cfg_aliases!(@parser_clause all [] [$($tokens)+])
+ };
+
+ // Likewise for `any(clause1, clause2...)`
+ (
+ @parser
+ any($($tokens:tt)+)
+ ) => {
+ $crate::cfg_aliases!(@parser_clause any [] [$($tokens)+])
+ };
+
+ // `not(clause)`: compute the inner clause, then just negate it.
+ (
+ @parser
+ not($($tokens:tt)+)
+ ) => {
+ !($crate::cfg_aliases!(@parser $($tokens)+))
+ };
+
+ // `feature = value`: test for a feature.
+ (@parser feature = $value:expr) => {
+ $crate::cfg_aliases!(@cfg_has_feature $value)
+ };
+ // `param = value`: test for equality.
+ (@parser $key:ident = $value:expr) => {
+ $crate::cfg_aliases!(@cfg_contains $key = $value)
+ };
+ // Parse a lone identifier that might be an alias
+ (@parser $e:ident) => {
+ __cfg_aliases_matcher__!($e)
+ };
+
+ // Entrypoint that defines the matcher
+ (
+ @with_dollar[$dol:tt]
+ $( $alias:ident : { $($config:tt)* } ),* $(,)?
+ ) => {
+ // Create a macro that expands other aliases and outputs any non
+ // alias by checking whether that CFG value is set
+ macro_rules! __cfg_aliases_matcher__ {
+ // Parse config expression for the alias
+ $(
+ ( $alias ) => {
+ $crate::cfg_aliases!(@parser $($config)*)
+ };
+ )*
+ // Anything that doesn't match evaluate the item
+ ( $dol e:ident ) => {
+ $crate::cfg_aliases!(@cfg_is_set $dol e)
+ };
+ }
+
+ $(
+ if $crate::cfg_aliases!(@parser $($config)*) {
+ println!("cargo:rustc-cfg={}", stringify!($alias));
+ }
+ )*
+ };
+
+ // Catch all that starts the macro
+ ($($tokens:tt)*) => {
+ $crate::cfg_aliases!(@with_dollar[$] $($tokens)*)
+ }
+}