serde_xml_rs/
config.rs

1use crate::{error::Result, Deserializer, Serializer};
2use serde::{Deserialize, Serialize};
3use std::{
4    collections::BTreeMap,
5    io::{Read, Write},
6};
7use xml::{
8    namespace::NS_NO_PREFIX, writer::events::StartElementBuilder, EmitterConfig, ParserConfig,
9};
10
11pub const TEXT: &str = "#text";
12pub const CONTENT: &str = "#content";
13
14#[derive(Clone, Debug)]
15pub struct SerdeXml {
16    pub(crate) emitter: EmitterConfig,
17    pub(crate) parser: ParserConfig,
18    pub(crate) namespaces: Namespaces,
19    pub(crate) overlapping_sequences: bool,
20}
21
22impl Default for SerdeXml {
23    fn default() -> Self {
24        Self {
25            emitter: Default::default(),
26            parser: ParserConfig::new()
27                .trim_whitespace(true)
28                .whitespace_to_characters(true)
29                .cdata_to_characters(true)
30                .ignore_comments(true)
31                .coalesce_characters(true),
32            namespaces: Default::default(),
33            overlapping_sequences: false,
34        }
35    }
36}
37
38impl SerdeXml {
39    pub fn new() -> Self {
40        Default::default()
41    }
42
43    pub fn emitter(mut self, emitter: EmitterConfig) -> Self {
44        self.emitter = emitter;
45        self
46    }
47
48    pub fn parser(mut self, parser: ParserConfig) -> Self {
49        self.parser = parser;
50        self
51    }
52
53    pub fn default_namespace<S: ToString>(mut self, name: S) -> Self {
54        self.namespaces.put_default(name);
55        self
56    }
57
58    pub fn namespace<S: ToString>(mut self, prefix: S, name: S) -> Self {
59        self.namespaces.put(prefix, name);
60        self
61    }
62
63    /// Configures whether the deserializer should search all sibling elements when building a
64    /// sequence. Not required if all XML elements for sequences are adjacent. Disabled by
65    /// default. Enabling this option may incur additional memory usage.
66    ///
67    /// ```rust
68    /// # use serde::Deserialize;
69    /// # use serde_xml_rs::from_reader;
70    /// #[derive(Debug, Deserialize, PartialEq)]
71    /// struct Foo {
72    ///     bar: Vec<usize>,
73    ///     baz: String,
74    /// }
75    /// # fn main() {
76    /// let s = r##"
77    ///     <foo>
78    ///         <bar>1</bar>
79    ///         <bar>2</bar>
80    ///         <baz>Hello, world</baz>
81    ///         <bar>3</bar>
82    ///         <bar>4</bar>
83    ///     </foo>
84    /// "##;
85    /// let foo: Foo = serde_xml_rs::SerdeXml::new().overlapping_sequences(true).from_str(s).unwrap();
86    /// assert_eq!(foo, Foo { bar: vec![1, 2, 3, 4], baz: "Hello, world".to_string()});
87    /// # }
88    /// ```
89    pub fn overlapping_sequences(mut self, b: bool) -> Self {
90        self.overlapping_sequences = b;
91        self
92    }
93
94    pub fn from_str<'de, T: Deserialize<'de>>(self, s: &str) -> Result<T> {
95        self.from_reader(s.as_bytes())
96    }
97
98    pub fn from_reader<'de, T: Deserialize<'de>, R: Read>(self, reader: R) -> Result<T> {
99        T::deserialize(&mut Deserializer::from_config(self, reader))
100    }
101
102    pub fn to_string<S: Serialize>(self, value: &S) -> Result<String> {
103        let mut buffer = Vec::new();
104        self.to_writer(&mut buffer, value)?;
105        Ok(String::from_utf8(buffer)?)
106    }
107
108    pub fn to_writer<W, S>(self, writer: W, value: &S) -> Result<()>
109    where
110        W: Write,
111        S: Serialize,
112    {
113        let mut s = Serializer::from_config(self, writer);
114        value.serialize(&mut s)
115    }
116}
117
118#[derive(Clone, Debug, Default)]
119pub struct Namespaces {
120    mapping: BTreeMap<String, String>,
121}
122
123impl Namespaces {
124    pub fn put_default<S: ToString>(&mut self, name: S) {
125        self.mapping
126            .insert(NS_NO_PREFIX.to_string(), name.to_string());
127    }
128
129    pub fn put<S: ToString>(&mut self, prefix: S, name: S) {
130        self.mapping.insert(prefix.to_string(), name.to_string());
131    }
132
133    pub fn get<S: AsRef<str>>(&self, prefix: S) -> Option<&String> {
134        self.mapping.get(prefix.as_ref())
135    }
136
137    pub(crate) fn add_to_start_element<'a>(
138        &self,
139        mut start_element_builder: StartElementBuilder<'a>,
140    ) -> StartElementBuilder<'a> {
141        for (prefix, name) in &self.mapping {
142            start_element_builder = start_element_builder.ns(prefix, name);
143        }
144        start_element_builder
145    }
146}