bevy_platform 0.18.1

Provides common platform agnostic APIs, as well as platform-specific features for Bevy Engine
Documentation
//! Provides helpful configuration macros, allowing detection of platform features such as
//! [`alloc`](crate::cfg::alloc) or [`std`](crate::cfg::std) without explicit features.

/// Provides a `match`-like expression similar to [`cfg_if`] and based on the experimental
/// [`cfg_match`].
/// The name `switch` is used to avoid conflict with the `match` keyword.
/// Arms are evaluated top to bottom, and an optional wildcard arm can be provided if no match
/// can be made.
///
/// An arm can either be:
/// - a `cfg(...)` pattern (e.g., `feature = "foo"`)
/// - a wildcard `_`
/// - an alias defined using [`define_alias`]
///
/// Common aliases are provided by [`cfg`](crate::cfg).
/// Note that aliases are evaluated from the context of the defining crate, not the consumer.
///
/// # Examples
///
/// ```
/// # use bevy_platform::cfg;
/// # fn log(_: &str) {}
/// # fn foo(_: &str) {}
/// #
/// cfg::switch! {
///     #[cfg(feature = "foo")] => {
///         foo("We have the `foo` feature!")
///     }
///     cfg::std => {
///         extern crate std;
///         std::println!("No `foo`, but we have `std`!");
///     }
///     _ => {
///         log("Don't have `std` or `foo`");
///     }
/// }
/// ```
///
/// [`cfg_if`]: https://crates.io/crates/cfg-if
/// [`cfg_match`]: https://github.com/rust-lang/rust/issues/115585
#[doc(inline)]
pub use crate::switch;

/// Defines an alias for a particular configuration.
/// This has two advantages over directly using `#[cfg(...)]`:
///
/// 1. Complex configurations can be abbreviated to more meaningful shorthand.
/// 2. Features are evaluated in the context of the _defining_ crate, not the consuming.
///
/// The second advantage is a particularly powerful tool, as it allows consuming crates to use
/// functionality in a defining crate regardless of what crate in the dependency graph enabled the
/// relevant feature.
///
/// For example, consider a crate `foo` that depends on another crate `bar`.
/// `bar` has a feature "`faster_algorithms`".
/// If `bar` defines a "`faster_algorithms`" alias:
///
/// ```ignore
/// define_alias! {
///     #[cfg(feature = "faster_algorithms")] => { faster_algorithms }
/// }
/// ```
///
/// Now, `foo` can gate its usage of those faster algorithms on the alias, avoiding the need to
/// expose its own "`faster_algorithms`" feature.
/// This also avoids the unfortunate situation where one crate activates "`faster_algorithms`" on
/// `bar` without activating that same feature on `foo`.
///
/// Once an alias is defined, there are 4 ways you can use it:
///
/// 1. Evaluate with no contents to return a `bool` indicating if the alias is active.
///    ```
///    # use bevy_platform::cfg;
///    if cfg::std!() {
///        // Have `std`!
///    } else {
///        // No `std`...
///    }
///    ```
/// 2. Pass a single code block which will only be compiled if the alias is active.
///    ```
///    # use bevy_platform::cfg;
///    cfg::std! {
///        // Have `std`!
///    # ()
///    }
///    ```
/// 3. Pass a single `if { ... } else { ... }` expression to conditionally compile either the first
///    or the second code block.
///    ```
///    # use bevy_platform::cfg;
///    cfg::std! {
///        if {
///            // Have `std`!
///        } else {
///            // No `std`...
///        }
///    }
///    ```
/// 4. Use in a [`switch`] arm for more complex conditional compilation.
///    ```
///    # use bevy_platform::cfg;
///    cfg::switch! {
///        cfg::std => {
///            // Have `std`!
///        }
///        cfg::alloc => {
///            // No `std`, but do have `alloc`!
///        }
///        _ => {
///            // No `std` or `alloc`...
///        }
///    }
///    ```
#[doc(inline)]
pub use crate::define_alias;

/// Macro which represents an enabled compilation condition.
#[doc(inline)]
pub use crate::enabled;

/// Macro which represents a disabled compilation condition.
#[doc(inline)]
pub use crate::disabled;

#[doc(hidden)]
#[macro_export]
macro_rules! switch {
    ({ $($tt:tt)* }) => {{
        $crate::switch! { $($tt)* }
    }};
    (_ => { $($output:tt)* }) => {
        $($output)*
    };
    (
        $cond:path => $output:tt
        $($( $rest:tt )+)?
    ) => {
        $cond! {
            if {
                $crate::switch! { _ => $output }
            } else {
                $(
                    $crate::switch! { $($rest)+ }
                )?
            }
        }
    };
    (
        #[cfg($cfg:meta)] => $output:tt
        $($( $rest:tt )+)?
    ) => {
        #[cfg($cfg)]
        $crate::switch! { _ => $output }
        $(
            #[cfg(not($cfg))]
            $crate::switch! { $($rest)+ }
        )?
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! disabled {
    () => { false };
    (if { $($p:tt)* } else { $($n:tt)* }) => { $($n)* };
    ($($p:tt)*) => {};
}

#[doc(hidden)]
#[macro_export]
macro_rules! enabled {
    () => { true };
    (if { $($p:tt)* } else { $($n:tt)* }) => { $($p)* };
    ($($p:tt)*) => { $($p)* };
}

#[doc(hidden)]
#[macro_export]
macro_rules! define_alias {
    (
        #[cfg($meta:meta)] => $p:ident
        $(, $( $rest:tt )+)?
    ) => {
        $crate::define_alias! {
            #[cfg($meta)] => { $p }
            $(
                $($rest)+
            )?
        }
    };
    (
        #[cfg($meta:meta)] => $p:ident,
        $($( $rest:tt )+)?
    ) => {
        $crate::define_alias! {
            #[cfg($meta)] => { $p }
            $(
                $($rest)+
            )?
        }
    };
    (
        #[cfg($meta:meta)] => {
            $(#[$p_meta:meta])*
            $p:ident
        }
        $($( $rest:tt )+)?
    ) => {
        $crate::switch! {
            #[cfg($meta)] => {
                $(#[$p_meta])*
                #[doc(inline)]
                ///
                #[doc = concat!("This macro passes the provided code because `#[cfg(", stringify!($meta), ")]` is currently active.")]
                pub use $crate::enabled as $p;
            }
            _ => {
                $(#[$p_meta])*
                #[doc(inline)]
                ///
                #[doc = concat!("This macro suppresses the provided code because `#[cfg(", stringify!($meta), ")]` is _not_ currently active.")]
                pub use $crate::disabled as $p;
            }
        }

        $(
            $crate::define_alias! {
                $($rest)+
            }
        )?
    }
}

define_alias! {
    #[cfg(feature = "alloc")] => {
        /// Indicates the `alloc` crate is available and can be used.
        alloc
    }
    #[cfg(feature = "std")] => {
        /// Indicates the `std` crate is available and can be used.
        std
    }
    #[cfg(panic = "unwind")] => {
        /// Indicates that a [`panic`] will be unwound, and can be potentially caught.
        panic_unwind
    }
    #[cfg(panic = "abort")] => {
        /// Indicates that a [`panic`] will lead to an abort, and cannot be caught.
        panic_abort
    }
    #[cfg(all(target_arch = "wasm32", feature = "web"))] => {
        /// Indicates that this target has access to browser APIs.
        web
    }
    #[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] => {
        /// Indicates that this target has access to a native implementation of `Arc`.
        arc
    }
    #[cfg(feature = "critical-section")] => {
        /// Indicates `critical-section` is available.
        critical_section
    }
}