xmlserde/
lib.rs

1//! `xmlserde` is another tool for serializing and deserializing XML. It is designed
2//! for easy and clear use.
3//!
4//! Please add these dependencies in your `Cargo.toml`.
5//! ```toml
6//! xmlserde = "0.10"
7//! xmlserde_derives = "0.10"
8//! ```
9//!
10//! # Deserialize
11//! Suppose that XML struct is to be deserialized as below:
12//! ```xml
13//! <person age="8">
14//!     <name>Jeremy</name>
15//!     <pet t="cat">Tom</pet>
16//!     <pet t="dog">Spike</pet>
17//! </person>
18//! ```
19//! You can create a struct and derive the `XmlDeserialize` from `xmlserde_derives`, like:
20//! ```ignore
21//! use xmlserde_derives::XmlDeserialize;
22//! #[derive(XmlDeserialize)]
23//! pub struct Person {
24//!     #[xmlserde(name = b"age", ty = "attr")]
25//!     pub age: u16,
26//!     #[xmlserde(name = b"pet", ty = "child")]
27//!     pub pets: Vec<Pet>,
28//! }
29//!
30//! #[derive(XmlDeserialize)]
31//! pub struct Pet {
32//!     #[xmlserde(name = b"t", ty = "attr")]
33//!     pub t: String,
34//!     #[xmlserde(ty = "text")]
35//!     pub name: String,
36//! }
37//! ```
38//! In `xmlserde`, you need to declare clearly that which tag and which type you are going to `serde`.
39//! Notice that it is a binary string for the `name`.
40//!
41//! # Serialize
42//! As for serializing, you need to derive the `XmlSerialize`.
43//!
44//! # Enum
45//! ## For attribute value
46//! Please check in `xml_serde_enum` section.
47//!
48//! ## For children element
49//! You can define an enum like this.
50//! ```ignore
51//! #[derive(XmlSerialize, Deserialize)]
52//! pub enum Pet{
53//!     #[xmlserde(name = b"dog")]
54//!     Dog(Dog),
55//!     #[xmlserde(name = b"cat")]
56//!     Cat(Cat),
57//! }
58//! pub struct Dog{}
59//! pub struct Cat{}
60//! ```
61//! In a field whose type is an `enum`, we can use `ty = untag`:
62//! ```ignore
63//! #[derive(XmlSerialize, Deserialize)]
64//! pub struct Person {
65//!     #[xmlserde(ty="untag")]
66//!     pub pet: Pet,
67//! }
68//! ```
69//! In this case, `Person` can be serialized as
70//! ```xml
71//! <person>
72//!     <dog>
73//!     ...
74//!     </dog>
75//! </person>
76//! ```
77//! or
78//! ```xml
79//! <person>
80//!     <cat>
81//!     ...
82//!     </cat>
83//! </person>
84//! ```
85//!
86//! # Attributes
87//! - name: the tag of the XML element.
88//! - vec_size: creating a vector with the given capacity before deserilizing a element lists. `vec_size=4` or if your initial capacity is defined in an attr, you can use like this `vec_size="cnt"`.
89//! - default: assigning a parameter-free function to create a default value for a certain field. Notice that it requires the type of this value impls `Eq` and it will skip serializing when the value equals to the default one.
90//! - untag: see the `Enum` above.
91//!
92//! # Examples
93//! Please see [LogiSheets](https://github.com/proclml/LogiSheets/tree/master/crates/workbook) for examples.
94
95/// A macro to help you create mappings between string values in XML and Rust enums.
96///
97/// For example, we can define a mapping like this:
98/// ```
99/// use xmlserde::xml_serde_enum;
100/// xml_serde_enum!{
101///     #[derive(Debug, Clone)]
102///     Gender{
103///         Male => "male",
104///         Female => "female",
105///     }
106/// }
107/// ```
108/// After expansion, you can find an enum is defined like this:
109/// ```
110/// #[derive(Debug, Clone)]
111/// pub enum Gender {
112///     Male,
113///     Female,
114/// }
115/// ```
116/// And string value of `male` will be deserialized as `Gender::Male` while `female` will be as `Gender::Female`.
117/// In the same way, `Gender` will be serialized as `male` of `female`.
118///
119/// Panic if the given string is out of `male` and `female`.
120#[macro_export]
121macro_rules! xml_serde_enum {
122    (
123         $(#[$outer:meta])*
124        $name:ident {
125            $($f:ident => $s:literal,)*
126        }
127    ) => {
128        #[warn(dead_code)]
129        $(#[$outer])*
130        pub enum $name {
131            $($f,)*
132        }
133
134        impl xmlserde::XmlValue for $name {
135            fn serialize(&self) -> String {
136                match &self {
137                    $(Self::$f => String::from($s),)*
138                }
139            }
140            fn deserialize(s: &str) -> Result<Self, String> {
141                match s {
142                    $($s => Ok(Self::$f),)*
143                    _ => Err(String::from("")),
144                }
145            }
146        }
147    };
148}
149
150use std::{
151    fmt::Debug,
152    io::{BufRead, Write},
153};
154
155// We republic the `quick_xml` here is for helping the `derives` crate import
156// it easily. In this way users don't need to import the `quick-xml` on
157// their own.
158pub use quick_xml;
159
160use quick_xml::events::Event;
161
162pub trait XmlSerialize {
163    fn serialize<W: Write>(&self, tag: &[u8], writer: &mut quick_xml::Writer<W>);
164    fn ser_root() -> Option<&'static [u8]> {
165        None
166    }
167}
168
169impl<T: XmlSerialize> XmlSerialize for Option<T> {
170    fn serialize<W: Write>(&self, tag: &[u8], writer: &mut quick_xml::Writer<W>) {
171        match self {
172            Some(t) => t.serialize(tag, writer),
173            None => {}
174        }
175    }
176}
177
178impl<T: XmlSerialize> XmlSerialize for Vec<T> {
179    fn serialize<W: Write>(&self, _tag_: &[u8], _writer_: &mut quick_xml::Writer<W>) {
180        self.iter().for_each(|c| {
181            let _ = c.serialize(_tag_, _writer_);
182        });
183    }
184}
185
186pub trait XmlDeserialize: Sized {
187    fn deserialize<B: BufRead>(
188        tag: &[u8],
189        reader: &mut quick_xml::Reader<B>,
190        attrs: quick_xml::events::attributes::Attributes,
191        is_empty: bool,
192    ) -> Self;
193
194    fn de_root() -> Option<&'static [u8]> {
195        None
196    }
197
198    /// A helper function used when ty = `untag`. It could help
199    /// us to find out the children tags when deserializing
200    fn __get_children_tags() -> Vec<&'static [u8]> {
201        vec![]
202    }
203
204    /// A helper function used when handling the untag types.
205    ///
206    /// For a outside struct, it doesn't
207    /// know how to deal with an untag type. The current solution is to treat them as `Unparsed`
208    /// types first, and then pass them into this function to deserialize. Since the type is untagged,
209    /// it doesn't require the attributes.
210    fn __deserialize_from_unparsed_array(_array: Vec<(&'static [u8], Unparsed)>) -> Self {
211        unreachable!("untagged types require having `child` types only")
212    }
213
214    /// A helper function for handling the untagged types.
215    ///
216    /// For efficiency, deserializing enums has no need to handle the untagged types by `__deserialize_from_unparsed_array` method.
217    /// But we have no idea of whether this field is not enum or not, we make a helper function to discern it
218    /// in the runtime.
219    fn __is_enum() -> bool {
220        false
221    }
222
223    fn __deserialize_from_text(_: &str) -> Option<Self>
224    where
225        Self: Sized,
226    {
227        None
228    }
229}
230
231/// `Unparsed` keeps the XML struct and will be serialized to XML with nothing change.
232/// It is helpful when you are debugging on deserializeing certain element.
233///
234/// ```ignore
235/// use xmlserde::Unparsed;
236/// use xmlserde_derive::{XmlSerialize, XmlDeserialize};
237///
238/// #[derive(XmlSerialize, Deserialize)]
239/// pub struct Person {
240///     #[xmlserde(name=b"gender", ty = "attr")]
241///     pub gender: Gender,
242///     #[xmlserde(name=b"hobbies", ty = "child")]
243///     pub hobbies: Unparsed
244/// }
245/// ```
246/// In the example above, `<hobbies>` element keeps unchange after serializing and deserializing.
247/// You can easily make a diff the former and latter version to check if other elments work well.
248#[derive(Debug, Clone)]
249pub struct Unparsed {
250    data: Vec<Event<'static>>,
251    attrs: Vec<(String, String)>,
252}
253
254impl XmlSerialize for Unparsed {
255    fn serialize<W: Write>(&self, _tag_: &[u8], _writer_: &mut quick_xml::Writer<W>) {
256        use quick_xml::events::*;
257        let mut start = BytesStart::new(String::from_utf8_lossy(_tag_));
258        self.attrs.iter().for_each(|(k, v)| {
259            let k = k as &str;
260            let v = v as &str;
261            start.push_attribute((k, v));
262        });
263        if self.data.len() > 0 {
264            let _ = _writer_.write_event(Event::Start(start));
265            self.data.iter().for_each(|e| {
266                let _ = _writer_.write_event(e.clone());
267            });
268            let _ = _writer_.write_event(Event::End(BytesEnd::new(String::from_utf8_lossy(_tag_))));
269        } else {
270            let _ = _writer_.write_event(Event::Empty(start));
271        }
272    }
273}
274
275impl XmlDeserialize for Unparsed {
276    fn deserialize<B: BufRead>(
277        _tag_: &[u8],
278        _reader_: &mut quick_xml::Reader<B>,
279        _attrs_: quick_xml::events::attributes::Attributes,
280        _is_empty_: bool,
281    ) -> Self {
282        use quick_xml::events::*;
283        let mut attrs_vec = Vec::<(String, String)>::new();
284        let mut data = Vec::<Event<'static>>::new();
285        let mut buf = Vec::<u8>::new();
286        _attrs_.into_iter().for_each(|a| {
287            if let Ok(attr) = a {
288                let key =
289                    String::from_utf8(attr.key.into_inner().to_vec()).unwrap_or(String::from(""));
290                let value = String::from_utf8(attr.value.to_vec()).unwrap_or(String::from(""));
291                attrs_vec.push((key, value))
292            }
293        });
294        if _is_empty_ {
295            return Unparsed {
296                data,
297                attrs: attrs_vec,
298            };
299        }
300        loop {
301            match _reader_.read_event_into(&mut buf) {
302                Ok(Event::End(e)) if e.name().into_inner() == _tag_ => break,
303                Ok(Event::Eof) => break,
304                Err(_) => break,
305                Ok(e) => data.push(e.into_owned()),
306            }
307        }
308        Unparsed {
309            data,
310            attrs: attrs_vec,
311        }
312    }
313
314    fn __deserialize_from_unparsed_array(_array: Vec<(&'static [u8], Unparsed)>) -> Self {
315        unreachable!(
316            r#"seems you are using a struct having `attrs` or `text` as an UntaggedStruct"#
317        )
318    }
319}
320
321impl Unparsed {
322    pub fn deserialize_to<T>(self) -> Result<T, String>
323    where
324        T: XmlDeserialize + Sized,
325    {
326        // TODO: Find a more efficient way
327        let mut writer = quick_xml::Writer::new(Vec::new());
328        let t = b"tmptag";
329        self.serialize(t, &mut writer);
330        let result = writer.into_inner();
331
332        xml_deserialize_from_reader_with_root::<T, _>(result.as_slice(), t)
333    }
334}
335
336/// The entry for serializing. `T` should have declared the `root` by `#[xmlserde(root=b"")]`
337/// to tell the serializer the tag name of the root. This function will add the header needed for
338/// a XML file.
339pub fn xml_serialize_with_decl<T>(obj: T) -> String
340where
341    T: XmlSerialize,
342{
343    use quick_xml::events::BytesDecl;
344    let mut writer = quick_xml::Writer::new(Vec::new());
345    let decl = BytesDecl::new("1.0", Some("UTF-8"), Some("yes"));
346    let _ = writer.write_event(Event::Decl(decl));
347    obj.serialize(
348        T::ser_root().expect(r#"Expect a root element to serialize: #[xmlserde(root=b"tag")]"#),
349        &mut writer,
350    );
351    String::from_utf8(writer.into_inner()).unwrap()
352}
353
354/// The entry for serializing. `T` should have declared the `root` by `#[xmlserde(root=b"")]`
355/// to tell the serializer the tag name of the root.
356pub fn xml_serialize<T>(obj: T) -> String
357where
358    T: XmlSerialize,
359{
360    let mut writer = quick_xml::Writer::new(Vec::new());
361    obj.serialize(T::ser_root().expect("Expect root"), &mut writer);
362    String::from_utf8(writer.into_inner()).expect("decode error")
363}
364
365/// The entry for deserializing. `T` should have declared the `root` by `#[xmlserde(root=b"")]`
366/// to tell the deserializer which tag is the start for deserializing.
367/// ```ignore
368/// use xmlserde_derives::XmlDeserialize;
369/// #[derive(XmlDeserialize)]
370/// #[xmlserde(root=b"person")]
371/// pub struct Person {
372///     #[xmlserde(name = b"age", ty = "attr")]
373///     pub age: u16,
374///     #[xmlserde(name = b"pet", ty = "child")]
375///     pub pets: Vec<Pet>,
376/// }
377/// ```
378pub fn xml_deserialize_from_reader<T, R>(reader: R) -> Result<T, String>
379where
380    T: XmlDeserialize,
381    R: BufRead,
382{
383    let root = T::de_root().expect(r#"#[xmlserde(root = b"tag")]"#);
384    xml_deserialize_from_reader_with_root(reader, root)
385}
386
387pub(crate) fn xml_deserialize_from_reader_with_root<T, R>(
388    reader: R,
389    root: &[u8],
390) -> Result<T, String>
391where
392    T: XmlDeserialize,
393    R: BufRead,
394{
395    let mut reader = quick_xml::Reader::from_reader(reader);
396    let mut buf = Vec::<u8>::new();
397    loop {
398        match reader.read_event_into(&mut buf) {
399            Ok(Event::Start(start)) => {
400                if start.name().into_inner() == root {
401                    let result = T::deserialize(root, &mut reader, start.attributes(), false);
402                    return Ok(result);
403                }
404            }
405            Ok(Event::Empty(start)) => {
406                if start.name().into_inner() == root {
407                    let result = T::deserialize(root, &mut reader, start.attributes(), true);
408                    return Ok(result);
409                }
410            }
411            Ok(Event::Eof) => {
412                return Err(format!(
413                    "Cannot find the element: {}",
414                    String::from_utf8(root.to_vec()).unwrap()
415                ))
416            }
417            Err(e) => return Err(e.to_string()),
418            _ => {}
419        }
420    }
421}
422
423/// The entry for deserializing. `T` should have declared the `root` by `#[xmlserde(root=b"")]`
424/// to tell the deserializer which tag is the start for deserializing.
425/// ```ignore
426/// use xmlserde_derives::XmlDeserialize;
427/// #[derive(XmlDeserialize)]
428/// #[xmlserde(root=b"person")]
429/// pub struct Person {
430///     #[xmlserde(name = b"age", ty = "attr")]
431///     pub age: u16,
432///     #[xmlserde(name = b"pet", ty = "child")]
433///     pub pets: Vec<Pet>,
434/// }
435/// ```
436pub fn xml_deserialize_from_str<T>(xml_str: &str) -> Result<T, String>
437where
438    T: XmlDeserialize,
439{
440    xml_deserialize_from_reader(xml_str.as_bytes())
441}
442
443pub trait XmlValue: Sized {
444    fn serialize(&self) -> String;
445    fn deserialize(s: &str) -> Result<Self, String>;
446}
447
448impl XmlValue for bool {
449    fn serialize(&self) -> String {
450        if *self {
451            String::from("1")
452        } else {
453            String::from("0")
454        }
455    }
456
457    fn deserialize(s: &str) -> Result<Self, String> {
458        let s = s.to_ascii_lowercase();
459        if s == "1" || s == "true" {
460            Ok(true)
461        } else if s == "0" || s == "false" {
462            Ok(false)
463        } else {
464            Err(format!("Cannot parse {} into a boolean", s))
465        }
466    }
467}
468
469impl XmlValue for String {
470    fn serialize(&self) -> String {
471        self.to_owned()
472    }
473
474    fn deserialize(s: &str) -> Result<Self, String> {
475        Ok(s.to_owned())
476    }
477}
478
479macro_rules! impl_xml_value_for_num {
480    ($num:ty) => {
481        impl XmlValue for $num {
482            fn serialize(&self) -> String {
483                self.to_string()
484            }
485
486            fn deserialize(s: &str) -> Result<Self, String> {
487                let r = s.parse::<$num>();
488                match r {
489                    Ok(f) => Ok(f),
490                    Err(e) => Err(e.to_string()),
491                }
492            }
493        }
494    };
495}
496
497impl_xml_value_for_num!(i8);
498impl_xml_value_for_num!(u8);
499impl_xml_value_for_num!(i16);
500impl_xml_value_for_num!(u16);
501impl_xml_value_for_num!(i32);
502impl_xml_value_for_num!(u32);
503impl_xml_value_for_num!(i64);
504impl_xml_value_for_num!(u64);
505impl_xml_value_for_num!(i128);
506impl_xml_value_for_num!(u128);
507impl_xml_value_for_num!(isize);
508impl_xml_value_for_num!(usize);
509impl_xml_value_for_num!(f32);
510impl_xml_value_for_num!(f64);
511impl_xml_value_for_num!(std::num::NonZeroI8);
512impl_xml_value_for_num!(std::num::NonZeroU8);
513impl_xml_value_for_num!(std::num::NonZeroI16);
514impl_xml_value_for_num!(std::num::NonZeroU16);
515impl_xml_value_for_num!(std::num::NonZeroI32);
516impl_xml_value_for_num!(std::num::NonZeroU32);
517impl_xml_value_for_num!(std::num::NonZeroI64);
518impl_xml_value_for_num!(std::num::NonZeroU64);
519impl_xml_value_for_num!(std::num::NonZeroI128);
520impl_xml_value_for_num!(std::num::NonZeroU128);
521impl_xml_value_for_num!(std::num::NonZeroIsize);
522impl_xml_value_for_num!(std::num::NonZeroUsize);