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::{Chunk, Describe, 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::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(&self, state: &mut State) -> Result<Chunk<'_>, 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 chunk = self.value.serialize(state)?;
147        if self.name.is_some() || !self.namespaces.is_empty() {
148            let data = state.event_mut::<RootData>();
149            data.name.clone_from(&self.name);
150            data.namespaces.clone_from(&self.namespaces);
151        }
152        Ok(chunk)
153    }
154
155    fn finish(&self, state: &mut State) -> Result<(), Error> {
156        self.value.finish(state)
157    }
158
159    fn is_optional(&self) -> bool {
160        self.value.is_optional()
161    }
162
163    fn container_shape(&self) -> ContainerShape {
164        self.value.container_shape()
165    }
166
167    fn describe(&self, d: &mut dyn Describe) {
168        self.value.describe(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
189struct RootSink<'a, 'de, T> {
190    out: &'a mut Option<Root<T>>,
191    // atoms are deserialized directly into this slot, maps and sequences
192    // need a sink that lives across calls
193    slot: Option<T>,
194    compound: Option<OwnedSink<'de, T>>,
195    data: RootData,
196}
197
198impl<'a, 'de, T: Deserialize<'de>> RootSink<'a, 'de, T> {
199    /// Takes the root data of the first event from the state.
200    ///
201    /// It's detached so that the value does not see (or capture) it.
202    fn take_data(&mut self, state: &mut State) {
203        if let Some(data) = state.take_event::<RootData>() {
204            self.data = data;
205        }
206    }
207
208    fn compound(&mut self, state: &mut State) -> &mut dyn Sink<'de> {
209        self.compound
210            .get_or_insert_with(|| OwnedSink::deserialize(state))
211            .borrow_mut()
212    }
213}
214
215impl<'a, 'de, T: Deserialize<'de>> Sink<'de> for RootSink<'a, 'de, T> {
216    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
217        self.take_data(state);
218        let mut sink = T::deserialize_into(&mut self.slot, state);
219        sink.atom(atom, state)?;
220        sink.finish(state)
221    }
222
223    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
224        self.take_data(state);
225        let mut sink = T::deserialize_into(&mut self.slot, state);
226        sink.borrowed_atom(atom, state)?;
227        sink.finish(state)
228    }
229
230    fn map(&mut self, state: &mut State) -> Result<(), Error> {
231        self.take_data(state);
232        self.compound(state).map(state)
233    }
234
235    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
236        self.take_data(state);
237        self.compound(state).seq(state)
238    }
239
240    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
241        self.compound(state).next_key(state)
242    }
243
244    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
245        self.compound(state).next_value(state)
246    }
247
248    fn value_for_key(
249        &mut self,
250        key: &str,
251        state: &mut State,
252    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
253        self.compound(state).value_for_key(key, state)
254    }
255
256    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
257        match self.compound {
258            Some(ref mut compound) => compound.borrow_mut().recover(err, state),
259            None => Err(err),
260        }
261    }
262
263    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
264        let value = match self.compound {
265            Some(ref mut compound) => {
266                compound.borrow_mut().finish(state)?;
267                compound.take()
268            }
269            None => self.slot.take(),
270        };
271        let RootData { name, namespaces } = std::mem::take(&mut self.data);
272        *self.out = value.map(|value| Root {
273            name,
274            namespaces,
275            value,
276        });
277        Ok(())
278    }
279
280    fn expecting(&self) -> Cow<'_, str> {
281        if let Some(ref compound) = self.compound {
282            return compound.borrow().expecting();
283        }
284        let mut slot = None;
285        let mut state = State::new();
286        Cow::Owned(
287            T::deserialize_into(&mut slot, &mut state)
288                .expecting()
289                .into_owned(),
290        )
291    }
292}