bevy_reflect/serde/de/
tuple_utils.rs

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