xmlity/value/
mod.rs

1//! This module contains the [`XmlValue`] type, which is a type which can be serialized or deserialized as XML, and a type which other types can deserialize from/serialize into.
2//!
3//! It also contains subtypes to [`XmlValue`] including [`XmlText`], [`XmlElement`], and [`XmlAttribute`], which can be used to deserialize from/serialize into specific types of XML data.
4//!
5//! This is very useful in cases where you have arbitrary XML data, and you want to deserialize it into a type which can be used in your application, but you don't know what the type is ahead of time and want to be able to handle it generically.
6//!
7//! The types in this module can be constructed using the [`crate::xml!`] macro.
8use core::{
9    fmt::{self, Debug},
10    str,
11};
12use std::{
13    borrow::Cow,
14    collections::VecDeque,
15    fmt::Formatter,
16    iter,
17    ops::{Deref, DerefMut},
18};
19
20use crate::{
21    de,
22    ser::{self, IncludePrefix},
23    types::iterator::IteratorVisitor,
24    ExpandedName, Prefix,
25};
26
27pub mod deserialize;
28mod deserializer;
29mod serialize;
30mod serializer;
31
32/// Creates any `T` implementing [`Deserialize`] from an [`XmlValue`]
33pub fn from_value<'de, T: crate::Deserialize<'de>>(
34    value: &'de XmlValue,
35) -> Result<T, XmlValueDeserializerError> {
36    T::deserialize_seq(value)
37}
38
39/// Creates an [`XmlValue`] from any `T` implementing [`Serialize`].
40pub fn to_value<T: crate::Serialize>(input: &T) -> Result<XmlValue, XmlValueSerializerError> {
41    let mut value = XmlValue::None;
42    input.serialize(&mut value)?;
43    Ok(value)
44}
45
46/// A value that can be serialized or deserialized as XML, and a type which other types can deserialize from/serialize into.
47#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
48pub enum XmlValue {
49    /// A text node.
50    Text(XmlText),
51    /// A CDATA section.
52    CData(XmlCData),
53    /// An element.
54    Element(XmlElement),
55    /// A sequence of XML values.
56    Seq(XmlSeq<XmlValue>),
57    /// A processing instruction.
58    PI(XmlProcessingInstruction),
59    /// A declaration.
60    Decl(XmlDecl),
61    /// A comment.
62    Comment(XmlComment),
63    /// A doctype.
64    Doctype(XmlDoctype),
65    /// Nothing.
66    #[default]
67    None,
68}
69
70impl From<XmlText> for XmlValue {
71    fn from(value: XmlText) -> Self {
72        XmlValue::Text(value)
73    }
74}
75
76impl From<XmlCData> for XmlValue {
77    fn from(value: XmlCData) -> Self {
78        XmlValue::CData(value)
79    }
80}
81
82impl From<XmlElement> for XmlValue {
83    fn from(value: XmlElement) -> Self {
84        XmlValue::Element(value)
85    }
86}
87
88impl From<XmlSeq<XmlValue>> for XmlValue {
89    fn from(value: XmlSeq<XmlValue>) -> Self {
90        XmlValue::Seq(value)
91    }
92}
93
94impl From<XmlProcessingInstruction> for XmlValue {
95    fn from(value: XmlProcessingInstruction) -> Self {
96        XmlValue::PI(value)
97    }
98}
99impl From<XmlDecl> for XmlValue {
100    fn from(value: XmlDecl) -> Self {
101        XmlValue::Decl(value)
102    }
103}
104impl From<XmlComment> for XmlValue {
105    fn from(value: XmlComment) -> Self {
106        XmlValue::Comment(value)
107    }
108}
109impl From<XmlDoctype> for XmlValue {
110    fn from(value: XmlDoctype) -> Self {
111        XmlValue::Doctype(value)
112    }
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
116enum XmlValueWithoutSeq {
117    /// A text node.
118    Text(XmlText),
119    /// A CDATA section.
120    CData(XmlCData),
121    /// An element.
122    Element(XmlElement),
123    /// A processing instruction.
124    PI(XmlProcessingInstruction),
125    /// A declaration.
126    Decl(XmlDecl),
127    /// A comment.
128    Comment(XmlComment),
129    /// A doctype.
130    Doctype(XmlDoctype),
131    /// Nothing.
132    #[default]
133    None,
134}
135
136impl From<XmlValueWithoutSeq> for XmlValue {
137    fn from(value: XmlValueWithoutSeq) -> Self {
138        match value {
139            XmlValueWithoutSeq::Text(xml_text) => XmlValue::Text(xml_text),
140            XmlValueWithoutSeq::CData(xml_cdata) => XmlValue::CData(xml_cdata),
141            XmlValueWithoutSeq::Element(xml_element) => XmlValue::Element(xml_element),
142            XmlValueWithoutSeq::PI(xml_processing_instruction) => {
143                XmlValue::PI(xml_processing_instruction)
144            }
145            XmlValueWithoutSeq::Decl(xml_decl) => XmlValue::Decl(xml_decl),
146            XmlValueWithoutSeq::Comment(xml_comment) => XmlValue::Comment(xml_comment),
147            XmlValueWithoutSeq::Doctype(xml_doctype) => XmlValue::Doctype(xml_doctype),
148            XmlValueWithoutSeq::None => XmlValue::None,
149        }
150    }
151}
152
153/// A text node in an XML document.
154#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
155#[non_exhaustive]
156pub struct XmlText(pub Vec<u8>);
157
158impl XmlText {
159    /// Creates a new [`XmlText`] from a string.
160    pub fn new<T: AsRef<str>>(text: T) -> Self {
161        Self(text.as_ref().as_bytes().to_vec())
162    }
163}
164
165impl Debug for XmlText {
166    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
167        f.debug_tuple("XmlText")
168            .field(&String::from_utf8_lossy(&self.0))
169            .finish()
170    }
171}
172
173impl From<String> for XmlText {
174    fn from(value: String) -> Self {
175        Self(value.into_bytes())
176    }
177}
178
179impl From<&str> for XmlText {
180    fn from(value: &str) -> Self {
181        Self(value.to_owned().into_bytes())
182    }
183}
184
185/// CDATA section.
186#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
187pub struct XmlCData(pub Vec<u8>);
188
189impl XmlCData {
190    /// Creates a new [CDATA section](`XmlCData`).
191    pub fn new<T: Into<Vec<u8>>>(text: T) -> Self {
192        Self(text.into())
193    }
194}
195
196/// An XML child node.
197#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
198pub enum XmlChild {
199    /// A text node.
200    Text(XmlText),
201    /// A CDATA node.
202    CData(XmlCData),
203    /// An element node.
204    Element(XmlElement),
205    /// A processing instruction node.
206    PI(XmlProcessingInstruction),
207    /// A comment node.
208    Comment(XmlComment),
209    /// Nothing.
210    #[default]
211    None,
212}
213
214impl From<XmlText> for XmlChild {
215    fn from(value: XmlText) -> Self {
216        XmlChild::Text(value)
217    }
218}
219
220impl From<XmlCData> for XmlChild {
221    fn from(value: XmlCData) -> Self {
222        XmlChild::CData(value)
223    }
224}
225
226impl From<XmlElement> for XmlChild {
227    fn from(value: XmlElement) -> Self {
228        XmlChild::Element(value)
229    }
230}
231
232impl From<XmlProcessingInstruction> for XmlChild {
233    fn from(value: XmlProcessingInstruction) -> Self {
234        XmlChild::PI(value)
235    }
236}
237
238impl From<XmlComment> for XmlChild {
239    fn from(value: XmlComment) -> Self {
240        XmlChild::Comment(value)
241    }
242}
243
244/// An XML element.
245#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
246#[non_exhaustive]
247pub struct XmlElement {
248    /// The name of the element.
249    pub name: ExpandedName<'static>,
250    /// The attributes of the element.
251    pub attributes: VecDeque<XmlAttribute>,
252    /// The children of the element.
253    pub children: XmlSeq<XmlChild>,
254    /// Whether to enforce the prefix of the element.
255    pub enforce_prefix: IncludePrefix,
256    /// The preferred prefix of the element.
257    pub preferred_prefix: Option<Prefix<'static>>,
258}
259
260impl XmlElement {
261    /// Creates a new XML element.
262    pub fn new<T: Into<ExpandedName<'static>>>(name: T) -> Self {
263        Self {
264            name: name.into(),
265            attributes: VecDeque::new(),
266            children: XmlSeq::new(),
267            enforce_prefix: IncludePrefix::default(),
268            preferred_prefix: None,
269        }
270    }
271
272    /// Adds an attribute to the element.
273    pub fn with_attribute<T: Into<XmlAttribute>>(mut self, attribute: T) -> Self {
274        self.attributes.push_back(attribute.into());
275        self
276    }
277
278    /// Adds multiple attributes to the element.
279    pub fn with_attributes<U: Into<XmlAttribute>, T: IntoIterator<Item = U>>(
280        mut self,
281        attributes: T,
282    ) -> Self {
283        self.attributes
284            .extend(attributes.into_iter().map(Into::into));
285        self
286    }
287
288    /// Adds a child to the element.
289    pub fn with_child<T: Into<XmlChild>>(mut self, child: T) -> Self {
290        self.children.values.push_back(child.into());
291        self
292    }
293
294    /// Adds multiple children to the element.
295    pub fn with_children<U: Into<XmlChild>, T: IntoIterator<Item = U>>(
296        mut self,
297        children: T,
298    ) -> Self {
299        self.children
300            .values
301            .extend(children.into_iter().map(Into::into));
302        self
303    }
304}
305
306/// An XML attribute.
307#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
308#[non_exhaustive]
309pub struct XmlAttribute {
310    /// The name of the attribute.
311    pub name: ExpandedName<'static>,
312    /// The value of the attribute.
313    pub value: XmlText,
314}
315
316impl XmlAttribute {
317    /// Creates a new XML attribute.
318    pub fn new<T: Into<ExpandedName<'static>>, U: Into<XmlText>>(name: T, value: U) -> Self {
319        Self {
320            name: name.into(),
321            value: value.into(),
322        }
323    }
324}
325
326/// A sequence of XML elements.
327#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
328#[non_exhaustive]
329pub struct XmlSeq<T> {
330    values: VecDeque<T>,
331}
332
333impl<T> IntoIterator for XmlSeq<T> {
334    type Item = T;
335    type IntoIter = std::collections::vec_deque::IntoIter<T>;
336    fn into_iter(self) -> Self::IntoIter {
337        self.values.into_iter()
338    }
339}
340
341impl<T> FromIterator<T> for XmlSeq<T> {
342    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
343        Self {
344            values: iter.into_iter().collect(),
345        }
346    }
347}
348
349impl<T> From<VecDeque<T>> for XmlSeq<T> {
350    fn from(value: VecDeque<T>) -> Self {
351        Self::from_vec_deque(value)
352    }
353}
354
355impl<T> XmlSeq<T> {
356    /// Creates a new empty sequence.
357    pub fn new() -> Self {
358        Self::from_vec_deque(VecDeque::new())
359    }
360
361    /// Creates a new sequence from a [`VecDeque<T>`].
362    pub fn from_vec_deque(values: VecDeque<T>) -> Self {
363        Self { values }
364    }
365
366    /// Gets the inner [`VecDeque<T>`] of the sequence.
367    pub fn into_inner(self) -> VecDeque<T> {
368        self.values
369    }
370}
371
372impl Deref for XmlSeq<XmlValue> {
373    type Target = VecDeque<XmlValue>;
374
375    fn deref(&self) -> &Self::Target {
376        &self.values
377    }
378}
379
380impl DerefMut for XmlSeq<XmlValue> {
381    fn deref_mut(&mut self) -> &mut Self::Target {
382        &mut self.values
383    }
384}
385
386impl<T> Default for XmlSeq<T> {
387    fn default() -> Self {
388        Self::new()
389    }
390}
391
392/// A processing instruction.
393#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
394#[non_exhaustive]
395pub struct XmlProcessingInstruction {
396    target: Vec<u8>,
397    content: Vec<u8>,
398}
399
400impl XmlProcessingInstruction {
401    /// Creates a new processing instruction.
402    pub fn new<T: Into<Vec<u8>>, U: Into<Vec<u8>>>(target: T, content: U) -> Self {
403        Self {
404            target: target.into(),
405            content: content.into(),
406        }
407    }
408}
409
410/// Represents an XML declaration.
411#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
412#[non_exhaustive]
413pub struct XmlDecl {
414    /// The version of the XML document.
415    pub version: String,
416    /// The encoding of the XML document.
417    pub encoding: Option<String>,
418    /// The standalone status of the XML document.
419    pub standalone: Option<String>,
420}
421
422impl XmlDecl {
423    /// Creates a new XML declaration.
424    pub fn new<T: AsRef<str>>(version: T, encoding: Option<T>, standalone: Option<T>) -> Self {
425        Self {
426            version: version.as_ref().to_string(),
427            encoding: encoding.map(|e| e.as_ref().to_string()),
428            standalone: standalone.map(|s| s.as_ref().to_string()),
429        }
430    }
431}
432
433/// XML Comment
434#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
435#[non_exhaustive]
436pub struct XmlComment(pub Vec<u8>);
437
438impl XmlComment {
439    /// Creates a new XML comment.
440    pub fn new<T: Into<Vec<u8>>>(comment: T) -> Self {
441        Self(comment.into())
442    }
443}
444
445/// A doctype declaration.
446#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
447#[non_exhaustive]
448pub struct XmlDoctype(pub Vec<u8>);
449
450impl XmlDoctype {
451    /// Creates a new doctype declaration.
452    pub fn new<T: Into<Vec<u8>>>(value: T) -> Self {
453        Self(value.into())
454    }
455}
456
457/// Error type for serializing XML values.
458#[derive(Debug, thiserror::Error)]
459pub enum XmlValueSerializerError {
460    /// Error for when a custom error occurs during serialization.
461    #[error("Custom error: {0}")]
462    Custom(String),
463    /// Error for when an unexpected serialization occurs.
464    #[error("Unexpected serialization: {0}")]
465    UnexpectedSerialize(ser::Unexpected),
466}
467
468impl ser::Error for XmlValueSerializerError {
469    fn unexpected_serialize(unexpected: ser::Unexpected) -> Self {
470        Self::UnexpectedSerialize(unexpected)
471    }
472
473    fn custom<T>(msg: T) -> Self
474    where
475        T: std::fmt::Display,
476    {
477        Self::Custom(msg.to_string())
478    }
479}
480
481/// Error type for deserializing XML values.
482#[derive(Debug, thiserror::Error)]
483pub enum XmlValueDeserializerError {
484    /// Error for when an unexpected visit occurs during deserialization.
485    #[error("Unexpected visit: {0}")]
486    UnexpectedVisit(crate::de::Unexpected),
487    /// Error for when a custom error occurs during deserialization.
488    #[error("Custom error: {0}")]
489    Custom(String),
490    /// Error for when a name is expected to be a certain value, but it is not.
491    #[error("Wrong name: {actual:?}, expected: {expected:?}")]
492    WrongName {
493        /// The actual name that was encountered.
494        actual: Box<ExpandedName<'static>>,
495        /// The expected name.
496        expected: Box<ExpandedName<'static>>,
497    },
498    /// Error for when a field is missing.
499    #[error("Missing field: {0}")]
500    MissingField(String),
501    /// Error for when a child cannot be identified, and ignoring it is not allowed.
502    #[error("Unknown child")]
503    UnknownChild,
504    /// Error for when a string is invalid for the type.
505    #[error("Invalid string")]
506    InvalidString,
507    /// Error for when a type has no possible variants to deserialize into.
508    #[error("No possible variant")]
509    NoPossibleVariant {
510        /// The name of the type that has no possible variants.
511        ident: String,
512    },
513    /// Error for when a type is missing data that is required to deserialize it.
514    #[error("Missing data")]
515    MissingData,
516}
517
518impl de::Error for XmlValueDeserializerError {
519    fn custom<T>(msg: T) -> Self
520    where
521        T: std::fmt::Display,
522    {
523        Self::Custom(msg.to_string())
524    }
525
526    fn wrong_name(name: &ExpandedName<'_>, expected: &ExpandedName<'_>) -> Self {
527        Self::WrongName {
528            actual: Box::new(name.clone().into_owned()),
529            expected: Box::new(expected.clone().into_owned()),
530        }
531    }
532
533    fn unexpected_visit<T>(unexpected: de::Unexpected, _expected: &T) -> Self {
534        Self::UnexpectedVisit(unexpected)
535    }
536
537    fn missing_field(field: &str) -> Self {
538        Self::MissingField(field.to_string())
539    }
540
541    fn no_possible_variant(ident: &str) -> Self {
542        Self::NoPossibleVariant {
543            ident: ident.to_string(),
544        }
545    }
546
547    fn missing_data() -> Self {
548        Self::MissingData
549    }
550
551    fn unknown_child() -> Self {
552        Self::UnknownChild
553    }
554
555    fn invalid_string() -> Self {
556        Self::InvalidString
557    }
558}