Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_derive/src/lib.rs
6598 views
1
//! Assorted proc macro derive functions.
2
3
#![forbid(unsafe_code)]
4
#![cfg_attr(docsrs, feature(doc_auto_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
10
extern crate proc_macro;
11
12
mod bevy_main;
13
mod derefs;
14
mod enum_variant_meta;
15
16
use bevy_macro_utils::{derive_label, BevyManifest};
17
use proc_macro::TokenStream;
18
use 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))]
100
pub 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))]
188
pub 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]
194
pub 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)]
221
pub 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)]
229
pub 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
}
235
236