Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/serde/de/tuple_utils.rs
9395 views
1
use crate::{
2
enums::TupleVariantInfo,
3
serde::{
4
de::{error_utils::make_custom_error, registration_utils::try_get_registration},
5
SerializationData, TypedReflectDeserializer,
6
},
7
tuple::{DynamicTuple, TupleInfo},
8
tuple_struct::TupleStructInfo,
9
TypeRegistration, TypeRegistry, UnnamedField,
10
};
11
use alloc::string::ToString;
12
use serde::de::{Error, SeqAccess};
13
14
use super::ReflectDeserializerProcessor;
15
16
pub(super) trait TupleLikeInfo {
17
fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E>;
18
fn field_len(&self) -> usize;
19
}
20
21
impl TupleLikeInfo for TupleInfo {
22
fn field_len(&self) -> usize {
23
Self::field_len(self)
24
}
25
26
fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E> {
27
Self::field_at(self, index).ok_or_else(|| {
28
make_custom_error(format_args!(
29
"no field at index `{}` on tuple `{}`",
30
index,
31
self.type_path(),
32
))
33
})
34
}
35
}
36
37
impl TupleLikeInfo for TupleStructInfo {
38
fn field_len(&self) -> usize {
39
Self::field_len(self)
40
}
41
42
fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E> {
43
Self::field_at(self, index).ok_or_else(|| {
44
make_custom_error(format_args!(
45
"no field at index `{}` on tuple struct `{}`",
46
index,
47
self.type_path(),
48
))
49
})
50
}
51
}
52
53
impl TupleLikeInfo for TupleVariantInfo {
54
fn field_len(&self) -> usize {
55
Self::field_len(self)
56
}
57
58
fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E> {
59
Self::field_at(self, index).ok_or_else(|| {
60
make_custom_error(format_args!(
61
"no field at index `{}` on tuple variant `{}`",
62
index,
63
self.name(),
64
))
65
})
66
}
67
}
68
69
/// Deserializes a [tuple-like] type from a sequence of elements, returning a [`DynamicTuple`].
70
///
71
/// [tuple-like]: TupleLikeInfo
72
pub(super) fn visit_tuple<'de, T, V, P>(
73
seq: &mut V,
74
info: &T,
75
registration: &TypeRegistration,
76
registry: &TypeRegistry,
77
mut processor: Option<&mut P>,
78
) -> Result<DynamicTuple, V::Error>
79
where
80
T: TupleLikeInfo,
81
V: SeqAccess<'de>,
82
P: ReflectDeserializerProcessor,
83
{
84
let mut tuple = DynamicTuple::default();
85
86
let len = info.field_len();
87
88
if len == 0 {
89
// Handle empty tuple/tuple struct
90
return Ok(tuple);
91
}
92
93
let serialization_data = registration.data::<SerializationData>();
94
95
for index in 0..len {
96
if let Some(value) = serialization_data.and_then(|data| data.generate_default(index)) {
97
tuple.insert_boxed(value.into_partial_reflect());
98
continue;
99
}
100
101
let value = seq
102
.next_element_seed(TypedReflectDeserializer::new_internal(
103
try_get_registration(*info.field_at(index)?.ty(), registry)?,
104
registry,
105
processor.as_deref_mut(),
106
))?
107
.ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?;
108
tuple.insert_boxed(value);
109
}
110
111
Ok(tuple)
112
}
113
114