//! Assorted proc macro derive functions.12#![forbid(unsafe_code)]3#![cfg_attr(docsrs, feature(doc_auto_cfg))]4#![doc(5html_logo_url = "https://bevy.org/assets/icon.png",6html_favicon_url = "https://bevy.org/assets/icon.png"7)]89extern crate proc_macro;1011mod bevy_main;12mod derefs;13mod enum_variant_meta;1415use bevy_macro_utils::{derive_label, BevyManifest};16use proc_macro::TokenStream;17use quote::format_ident;1819/// Implements [`Deref`] for structs. This is especially useful when utilizing the [newtype] pattern.20///21/// For single-field structs, the implementation automatically uses that field.22/// For multi-field structs, you must specify which field to use with the `#[deref]` attribute.23///24/// If you need [`DerefMut`] as well, consider using the other [derive] macro alongside25/// this one.26///27/// # Example28///29/// ## Tuple Structs30///31/// Using a single-field struct:32///33/// ```34/// use bevy_derive::Deref;35///36/// #[derive(Deref)]37/// struct MyNewtype(String);38///39/// let foo = MyNewtype(String::from("Hello"));40/// assert_eq!("Hello", *foo);41/// ```42///43/// Using a multi-field struct:44///45/// ```46/// # use std::marker::PhantomData;47/// use bevy_derive::Deref;48///49/// #[derive(Deref)]50/// struct MyStruct<T>(#[deref] String, PhantomData<T>);51///52/// let foo = MyStruct(String::from("Hello"), PhantomData::<usize>);53/// assert_eq!("Hello", *foo);54/// ```55///56/// ## Named Structs57///58/// Using a single-field struct:59///60/// ```61/// use bevy_derive::{Deref, DerefMut};62///63/// #[derive(Deref, DerefMut)]64/// struct MyStruct {65/// value: String,66/// }67///68/// let foo = MyStruct {69/// value: String::from("Hello")70/// };71/// assert_eq!("Hello", *foo);72/// ```73///74/// Using a multi-field struct:75///76/// ```77/// # use std::marker::PhantomData;78/// use bevy_derive::{Deref, DerefMut};79///80/// #[derive(Deref, DerefMut)]81/// struct MyStruct<T> {82/// #[deref]83/// value: String,84/// _phantom: PhantomData<T>,85/// }86///87/// let foo = MyStruct {88/// value:String::from("Hello"),89/// _phantom:PhantomData::<usize>90/// };91/// assert_eq!("Hello", *foo);92/// ```93///94/// [`Deref`]: std::ops::Deref95/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html96/// [`DerefMut`]: std::ops::DerefMut97/// [derive]: crate::derive_deref_mut98#[proc_macro_derive(Deref, attributes(deref))]99pub fn derive_deref(input: TokenStream) -> TokenStream {100derefs::derive_deref(input)101}102103/// Implements [`DerefMut`] for structs. This is especially useful when utilizing the [newtype] pattern.104///105/// For single-field structs, the implementation automatically uses that field.106/// For multi-field structs, you must specify which field to use with the `#[deref]` attribute.107///108/// [`DerefMut`] requires a [`Deref`] implementation. You can implement it manually or use109/// Bevy's [derive] macro for convenience.110///111/// # Example112///113/// ## Tuple Structs114///115/// Using a single-field struct:116///117/// ```118/// use bevy_derive::{Deref, DerefMut};119///120/// #[derive(Deref, DerefMut)]121/// struct MyNewtype(String);122///123/// let mut foo = MyNewtype(String::from("Hello"));124/// foo.push_str(" World!");125/// assert_eq!("Hello World!", *foo);126/// ```127///128/// Using a multi-field struct:129///130/// ```131/// # use std::marker::PhantomData;132/// use bevy_derive::{Deref, DerefMut};133///134/// #[derive(Deref, DerefMut)]135/// struct MyStruct<T>(#[deref] String, PhantomData<T>);136///137/// let mut foo = MyStruct(String::from("Hello"), PhantomData::<usize>);138/// foo.push_str(" World!");139/// assert_eq!("Hello World!", *foo);140/// ```141///142/// ## Named Structs143///144/// Using a single-field struct:145///146/// ```147/// use bevy_derive::{Deref, DerefMut};148///149/// #[derive(Deref, DerefMut)]150/// struct MyStruct {151/// value: String,152/// }153///154/// let mut foo = MyStruct {155/// value: String::from("Hello")156/// };157/// foo.push_str(" World!");158/// assert_eq!("Hello World!", *foo);159/// ```160///161/// Using a multi-field struct:162///163/// ```164/// # use std::marker::PhantomData;165/// use bevy_derive::{Deref, DerefMut};166///167/// #[derive(Deref, DerefMut)]168/// struct MyStruct<T> {169/// #[deref]170/// value: String,171/// _phantom: PhantomData<T>,172/// }173///174/// let mut foo = MyStruct {175/// value:String::from("Hello"),176/// _phantom:PhantomData::<usize>177/// };178/// foo.push_str(" World!");179/// assert_eq!("Hello World!", *foo);180/// ```181///182/// [`DerefMut`]: std::ops::DerefMut183/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html184/// [`Deref`]: std::ops::Deref185/// [derive]: crate::derive_deref186#[proc_macro_derive(DerefMut, attributes(deref))]187pub fn derive_deref_mut(input: TokenStream) -> TokenStream {188derefs::derive_deref_mut(input)189}190191/// Generates the required main function boilerplate for Android.192#[proc_macro_attribute]193pub fn bevy_main(attr: TokenStream, item: TokenStream) -> TokenStream {194bevy_main::bevy_main(attr, item)195}196197/// Adds `enum_variant_index` and `enum_variant_name` functions to enums.198///199/// # Example200///201/// ```202/// use bevy_derive::{EnumVariantMeta};203///204/// #[derive(EnumVariantMeta)]205/// enum MyEnum {206/// A,207/// B,208/// }209///210/// let a = MyEnum::A;211/// let b = MyEnum::B;212///213/// assert_eq!(0, a.enum_variant_index());214/// assert_eq!("A", a.enum_variant_name());215///216/// assert_eq!(1, b.enum_variant_index());217/// assert_eq!("B", b.enum_variant_name());218/// ```219#[proc_macro_derive(EnumVariantMeta)]220pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {221enum_variant_meta::derive_enum_variant_meta(input)222}223224/// Generates an impl of the `AppLabel` trait.225///226/// This does not work for unions.227#[proc_macro_derive(AppLabel)]228pub fn derive_app_label(input: TokenStream) -> TokenStream {229let input = syn::parse_macro_input!(input as syn::DeriveInput);230let mut trait_path = BevyManifest::shared().get_path("bevy_app");231trait_path.segments.push(format_ident!("AppLabel").into());232derive_label(input, "AppLabel", &trait_path)233}234235236