Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/serde/de/struct_utils.rs
9353 views
1
use crate::{
2
enums::StructVariantInfo,
3
serde::{
4
de::{
5
error_utils::make_custom_error,
6
helpers::{ExpectedValues, Ident},
7
registration_utils::try_get_registration,
8
},
9
SerializationData, TypedReflectDeserializer,
10
},
11
structs::{DynamicStruct, StructInfo},
12
NamedField, TypeRegistration, TypeRegistry,
13
};
14
use alloc::string::ToString;
15
use core::slice::Iter;
16
use serde::de::{Error, MapAccess, SeqAccess};
17
18
use super::ReflectDeserializerProcessor;
19
20
/// A helper trait for accessing type information from struct-like types.
21
pub(super) trait StructLikeInfo {
22
fn field<E: Error>(&self, name: &str) -> Result<&NamedField, E>;
23
fn field_at<E: Error>(&self, index: usize) -> Result<&NamedField, E>;
24
fn field_len(&self) -> usize;
25
fn iter_fields(&self) -> Iter<'_, NamedField>;
26
}
27
28
impl StructLikeInfo for StructInfo {
29
fn field<E: Error>(&self, name: &str) -> Result<&NamedField, E> {
30
Self::field(self, name).ok_or_else(|| {
31
make_custom_error(format_args!(
32
"no field named `{}` on struct `{}`",
33
name,
34
self.type_path(),
35
))
36
})
37
}
38
39
fn field_at<E: Error>(&self, index: usize) -> Result<&NamedField, E> {
40
Self::field_at(self, index).ok_or_else(|| {
41
make_custom_error(format_args!(
42
"no field at index `{}` on struct `{}`",
43
index,
44
self.type_path(),
45
))
46
})
47
}
48
49
fn field_len(&self) -> usize {
50
Self::field_len(self)
51
}
52
53
fn iter_fields(&self) -> Iter<'_, NamedField> {
54
self.iter()
55
}
56
}
57
58
impl StructLikeInfo for StructVariantInfo {
59
fn field<E: Error>(&self, name: &str) -> Result<&NamedField, E> {
60
Self::field(self, name).ok_or_else(|| {
61
make_custom_error(format_args!(
62
"no field named `{}` on variant `{}`",
63
name,
64
self.name(),
65
))
66
})
67
}
68
69
fn field_at<E: Error>(&self, index: usize) -> Result<&NamedField, E> {
70
Self::field_at(self, index).ok_or_else(|| {
71
make_custom_error(format_args!(
72
"no field at index `{}` on variant `{}`",
73
index,
74
self.name(),
75
))
76
})
77
}
78
79
fn field_len(&self) -> usize {
80
Self::field_len(self)
81
}
82
83
fn iter_fields(&self) -> Iter<'_, NamedField> {
84
self.iter()
85
}
86
}
87
88
/// Deserializes a [struct-like] type from a mapping of fields, returning a [`DynamicStruct`].
89
///
90
/// [struct-like]: StructLikeInfo
91
pub(super) fn visit_struct<'de, T, V, P>(
92
map: &mut V,
93
info: &'static T,
94
registration: &TypeRegistration,
95
registry: &TypeRegistry,
96
mut processor: Option<&mut P>,
97
) -> Result<DynamicStruct, V::Error>
98
where
99
T: StructLikeInfo,
100
V: MapAccess<'de>,
101
P: ReflectDeserializerProcessor,
102
{
103
let mut dynamic_struct = DynamicStruct::default();
104
while let Some(Ident(key)) = map.next_key::<Ident>()? {
105
let field = info.field::<V::Error>(&key).map_err(|_| {
106
let fields = info.iter_fields().map(NamedField::name);
107
make_custom_error(format_args!(
108
"unknown field `{}`, expected one of {:?}",
109
key,
110
ExpectedValues::from_iter(fields)
111
))
112
})?;
113
let registration = try_get_registration(*field.ty(), registry)?;
114
let value = map.next_value_seed(TypedReflectDeserializer::new_internal(
115
registration,
116
registry,
117
processor.as_deref_mut(),
118
))?;
119
dynamic_struct.insert_boxed(&key, value);
120
}
121
122
if let Some(serialization_data) = registration.data::<SerializationData>() {
123
for (skipped_index, skipped_field) in serialization_data.iter_skipped() {
124
let Ok(field) = info.field_at::<V::Error>(*skipped_index) else {
125
continue;
126
};
127
dynamic_struct.insert_boxed(
128
field.name(),
129
skipped_field.generate_default().into_partial_reflect(),
130
);
131
}
132
}
133
134
Ok(dynamic_struct)
135
}
136
137
/// Deserializes a [struct-like] type from a sequence of fields, returning a [`DynamicStruct`].
138
///
139
/// [struct-like]: StructLikeInfo
140
pub(super) fn visit_struct_seq<'de, T, V, P>(
141
seq: &mut V,
142
info: &T,
143
registration: &TypeRegistration,
144
registry: &TypeRegistry,
145
mut processor: Option<&mut P>,
146
) -> Result<DynamicStruct, V::Error>
147
where
148
T: StructLikeInfo,
149
V: SeqAccess<'de>,
150
P: ReflectDeserializerProcessor,
151
{
152
let mut dynamic_struct = DynamicStruct::default();
153
154
let len = info.field_len();
155
156
if len == 0 {
157
// Handle unit structs
158
return Ok(dynamic_struct);
159
}
160
161
let serialization_data = registration.data::<SerializationData>();
162
163
for index in 0..len {
164
let name = info.field_at::<V::Error>(index)?.name();
165
166
if serialization_data
167
.map(|data| data.is_field_skipped(index))
168
.unwrap_or_default()
169
{
170
if let Some(value) = serialization_data.unwrap().generate_default(index) {
171
dynamic_struct.insert_boxed(name, value.into_partial_reflect());
172
}
173
continue;
174
}
175
176
let value = seq
177
.next_element_seed(TypedReflectDeserializer::new_internal(
178
try_get_registration(*info.field_at(index)?.ty(), registry)?,
179
registry,
180
processor.as_deref_mut(),
181
))?
182
.ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?;
183
dynamic_struct.insert_boxed(name, value);
184
}
185
186
Ok(dynamic_struct)
187
}
188
189