xmlity/
de.rs

1//! This module contains the [`Deserialize`], [`Deserializer`] and [`DeserializationGroup`] traits and associated types.
2
3use std::{
4    borrow::Cow,
5    error::Error as StdError,
6    fmt::{self, Debug, Display},
7};
8
9use crate::{ExpandedName, Prefix, XmlNamespace};
10
11/// A trait for errors that can be returned by a [`Deserializer`].
12pub trait Error: Sized + StdError {
13    /// Error for when a custom error occurs during deserialization.
14    fn custom<T>(msg: T) -> Self
15    where
16        T: Display;
17
18    /// Error for when a name is expected to be a certain value, but it is not.
19    fn wrong_name(name: &ExpandedName<'_>, expected: &ExpandedName<'_>) -> Self;
20
21    /// Error for when a type is expected to be a certain type, but it is not.
22    fn unexpected_visit<T>(unexpected: Unexpected, expected: &T) -> Self;
23
24    /// Error for when a field is missing.
25    fn missing_field(field: &str) -> Self;
26
27    /// Error for when a type has no possible variants to deserialize into.
28    fn no_possible_variant(ident: &str) -> Self;
29
30    /// Error for when a type is missing data that is required to deserialize it.
31    fn missing_data() -> Self;
32
33    /// Error for when a child cannot be identified, and ignoring it is not allowed.
34    fn unknown_child() -> Self;
35
36    /// Error for when a string is invalid for the type.
37    fn invalid_string() -> Self;
38}
39
40/// An enum representing the unexpected type of data that was encountered.
41#[derive(Debug, thiserror::Error)]
42#[non_exhaustive]
43pub enum Unexpected {
44    /// A text node.
45    #[error("text")]
46    Text,
47    /// A CDATA section.
48    #[error("cdata")]
49    CData,
50    /// A sequence of XML values.
51    #[error("sequence")]
52    Seq,
53    /// An element start.
54    #[error("element start")]
55    ElementStart,
56    /// An element end.
57    #[error("element end")]
58    ElementEnd,
59    /// An attribute.
60    #[error("attribute")]
61    Attribute,
62    /// A comment.
63    #[error("comment")]
64    Comment,
65    /// A declaration.
66    #[error("declaration")]
67    Decl,
68    /// A processing instruction.
69    #[error("processing instruction")]
70    PI,
71    /// A doctype.
72    #[error("doctype")]
73    DocType,
74    /// End of file.
75    #[error("eof")]
76    Eof,
77    /// Nothing.
78    #[error("none")]
79    None,
80}
81
82/// Trait that lets you access the namespaces declared on an XML node.
83pub trait DeserializeContext {
84    /// Get the default namespace.
85    fn default_namespace(&self) -> Option<XmlNamespace<'_>>;
86
87    /// Resolve a prefix to a namespace.
88    fn resolve_prefix(&self, prefix: Prefix<'_>) -> Option<XmlNamespace<'_>>;
89
90    /// Get a reference to external data associated with this context.
91    fn external_data<T>(&self) -> Option<&T>
92    where
93        T: core::any::Any;
94}
95
96/// Trait that lets you access the attributes of an XML node.
97pub trait AttributesAccess<'de> {
98    /// The error type for this attributes access.
99    type Error: Error;
100    /// The type of the sub access for this attributes access returned by [`AttributesAccess::sub_access`].
101    type SubAccess<'a>: AttributesAccess<'de, Error = Self::Error> + 'a
102    where
103        Self: 'a;
104
105    /// Get the next attribute.
106    fn next_attribute<T>(&mut self) -> Result<Option<T>, Self::Error>
107    where
108        T: Deserialize<'de>;
109
110    /// Get a sub access to the attributes.
111    fn sub_access(&mut self) -> Result<Self::SubAccess<'_>, Self::Error>;
112}
113
114impl<'de, T: AttributesAccess<'de>> AttributesAccess<'de> for &mut T {
115    type Error = T::Error;
116    type SubAccess<'a>
117        = T::SubAccess<'a>
118    where
119        Self: 'a;
120
121    fn next_attribute<D>(&mut self) -> Result<Option<D>, Self::Error>
122    where
123        D: Deserialize<'de>,
124    {
125        (*self).next_attribute()
126    }
127
128    fn sub_access(&mut self) -> Result<Self::SubAccess<'_>, Self::Error> {
129        (*self).sub_access()
130    }
131}
132
133/// A trait for accessing properties of an element. This is the first stage of element deserialization, where the element's name and attributes are accessed. The second stage is accessing the element's children, which is done by calling [`ElementAccess::children`].
134pub trait ElementAccess<'de>: AttributesAccess<'de> {
135    /// The type of the children accessor returned by [`ElementAccess::children`].
136    type ChildrenAccess: SeqAccess<'de, Error = Self::Error>;
137
138    /// The type of the namespace context returned by [`ElementAccess::context`].
139    type DeserializeContext<'a>: DeserializeContext + 'a
140    where
141        Self: 'a;
142
143    /// Returns the name of the element.
144    fn name(&self) -> ExpandedName<'_>;
145
146    /// Returns an accessor for the element's children.
147    fn children(self) -> Result<Self::ChildrenAccess, Self::Error>;
148
149    /// Returns the namespace context for this attribute.
150    fn context(&self) -> Self::DeserializeContext<'_>;
151}
152
153/// An extension trait for [`ElementAccess`] that provides additional methods.
154pub trait ElementAccessExt<'de>: ElementAccess<'de> {
155    /// Ensures that the element has the given name. If it does not, returns an error.
156    fn ensure_name<E: Error>(&self, name: &ExpandedName) -> Result<(), E>;
157}
158
159impl<'de, T: ElementAccess<'de>> ElementAccessExt<'de> for T {
160    fn ensure_name<E: Error>(&self, name: &ExpandedName) -> Result<(), E> {
161        if self.name() == *name {
162            Ok(())
163        } else {
164            Err(Error::wrong_name(&self.name(), name))
165        }
166    }
167}
168
169/// A trait for accessing properties of an attribute.
170pub trait AttributeAccess<'de> {
171    /// The error type for this attribute access.
172    type Error: Error;
173
174    /// Returns the name of the attribute.
175    fn name(&self) -> ExpandedName<'_>;
176
177    /// Deserializes the value of the attribute.
178    fn value<T>(self) -> Result<T, Self::Error>
179    where
180        T: Deserialize<'de>;
181}
182
183/// An extension trait for [`AttributeAccess`] that provides additional methods.
184pub trait AttributeAccessExt<'de>: AttributeAccess<'de> {
185    /// Ensures that the attribute has the given name.
186    fn ensure_name<E: Error>(&self, name: &ExpandedName) -> Result<(), E>;
187}
188
189impl<'de, T: AttributeAccess<'de>> AttributeAccessExt<'de> for T {
190    fn ensure_name<E: Error>(&self, name: &ExpandedName) -> Result<(), E> {
191        if self.name() == *name {
192            Ok(())
193        } else {
194            Err(Error::wrong_name(&self.name(), name))
195        }
196    }
197}
198
199/// A trait for accessing a sequence of nodes, which could include a mix of elements and text nodes.
200pub trait SeqAccess<'de> {
201    /// The error type for this sequence access.
202    type Error: Error;
203
204    /// The type of the sub-access for this sequence access returned by [`SeqAccess::sub_access`].
205    type SubAccess<'g>: SeqAccess<'de, Error = Self::Error>
206    where
207        Self: 'g;
208
209    /// Gets the next element in the sequence.
210    fn next_element<T>(&mut self) -> Result<Option<T>, Self::Error>
211    where
212        T: Deserialize<'de>;
213
214    /// Gets the next element by trying to deserialize it as a sequence.
215    fn next_element_seq<T>(&mut self) -> Result<Option<T>, Self::Error>
216    where
217        T: Deserialize<'de>;
218
219    /// Gets the sub-access for the current sequence access.
220    fn sub_access(&mut self) -> Result<Self::SubAccess<'_>, Self::Error>;
221}
222
223impl<'de, T: SeqAccess<'de>> SeqAccess<'de> for &mut T {
224    type Error = T::Error;
225    type SubAccess<'g>
226        = T::SubAccess<'g>
227    where
228        Self: 'g;
229
230    fn next_element<U>(&mut self) -> Result<Option<U>, Self::Error>
231    where
232        U: Deserialize<'de>,
233    {
234        (*self).next_element()
235    }
236
237    fn next_element_seq<U>(&mut self) -> Result<Option<U>, Self::Error>
238    where
239        U: Deserialize<'de>,
240    {
241        (*self).next_element_seq()
242    }
243
244    fn sub_access(&mut self) -> Result<Self::SubAccess<'_>, Self::Error> {
245        (*self).sub_access()
246    }
247}
248
249/// Trait for XML text.
250pub trait XmlText<'de> {
251    /// The type of the namespace context returned by [`XmlText::context`].
252    type DeserializeContext<'a>: DeserializeContext + 'a
253    where
254        Self: 'a;
255
256    /// Returns the owned byte representation of the text.
257    fn into_bytes(self) -> Cow<'de, [u8]>;
258
259    /// Returns the byte representation of the text.
260    fn as_bytes(&self) -> &[u8];
261
262    /// Returns the owned string representation of the text.
263    fn into_string(self) -> Cow<'de, str>;
264
265    /// Returns the string representation of the text.
266    fn as_str(&self) -> &str;
267
268    /// Returns the namespace context of the text.
269    fn context(&self) -> Self::DeserializeContext<'_>;
270}
271
272/// Trait for XML CDATA.
273pub trait XmlCData<'de> {
274    /// The type of the namespace context returned by [`XmlCData::context`].
275    type DeserializeContext<'a>: DeserializeContext + 'a
276    where
277        Self: 'a;
278
279    /// Returns the owned byte representation of the CDATA.
280    fn into_bytes(self) -> Cow<'de, [u8]>;
281
282    /// Returns the byte representation of the CDATA.
283    fn as_bytes(&self) -> &[u8];
284
285    /// Returns the owned string representation of the CDATA.
286    fn into_string(self) -> Cow<'de, str>;
287
288    /// Returns the string representation of the CDATA.
289    fn as_str(&self) -> &str;
290
291    /// Returns the namespace context of the CDATA.
292    fn context(&self) -> Self::DeserializeContext<'_>;
293}
294
295/// Trait for XML processing instructions.
296pub trait XmlProcessingInstruction {
297    /// The type of the namespace context returned by [`XmlProcessingInstruction::context`].
298    type DeserializeContext<'a>: DeserializeContext + 'a
299    where
300        Self: 'a;
301
302    /// Returns the target of the PI.
303    fn target(&self) -> &[u8];
304
305    /// Returns the content of the PI.
306    fn content(&self) -> &[u8];
307
308    /// Returns the namespace context of the PI.
309    fn context(&self) -> Self::DeserializeContext<'_>;
310}
311
312/// Trait for XML declarations.
313pub trait XmlDeclaration {
314    /// The type of the namespace context returned by [`XmlDeclaration::context`].
315    type DeserializeContext<'a>: DeserializeContext + 'a
316    where
317        Self: 'a;
318
319    /// Returns the version value of the declaration.
320    fn version(&self) -> &[u8];
321
322    /// Returns the encoding value of the declaration.
323    fn encoding(&self) -> Option<&[u8]>;
324
325    /// Returns the standalone value of the declaration.
326    fn standalone(&self) -> Option<&[u8]>;
327
328    /// Returns the namespace context of the declaration.
329    fn context(&self) -> Self::DeserializeContext<'_>;
330}
331
332/// Trait for XML comments.
333pub trait XmlComment<'de> {
334    /// The type of the namespace context returned by [`XmlComment::context`].
335    type DeserializeContext<'a>: DeserializeContext + 'a
336    where
337        Self: 'a;
338
339    /// Returns the owned byte representation of the comment.
340    fn into_bytes(self) -> Cow<'de, [u8]>;
341
342    /// Returns the byte representation of the comment.
343    fn as_bytes(&self) -> &[u8];
344
345    /// Returns the namespace context of the comment.
346    fn context(&self) -> Self::DeserializeContext<'_>;
347}
348
349/// Trait for XML doctypes.
350pub trait XmlDoctype<'de> {
351    /// The type of the namespace context returned by [`XmlDoctype::context`].
352    type DeserializeContext<'a>: DeserializeContext + 'a
353    where
354        Self: 'a;
355
356    /// Returns the owned byte representation of the doctype.
357    fn into_bytes(self) -> Cow<'de, [u8]>;
358
359    /// Returns the byte representation of the doctype.
360    fn as_bytes(&self) -> &[u8];
361
362    /// Returns the namespace context of the doctype.
363    fn context(&self) -> Self::DeserializeContext<'_>;
364}
365
366/// Visitor trait that lets you define how to handle different types of XML nodes.
367pub trait Visitor<'de>: Sized {
368    /// The type of value that this visitor will produce.
369    type Value: Deserialize<'de>;
370
371    /// Returns a description of the type that this visitor expects.
372    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
373
374    /// Visits an XML text node.
375    fn visit_text<E, V>(self, value: V) -> Result<Self::Value, E>
376    where
377        E: Error,
378        V: XmlText<'de>,
379    {
380        let _ = value;
381        Err(Error::unexpected_visit(Unexpected::Text, &self))
382    }
383
384    /// Visits an XML CDATA node.
385    fn visit_cdata<E, V>(self, value: V) -> Result<Self::Value, E>
386    where
387        E: Error,
388        V: XmlCData<'de>,
389    {
390        let _ = value;
391        Err(Error::unexpected_visit(Unexpected::CData, &self))
392    }
393
394    /// Visits an XML element.
395    fn visit_element<A>(self, element: A) -> Result<Self::Value, A::Error>
396    where
397        A: ElementAccess<'de>,
398    {
399        let _ = element;
400        Err(Error::unexpected_visit(Unexpected::ElementStart, &self))
401    }
402
403    /// Visits an XML attribute.
404    fn visit_attribute<A>(self, attribute: A) -> Result<Self::Value, A::Error>
405    where
406        A: AttributeAccess<'de>,
407    {
408        let _ = attribute;
409        Err(Error::unexpected_visit(Unexpected::Attribute, &self))
410    }
411
412    /// Visits a sequence of values.
413    fn visit_seq<S>(self, mut sequence: S) -> Result<Self::Value, S::Error>
414    where
415        S: SeqAccess<'de>,
416    {
417        sequence
418            .next_element::<Self::Value>()?
419            .ok_or_else(Error::missing_data)
420    }
421
422    /// Visits an XML PI node.
423    fn visit_pi<E, V>(self, pi: V) -> Result<Self::Value, E>
424    where
425        E: Error,
426        V: XmlProcessingInstruction,
427    {
428        let _ = pi;
429        Err(Error::unexpected_visit(Unexpected::PI, &self))
430    }
431
432    /// Visits a declaration.
433    fn visit_decl<E, V>(self, declaration: V) -> Result<Self::Value, E>
434    where
435        E: Error,
436        V: XmlDeclaration,
437    {
438        let _ = declaration;
439        Err(Error::unexpected_visit(Unexpected::Decl, &self))
440    }
441
442    /// Visits a comment.
443    fn visit_comment<E, V>(self, comment: V) -> Result<Self::Value, E>
444    where
445        E: Error,
446        V: XmlComment<'de>,
447    {
448        let _ = comment;
449        Err(Error::unexpected_visit(Unexpected::Comment, &self))
450    }
451
452    /// Visits a doctype declaration.
453    fn visit_doctype<E, V>(self, doctype: V) -> Result<Self::Value, E>
454    where
455        E: Error,
456        V: XmlDoctype<'de>,
457    {
458        let _ = doctype;
459        Err(Error::unexpected_visit(Unexpected::DocType, &self))
460    }
461
462    /// Visits nothing. This is used when a value is not present.
463    fn visit_none<E>(self) -> Result<Self::Value, E>
464    where
465        E: Error,
466    {
467        Err(Error::unexpected_visit(Unexpected::None, &self))
468    }
469}
470
471/// A type that can be used to deserialize XML documents.
472pub trait Deserializer<'de>: Sized {
473    /// The error type that can be returned from the deserializer.
474    type Error: Error;
475
476    /// Deserializes a value from the deserializer.
477    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
478    where
479        V: Visitor<'de>;
480
481    /// Deserializes a value from the deserializer, but tries to do it from a sequence of values.
482    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
483    where
484        V: Visitor<'de>;
485}
486
487/// A type that can be deserialized from a deserializer. This type has two methods: [`Deserialize::deserialize`] and [`Deserialize::deserialize_seq`]. The latter is used in cases where types can be constructed from multiple nodes, such as constructing a [`std::vec::Vec`] from multiple elements, or a [`std::string::String`] from multiple text nodes that are concatenated together.
488///
489/// To see the documentation for the derive macro, see [`xmlity_derive::Deserialize`].
490pub trait Deserialize<'de>: Sized {
491    /// Deserializes a value from a deserializer.
492    fn deserialize<D: Deserializer<'de>>(reader: D) -> Result<Self, D::Error>;
493
494    /// Deserializes a value from a deserializer, but tries to do it from a sequence of values.
495    fn deserialize_seq<D: Deserializer<'de>>(reader: D) -> Result<Self, D::Error> {
496        Self::deserialize(reader)
497    }
498}
499
500/// A utility type for easier use of [`Deserialize`] trait without needing to specify the lifetime.
501pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
502impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
503
504/// A group of types that can be deserialized together. While this is being built, the type of a [`DeserializationGroup`] is the [`DeserializationGroup::Builder`] type.
505///
506/// To see the documentation for the derive macro, see [`xmlity_derive::DeserializationGroup`].
507pub trait DeserializationGroup<'de> {
508    /// The type of the builder for this deserialization group returned by [`DeserializationGroup::builder`].
509    type Builder: DeserializationGroupBuilder<'de, Value = Self>;
510
511    /// Initializes the deserialization group builder.
512    fn builder() -> Self::Builder;
513}
514
515/// A builder for a deserialization group. When completed (through [`DeserializationGroupBuilder::finish`]), the builder is converted into the deserialization group type that initated the builder.
516pub trait DeserializationGroupBuilder<'de>: Sized {
517    /// The type of the deserialization group that this builder builds when finished through [`DeserializationGroupBuilder::finish`].
518    type Value;
519
520    /// Returns true if the deserializer made progress
521    fn contribute_attributes<D: AttributesAccess<'de>>(
522        &mut self,
523        access: D,
524    ) -> Result<bool, D::Error> {
525        let _ = access;
526
527        Ok(false)
528    }
529
530    /// This hint function is used to avoid calling [`DeserializationGroupBuilder::contribute_attributes`] unnecessarily.
531    fn attributes_done(&self) -> bool {
532        false
533    }
534
535    /// Returns true if the deserializer made progress
536    fn contribute_elements<D: SeqAccess<'de>>(&mut self, access: D) -> Result<bool, D::Error> {
537        let _ = access;
538
539        Ok(false)
540    }
541
542    /// This hint function is used to avoid calling [`DeserializationGroupBuilder::contribute_elements`] unnecessarily.
543    fn elements_done(&self) -> bool {
544        false
545    }
546
547    /// This function is called after all attributes and elements have been contributed.
548    fn finish<E: Error>(self) -> Result<Self::Value, E>;
549}