Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_macro_utils/src/member.rs
9334 views
1
use syn::{Ident, Member};
2
3
/// Converts an optional identifier or index into a [`syn::Member`] variant.
4
///
5
/// This is useful for when you want to access a field inside a `quote!` block regardless of whether it is an identifier or an index.
6
/// There is also [`syn::Fields::members`], but this method doesn't work when you're dealing with single / filtered fields.
7
///
8
/// Rust struct syntax allows for `Struct { foo: "string" }` with explicitly
9
/// named fields. It allows the `Struct { 0: "string" }` syntax when the struct
10
/// is declared as a tuple struct.
11
///
12
/// # Example
13
/// ```rust
14
/// use syn::{Ident, parse_str, DeriveInput, Data, DataStruct};
15
/// use quote::quote;
16
/// use bevy_macro_utils::as_member;
17
///
18
/// let ast: DeriveInput = syn::parse_str(
19
/// r#"
20
/// struct Mystruct {
21
/// field: usize,
22
/// #[my_derive]
23
/// other_field: usize
24
/// }
25
/// "#,
26
/// )
27
/// .unwrap();
28
///
29
/// let Data::Struct(DataStruct { fields, .. }) = &ast.data else { return };
30
///
31
/// let field_members = fields
32
/// .iter()
33
/// .enumerate()
34
/// .filter(|(_, field)| field.attrs.iter().any(|attr| attr.path().is_ident("my_derive")))
35
/// .map(|(i, field)| { as_member(field.ident.as_ref(), i) });
36
///
37
/// // it won't matter now if it's a named field or a unnamed field. e.g self.field or self.0
38
/// quote!(
39
/// #(self.#field_members.do_something();)*
40
/// );
41
///
42
/// ```
43
///
44
pub fn as_member(ident: Option<&Ident>, index: usize) -> Member {
45
ident.map_or_else(|| Member::from(index), |ident| Member::Named(ident.clone()))
46
}
47
48