xmlity/types/
utils.rs

1//! This module contains some utility types and visitors that can be reused.
2
3use core::fmt::{self, Debug};
4use std::{borrow::Cow, marker::PhantomData, str::FromStr};
5
6use crate::{
7    de::{
8        self, Visitor, XmlCData, XmlComment, XmlDeclaration, XmlDoctype, XmlProcessingInstruction,
9        XmlText,
10    },
11    value::{self, XmlDecl},
12    Deserialize, Deserializer, Serialize, Serializer,
13};
14
15/// This utility type represents an XML root document.
16#[derive(Debug, PartialEq, Eq, Clone)]
17pub struct XmlRoot<T> {
18    /// The declaration of the XML document.
19    pub decl: Option<XmlDecl>,
20    /// The top-level elements of the XML document.
21    pub elements: Vec<XmlRootTop<T>>,
22}
23
24impl<T: Serialize> crate::Serialize for XmlRoot<T> {
25    fn serialize<S>(
26        &self,
27        serializer: S,
28    ) -> Result<<S as crate::Serializer>::Ok, <S as crate::Serializer>::Error>
29    where
30        S: crate::Serializer,
31    {
32        let mut __elements = crate::Serializer::serialize_seq(serializer)?;
33        crate::ser::SerializeSeq::serialize_element(&mut __elements, &self.decl)?;
34        crate::ser::SerializeSeq::serialize_element(&mut __elements, &self.elements)?;
35        crate::ser::SerializeSeq::end(__elements)
36    }
37}
38
39impl<'__deserialize, T: Deserialize<'__deserialize> + Debug> Deserialize<'__deserialize>
40    for XmlRoot<T>
41{
42    fn deserialize<D>(__deserializer: D) -> Result<Self, <D as Deserializer<'__deserialize>>::Error>
43    where
44        D: Deserializer<'__deserialize>,
45    {
46        struct __XmlRootVisitor<'__visitor, T> {
47            marker: ::core::marker::PhantomData<XmlRoot<T>>,
48            lifetime: ::core::marker::PhantomData<&'__visitor ()>,
49        }
50        impl<'__visitor, T: Deserialize<'__visitor> + Debug> crate::de::Visitor<'__visitor>
51            for __XmlRootVisitor<'__visitor, T>
52        {
53            type Value = XmlRoot<T>;
54            fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
55                ::core::fmt::Formatter::write_str(formatter, "struct XmlRoot")
56            }
57
58            fn visit_seq<S>(self, mut sequence: S) -> Result<Self::Value, S::Error>
59            where
60                S: de::SeqAccess<'__visitor>,
61            {
62                Ok(Self::Value {
63                    decl: crate::de::SeqAccess::next_element::<XmlDecl>(&mut sequence)
64                        .ok()
65                        .flatten(),
66                    elements: crate::de::SeqAccess::next_element_seq::<Vec<XmlRootTop<T>>>(
67                        &mut sequence,
68                    )?
69                    .unwrap_or_default(),
70                })
71            }
72        }
73        Deserializer::deserialize_seq(
74            __deserializer,
75            __XmlRootVisitor {
76                lifetime: ::core::marker::PhantomData,
77                marker: ::core::marker::PhantomData,
78            },
79        )
80    }
81}
82
83/// A top-level element of the XML document.
84#[derive(Debug, PartialEq, Eq, Clone)]
85pub enum XmlRootTop<T> {
86    /// An element of the XML document.
87    Value(T),
88    /// A comment in the XML document.
89    Comment(value::XmlComment),
90    /// A processing instructions in the XML document.
91    PI(value::XmlProcessingInstruction),
92    /// A doctype declarations in the XML document.
93    Doctype(value::XmlDoctype),
94}
95
96impl<T> From<value::XmlComment> for XmlRootTop<T> {
97    fn from(value: value::XmlComment) -> Self {
98        XmlRootTop::Comment(value)
99    }
100}
101
102impl<T> From<value::XmlProcessingInstruction> for XmlRootTop<T> {
103    fn from(value: value::XmlProcessingInstruction) -> Self {
104        XmlRootTop::PI(value)
105    }
106}
107
108impl<T> From<value::XmlDoctype> for XmlRootTop<T> {
109    fn from(value: value::XmlDoctype) -> Self {
110        XmlRootTop::Doctype(value)
111    }
112}
113
114impl<T: Serialize> crate::Serialize for XmlRootTop<T> {
115    fn serialize<S>(
116        &self,
117        serializer: S,
118    ) -> Result<<S as crate::Serializer>::Ok, <S as crate::Serializer>::Error>
119    where
120        S: crate::Serializer,
121    {
122        match self {
123            XmlRootTop::Value(__v) => crate::Serialize::serialize(&__v, serializer),
124            XmlRootTop::Comment(__v) => crate::Serialize::serialize(&__v, serializer),
125            XmlRootTop::PI(__v) => crate::Serialize::serialize(&__v, serializer),
126            XmlRootTop::Doctype(__v) => crate::Serialize::serialize(&__v, serializer),
127        }
128    }
129}
130
131impl<'__deserialize, T: Deserialize<'__deserialize>> Deserialize<'__deserialize> for XmlRootTop<T> {
132    fn deserialize<D>(__deserializer: D) -> Result<Self, <D as Deserializer<'__deserialize>>::Error>
133    where
134        D: Deserializer<'__deserialize>,
135    {
136        struct __XmlRootTopVisitor<'__visitor, T> {
137            marker: ::core::marker::PhantomData<XmlRootTop<T>>,
138            lifetime: ::core::marker::PhantomData<&'__visitor ()>,
139        }
140        impl<'__visitor, T: Deserialize<'__visitor>> crate::de::Visitor<'__visitor>
141            for __XmlRootTopVisitor<'__visitor, T>
142        {
143            type Value = XmlRootTop<T>;
144            fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
145                ::core::fmt::Formatter::write_str(formatter, "enum XmlRootTop")
146            }
147            fn visit_seq<S>(
148                self,
149                mut __sequence: S,
150            ) -> Result<Self::Value, <S as crate::de::SeqAccess<'__visitor>>::Error>
151            where
152                S: crate::de::SeqAccess<'__visitor>,
153            {
154                if let ::core::result::Result::Ok(::core::option::Option::Some(_v)) =
155                    crate::de::SeqAccess::next_element::<T>(&mut __sequence)
156                {
157                    return ::core::result::Result::Ok(XmlRootTop::Value(_v));
158                }
159                if let ::core::result::Result::Ok(::core::option::Option::Some(_v)) =
160                    crate::de::SeqAccess::next_element::<value::XmlComment>(&mut __sequence)
161                {
162                    return ::core::result::Result::Ok(XmlRootTop::Comment(_v));
163                }
164                if let ::core::result::Result::Ok(::core::option::Option::Some(_v)) =
165                    crate::de::SeqAccess::next_element::<value::XmlProcessingInstruction>(
166                        &mut __sequence,
167                    )
168                {
169                    return ::core::result::Result::Ok(XmlRootTop::PI(_v));
170                }
171                if let ::core::result::Result::Ok(::core::option::Option::Some(_v)) =
172                    crate::de::SeqAccess::next_element::<value::XmlDoctype>(&mut __sequence)
173                {
174                    return ::core::result::Result::Ok(XmlRootTop::Doctype(_v));
175                }
176                ::core::result::Result::Err(crate::de::Error::no_possible_variant("XmlRootTop"))
177            }
178        }
179        Deserializer::deserialize_seq(
180            __deserializer,
181            __XmlRootTopVisitor {
182                lifetime: ::core::marker::PhantomData,
183                marker: ::core::marker::PhantomData,
184            },
185        )
186    }
187}
188
189impl<T> XmlRoot<T> {
190    /// Creates a new `XmlRoot` with the given value.
191    pub fn new() -> Self {
192        Self {
193            decl: None,
194            elements: Vec::new(),
195        }
196    }
197
198    /// Adds a declaration to the XML document.
199    pub fn with_decl<U: Into<XmlDecl>>(mut self, decl: U) -> Self {
200        let decl: XmlDecl = decl.into();
201        self.decl = Some(decl);
202        self
203    }
204
205    /// Adds an element to the XML document.
206    pub fn with_element<U: Into<T>>(mut self, element: U) -> Self {
207        let element: T = element.into();
208        self.elements.push(XmlRootTop::Value(element));
209        self
210    }
211
212    /// Adds multiple elements to the XML document.
213    pub fn with_elements<U: Into<T>, I: IntoIterator<Item = U>>(mut self, elements: I) -> Self {
214        self.elements.extend(
215            elements
216                .into_iter()
217                .map(Into::<T>::into)
218                .map(XmlRootTop::Value),
219        );
220        self
221    }
222
223    /// Adds a comment to the XML document.
224    pub fn with_comment<U: Into<value::XmlComment>>(mut self, comment: U) -> Self {
225        let comment: value::XmlComment = comment.into();
226        self.elements.push(comment.into());
227        self
228    }
229
230    /// Adds multiple attributes to the element.
231    pub fn with_comments<U: Into<value::XmlComment>, I: IntoIterator<Item = U>>(
232        mut self,
233        comments: I,
234    ) -> Self {
235        self.elements.extend(
236            comments
237                .into_iter()
238                .map(Into::<value::XmlComment>::into)
239                .map(Into::into),
240        );
241        self
242    }
243
244    /// Adds a processing instruction to the XML document.
245    pub fn with_pi<U: Into<value::XmlProcessingInstruction>>(mut self, pi: U) -> Self {
246        let pi: value::XmlProcessingInstruction = pi.into();
247        self.elements.push(pi.into());
248        self
249    }
250
251    /// Adds multiple processing instructions to the XML document.
252    pub fn with_pis<U: Into<value::XmlProcessingInstruction>, I: IntoIterator<Item = U>>(
253        mut self,
254        pis: I,
255    ) -> Self {
256        self.elements.extend(
257            pis.into_iter()
258                .map(Into::<value::XmlProcessingInstruction>::into)
259                .map(Into::into),
260        );
261        self
262    }
263
264    /// Adds a doctype declaration to the XML document.
265    pub fn with_doctype<U: Into<value::XmlDoctype>>(mut self, doctype: U) -> Self {
266        let doctype: value::XmlDoctype = doctype.into();
267        self.elements.push(doctype.into());
268        self
269    }
270
271    /// Adds multiple doctype declarations to the XML document.
272    pub fn with_doctypes<U: Into<value::XmlDoctype>, I: IntoIterator<Item = U>>(
273        mut self,
274        doctypes: I,
275    ) -> Self {
276        self.elements.extend(
277            doctypes
278                .into_iter()
279                .map(Into::<value::XmlDoctype>::into)
280                .map(Into::into),
281        );
282        self
283    }
284}
285
286impl<T> Default for XmlRoot<T> {
287    fn default() -> Self {
288        Self::new()
289    }
290}
291
292/// A visitor for deserializing a string from a CDATA section.
293pub struct FromCDataVisitor<T> {
294    _marker: PhantomData<fn() -> T>,
295}
296
297impl<T> Default for FromCDataVisitor<T> {
298    fn default() -> Self {
299        Self {
300            _marker: PhantomData,
301        }
302    }
303}
304
305impl<'de, T: Deserialize<'de>> Visitor<'de> for FromCDataVisitor<T>
306where
307    T: FromStr,
308{
309    type Value = T;
310    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
311        write!(formatter, "a string")
312    }
313
314    fn visit_cdata<E, V: XmlCData<'de>>(self, v: V) -> Result<Self::Value, E>
315    where
316        E: de::Error,
317    {
318        v.as_str().parse().map_err(|_| E::custom("invalid value"))
319    }
320}
321
322/// A wrapper type for CDATA sections.
323#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
324pub struct CData<S>(pub S);
325
326impl<'de, S: FromStr + Deserialize<'de>> Deserialize<'de> for CData<S> {
327    fn deserialize<D: Deserializer<'de>>(reader: D) -> Result<Self, D::Error> {
328        reader
329            .deserialize_any(FromCDataVisitor::default())
330            .map(CData)
331    }
332}
333
334impl<S: AsRef<str>> Serialize for CData<S> {
335    fn serialize<Ser: Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
336        serializer.serialize_cdata(self.0.as_ref())
337    }
338}
339
340/// A type that ignores that uses the value that visits it, but results in nothing. Useful for skipping over values.
341#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
342pub struct Whitespace<'a>(pub std::borrow::Cow<'a, str>);
343
344impl<'de> Deserialize<'de> for Whitespace<'de> {
345    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
346    where
347        D: Deserializer<'de>,
348    {
349        struct __Visitor<'v> {
350            lifetime: ::core::marker::PhantomData<&'v ()>,
351        }
352
353        impl<'v> crate::de::Visitor<'v> for __Visitor<'v> {
354            type Value = Whitespace<'v>;
355
356            fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
357                formatter.write_str("ignored any value")
358            }
359
360            fn visit_text<E, V: XmlText<'v>>(self, text: V) -> Result<Self::Value, E>
361            where
362                E: de::Error,
363            {
364                let text = text.into_string();
365                if text.trim().is_empty() {
366                    Ok(Whitespace(text))
367                } else {
368                    Err(E::custom("expected whitespace"))
369                }
370            }
371        }
372
373        deserializer.deserialize_any(__Visitor {
374            lifetime: ::core::marker::PhantomData,
375        })
376    }
377}
378
379#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
380/// Utility type for a type that can either be whitespace or a specific value
381pub enum ValueOrWhitespace<'a, T> {
382    /// Whitespace
383    Whitespace(Cow<'a, str>),
384    /// Value
385    Value(T),
386}
387
388impl<'de, T: Deserialize<'de>> Deserialize<'de> for ValueOrWhitespace<'de, T> {
389    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
390    where
391        D: Deserializer<'de>,
392    {
393        struct __Visitor<'v, T> {
394            marker: ::core::marker::PhantomData<T>,
395            lifetime: ::core::marker::PhantomData<&'v ()>,
396        }
397
398        impl<'v, T: Deserialize<'v>> crate::de::Visitor<'v> for __Visitor<'v, T> {
399            type Value = ValueOrWhitespace<'v, T>;
400
401            fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
402                formatter.write_str("ignored any value")
403            }
404
405            fn visit_seq<S>(self, mut sequence: S) -> Result<Self::Value, S::Error>
406            where
407                S: de::SeqAccess<'v>,
408            {
409                if let Ok(Some(text)) = sequence.next_element::<Whitespace>() {
410                    Ok(ValueOrWhitespace::Whitespace(text.0))
411                } else {
412                    sequence
413                        .next_element_seq::<T>()?
414                        .ok_or_else(de::Error::missing_data)
415                        .map(ValueOrWhitespace::Value)
416                }
417            }
418
419            fn visit_none<E>(self) -> Result<Self::Value, E>
420            where
421                E: de::Error,
422            {
423                T::deserialize_seq(crate::types::utils::NoneDeserializer::new())
424                    .map(ValueOrWhitespace::Value)
425            }
426        }
427
428        deserializer.deserialize_seq(__Visitor {
429            lifetime: ::core::marker::PhantomData,
430            marker: ::core::marker::PhantomData,
431        })
432    }
433}
434
435/// A type that ignores that uses the value that visits it, but results in nothing. Useful for skipping over values.
436#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
437pub struct IgnoredAny;
438
439impl<'de> Deserialize<'de> for IgnoredAny {
440    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
441    where
442        D: Deserializer<'de>,
443    {
444        struct __Visitor<'v> {
445            marker: ::core::marker::PhantomData<IgnoredAny>,
446            lifetime: ::core::marker::PhantomData<&'v ()>,
447        }
448
449        impl<'v> crate::de::Visitor<'v> for __Visitor<'v> {
450            type Value = IgnoredAny;
451
452            fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
453                formatter.write_str("ignored any value")
454            }
455
456            fn visit_seq<S>(self, _sequence: S) -> Result<Self::Value, S::Error>
457            where
458                S: crate::de::SeqAccess<'v>,
459            {
460                Ok(IgnoredAny)
461            }
462
463            fn visit_text<E, V: XmlText<'v>>(self, _value: V) -> Result<Self::Value, E>
464            where
465                E: de::Error,
466            {
467                Ok(IgnoredAny)
468            }
469
470            fn visit_cdata<E, V: XmlCData<'v>>(self, _value: V) -> Result<Self::Value, E>
471            where
472                E: de::Error,
473            {
474                Ok(IgnoredAny)
475            }
476
477            fn visit_element<A>(self, _element: A) -> Result<Self::Value, A::Error>
478            where
479                A: de::ElementAccess<'v>,
480            {
481                Ok(IgnoredAny)
482            }
483
484            fn visit_attribute<A>(self, _attribute: A) -> Result<Self::Value, A::Error>
485            where
486                A: de::AttributeAccess<'v>,
487            {
488                Ok(IgnoredAny)
489            }
490
491            fn visit_pi<E, V: XmlProcessingInstruction>(self, _pi: V) -> Result<Self::Value, E>
492            where
493                E: de::Error,
494            {
495                Ok(IgnoredAny)
496            }
497
498            fn visit_decl<E, V: XmlDeclaration>(self, _declaration: V) -> Result<Self::Value, E>
499            where
500                E: de::Error,
501            {
502                Ok(IgnoredAny)
503            }
504
505            fn visit_comment<E, V: XmlComment<'v>>(self, _comment: V) -> Result<Self::Value, E>
506            where
507                E: de::Error,
508            {
509                Ok(IgnoredAny)
510            }
511
512            fn visit_doctype<E, V: XmlDoctype<'v>>(self, _doctype: V) -> Result<Self::Value, E>
513            where
514                E: de::Error,
515            {
516                Ok(IgnoredAny)
517            }
518
519            fn visit_none<E>(self) -> Result<Self::Value, E>
520            where
521                E: de::Error,
522            {
523                Ok(IgnoredAny)
524            }
525        }
526
527        deserializer.deserialize_any(__Visitor {
528            lifetime: ::core::marker::PhantomData,
529            marker: ::core::marker::PhantomData,
530        })
531    }
532}
533
534/// A deserializer that always runs [`Visitor::visit_none`].
535pub struct NoneDeserializer<E: de::Error> {
536    _marker: PhantomData<E>,
537}
538
539impl<E: de::Error> NoneDeserializer<E> {
540    /// Creates a new [`NoneDeserializer`].
541    pub fn new() -> Self {
542        Self {
543            _marker: PhantomData,
544        }
545    }
546}
547
548impl<E: de::Error> Default for NoneDeserializer<E> {
549    fn default() -> Self {
550        Self::new()
551    }
552}
553
554impl<'de, E: de::Error> Deserializer<'de> for NoneDeserializer<E> {
555    type Error = E;
556
557    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
558    where
559        V: Visitor<'de>,
560    {
561        visitor.visit_none()
562    }
563
564    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
565    where
566        V: Visitor<'de>,
567    {
568        visitor.visit_none()
569    }
570}