bevy_reflect_derive/
serialization.rs1use crate::{
2 derive_data::StructField,
3 field_attributes::{DefaultBehavior, ReflectIgnoreBehavior},
4};
5use bevy_macro_utils::fq_std::FQDefault;
6use quote::quote;
7use std::collections::HashMap;
8use syn::{spanned::Spanned, Path};
9
10type ReflectionIndex = usize;
11
12pub(crate) struct SerializationDataDef {
14 skipped: HashMap<ReflectionIndex, SkippedFieldDef>,
16}
17
18impl SerializationDataDef {
19 pub fn new(
24 fields: &[StructField<'_>],
25 bevy_reflect_path: &Path,
26 ) -> Result<Option<Self>, syn::Error> {
27 let mut skipped = <HashMap<_, _>>::default();
28
29 for field in fields {
30 match field.attrs.ignore {
31 ReflectIgnoreBehavior::IgnoreSerialization => {
32 skipped.insert(
33 field.reflection_index.ok_or_else(|| {
34 syn::Error::new(
35 field.data.span(),
36 "internal error: field is missing a reflection index",
37 )
38 })?,
39 SkippedFieldDef::new(field, bevy_reflect_path)?,
40 );
41 }
42 _ => continue,
43 }
44 }
45
46 if skipped.is_empty() {
47 Ok(None)
48 } else {
49 Ok(Some(Self { skipped }))
50 }
51 }
52
53 pub fn as_serialization_data(&self, bevy_reflect_path: &Path) -> proc_macro2::TokenStream {
55 let fields =
56 self.skipped
57 .iter()
58 .map(|(reflection_index, SkippedFieldDef { default_fn })| {
59 quote! {(
60 #reflection_index,
61 #bevy_reflect_path::serde::SkippedField::new(#default_fn)
62 )}
63 });
64 quote! {
65 #bevy_reflect_path::serde::SerializationData::new(
66 ::core::iter::IntoIterator::into_iter([#(#fields),*])
67 )
68 }
69 }
70}
71
72pub(crate) struct SkippedFieldDef {
74 default_fn: proc_macro2::TokenStream,
78}
79
80impl SkippedFieldDef {
81 pub fn new(field: &StructField<'_>, bevy_reflect_path: &Path) -> Result<Self, syn::Error> {
82 let ty = &field.data.ty;
83
84 let default_fn = match &field.attrs.default {
85 DefaultBehavior::Func(func) => quote! {
86 || { #bevy_reflect_path::__macro_exports::alloc_utils::Box::new(#func()) }
87 },
88 _ => quote! {
89 || { #bevy_reflect_path::__macro_exports::alloc_utils::Box::new(<#ty as #FQDefault>::default()) }
90 },
91 };
92
93 Ok(Self { default_fn })
94 }
95}