Skip to main content

deser_xml/
de.rs

1use std::borrow::Cow;
2
3use deser_core::de::{
4    self, ContentKey, Deserialize, DeserializeDriver, DuplicateKeys, LexicalRules,
5};
6use deser_core::{Atom, ContainerShape, Error, ErrorKind, Event, Order, Source, Text};
7use quick_xml::XmlVersion;
8use quick_xml::events::{BytesRef, BytesStart, Event as XmlEvent};
9use quick_xml::name::{QName, ResolveResult};
10use quick_xml::reader::NsReader;
11
12use crate::Names;
13use crate::mixed::WhitespaceDepths;
14use crate::root::{Declarations, RootData};
15
16/// Configures how XML documents are deserialized.
17///
18/// See the [crate documentation](crate) for how XML maps onto the data
19/// model of deser.
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct DeserializerConfig {
22    pub(crate) names: Names,
23    resolve_namespaces: bool,
24    duplicate_keys: DuplicateKeys,
25    track_locations: bool,
26}
27
28impl Default for DeserializerConfig {
29    fn default() -> DeserializerConfig {
30        DeserializerConfig::new()
31    }
32}
33
34impl DeserializerConfig {
35    /// Creates the default configuration.
36    pub const fn new() -> DeserializerConfig {
37        DeserializerConfig {
38            names: Names::new(),
39            resolve_namespaces: false,
40            duplicate_keys: DuplicateKeys::Error,
41            track_locations: true,
42        }
43    }
44
45    /// Sets the prefix of the keys of attributes.
46    ///
47    /// The default is `@`: `<a href="x"/>` is `{"@href": "x"}`.
48    pub const fn attribute_prefix(mut self, prefix: &'static str) -> DeserializerConfig {
49        self.names.attribute_prefix = prefix;
50        self
51    }
52
53    /// Sets the key of the text of elements that are maps.
54    ///
55    /// The default is `$text`: `<a href="x">y</a>` is
56    /// `{"@href": "x", "$text": "y"}`.
57    pub const fn text_key(mut self, key: &'static str) -> DeserializerConfig {
58        self.names.text_key = key;
59        self
60    }
61
62    /// Sets the prefixes of namespaces.
63    ///
64    /// Names are passed on as written in the document (`atom:link`),
65    /// unless their namespace has a prefix here: then they are written
66    /// with this prefix, whichever prefix the document uses.  The empty
67    /// prefix leaves only the local name.  Names in other namespaces are
68    /// passed on as written or, if namespaces are
69    /// [resolved](Self::resolve_namespaces), as `{uri}local`.  The table
70    /// can be written with [`prefixes!`](crate::prefixes).
71    ///
72    /// ```
73    /// use deser_xml::DeserializerConfig;
74    ///
75    /// #[derive(deser::Deserialize)]
76    /// struct Feed {
77    ///     title: String,
78    ///     #[deser(rename = "dc:creator")]
79    ///     creator: String,
80    /// }
81    ///
82    /// const CONFIG: DeserializerConfig = DeserializerConfig::new().namespaces(&[
83    ///     ("", "http://www.w3.org/2005/Atom"),
84    ///     ("dc", "http://purl.org/dc/elements/1.1/"),
85    /// ]);
86    /// let feed: Feed = CONFIG.from_str(r#"
87    ///     <a:feed xmlns:a="http://www.w3.org/2005/Atom"
88    ///             xmlns:x="http://purl.org/dc/elements/1.1/">
89    ///       <a:title>Example</a:title>
90    ///       <x:creator>Jane</x:creator>
91    ///     </a:feed>
92    /// "#).unwrap();
93    /// assert_eq!(feed.title, "Example");
94    /// assert_eq!(feed.creator, "Jane");
95    /// ```
96    pub const fn namespaces(
97        mut self,
98        namespaces: &'static [(&'static str, &'static str)],
99    ) -> DeserializerConfig {
100        self.names.namespaces = namespaces;
101        self
102    }
103
104    /// Enables or disables resolving namespaces.
105    ///
106    /// By default names are passed on as written in the document.  If
107    /// namespaces are resolved, names in a namespace are passed on as
108    /// `{uri}local` (the notation of James Clark, attributes are
109    /// `@{uri}local`) unless the namespace has a
110    /// [prefix](Self::namespaces), so the prefixes of the document do not
111    /// matter.  Names without namespace are their local name, the `xml`
112    /// prefix is kept (`@xml:lang`).  Prefixes that are not declared are
113    /// an error.  The default is `false`.
114    ///
115    /// The names can be written with [`qname!`](crate::qname) and
116    /// [`namespace!`](crate::namespace):
117    ///
118    /// ```
119    /// use deser_xml::DeserializerConfig;
120    ///
121    /// deser_xml::namespace!(atom = "http://www.w3.org/2005/Atom");
122    ///
123    /// #[derive(deser::Deserialize)]
124    /// struct Link {
125    ///     #[deser(rename = "@href")]
126    ///     href: String,
127    /// }
128    ///
129    /// #[derive(deser::Deserialize)]
130    /// struct Feed {
131    ///     #[deser(rename = atom!("title"))]
132    ///     title: String,
133    ///     #[deser(rename = atom!("link"))]
134    ///     link: Link,
135    /// }
136    ///
137    /// const CONFIG: DeserializerConfig =
138    ///     DeserializerConfig::new().resolve_namespaces(true);
139    /// let xml = r#"
140    ///     <feed xmlns="http://www.w3.org/2005/Atom">
141    ///       <title>Example</title>
142    ///       <link href="/a"/>
143    ///     </feed>
144    /// "#;
145    /// let feed: Feed = CONFIG.from_str(xml).unwrap();
146    /// assert_eq!(feed.title, "Example");
147    /// assert_eq!(feed.link.href, "/a");
148    /// ```
149    pub const fn resolve_namespaces(mut self, yes: bool) -> DeserializerConfig {
150        self.resolve_namespaces = yes;
151        self
152    }
153
154    /// Sets what happens if an element that stands for a single value is
155    /// given more than once.
156    ///
157    /// Elements are [multimaps](deser_core::ContainerShape::with_multimap):
158    /// collections (like `Vec<T>`) collect all child elements with their
159    /// name, for other types this decides.  The default is
160    /// [`DuplicateKeys::Error`].
161    pub const fn duplicate_keys(mut self, policy: DuplicateKeys) -> DeserializerConfig {
162        self.duplicate_keys = policy;
163        self
164    }
165
166    /// Enables or disables location tracking.
167    ///
168    /// The byte range of every event is always published into the state
169    /// (see [`State::input_range`](deser_core::State::input_range)), this
170    /// controls if the input is published as [`Source`] so that errors can
171    /// be resolved into lines and columns.  The default is `true`.
172    pub const fn track_locations(mut self, yes: bool) -> DeserializerConfig {
173        self.track_locations = yes;
174        self
175    }
176
177    /// Deserializes a value from a string with this configuration.
178    pub fn from_str<'de, T: Deserialize<'de>>(&self, s: &'de str) -> Result<T, Error> {
179        Deserializer::from_str_with_config(s, self).deserialize()
180    }
181
182    /// Deserializes a value from bytes with this configuration.
183    ///
184    /// The input must be UTF-8.
185    pub fn from_slice<'de, T: Deserialize<'de>>(&self, bytes: &'de [u8]) -> Result<T, Error> {
186        Deserializer::from_slice_with_config(bytes, self).deserialize()
187    }
188}
189
190/// Deserializes a value from an XML string.
191///
192/// ```
193/// #[derive(deser::Deserialize)]
194/// struct Link {
195///     #[deser(rename = "@href")]
196///     href: String,
197/// }
198///
199/// let link: Link = deser_xml::from_str(r#"<a href="/x"/>"#).unwrap();
200/// assert_eq!(link.href, "/x");
201/// ```
202pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> {
203    Deserializer::from_str(s).deserialize()
204}
205
206/// Deserializes a value from UTF-8 encoded XML.
207pub fn from_slice<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, Error> {
208    Deserializer::from_slice(bytes).deserialize()
209}
210
211/// Deserializes XML documents.
212pub struct Deserializer<'a> {
213    input: &'a str,
214    error: Option<Error>,
215    config: DeserializerConfig,
216}
217
218impl<'a> Deserializer<'a> {
219    /// Creates a deserializer for a string.
220    #[allow(clippy::should_implement_trait)]
221    pub fn from_str(input: &'a str) -> Deserializer<'a> {
222        Deserializer::from_str_with_config(input, &DeserializerConfig::new())
223    }
224
225    /// Creates a deserializer for a string with the given configuration.
226    pub fn from_str_with_config(input: &'a str, config: &DeserializerConfig) -> Deserializer<'a> {
227        Deserializer {
228            input,
229            error: None,
230            config: config.clone(),
231        }
232    }
233
234    /// Creates a deserializer for UTF-8 encoded bytes.
235    pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
236        Deserializer::from_slice_with_config(input, &DeserializerConfig::new())
237    }
238
239    /// Creates a deserializer for UTF-8 encoded bytes with the given
240    /// configuration.
241    pub fn from_slice_with_config(
242        input: &'a [u8],
243        config: &DeserializerConfig,
244    ) -> Deserializer<'a> {
245        // a byte order mark is not part of the document
246        let input = input.strip_prefix(b"\xef\xbb\xbf").unwrap_or(input);
247        match std::str::from_utf8(input) {
248            Ok(input) => Deserializer::from_str_with_config(input, config),
249            Err(err) => Deserializer {
250                input: "",
251                error: Some(
252                    Error::new(ErrorKind::Unexpected, "input is not valid UTF-8")
253                        .with_offset(err.valid_up_to()),
254                ),
255                config: config.clone(),
256            },
257        }
258    }
259
260    /// Deserializes the document.
261    pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
262        de::Deserializer::deserialize(self)
263    }
264
265    /// Deserializes the document with a configured driver.
266    ///
267    /// The callback is invoked with the driver before the value is
268    /// deserialized, for instance to add [`Layer`](deser_core::de::Layer)s.
269    pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
270    where
271        T: Deserialize<'a>,
272        F: FnOnce(&mut DeserializeDriver<'_, 'a>),
273    {
274        de::Deserializer::deserialize_with(self, setup)
275    }
276
277    /// Parses the document and feeds the events into the driver.
278    ///
279    /// Events are emitted while the document is parsed.  Text is passed on
280    /// borrowed from the input unless it has references or line breaks
281    /// that are normalized.
282    pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
283        if let Some(err) = self.error.take() {
284            return Err(err);
285        }
286        let state = driver.state_mut();
287        if self.config.track_locations {
288            Source::set(state, self.input);
289        }
290        self.config.duplicate_keys.set(state);
291        TEXT_RULES.set(state);
292        // elements with attributes are text for types that expect text,
293        // text is an element for types that expect maps
294        ContentKey(self.config.names.text_key).set(state);
295        *state.get_mut::<Names>() = self.config.names.clone();
296        Parser {
297            input: self.input,
298            config: &self.config,
299            reader: NsReader::from_str(self.input),
300            stack: Vec::new(),
301            root_done: false,
302            root: None,
303            declarations: None,
304        }
305        .run(driver)
306        .map_err(|err| err.resolve_position(self.input.as_bytes()))
307    }
308}
309
310impl<'a> de::Deserializer<'a> for Deserializer<'a> {
311    fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
312        Deserializer::drive(self, driver)
313    }
314}
315
316/// How the text of XML is interpreted.
317///
318/// Booleans are `true` and `false` (XML Schema also allows `1` and `0`,
319/// which are integers here), an empty element is a missing value for types
320/// that do not accept it (`<age/>` is `None` for an `Option<u32>`).
321const TEXT_RULES: LexicalRules = LexicalRules::STRICT.with_empty_is_null(true);
322
323/// A byte range in the input.
324type Range = (usize, usize);
325
326/// The text of an element that was not passed on yet.
327enum PendingText<'a> {
328    None,
329    Borrowed(&'a str, Range),
330    Owned(String, Range),
331}
332
333impl<'a> PendingText<'a> {
334    fn push(&mut self, text: Cow<'a, str>, range: Range) {
335        *self = match (std::mem::replace(self, PendingText::None), text) {
336            (PendingText::None, Cow::Borrowed(text)) => PendingText::Borrowed(text, range),
337            (PendingText::None, Cow::Owned(text)) => PendingText::Owned(text, range),
338            (PendingText::Borrowed(prev, (start, _)), text) => {
339                PendingText::Owned(prev.to_string() + &text, (start, range.1))
340            }
341            (PendingText::Owned(mut prev, (start, _)), text) => {
342                prev.push_str(&text);
343                PendingText::Owned(prev, (start, range.1))
344            }
345        };
346    }
347
348    fn is_blank(&self) -> bool {
349        match self {
350            PendingText::None => true,
351            PendingText::Borrowed(text, _) => is_blank(text),
352            PendingText::Owned(text, _) => is_blank(text),
353        }
354    }
355
356    /// Emits the text as lexical atom.
357    fn emit(self, driver: &mut DeserializeDriver<'_, 'a>, fallback: Range) -> Result<(), Error> {
358        match self {
359            PendingText::None => emit_at(driver, Atom::Lexical(Text::borrowed("")), fallback),
360            PendingText::Borrowed(text, range) => {
361                driver.state_mut().set_input_range(range.0, range.1);
362                driver.emit_borrowed(Atom::Lexical(Text::borrowed(text)))
363            }
364            PendingText::Owned(text, range) => {
365                emit_at(driver, Atom::Lexical(Text::owned(text)), range)
366            }
367        }
368    }
369}
370
371fn is_blank(text: &str) -> bool {
372    text.bytes()
373        .all(|b| matches!(b, b' ' | b'\t' | b'\n' | b'\r'))
374}
375
376/// An open element.
377struct Element<'a> {
378    /// `true` once the element was passed on as map.
379    is_map: bool,
380    text: PendingText<'a>,
381    /// The range of the start tag.
382    start: Range,
383}
384
385struct Parser<'a, 'c> {
386    input: &'a str,
387    config: &'c DeserializerConfig,
388    reader: NsReader<&'a [u8]>,
389    stack: Vec<Element<'a>>,
390    root_done: bool,
391    /// The name and the namespaces of the root element until they are
392    /// attached to its first event.
393    root: Option<RootData>,
394    /// The namespaces declared on the last element that was started until
395    /// they are attached to its first event.
396    declarations: Option<Vec<(String, String)>>,
397}
398
399impl<'a> Parser<'a, '_> {
400    fn run(mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
401        loop {
402            let start = self.position();
403            let event = self
404                .reader
405                .read_event()
406                .map_err(|err| xml_error(err, self.reader.error_position() as usize))?;
407            let range = (start, self.position());
408            match event {
409                XmlEvent::Start(ref tag) => self.start(driver, tag, range)?,
410                XmlEvent::Empty(ref tag) => {
411                    self.start(driver, tag, range)?;
412                    self.end(driver, range)?;
413                }
414                XmlEvent::End(_) => self.end(driver, range)?,
415                XmlEvent::Text(text) => {
416                    self.text(text.xml_content(XmlVersion::Implicit1_0), range)?
417                }
418                XmlEvent::CData(text) => {
419                    self.text(text.xml_content(XmlVersion::Implicit1_0), range)?
420                }
421                XmlEvent::GeneralRef(reference) => {
422                    let text = resolve_reference(&reference, start)?;
423                    self.text(Cow::Owned(text.to_string()), range)?
424                }
425                XmlEvent::Decl(_)
426                | XmlEvent::PI(_)
427                | XmlEvent::Comment(_)
428                | XmlEvent::DocType(_) => {}
429                XmlEvent::Eof => {
430                    if !self.stack.is_empty() {
431                        return Err(Error::new(
432                            ErrorKind::EndOfFile,
433                            "unexpected end of input, an element is not closed",
434                        )
435                        .with_offset(start));
436                    }
437                    if !self.root_done {
438                        return Err(
439                            Error::new(ErrorKind::EndOfFile, "no root element").with_offset(start)
440                        );
441                    }
442                    return Ok(());
443                }
444            }
445        }
446    }
447
448    fn position(&self) -> usize {
449        self.reader.buffer_position() as usize
450    }
451
452    /// Passes on the element on top of the stack as map if it's not yet.
453    fn make_map(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
454        if !self.stack.last().unwrap().is_map {
455            self.attach_element(driver);
456            let element = self.stack.last_mut().unwrap();
457            element.is_map = true;
458            emit_at(
459                driver,
460                Event::MapStart(
461                    ContainerShape::new()
462                        .with_order(Order::Significant)
463                        .with_multimap(true),
464                ),
465                element.start,
466            )?;
467        }
468        self.flush_text(driver)
469    }
470
471    /// Passes on the text of the element on top of the stack as entry.
472    fn flush_text(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
473        let element = self.stack.last_mut().unwrap();
474        // whitespace between elements is not text, unless the content is
475        // mixed
476        if matches!(element.text, PendingText::None)
477            || (element.text.is_blank() && !WhitespaceDepths::applies(driver.state()))
478        {
479            element.text = PendingText::None;
480            return Ok(());
481        }
482        let text = std::mem::replace(&mut element.text, PendingText::None);
483        let range = match text {
484            PendingText::Borrowed(_, range) | PendingText::Owned(_, range) => range,
485            PendingText::None => unreachable!(),
486        };
487        emit_at(
488            driver,
489            Atom::Lexical(Text::borrowed(self.config.names.text_key)),
490            range,
491        )?;
492        text.emit(driver, range)
493    }
494
495    fn start(
496        &mut self,
497        driver: &mut DeserializeDriver<'_, 'a>,
498        tag: &BytesStart<'a>,
499        range: Range,
500    ) -> Result<(), Error> {
501        if self.stack.is_empty() {
502            if self.root_done {
503                return Err(
504                    Error::new(ErrorKind::Unexpected, "more than one root element")
505                        .with_offset(range.0),
506                );
507            }
508            self.root = Some(self.root_data(tag, range.0)?);
509        } else {
510            self.make_map(driver)?;
511            let name = self.name(tag.name(), false, range.0)?;
512            emit_key(driver, name, range)?;
513            // most elements declare nothing, the attributes are only
514            // looked at if they might
515            if tag.attributes_raw().contains("xmlns") {
516                let declarations = self.declarations(tag, false, range.0)?;
517                if !declarations.is_empty() {
518                    self.declarations = Some(declarations);
519                }
520            }
521        }
522        self.stack.push(Element {
523            is_map: false,
524            text: PendingText::None,
525            start: range,
526        });
527
528        for attr in tag.attributes() {
529            let attr = attr.map_err(|err| {
530                Error::new(ErrorKind::Unexpected, format!("invalid attribute: {err}"))
531                    .with_offset(range.0)
532            })?;
533            let raw = attr.key.as_ref();
534            // namespace declarations are not data
535            if raw == "xmlns" || raw.starts_with("xmlns:") {
536                continue;
537            }
538            self.make_map(driver)?;
539            let name = self.name(attr.key, true, range.0)?;
540            emit_key(driver, name, range)?;
541            let value = attr
542                .normalized_value(XmlVersion::Implicit1_0)
543                .map_err(|err| xml_error(err, range.0))?;
544            match reborrow(self.input, &value) {
545                Some(value) => {
546                    driver.state_mut().set_input_range(range.0, range.1);
547                    driver.emit_borrowed(Atom::Lexical(Text::borrowed(value)))?;
548                }
549                None => emit_at(driver, Atom::Lexical(Text::borrowed(&value)), range)?,
550            }
551        }
552        Ok(())
553    }
554
555    /// Returns the name of the root element and the namespaces declared
556    /// on it.
557    ///
558    /// Namespaces with a configured prefix are declared with it as that's
559    /// how names in them are passed on.
560    fn root_data(&self, tag: &BytesStart<'a>, offset: usize) -> Result<RootData, Error> {
561        Ok(RootData {
562            name: Some(self.name(tag.name(), false, offset)?.into_owned()),
563            namespaces: self.declarations(tag, true, offset)?,
564        })
565    }
566
567    /// Returns the namespaces declared on an element.
568    ///
569    /// Namespaces with a configured prefix are declared with it as that's
570    /// how names in them are passed on.  Undeclaring the default namespace
571    /// (`xmlns=""`) is a declaration with an empty URI, except on the root
572    /// where there is nothing to undeclare.
573    fn declarations(
574        &self,
575        tag: &BytesStart<'a>,
576        is_root: bool,
577        offset: usize,
578    ) -> Result<Vec<(String, String)>, Error> {
579        let mut namespaces: Vec<(String, String)> = Vec::new();
580        // invalid attributes are reported when the attributes are passed on
581        for attr in tag.attributes().flatten() {
582            let raw: &str = attr.key.as_ref();
583            let prefix = match raw.strip_prefix("xmlns") {
584                Some("") => "",
585                Some(rest) => match rest.strip_prefix(':') {
586                    Some(prefix) => prefix,
587                    None => continue,
588                },
589                None => continue,
590            };
591            let uri = attr
592                .normalized_value(XmlVersion::Implicit1_0)
593                .map_err(|err| xml_error(err, offset))?;
594            if uri.is_empty() && (is_root || !prefix.is_empty()) {
595                continue;
596            }
597            let prefix = match self.config.names.namespaces.iter().find(|(_, x)| *x == uri) {
598                Some((alias, _)) => alias,
599                None => prefix,
600            };
601            if !namespaces.iter().any(|(x, _)| x == prefix) {
602                namespaces.push((prefix.to_string(), uri.into_owned()));
603            }
604        }
605        Ok(namespaces)
606    }
607
608    /// Attaches the name and the namespaces of the root element or the
609    /// namespaces declared on another element to its first event.
610    ///
611    /// The first event of an element comes before the events of the
612    /// elements in it, so the element they are for is the last one that was
613    /// started.
614    fn attach_element(&mut self, driver: &mut DeserializeDriver<'_, 'a>) {
615        if let Some(root) = self.root.take() {
616            *driver.state_mut().event_mut::<RootData>() = root;
617        }
618        if let Some(declarations) = self.declarations.take() {
619            driver.state_mut().event_mut::<Declarations>().0 = declarations;
620        }
621    }
622
623    fn end(&mut self, driver: &mut DeserializeDriver<'_, 'a>, range: Range) -> Result<(), Error> {
624        if self.stack.last().unwrap().is_map {
625            self.flush_text(driver)?;
626            self.stack.pop();
627            emit_at(driver, Event::MapEnd, range)?;
628            WhitespaceDepths::prune(driver.state_mut());
629        } else {
630            self.attach_element(driver);
631            let element = self.stack.pop().unwrap();
632            element.text.emit(driver, element.start)?;
633        }
634        if self.stack.is_empty() {
635            self.root_done = true;
636        }
637        Ok(())
638    }
639
640    fn text(&mut self, text: Cow<'a, str>, range: Range) -> Result<(), Error> {
641        match self.stack.last_mut() {
642            Some(element) => {
643                element.text.push(text, range);
644                Ok(())
645            }
646            None if is_blank(&text) => Ok(()),
647            None => Err(
648                Error::new(ErrorKind::Unexpected, "text outside of the root element")
649                    .with_offset(range.0),
650            ),
651        }
652    }
653
654    /// Returns the key of an element or attribute.
655    fn name(
656        &self,
657        name: QName<'_>,
658        is_attribute: bool,
659        offset: usize,
660    ) -> Result<Cow<'a, str>, Error> {
661        let names = &self.config.names;
662        let written: &str = name.as_ref();
663        let local_name = name.local_name();
664        let local: &str = local_name.as_ref();
665        let mut key = match self.namespace(name, is_attribute) {
666            Namespace::Alias("") => Cow::Owned(local.to_string()),
667            Namespace::Alias(alias) => Cow::Owned(format!("{alias}:{local}")),
668            Namespace::Uri(uri) => Cow::Owned(format!("{{{uri}}}{local}")),
669            Namespace::Unknown if self.config.resolve_namespaces => {
670                return Err(Error::new(
671                    ErrorKind::Unexpected,
672                    format!("the prefix of `{written}` is not declared"),
673                )
674                .with_offset(offset));
675            }
676            Namespace::Written | Namespace::Unknown => match reborrow(self.input, written) {
677                Some(written) => Cow::Borrowed(written),
678                None => Cow::Owned(written.to_string()),
679            },
680        };
681        if is_attribute && !names.attribute_prefix.is_empty() {
682            key = Cow::Owned(format!("{}{}", names.attribute_prefix, key));
683        }
684        Ok(key)
685    }
686
687    /// Returns how the namespace of a name is written.
688    fn namespace(&self, name: QName<'_>, is_attribute: bool) -> Namespace {
689        let namespaces = self.config.names.namespaces;
690        let resolve = self.config.resolve_namespaces;
691        if namespaces.is_empty() && !resolve {
692            return Namespace::Written;
693        }
694        let resolver = self.reader.resolver();
695        let (ns, _) = if is_attribute {
696            resolver.resolve_attribute(name)
697        } else {
698            resolver.resolve_element(name)
699        };
700        match ns {
701            ResolveResult::Bound(ns) => {
702                let uri: &str = ns.as_ref();
703                if let Some((alias, _)) = namespaces.iter().find(|(_, x)| *x == uri) {
704                    Namespace::Alias(alias)
705                } else if !resolve {
706                    Namespace::Written
707                } else if uri == XML_NAMESPACE {
708                    Namespace::Alias("xml")
709                } else {
710                    Namespace::Uri(uri.to_string())
711                }
712            }
713            ResolveResult::Unbound => Namespace::Written,
714            ResolveResult::Unknown(_) => Namespace::Unknown,
715        }
716    }
717}
718
719/// The namespace of the `xml` prefix.
720pub(crate) const XML_NAMESPACE: &str = "http://www.w3.org/XML/1998/namespace";
721
722/// How the namespace of a name is written.
723enum Namespace {
724    /// The name is passed on as written.
725    Written,
726    /// The name has the configured prefix.
727    Alias(&'static str),
728    /// The name is `{uri}local`.
729    Uri(String),
730    /// The prefix is not declared.
731    Unknown,
732}
733
734/// Returns the text as a slice of the input if it is one.
735fn reborrow<'a>(input: &'a str, text: &str) -> Option<&'a str> {
736    let start = (text.as_ptr() as usize).checked_sub(input.as_ptr() as usize)?;
737    let end = start.checked_add(text.len())?;
738    input
739        .get(start..end)
740        .filter(|x| x.as_ptr() == text.as_ptr())
741}
742
743/// Resolves a character or entity reference.
744///
745/// Only the predefined entities are supported, the entities of document
746/// types are never expanded.
747fn resolve_reference(reference: &BytesRef<'_>, offset: usize) -> Result<char, Error> {
748    if let Some(c) = reference
749        .resolve_char_ref()
750        .map_err(|err| xml_error(err, offset))?
751    {
752        return Ok(c);
753    }
754    match &*reference.xml_content(XmlVersion::Implicit1_0) {
755        "lt" => Ok('<'),
756        "gt" => Ok('>'),
757        "amp" => Ok('&'),
758        "apos" => Ok('\''),
759        "quot" => Ok('"'),
760        name => Err(
761            Error::new(ErrorKind::Unexpected, format!("unknown entity `&{name};`"))
762                .with_offset(offset),
763        ),
764    }
765}
766
767fn xml_error(err: quick_xml::Error, offset: usize) -> Error {
768    Error::new(ErrorKind::Unexpected, format!("invalid XML: {err}")).with_offset(offset)
769}
770
771fn emit_key<'a>(
772    driver: &mut DeserializeDriver<'_, 'a>,
773    key: Cow<'a, str>,
774    range: Range,
775) -> Result<(), Error> {
776    driver.state_mut().set_input_range(range.0, range.1);
777    match key {
778        Cow::Borrowed(key) => driver.emit_borrowed(Atom::Lexical(Text::borrowed(key))),
779        Cow::Owned(key) => driver.emit(Atom::Lexical(Text::owned(key))),
780    }
781}
782
783fn emit_at<'e, E: Into<Event<'e>>>(
784    driver: &mut DeserializeDriver<'_, '_>,
785    event: E,
786    range: Range,
787) -> Result<(), Error> {
788    driver.state_mut().set_input_range(range.0, range.1);
789    driver.emit(event)
790}