serde_hkx/xml/de/
seq.rs

1//! Deserializing each element in an `Array`
2use super::XmlDeserializer;
3use super::parser::{
4    comment_multispace0,
5    tag::{end_tag, start_tag},
6};
7
8use crate::errors::de::{Error, Result};
9use crate::tri;
10
11use havok_serde::de::{DeserializeSeed, SeqAccess};
12use winnow::combinator::alt;
13
14/// A structure for deserializing each element in an `Array`.
15///
16/// Since XML Array has strings to be parsed before and after parsing the value, the methods of this structure process
17/// them and call `deserialize` to parse and return the internal value.
18pub struct SeqDeserializer<'a, 'de: 'a> {
19    /// Deserializer
20    de: &'a mut XmlDeserializer<'de>,
21}
22
23impl<'a, 'de> SeqDeserializer<'a, 'de> {
24    /// Create a new seq deserializer
25    #[inline]
26    pub const fn new(de: &'a mut XmlDeserializer<'de>) -> Self {
27        Self { de }
28    }
29}
30
31// `SeqAccess` is provided to the `Visitor` to give it the ability to iterate
32// through elements of the sequence.
33impl<'de> SeqAccess<'de> for SeqDeserializer<'_, 'de> {
34    type Error = Error;
35
36    #[inline]
37    fn class_ptr(&self) -> Result<usize> {
38        self.de.class_index.ok_or(Error::NotFoundClassPtr)
39    }
40
41    /// # Expected XML Examples
42    ///
43    /// - `hkArray<hkInt8>`(same as ptr, hkReal, etc...)
44    /// ```xml
45    /// <hkparam name="key" numelements="20">
46    ///     0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
47    ///     16 17 18 19 20
48    /// </hkparam>
49    /// ```
50    fn next_primitive_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
51    where
52        T: DeserializeSeed<'de>,
53    {
54        // Space is required before every element except the first.
55        tri!(self.de.parse_next(comment_multispace0));
56
57        // Check if there are no more elements.
58        if self.de.input.is_empty() || self.de.parse_peek(end_tag("hkparam")).is_ok() {
59            return Ok(None);
60        };
61
62        seed.deserialize(&mut *self.de).map(Some) // Deserialize an array element.
63    }
64
65    fn next_class_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
66    where
67        T: DeserializeSeed<'de>,
68    {
69        // Check if there are no more elements.
70        // NOTE: If there is no empty confirmation in this location, the test or partial parsing will result in an infinite loop.
71        if self.de.input.is_empty()
72            || self
73                .de
74                .parse_peek(alt((end_tag("hkparam"), end_tag("hksection"))))
75                .is_ok()
76        {
77            return Ok(None);
78        };
79
80        seed.deserialize(&mut *self.de).map(Some) // Deserialize an array element.
81    }
82
83    /// - `hkArray<Vector4>`
84    /// ```xml
85    /// <hkparam name="key" numelements="2">
86    ///     (0.000000 0.000000 0.000000 0.000000)
87    ///     (0.000000 0.000000 0.000000 0.000000)
88    /// </hkparam>
89    /// ```
90    #[inline]
91    fn next_math_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
92    where
93        T: DeserializeSeed<'de>,
94    {
95        self.next_primitive_element_seed(seed)
96    }
97
98    #[inline]
99    fn next_cstring_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
100    where
101        T: DeserializeSeed<'de>,
102    {
103        self.next_stringptr_element_seed(seed)
104    }
105
106    /// struct S {
107    ///    key: StringPtr
108    /// }
109    ///
110    /// ```xml
111    /// <hkparam name="key">StringPtr1</hkparam>
112    /// ```
113    ///
114    /// - `hkArray<hkStringPtr>`
115    /// ```xml
116    /// <hkparam name="key" numelements="3">
117    ///     <hkcstring>StringPtr1</hkcstring>
118    ///     <hkcstring>StringPtr2</hkcstring>
119    ///     <hkcstring>StringPtr3</hkcstring>
120    /// </hkparam>
121    /// ```
122    fn next_stringptr_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
123    where
124        T: DeserializeSeed<'de>,
125    {
126        // Check if there are no more elements.
127        // NOTE: If there is no empty confirmation in this location, the test or partial parsing will result in an infinite loop.
128        if self.de.input.is_empty() || self.de.parse_peek(end_tag("hkparam")).is_ok() {
129            return Ok(None);
130        };
131
132        tri!(self.de.parse_next(start_tag("hkcstring")));
133        let ret = seed.deserialize(&mut *self.de).map(Some)?;
134        tri!(self.de.parse_next(end_tag("hkcstring")));
135        Ok(ret)
136    }
137}