bevy_derive/
lib.rs

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