Skip to main content

bevy_reflect/serde/de/
tuple_utils.rs

1use 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};
11use alloc::string::ToString;
12use serde::de::{Error, SeqAccess};
13
14use super::ReflectDeserializerProcessor;
15
16pub(super) trait TupleLikeInfo {
17    fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E>;
18    fn field_len(&self) -> usize;
19}
20
21impl 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
37impl 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
53impl 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
72pub(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>
79where
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}