xsd_parser/quick_xml/
deserialize.rs

1use std::fmt::Debug;
2use std::marker::PhantomData;
3use std::str::{from_utf8, FromStr};
4
5use quick_xml::events::Event;
6
7use super::{Error, ErrorKind, XmlReader, XmlReaderSync};
8
9/// Trait that defines the [`Deserializer`] for a type.
10pub trait WithDeserializer: Sized {
11    /// The deserializer to use for this type.
12    type Deserializer: for<'de> Deserializer<'de, Self>;
13}
14
15impl<X> WithDeserializer for X
16where
17    X: DeserializeBytes + Debug,
18{
19    type Deserializer = ContentDeserializer<X>;
20}
21
22/// Trait that defines a deserializer that can be used to construct a type from a
23/// XML [`Event`]s.
24pub trait Deserializer<'de, T>: Debug + Sized {
25    /// Initializes a new deserializer from the passed `reader` and the initial `event`.
26    ///
27    /// # Errors
28    ///
29    /// Returns an [`Error`] if the initialization of the deserializer failed.
30    fn init<R>(reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
31    where
32        R: XmlReader;
33
34    /// Processes the next XML [`Event`].
35    ///
36    /// # Errors
37    ///
38    /// Returns an [`Error`] if processing the event failed.
39    fn next<R>(self, reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
40    where
41        R: XmlReader;
42
43    /// Force the deserializer to finish.
44    ///
45    /// # Errors
46    ///
47    /// Returns an [`Error`] if the deserializer could not finish.
48    fn finish<R>(self, reader: &R) -> Result<T, Error>
49    where
50        R: XmlReader;
51}
52
53/// Result type returned by the [`Deserializer`] trait.
54pub type DeserializerResult<'a, T, B> = Result<DeserializerOutput<'a, T, B>, Error>;
55
56/// Type that is used to bundle the output of a [`Deserializer`] operation.
57#[derive(Debug)]
58pub struct DeserializerOutput<'a, T, B> {
59    /// Contains the actual type constructed by the deserializer, once the deserializer has
60    /// finished it's construction. If this is `None`, constructing the object has
61    /// not been finished yet.
62    pub data: Option<T>,
63
64    /// Contains the deserializer after an operation on the deserializer has been executed.
65    /// If this is `None` the deserializer is finished and can not be re-used.
66    pub deserializer: Option<B>,
67
68    /// Contains the processed event if it was not consumed by the deserializer.
69    pub event: Option<Event<'a>>,
70
71    /// Whether the deserializer allows other XML elements in the current state or not.
72    /// If this is set to `true` and the `event` is not consumed, the event should
73    /// be skipped. For [`Event::Start`] this would mean to skip the whole element
74    /// until the corresponding [`Event::End`] is received.
75    pub allow_any: bool,
76}
77
78/// Trait that could be implemented by types to support deserialization from XML
79/// using the [`quick_xml`] crate.
80pub trait DeserializeSync<'de, R>: Sized
81where
82    R: XmlReaderSync<'de>,
83{
84    /// Error that is returned by the `deserialize` method.
85    type Error;
86
87    /// Deserialize the type from the passed `reader`.
88    ///
89    /// # Errors
90    ///
91    /// Will return a suitable error if the operation failed.
92    fn deserialize(reader: &mut R) -> Result<Self, Self::Error>;
93}
94
95impl<'de, R, X> DeserializeSync<'de, R> for X
96where
97    R: XmlReaderSync<'de>,
98    X: WithDeserializer,
99{
100    type Error = Error;
101
102    fn deserialize(reader: &mut R) -> Result<Self, Self::Error> {
103        DeserializeHelper::new(reader).deserialize_sync()
104    }
105}
106
107/// Trait that could be implemented by types to support asynchronous
108/// deserialization from XML using the [`quick_xml`] crate.
109#[cfg(feature = "async")]
110pub trait DeserializeAsync<'de, R>: Sized
111where
112    R: super::XmlReaderAsync<'de>,
113{
114    /// Future that is returned by the [`deserialize_async`] method.
115    type Future<'x>: std::future::Future<Output = Result<Self, Self::Error>>
116    where
117        R: 'x,
118        'de: 'x;
119
120    /// Error that is returned by the future generated by the [`deserialize_async`] method.
121    type Error;
122
123    /// Asynchronously deserializes the type from the passed `reader`.
124    fn deserialize_async<'x>(reader: &'x mut R) -> Self::Future<'x>
125    where
126        'de: 'x;
127}
128
129#[cfg(feature = "async")]
130impl<'de, R, X> DeserializeAsync<'de, R> for X
131where
132    R: super::XmlReaderAsync<'de>,
133    X: WithDeserializer,
134{
135    type Future<'x>
136        = std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self, Self::Error>> + 'x>>
137    where
138        R: 'x,
139        'de: 'x;
140
141    type Error = Error;
142
143    fn deserialize_async<'x>(reader: &'x mut R) -> Self::Future<'x>
144    where
145        'de: 'x,
146    {
147        Box::pin(async move { DeserializeHelper::new(reader).deserialize_async().await })
148    }
149}
150
151/// Trait that could be implemented by types to support deserialization from
152/// XML byte streams using the [`quick_xml`] crate.
153///
154/// This is usually implemented for simple types like numbers, strings or enums.
155pub trait DeserializeBytes: Sized {
156    /// Try to deserialize the type from bytes.
157    ///
158    /// This is used to deserialize the type from attributes or raw element
159    /// content.
160    ///
161    /// # Errors
162    ///
163    /// Returns a suitable [`Error`] if the deserialization was not successful.
164    fn deserialize_bytes<R: XmlReader>(reader: &R, bytes: &[u8]) -> Result<Self, Error>;
165}
166
167impl<X> DeserializeBytes for X
168where
169    X: FromStr,
170    X::Err: std::error::Error + Send + Sync + 'static,
171{
172    fn deserialize_bytes<R: XmlReader>(reader: &R, bytes: &[u8]) -> Result<Self, Error> {
173        let _reader = reader;
174        let s = from_utf8(bytes).map_err(Error::from)?;
175
176        X::from_str(s).map_err(Error::custom)
177    }
178}
179
180/// Implements a [`Deserializer`] for any type that implements [`DeserializeBytes`].
181#[derive(Debug)]
182pub struct ContentDeserializer<T> {
183    data: Vec<u8>,
184    marker: PhantomData<T>,
185}
186
187impl<'de, T> Deserializer<'de, T> for ContentDeserializer<T>
188where
189    T: DeserializeBytes + Debug,
190{
191    fn init<R>(reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
192    where
193        R: XmlReader,
194    {
195        match event {
196            Event::Start(_) => Ok(DeserializerOutput {
197                data: None,
198                deserializer: Some(Self {
199                    data: Vec::new(),
200                    marker: PhantomData,
201                }),
202                event: None,
203                allow_any: false,
204            }),
205            Event::Empty(_) => {
206                let data = T::deserialize_bytes(reader, &[])?;
207
208                Ok(DeserializerOutput {
209                    data: Some(data),
210                    deserializer: None,
211                    event: None,
212                    allow_any: false,
213                })
214            }
215            event => Ok(DeserializerOutput {
216                data: None,
217                deserializer: None,
218                event: Some(event),
219                allow_any: false,
220            }),
221        }
222    }
223
224    fn next<R>(mut self, reader: &R, event: Event<'de>) -> DeserializerResult<'de, T, Self>
225    where
226        R: XmlReader,
227    {
228        match event {
229            Event::Text(x) => {
230                self.data.extend_from_slice(&x.into_inner());
231
232                Ok(DeserializerOutput {
233                    data: None,
234                    deserializer: Some(self),
235                    event: None,
236                    allow_any: false,
237                })
238            }
239            Event::End(_) => {
240                let data = self.finish(reader)?;
241
242                Ok(DeserializerOutput {
243                    data: Some(data),
244                    deserializer: None,
245                    event: None,
246                    allow_any: false,
247                })
248            }
249            event => Ok(DeserializerOutput {
250                data: None,
251                deserializer: Some(self),
252                event: Some(event),
253                allow_any: false,
254            }),
255        }
256    }
257
258    fn finish<R>(self, reader: &R) -> Result<T, Error>
259    where
260        R: XmlReader,
261    {
262        T::deserialize_bytes(reader, self.data[..].trim_ascii())
263    }
264}
265
266/* DeserializeHelper */
267
268struct DeserializeHelper<'a, 'de, T, R>
269where
270    T: WithDeserializer,
271{
272    reader: &'a mut R,
273    deserializer: Option<T::Deserializer>,
274    skip_depth: Option<usize>,
275    marker: PhantomData<&'de ()>,
276}
277
278impl<'a, 'de, T, R> DeserializeHelper<'a, 'de, T, R>
279where
280    T: WithDeserializer,
281    R: XmlReader,
282{
283    fn new(reader: &'a mut R) -> Self {
284        Self {
285            reader,
286            deserializer: None,
287            skip_depth: None,
288            marker: PhantomData,
289        }
290    }
291
292    fn handle_event(&mut self, event: Event<'_>) -> Result<Option<T>, Error> {
293        let ret = match self.deserializer.take() {
294            None => T::Deserializer::init(self.reader, event),
295            Some(b) => b.next(self.reader, event),
296        };
297
298        let DeserializerOutput {
299            data,
300            deserializer,
301            event,
302            allow_any,
303        } = ret?;
304
305        self.deserializer = deserializer;
306
307        match event {
308            None
309            | Some(
310                Event::Decl(_)
311                | Event::Text(_)
312                | Event::Comment(_)
313                | Event::DocType(_)
314                | Event::PI(_),
315            ) => (),
316            Some(event) if allow_any => {
317                if matches!(event, Event::Start(_)) {
318                    self.skip_depth = Some(1);
319                }
320            }
321            Some(event) => return Err(ErrorKind::UnexpectedEvent(event.into_owned()).into()),
322        }
323
324        Ok(data)
325    }
326
327    fn handle_skip(&mut self, event: Event<'de>) -> Option<Event<'de>> {
328        let Some(skip_depth) = self.skip_depth.as_mut() else {
329            return Some(event);
330        };
331
332        match event {
333            Event::Start(_) => *skip_depth += 1,
334            Event::End(_) if *skip_depth == 1 => {
335                self.skip_depth = None;
336
337                return None;
338            }
339            Event::End(_) => *skip_depth -= 1,
340            Event::Eof => return Some(Event::Eof),
341            _ => (),
342        }
343
344        None
345    }
346}
347
348impl<'de, T, R> DeserializeHelper<'_, 'de, T, R>
349where
350    T: WithDeserializer,
351    R: XmlReaderSync<'de>,
352{
353    fn deserialize_sync(&mut self) -> Result<T, Error> {
354        loop {
355            let event = self.reader.read_event()?;
356
357            if let Some(event) = self.handle_skip(event) {
358                if let Some(data) = self
359                    .handle_event(event)
360                    .map_err(|error| self.reader.extend_error(error))?
361                {
362                    return Ok(data);
363                }
364            }
365        }
366    }
367}
368#[cfg(feature = "async")]
369impl<'de, T, R> DeserializeHelper<'_, 'de, T, R>
370where
371    T: WithDeserializer,
372    R: super::XmlReaderAsync<'de>,
373{
374    async fn deserialize_async(&mut self) -> Result<T, Error> {
375        loop {
376            let event = self.reader.read_event_async().await?;
377
378            if let Some(event) = self.handle_skip(event) {
379                if let Some(data) = self.handle_event(event)? {
380                    return Ok(data);
381                }
382            }
383        }
384    }
385}