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