Skip to main content

deser_xml/
de.rs

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