Skip to main content

deser_xml/
root.rs

1//! The root element of documents.
2use std::borrow::Cow;
3
4use deser_core::State;
5use deser_core::de::{Deserialize, OwnedSink, Sink, SinkHandle};
6use deser_core::ser::{Describe, Emit, Serialize};
7use deser_core::{Atom, ContainerShape, Error};
8
9/// The name of the root element and the namespaces declared on it,
10/// attached as event data to the first event of the root element.
11///
12/// The deserializer publishes them, the serializer writes the root element
13/// with them.  Like the tags of CBOR and YAML they are kept by values that
14/// capture event data (such as [`Recording`](deser_core::de::Recording)
15/// and the values of `deser-value`), so documents that are read into such
16/// values or transcoded keep their root element.
17#[derive(Debug, Default)]
18pub(crate) struct RootData {
19    pub(crate) name: Option<String>,
20    pub(crate) namespaces: Vec<(String, String)>,
21}
22
23// Event data is reset with `clone_from` which retains the memory only if
24// it's forwarded (derived clones do not do that).
25impl Clone for RootData {
26    fn clone(&self) -> RootData {
27        RootData {
28            name: self.name.clone(),
29            namespaces: self.namespaces.clone(),
30        }
31    }
32
33    fn clone_from(&mut self, source: &RootData) {
34        self.name.clone_from(&source.name);
35        self.namespaces.clone_from(&source.namespaces);
36    }
37}
38
39/// The namespaces declared on an element other than the root, attached as
40/// event data to its first event.
41///
42/// Like [`RootData`] it's published by the deserializer and written by the
43/// serializer, so values that capture event data keep the declarations.
44/// An empty URI undeclares the default namespace (`xmlns=""`).
45#[derive(Debug, Default)]
46pub(crate) struct Declarations(pub(crate) Vec<(String, String)>);
47
48impl Clone for Declarations {
49    fn clone(&self) -> Declarations {
50        Declarations(self.0.clone())
51    }
52
53    fn clone_from(&mut self, source: &Declarations) {
54        self.0.clone_from(&source.0);
55    }
56}
57
58/// A document: the value of the root element with its name and the
59/// namespaces declared on it.
60///
61/// When deserialized the name of the root element and its namespace
62/// declarations are captured, when serialized the root element is written
63/// with them.  The name is kept as the deserializer passes on names: as
64/// written, with the configured prefix of its namespace or as `{uri}local`
65/// if namespaces are resolved (see [`DeserializerConfig`]).  The prefixes
66/// of the namespaces are the ones the names use (the configured prefixes
67/// for namespaces that have one).
68///
69/// ```
70/// use std::collections::BTreeMap;
71/// use deser_xml::Root;
72///
73/// let doc: Root<BTreeMap<String, String>> =
74///     deser_xml::from_str(r#"<rss xmlns:dc="urn:dc"><dc:creator>Jane</dc:creator></rss>"#)
75///         .unwrap();
76/// assert_eq!(doc.name.as_deref(), Some("rss"));
77/// assert_eq!(doc.namespaces, [("dc".to_string(), "urn:dc".to_string())]);
78/// assert_eq!(doc.value["dc:creator"], "Jane");
79///
80/// // values without a name (like maps) are named by the root
81/// let doc = Root::new("r", BTreeMap::from([("@a", 1), ("b", 2)]));
82/// assert_eq!(deser_xml::to_string(&doc).unwrap(), r#"<r a="1"><b>2</b></r>"#);
83/// ```
84///
85/// The name of the root is used over the name of the type of the value
86/// and the [configured name](crate::SerializerConfig::set_root), its namespaces
87/// are declared before the [configured
88/// ones](crate::SerializerConfig::namespaces) (which are left out if their
89/// prefix is taken).  Only documents have a root: in other places, and when
90/// serializing to other formats, the name and the namespaces are ignored,
91/// when deserializing from other formats the name is `None` and there are
92/// no namespaces.
93///
94/// [`DeserializerConfig`]: crate::DeserializerConfig
95#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
96pub struct Root<T> {
97    /// The name of the root element.
98    pub name: Option<String>,
99    /// The namespaces declared on the root element as prefix and URI (the
100    /// empty prefix is the default namespace).
101    pub namespaces: Vec<(String, String)>,
102    /// The value of the root element.
103    pub value: T,
104}
105
106impl<T> Root<T> {
107    /// Creates a root element with a name.
108    pub fn new<S: Into<String>>(name: S, value: T) -> Root<T> {
109        Root {
110            name: Some(name.into()),
111            namespaces: Vec::new(),
112            value,
113        }
114    }
115
116    /// Declares a namespace on the root element.
117    ///
118    /// ```
119    /// use deser_xml::Root;
120    ///
121    /// let doc = Root::new("{urn:a}doc", "x").with_namespace("a", "urn:a");
122    /// assert_eq!(
123    ///     deser_xml::to_string(&doc).unwrap(),
124    ///     r#"<a:doc xmlns:a="urn:a">x</a:doc>"#
125    /// );
126    /// ```
127    pub fn with_namespace<P: Into<String>, U: Into<String>>(
128        mut self,
129        prefix: P,
130        uri: U,
131    ) -> Root<T> {
132        self.namespaces.push((prefix.into(), uri.into()));
133        self
134    }
135
136    /// Returns the value of the root element.
137    pub fn into_inner(self) -> T {
138        self.value
139    }
140}
141
142impl<T: Serialize> Serialize for Root<T> {
143    fn serialize<'a>(this: &'a Self, state: &mut State) -> Result<Emit<'a>, Error> {
144        // the root is set after the value attached its data (like the root
145        // of a recorded value), it replaces it
146        let emit = T::serialize(&this.value, state)?;
147        if this.name.is_some() || !this.namespaces.is_empty() {
148            let data = state.event_mut::<RootData>();
149            data.name.clone_from(&this.name);
150            data.namespaces.clone_from(&this.namespaces);
151        }
152        Ok(emit)
153    }
154
155    fn finish(this: &Self, state: &mut State) -> Result<(), Error> {
156        T::finish(&this.value, state)
157    }
158
159    fn is_optional(this: &Self) -> bool {
160        T::is_optional(&this.value)
161    }
162
163    fn container_shape(this: &Self) -> ContainerShape {
164        T::container_shape(&this.value)
165    }
166
167    fn describe(this: &Self, d: &mut dyn Describe) {
168        T::describe(&this.value, d)
169    }
170}
171
172impl<'de, T: Deserialize<'de>> Deserialize<'de> for Root<T> {
173    fn deserialize_into<'out>(
174        out: &'out mut Option<Self>,
175        state: &mut State,
176    ) -> SinkHandle<'out, 'de> {
177        SinkHandle::arena(
178            RootSink {
179                out,
180                slot: None,
181                compound: None,
182                data: RootData::default(),
183            },
184            state,
185        )
186    }
187
188    fn expecting() -> Cow<'static, str> {
189        T::expecting()
190    }
191
192    fn describe_type(d: &mut dyn Describe) {
193        T::describe_type(d)
194    }
195}
196
197struct RootSink<'a, 'de, T> {
198    out: &'a mut Option<Root<T>>,
199    // atoms are deserialized directly into this slot, maps and sequences
200    // need a sink that lives across calls
201    slot: Option<T>,
202    compound: Option<OwnedSink<'de, T>>,
203    data: RootData,
204}
205
206impl<'a, 'de, T: Deserialize<'de>> RootSink<'a, 'de, T> {
207    /// Takes the root data of the first event from the state.
208    ///
209    /// It's detached so that the value does not see (or capture) it.
210    fn take_data(&mut self, state: &mut State) {
211        if let Some(data) = state.take_event::<RootData>() {
212            self.data = data;
213        }
214    }
215
216    fn compound(&mut self, state: &mut State) -> &mut dyn Sink<'de> {
217        self.compound
218            .get_or_insert_with(|| OwnedSink::deserialize(state))
219            .get_mut()
220    }
221}
222
223impl<'a, 'de, T: Deserialize<'de>> Sink<'de> for RootSink<'a, 'de, T> {
224    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
225        self.take_data(state);
226        let mut sink = T::deserialize_into(&mut self.slot, state);
227        sink.atom(atom, state)?;
228        sink.finish(state)
229    }
230
231    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
232        self.take_data(state);
233        let mut sink = T::deserialize_into(&mut self.slot, state);
234        sink.borrowed_atom(atom, state)?;
235        sink.finish(state)
236    }
237
238    fn map(&mut self, state: &mut State) -> Result<(), Error> {
239        self.take_data(state);
240        self.compound(state).map(state)
241    }
242
243    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
244        self.take_data(state);
245        self.compound(state).seq(state)
246    }
247
248    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
249        self.compound(state).next_key(state)
250    }
251
252    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
253        self.compound(state).next_value(state)
254    }
255
256    fn value_for_key(
257        &mut self,
258        key: &str,
259        state: &mut State,
260    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
261        self.compound(state).value_for_key(key, state)
262    }
263
264    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
265        match self.compound {
266            Some(ref mut compound) => compound.get_mut().recover(err, state),
267            None => Err(err),
268        }
269    }
270
271    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
272        let value = match self.compound {
273            Some(ref mut compound) => {
274                compound.get_mut().finish(state)?;
275                compound.take()
276            }
277            None => self.slot.take(),
278        };
279        let RootData { name, namespaces } = std::mem::take(&mut self.data);
280        *self.out = value.map(|value| Root {
281            name,
282            namespaces,
283            value,
284        });
285        Ok(())
286    }
287
288    fn expecting(&self) -> Cow<'_, str> {
289        if let Some(ref compound) = self.compound {
290            return compound.get().expecting();
291        }
292        T::expecting()
293    }
294}