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