bevy_derive/
lib.rs

1#![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]
2#![forbid(unsafe_code)]
3#![cfg_attr(docsrs, feature(doc_auto_cfg))]
4#![doc(
5    html_logo_url = "https://bevyengine.org/assets/icon.png",
6    html_favicon_url = "https://bevyengine.org/assets/icon.png"
7)]
8
9extern crate proc_macro;
10
11mod bevy_main;
12mod derefs;
13mod enum_variant_meta;
14
15use bevy_macro_utils::{derive_label, BevyManifest};
16use proc_macro::TokenStream;
17use quote::format_ident;
18
19/// 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 alongside
25/// this one.
26///
27/// # Example
28///
29/// ## Tuple Structs
30///
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 Structs
57///
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::Deref
95/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
96/// [`DerefMut`]: std::ops::DerefMut
97/// [derive]: crate::derive_deref_mut
98#[proc_macro_derive(Deref, attributes(deref))]
99pub fn derive_deref(input: TokenStream) -> TokenStream {
100    derefs::derive_deref(input)
101}
102
103/// 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 use
109/// Bevy's [derive] macro for convenience.
110///
111/// # Example
112///
113/// ## Tuple Structs
114///
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 Structs
143///
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::DerefMut
183/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
184/// [`Deref`]: std::ops::Deref
185/// [derive]: crate::derive_deref
186#[proc_macro_derive(DerefMut, attributes(deref))]
187pub fn derive_deref_mut(input: TokenStream) -> TokenStream {
188    derefs::derive_deref_mut(input)
189}
190
191#[proc_macro_attribute]
192pub fn bevy_main(attr: TokenStream, item: TokenStream) -> TokenStream {
193    bevy_main::bevy_main(attr, item)
194}
195
196#[proc_macro_derive(EnumVariantMeta)]
197pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
198    enum_variant_meta::derive_enum_variant_meta(input)
199}
200
201/// Generates an impl of the `AppLabel` trait.
202///
203/// This does not work for unions.
204#[proc_macro_derive(AppLabel)]
205pub fn derive_app_label(input: TokenStream) -> TokenStream {
206    let input = syn::parse_macro_input!(input as syn::DeriveInput);
207    let mut trait_path = BevyManifest::shared().get_path("bevy_app");
208    let mut dyn_eq_path = trait_path.clone();
209    trait_path.segments.push(format_ident!("AppLabel").into());
210    dyn_eq_path.segments.push(format_ident!("DynEq").into());
211    derive_label(input, "AppLabel", &trait_path, &dyn_eq_path)
212}