Skip to main content

oxixml_xml/
name.rs

1//! Handling of names according to the W3C [Namespaces in XML 1.1 (Second
2//! Edition)][spec] specification.
3//!
4//! This mirrors quick-xml 0.41 `name`: [`QName`] is a raw, possibly-prefixed
5//! name; [`LocalName`], [`Prefix`] and [`Namespace`] are its pieces; and
6//! [`NamespaceResolver`] tracks the in-scope `prefix -> namespace` bindings a
7//! streaming parser pushes and pops one element at a time, producing a
8//! [`ResolveResult`].
9//!
10//! [spec]: https://www.w3.org/TR/xml-names11
11
12use crate::escape::normalize_xml10_attribute_value;
13use crate::escape::{is_xml10_normalization_char, resolve_xml_entity};
14use crate::events::attributes::Attribute;
15use crate::events::{BytesStart, Event};
16use crate::utils::{Bytes, write_byte_string};
17use oxixml_support::bytes::memchr;
18use std::borrow::Cow;
19use std::fmt::{self, Debug, Formatter};
20use std::iter::FusedIterator;
21
22/// Some namespace was invalid.
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum NamespaceError {
25    /// The specified namespace prefix is unknown; a namespace cannot be resolved for it.
26    UnknownPrefix(Vec<u8>),
27    /// Attempt to bind the `xml` prefix to something other than
28    /// `http://www.w3.org/XML/1998/namespace`. Contains the offending namespace.
29    InvalidXmlPrefixBind(Vec<u8>),
30    /// Attempt to bind the `xmlns` prefix. Contains the offending namespace.
31    InvalidXmlnsPrefixBind(Vec<u8>),
32    /// Attempt to bind some prefix (other than `xml`) to
33    /// `http://www.w3.org/XML/1998/namespace`. Contains the offending prefix.
34    InvalidPrefixForXml(Vec<u8>),
35    /// Attempt to bind some prefix to `http://www.w3.org/2000/xmlns/`. Contains
36    /// the offending prefix.
37    InvalidPrefixForXmlns(Vec<u8>),
38    /// A single start tag declared more `xmlns` / `xmlns:*` bindings than the
39    /// configured [`NamespaceResolver::max_declarations_per_element`] limit.
40    /// Contains the configured limit.
41    TooManyDeclarations(usize),
42    /// Opening a new element would nest the namespace scope deeper than the
43    /// allowed maximum, either because
44    /// [`Config::max_element_depth`](crate::reader::Config::max_element_depth)
45    /// was reached, or (independent of any configured limit) because the
46    /// nesting-level counter itself cannot represent a deeper scope. Contains
47    /// the limit that was reached.
48    TooDeeplyNested(usize),
49}
50
51impl fmt::Display for NamespaceError {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        match self {
54            Self::UnknownPrefix(prefix) => {
55                f.write_str("unknown namespace prefix '")?;
56                write_byte_string(f, prefix)?;
57                f.write_str("'")
58            }
59            Self::InvalidXmlPrefixBind(namespace) => {
60                f.write_str("the namespace prefix 'xml' cannot be bound to '")?;
61                write_byte_string(f, namespace)?;
62                f.write_str("'")
63            }
64            Self::InvalidXmlnsPrefixBind(namespace) => {
65                f.write_str("the namespace prefix 'xmlns' cannot be bound to '")?;
66                write_byte_string(f, namespace)?;
67                f.write_str("'")
68            }
69            Self::InvalidPrefixForXml(prefix) => {
70                f.write_str("the namespace prefix '")?;
71                write_byte_string(f, prefix)?;
72                f.write_str("' cannot be bound to 'http://www.w3.org/XML/1998/namespace'")
73            }
74            Self::InvalidPrefixForXmlns(prefix) => {
75                f.write_str("the namespace prefix '")?;
76                write_byte_string(f, prefix)?;
77                f.write_str("' cannot be bound to 'http://www.w3.org/2000/xmlns/'")
78            }
79            Self::TooManyDeclarations(limit) => write!(
80                f,
81                "start tag declares more than {} namespace bindings; \
82                 raise the limit with NamespaceResolver::set_max_declarations_per_element",
83                limit,
84            ),
85            Self::TooDeeplyNested(limit) => write!(
86                f,
87                "element nesting exceeds the maximum depth of {} elements",
88                limit,
89            ),
90        }
91    }
92}
93
94impl std::error::Error for NamespaceError {}
95
96////////////////////////////////////////////////////////////////////////////////////////////////////
97
98/// A [qualified name] of an element or an attribute, including an optional
99/// namespace [prefix](Prefix) and a [local name](LocalName).
100///
101/// [qualified name]: https://www.w3.org/TR/xml-names11/#dt-qualname
102#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
103#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
104pub struct QName<'a>(pub &'a [u8]);
105impl<'a> QName<'a> {
106    /// Converts this name to its internal slice representation.
107    #[inline(always)]
108    pub const fn into_inner(self) -> &'a [u8] {
109        self.0
110    }
111
112    /// Returns the local part of this qualified name.
113    ///
114    /// All content up to and including the first `:` character is removed.
115    ///
116    /// ```
117    /// # use oxixml_xml::name::QName;
118    /// let simple = QName(b"simple-name");
119    /// assert_eq!(simple.local_name().as_ref(), b"simple-name");
120    ///
121    /// let qname = QName(b"namespace:simple-name");
122    /// assert_eq!(qname.local_name().as_ref(), b"simple-name");
123    /// ```
124    pub fn local_name(&self) -> LocalName<'a> {
125        LocalName(self.index().map_or(self.0, |i| &self.0[i + 1..]))
126    }
127
128    /// Returns the namespace prefix of this qualified name, or `None` if it has no
129    /// prefix (no `:` was found).
130    ///
131    /// ```
132    /// # use oxixml_xml::name::QName;
133    /// let simple = QName(b"simple-name");
134    /// assert_eq!(simple.prefix(), None);
135    ///
136    /// let qname = QName(b"prefix:simple-name");
137    /// assert_eq!(qname.prefix().as_ref().map(|n| n.as_ref()), Some(b"prefix".as_ref()));
138    /// ```
139    pub fn prefix(&self) -> Option<Prefix<'a>> {
140        self.index().map(|i| Prefix(&self.0[..i]))
141    }
142
143    /// The same as `(qname.local_name(), qname.prefix())`, but performs only one
144    /// lookup for the `':'` symbol.
145    pub fn decompose(&self) -> (LocalName<'a>, Option<Prefix<'a>>) {
146        match self.index() {
147            None => (LocalName(self.0), None),
148            Some(i) => (LocalName(&self.0[i + 1..]), Some(Prefix(&self.0[..i]))),
149        }
150    }
151
152    /// If this `QName` represents an `xmlns` binding, returns `Some`, otherwise
153    /// `None`.
154    ///
155    /// ```
156    /// # use oxixml_xml::name::{QName, PrefixDeclaration};
157    /// let qname = QName(b"xmlns");
158    /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Default));
159    ///
160    /// let qname = QName(b"xmlns:prefix");
161    /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"prefix")));
162    ///
163    /// // This method does not validate the prefix — it can be empty!
164    /// let qname = QName(b"xmlns:");
165    /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"")));
166    ///
167    /// let qname = QName(b"other-name");
168    /// assert_eq!(qname.as_namespace_binding(), None);
169    ///
170    /// let qname = QName(b"xmlns-reserved-name");
171    /// assert_eq!(qname.as_namespace_binding(), None);
172    /// ```
173    pub fn as_namespace_binding(&self) -> Option<PrefixDeclaration<'a>> {
174        if self.0.starts_with(b"xmlns") {
175            return match self.0.get(5) {
176                None => Some(PrefixDeclaration::Default),
177                Some(&b':') => Some(PrefixDeclaration::Named(&self.0[6..])),
178                _ => None,
179            };
180        }
181        None
182    }
183
184    /// Returns the index in the name where the prefix ends.
185    #[inline(always)]
186    fn index(&self) -> Option<usize> {
187        memchr(b':', self.0)
188    }
189}
190impl<'a> Debug for QName<'a> {
191    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
192        write!(f, "QName(")?;
193        write_byte_string(f, self.0)?;
194        write!(f, ")")
195    }
196}
197impl<'a> AsRef<[u8]> for QName<'a> {
198    #[inline]
199    fn as_ref(&self) -> &[u8] {
200        self.0
201    }
202}
203
204////////////////////////////////////////////////////////////////////////////////////////////////////
205
206/// A [local (unqualified) name] of an element or an attribute, i.e. a name
207/// without a [prefix](Prefix).
208///
209/// [local (unqualified) name]: https://www.w3.org/TR/xml-names11/#dt-localname
210#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
211#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
212pub struct LocalName<'a>(pub(crate) &'a [u8]);
213impl<'a> LocalName<'a> {
214    /// Converts this name to its internal slice representation.
215    #[inline(always)]
216    pub const fn into_inner(self) -> &'a [u8] {
217        self.0
218    }
219}
220impl<'a> Debug for LocalName<'a> {
221    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
222        write!(f, "LocalName(")?;
223        write_byte_string(f, self.0)?;
224        write!(f, ")")
225    }
226}
227impl<'a> AsRef<[u8]> for LocalName<'a> {
228    #[inline]
229    fn as_ref(&self) -> &[u8] {
230        self.0
231    }
232}
233impl<'a> From<QName<'a>> for LocalName<'a> {
234    /// Creates a `LocalName` from a [`QName`].
235    ///
236    /// ```
237    /// # use oxixml_xml::name::{LocalName, QName};
238    /// let local: LocalName = QName(b"unprefixed").into();
239    /// assert_eq!(local.as_ref(), b"unprefixed");
240    ///
241    /// let local: LocalName = QName(b"some:prefix").into();
242    /// assert_eq!(local.as_ref(), b"prefix");
243    /// ```
244    #[inline]
245    fn from(name: QName<'a>) -> Self {
246        Self(name.index().map_or(name.0, |i| &name.0[i + 1..]))
247    }
248}
249
250////////////////////////////////////////////////////////////////////////////////////////////////////
251
252/// A [namespace prefix] part of the [qualified name](QName) of an element or an
253/// attribute: the `prefix` in `<prefix:local>` or `prefix:local="value"`.
254///
255/// [namespace prefix]: https://www.w3.org/TR/xml-names11/#dt-prefix
256#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
257#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
258pub struct Prefix<'a>(&'a [u8]);
259impl<'a> Prefix<'a> {
260    /// Extracts the internal slice.
261    #[inline(always)]
262    pub const fn into_inner(self) -> &'a [u8] {
263        self.0
264    }
265
266    /// Checks whether this prefix is the special prefix `xml`.
267    #[inline(always)]
268    pub const fn is_xml(&self) -> bool {
269        matches!(self.0, b"xml")
270    }
271
272    /// Checks whether this prefix is the special prefix `xmlns`.
273    #[inline(always)]
274    pub const fn is_xmlns(&self) -> bool {
275        matches!(self.0, b"xmlns")
276    }
277}
278impl<'a> Debug for Prefix<'a> {
279    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
280        write!(f, "Prefix(")?;
281        write_byte_string(f, self.0)?;
282        write!(f, ")")
283    }
284}
285impl<'a> AsRef<[u8]> for Prefix<'a> {
286    #[inline]
287    fn as_ref(&self) -> &[u8] {
288        self.0
289    }
290}
291
292////////////////////////////////////////////////////////////////////////////////////////////////////
293
294/// A namespace prefix declaration, `xmlns` or `xmlns:<name>`, as defined in the
295/// [Namespaces in XML specification](https://www.w3.org/TR/xml-names11/#ns-decl).
296#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
297pub enum PrefixDeclaration<'a> {
298    /// Binds the default namespace. Corresponds to `xmlns` in `xmlns="..."`.
299    Default,
300    /// Binds a specified prefix to a namespace. Corresponds to a `prefix` in
301    /// `xmlns:prefix="..."`, stored as the payload of this variant.
302    Named(&'a [u8]),
303}
304impl<'a> Debug for PrefixDeclaration<'a> {
305    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
306        match self {
307            Self::Default => f.write_str("PrefixDeclaration::Default"),
308            Self::Named(prefix) => {
309                f.write_str("PrefixDeclaration::Named(")?;
310                write_byte_string(f, prefix)?;
311                f.write_str(")")
312            }
313        }
314    }
315}
316
317////////////////////////////////////////////////////////////////////////////////////////////////////
318
319/// A [namespace name] that is declared in an `xmlns[:prefix]="namespace name"`.
320///
321/// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
322#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
323#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
324pub struct Namespace<'a>(pub &'a [u8]);
325impl<'a> Namespace<'a> {
326    /// Converts this namespace to its internal slice representation.
327    ///
328    /// This is a [non-normalized] attribute value, i.e. entity references are not
329    /// expanded and space characters are not removed, so two different byte slices
330    /// returned from this method can represent the same namespace.
331    ///
332    /// [non-normalized]: https://www.w3.org/TR/xml11/#AVNormalize
333    #[inline(always)]
334    pub const fn into_inner(self) -> &'a [u8] {
335        self.0
336    }
337}
338impl<'a> Debug for Namespace<'a> {
339    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
340        write!(f, "Namespace(")?;
341        write_byte_string(f, self.0)?;
342        write!(f, ")")
343    }
344}
345impl<'a> AsRef<[u8]> for Namespace<'a> {
346    #[inline]
347    fn as_ref(&self) -> &[u8] {
348        self.0
349    }
350}
351
352////////////////////////////////////////////////////////////////////////////////////////////////////
353
354/// Result of [prefix](Prefix) resolution produced by [`NamespaceResolver::resolve`].
355#[derive(Clone, PartialEq, Eq, Hash)]
356pub enum ResolveResult<'ns> {
357    /// The qualified name has no prefix and the resolver defines no default
358    /// namespace, so the name is not bound to any namespace.
359    Unbound,
360    /// The [`Prefix`] resolved to the specified namespace.
361    Bound(Namespace<'ns>),
362    /// The specified prefix was not found in scope.
363    Unknown(Vec<u8>),
364}
365impl<'ns> Debug for ResolveResult<'ns> {
366    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
367        match self {
368            Self::Unbound => write!(f, "Unbound"),
369            Self::Bound(ns) => write!(f, "Bound({:?})", ns),
370            Self::Unknown(p) => {
371                write!(f, "Unknown(")?;
372                write_byte_string(f, p)?;
373                write!(f, ")")
374            }
375        }
376    }
377}
378
379impl<'ns> TryFrom<ResolveResult<'ns>> for Option<Namespace<'ns>> {
380    type Error = NamespaceError;
381
382    /// Converts this result to an optional namespace, returning
383    /// [`NamespaceError::UnknownPrefix`] if the result represents an unknown prefix.
384    fn try_from(result: ResolveResult<'ns>) -> Result<Self, NamespaceError> {
385        use ResolveResult::*;
386
387        match result {
388            Unbound => Ok(None),
389            Bound(ns) => Ok(Some(ns)),
390            Unknown(p) => Err(NamespaceError::UnknownPrefix(p)),
391        }
392    }
393}
394
395////////////////////////////////////////////////////////////////////////////////////////////////////
396
397/// An entry that indexes into the namespace buffer with a single binding.
398#[derive(Debug, Clone)]
399struct NamespaceBinding {
400    /// Index of the namespace in the buffer.
401    start: usize,
402    /// Length of the prefix. If greater than zero, binds the namespace to the
403    /// slice `[start..start + prefix_len]`; else defines the default namespace.
404    prefix_len: usize,
405    /// Length of the namespace name (the URI). An empty value 'removes' the
406    /// binding for the extent of its scope.
407    value_len: usize,
408    /// Level of nesting at which this namespace was declared (the declaring
409    /// element is included, so a declaration on the document root has `level = 1`).
410    level: usize,
411}
412
413impl NamespaceBinding {
414    /// Gets the namespace prefix bound by this declaration, or `None` for a
415    /// default-namespace declaration (`xmlns="..."`).
416    #[inline]
417    const fn prefix<'b>(&self, buffer: &'b [u8]) -> Option<Prefix<'b>> {
418        if self.prefix_len == 0 {
419            None
420        } else {
421            let (_, prefix) = buffer.split_at(self.start);
422            let (prefix, _) = prefix.split_at(self.prefix_len);
423            Some(Prefix(prefix))
424        }
425    }
426
427    /// Gets the namespace name (the URI) of this binding, or [`ResolveResult::Unbound`]
428    /// if the binding was reset with `xmlns[:prefix]=""`.
429    #[inline]
430    const fn namespace<'ns>(&self, buffer: &'ns [u8]) -> ResolveResult<'ns> {
431        if self.value_len == 0 {
432            ResolveResult::Unbound
433        } else {
434            let (_, ns) = buffer.split_at(self.start + self.prefix_len);
435            let (ns, _) = ns.split_at(self.value_len);
436            ResolveResult::Bound(Namespace(ns))
437        }
438    }
439}
440
441/// Storage for the currently defined namespace bindings, used to resolve prefixes
442/// into namespaces. Holds all the internal logic to push and pop namespaces with
443/// their levels.
444#[derive(Clone)]
445pub struct NamespaceResolver {
446    /// Buffer that contains namespace prefix names and namespace values.
447    buffer: Vec<u8>,
448    /// A stack of namespace bindings currently in scope.
449    bindings: Vec<NamespaceBinding>,
450    /// The number of currently open tags, used to know which declarations to
451    /// remove when an `End` event is encountered. Widened to `usize` (rather
452    /// than a fixed-width integer) so that raising
453    /// [`Config::max_element_depth`](crate::reader::Config::max_element_depth)
454    /// past a small fixed bound can never overflow this counter; [`push`](Self::push)
455    /// still guards the arithmetic with `checked_add` as defense in depth for
456    /// callers that manipulate the level directly through [`set_level`](Self::set_level).
457    nesting_level: usize,
458    /// Maximum number of `xmlns` / `xmlns:*` declarations [`push`](Self::push)
459    /// will accept on a single start tag.
460    max_declarations_per_element: usize,
461}
462
463/// Default limit on the number of `xmlns` / `xmlns:*` declarations
464/// [`NamespaceResolver::push`] accepts on a single start tag.
465pub const DEFAULT_MAX_DECLARATIONS_PER_ELEMENT: usize = 256;
466
467impl Debug for NamespaceResolver {
468    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
469        f.debug_struct("NamespaceResolver")
470            .field("buffer", &Bytes(&self.buffer))
471            .field("bindings", &self.bindings)
472            .field("nesting_level", &self.nesting_level)
473            .field(
474                "max_declarations_per_element",
475                &self.max_declarations_per_element,
476            )
477            .finish()
478    }
479}
480
481/// The reserved `xml` namespace binding.
482const RESERVED_NAMESPACE_XML: (Prefix, Namespace) = (
483    Prefix(b"xml"),
484    Namespace(b"http://www.w3.org/XML/1998/namespace"),
485);
486/// The reserved `xmlns` namespace binding.
487const RESERVED_NAMESPACE_XMLNS: (Prefix, Namespace) = (
488    Prefix(b"xmlns"),
489    Namespace(b"http://www.w3.org/2000/xmlns/"),
490);
491
492impl Default for NamespaceResolver {
493    fn default() -> Self {
494        let mut buffer = Vec::new();
495        let mut bindings = Vec::new();
496        for ent in &[RESERVED_NAMESPACE_XML, RESERVED_NAMESPACE_XMLNS] {
497            let prefix = ent.0.into_inner();
498            let uri = ent.1.into_inner();
499            bindings.push(NamespaceBinding {
500                start: buffer.len(),
501                prefix_len: prefix.len(),
502                value_len: uri.len(),
503                level: 0,
504            });
505            buffer.extend(prefix);
506            buffer.extend(uri);
507        }
508
509        Self {
510            buffer,
511            bindings,
512            nesting_level: 0,
513            max_declarations_per_element: DEFAULT_MAX_DECLARATIONS_PER_ELEMENT,
514        }
515    }
516}
517
518/// Applies [XML §3.3.3] attribute-value normalization to the raw bytes of an
519/// `xmlns` / `xmlns:*` attribute, so that the namespace name a prefix is bound to
520/// is the one an application reading the same attribute would see.
521///
522/// Returns `None` when the raw bytes are already normal — the overwhelmingly
523/// common case, which then costs one scan and no allocation — and also when they
524/// cannot be normalized here at all: bytes that are not UTF-8, or a reference to
525/// an entity declared by the document rather than by the specification, which
526/// only the reader holding the internal subset can resolve. Neither is a
527/// namespace name this resolver can improve on, and neither is this resolver's
528/// to report: the raw bytes are bound, and the reader's own well-formedness
529/// checks — which do see the document's entity declarations — finish the job.
530///
531/// Only the five entities [XML §4.6] predefines are resolved, never a wider set:
532/// a namespace name is part of a document's identity, and which names two
533/// prefixes bind must not depend on whether this crate was built with HTML
534/// entity support.
535///
536/// The rules applied are XML 1.0's. XML 1.1 additionally folds U+0085 and U+2028
537/// as line breaks, but neither is permitted in a namespace name — which
538/// [Namespaces in XML §3] requires to be an IRI reference — so the two versions
539/// cannot disagree on a namespace name that is valid in the first place.
540///
541/// [XML §3.3.3]: https://www.w3.org/TR/xml/#AVNormalize
542/// [XML §4.6]: https://www.w3.org/TR/xml/#sec-predefined-ent
543/// [Namespaces in XML §3]: https://www.w3.org/TR/xml-names11/#ns-decl
544fn normalized_namespace(raw: &[u8]) -> Option<Vec<u8>> {
545    if !raw.iter().any(is_xml10_normalization_char) {
546        return None;
547    }
548    let text = std::str::from_utf8(raw).ok()?;
549    // A depth of 1 is enough: `resolve_xml_entity` never yields a replacement
550    // that holds a reference of its own.
551    match normalize_xml10_attribute_value(text, 1, resolve_xml_entity) {
552        Ok(Cow::Owned(normalized)) => Some(normalized.into_bytes()),
553        Ok(Cow::Borrowed(_)) | Err(_) => None,
554    }
555}
556
557impl NamespaceResolver {
558    /// Adds a new binding of `prefix` to `namespace` at the current nesting level.
559    ///
560    /// The binding is removed when the level is [popped out](Self::pop). May fail
561    /// if you try to (re-)declare the reserved prefixes `xml` and `xmlns`.
562    ///
563    /// ```
564    /// # use oxixml_xml::name::{Namespace, NamespaceResolver, PrefixDeclaration, QName, ResolveResult};
565    /// let mut resolver = NamespaceResolver::default();
566    /// assert_eq!(resolver.resolve_element(QName(b"name")).0, ResolveResult::Unbound);
567    /// assert_eq!(
568    ///     resolver.resolve_element(QName(b"ns:name")).0,
569    ///     ResolveResult::Unknown(b"ns".to_vec()),
570    /// );
571    ///
572    /// resolver.add(PrefixDeclaration::Default, Namespace(b"example.com")).expect("doc example");
573    /// resolver.add(PrefixDeclaration::Named(b"ns"), Namespace(b"my:namespace")).expect("doc example");
574    ///
575    /// assert_eq!(
576    ///     resolver.resolve_element(QName(b"name")).0,
577    ///     ResolveResult::Bound(Namespace(b"example.com")),
578    /// );
579    /// assert_eq!(
580    ///     resolver.resolve_element(QName(b"ns:name")).0,
581    ///     ResolveResult::Bound(Namespace(b"my:namespace")),
582    /// );
583    /// ```
584    pub fn add(
585        &mut self,
586        prefix: PrefixDeclaration,
587        namespace: Namespace,
588    ) -> Result<(), NamespaceError> {
589        let level = self.nesting_level;
590        match prefix {
591            PrefixDeclaration::Default => {
592                let start = self.buffer.len();
593                self.buffer.extend_from_slice(namespace.0);
594                self.bindings.push(NamespaceBinding {
595                    start,
596                    prefix_len: 0,
597                    value_len: namespace.0.len(),
598                    level,
599                });
600            }
601            PrefixDeclaration::Named(b"xml") => {
602                if namespace != RESERVED_NAMESPACE_XML.1 {
603                    return Err(NamespaceError::InvalidXmlPrefixBind(namespace.0.to_vec()));
604                }
605                // Do not add another binding for the `xml` namespace prefix.
606            }
607            PrefixDeclaration::Named(b"xmlns") => {
608                return Err(NamespaceError::InvalidXmlnsPrefixBind(namespace.0.to_vec()));
609            }
610            PrefixDeclaration::Named(prefix) => {
611                if namespace == RESERVED_NAMESPACE_XML.1 {
612                    return Err(NamespaceError::InvalidPrefixForXml(prefix.to_vec()));
613                } else if namespace == RESERVED_NAMESPACE_XMLNS.1 {
614                    return Err(NamespaceError::InvalidPrefixForXmlns(prefix.to_vec()));
615                }
616
617                let start = self.buffer.len();
618                self.buffer.extend_from_slice(prefix);
619                self.buffer.extend_from_slice(namespace.0);
620                self.bindings.push(NamespaceBinding {
621                    start,
622                    prefix_len: prefix.len(),
623                    value_len: namespace.0.len(),
624                    level,
625                });
626            }
627        }
628        Ok(())
629    }
630
631    /// Begins a new scope and adds to it all [namespace bindings] found in the
632    /// specified start element.
633    ///
634    /// The namespace name a declaration binds is its attribute's **normalized**
635    /// value: [Namespaces in XML §3] defines it as "the attribute value in the
636    /// namespace declaration", which [XML §3.3.3] has already normalized by the
637    /// time the value reaches an application. So a declaration written with a
638    /// literal tab in it binds a name with a *space* where the tab was, while
639    /// one written `urn:a&#9;b` binds a name that still holds the tab — a
640    /// character reference stands for the character it names, and is not white
641    /// space the algorithm folds. Either way the binding is the very string
642    /// [`Attribute::normalized_value`](crate::events::attributes::Attribute::normalized_value)
643    /// reports for the same attribute: one document cannot have two answers.
644    ///
645    /// [namespace bindings]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
646    /// [Namespaces in XML §3]: https://www.w3.org/TR/xml-names11/#ns-decl
647    /// [XML §3.3.3]: https://www.w3.org/TR/xml/#AVNormalize
648    pub fn push(&mut self, start: &BytesStart) -> Result<(), NamespaceError> {
649        // `usize` cannot realistically be exhausted by genuine XML nesting (it
650        // would require more open elements than fit in addressable memory),
651        // but a caller could still drive `nesting_level` to `usize::MAX`
652        // through direct `set_level` manipulation; guard the arithmetic
653        // instead of ever wrapping or panicking.
654        self.nesting_level = self
655            .nesting_level
656            .checked_add(1)
657            .ok_or(NamespaceError::TooDeeplyNested(usize::MAX))?;
658        let mut count = 0usize;
659        for a in start.attributes().with_checks(false) {
660            if let Ok(Attribute { key: k, value: v }) = a {
661                if let Some(prefix) = k.as_namespace_binding() {
662                    if count >= self.max_declarations_per_element {
663                        return Err(NamespaceError::TooManyDeclarations(
664                            self.max_declarations_per_element,
665                        ));
666                    }
667                    count += 1;
668                    match normalized_namespace(&v) {
669                        Some(normalized) => self.add(prefix, Namespace(&normalized))?,
670                        None => self.add(prefix, Namespace(&v))?,
671                    }
672                }
673            } else {
674                break;
675            }
676        }
677        Ok(())
678    }
679
680    /// Returns the maximum number of `xmlns` / `xmlns:*` declarations that
681    /// [`push`](Self::push) will accept on a single start tag.
682    #[inline]
683    pub const fn max_declarations_per_element(&self) -> usize {
684        self.max_declarations_per_element
685    }
686
687    /// Sets the maximum number of `xmlns` / `xmlns:*` declarations that
688    /// [`push`](Self::push) will accept on a single start tag. Pass `usize::MAX`
689    /// to disable the limit.
690    #[inline]
691    pub fn set_max_declarations_per_element(&mut self, limit: usize) -> &mut Self {
692        self.max_declarations_per_element = limit;
693        self
694    }
695
696    /// Ends the top-most scope, popping all bindings added by the last call to
697    /// [`push`](Self::push) or [`add`](Self::add).
698    #[inline]
699    pub fn pop(&mut self) {
700        self.set_level(self.nesting_level.saturating_sub(1));
701    }
702
703    /// Sets the number of [`push`](Self::push) calls not yet followed by a
704    /// [`pop`](Self::pop). Setting a value lower than the current [`level`](Self::level)
705    /// behaves as if `pop` were called until the level matches.
706    ///
707    /// ```
708    /// # use oxixml_xml::events::BytesStart;
709    /// # use oxixml_xml::name::NamespaceResolver;
710    /// let mut resolver = NamespaceResolver::default();
711    /// assert_eq!(resolver.level(), 0);
712    /// resolver.push(&BytesStart::new("tag")).expect("doc example");
713    /// assert_eq!(resolver.level(), 1);
714    /// resolver.set_level(10);
715    /// assert_eq!(resolver.level(), 10);
716    /// resolver.pop();
717    /// assert_eq!(resolver.level(), 9);
718    /// ```
719    pub fn set_level(&mut self, level: usize) {
720        self.nesting_level = level;
721        match self.bindings.iter().rposition(|n| n.level <= level) {
722            None => {
723                self.buffer.clear();
724                self.bindings.clear();
725            }
726            Some(last_valid_pos) => {
727                if let Some(len) = self.bindings.get(last_valid_pos + 1).map(|n| n.start) {
728                    self.buffer.truncate(len);
729                    self.bindings.truncate(last_valid_pos + 1);
730                }
731            }
732        }
733    }
734
735    /// Resolves a potentially qualified **element** or **attribute** name into
736    /// _(namespace name, local name)_.
737    ///
738    /// # Parameters
739    /// - `name`: the possibly qualified name to resolve;
740    /// - `use_default`: whether to translate an absent prefix to the current
741    ///   default namespace. Should be `true` for element names, `false` for
742    ///   attribute names.
743    #[inline]
744    pub fn resolve<'n>(
745        &self,
746        name: QName<'n>,
747        use_default: bool,
748    ) -> (ResolveResult<'_>, LocalName<'n>) {
749        let (local_name, prefix) = name.decompose();
750        (self.resolve_prefix(prefix, use_default), local_name)
751    }
752
753    /// Convenience for `resolve(name, true)`, expressing that an element name is
754    /// being resolved.
755    #[inline]
756    pub fn resolve_element<'n>(&self, name: QName<'n>) -> (ResolveResult<'_>, LocalName<'n>) {
757        self.resolve(name, true)
758    }
759
760    /// Convenience for `resolve(name, false)`, expressing that an attribute name
761    /// is being resolved.
762    #[inline]
763    pub fn resolve_attribute<'n>(&self, name: QName<'n>) -> (ResolveResult<'_>, LocalName<'n>) {
764        self.resolve(name, false)
765    }
766
767    /// Finds a [namespace name] for a given event, if applicable.
768    ///
769    /// A namespace is resolved only for [`Start`](Event::Start),
770    /// [`Empty`](Event::Empty) and [`End`](Event::End) events; for all other
771    /// events [`ResolveResult::Unbound`] is returned.
772    ///
773    /// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
774    pub fn resolve_event<'i>(&self, event: Event<'i>) -> (ResolveResult<'_>, Event<'i>) {
775        use Event::*;
776
777        match event {
778            Empty(e) => (self.resolve_prefix(e.name().prefix(), true), Empty(e)),
779            Start(e) => (self.resolve_prefix(e.name().prefix(), true), Start(e)),
780            End(e) => (self.resolve_prefix(e.name().prefix(), true), End(e)),
781            e => (ResolveResult::Unbound, e),
782        }
783    }
784
785    /// Resolves the given optional prefix (usually obtained from [`QName::prefix`])
786    /// into a corresponding namespace.
787    pub fn resolve_prefix(&self, prefix: Option<Prefix>, use_default: bool) -> ResolveResult<'_> {
788        let mut iter = self.bindings.iter().rev();
789        match (prefix, use_default) {
790            // Attribute name has no explicit prefix -> Unbound.
791            (None, false) => ResolveResult::Unbound,
792            // Element name has no explicit prefix -> find nearest default binding.
793            (None, true) => match iter.find(|n| n.prefix_len == 0) {
794                Some(n) => n.namespace(&self.buffer),
795                None => ResolveResult::Unbound,
796            },
797            // Attribute or element name with an explicit prefix.
798            (Some(p), _) => match iter.find(|n| n.prefix(&self.buffer) == prefix) {
799                Some(n) if n.value_len != 0 => n.namespace(&self.buffer),
800                _ => ResolveResult::Unknown(p.into_inner().to_vec()),
801            },
802        }
803    }
804
805    /// Returns all the bindings currently in effect except the default `xml` and
806    /// `xmlns` bindings.
807    ///
808    /// ```
809    /// # use oxixml_xml::events::BytesStart;
810    /// # use oxixml_xml::name::{Namespace, NamespaceResolver, PrefixDeclaration};
811    /// let mut resolver = NamespaceResolver::default();
812    /// assert_eq!(resolver.bindings().collect::<Vec<_>>(), vec![]);
813    ///
814    /// resolver.push(&BytesStart::from_content("a xmlns=\"a1\" xmlns:a=\"a2\"", 1)).expect("doc example");
815    /// assert_eq!(resolver.bindings().collect::<Vec<_>>(), vec![
816    ///     (PrefixDeclaration::Default, Namespace(b"a1")),
817    ///     (PrefixDeclaration::Named(b"a"), Namespace(b"a2")),
818    /// ]);
819    /// ```
820    #[inline]
821    pub const fn bindings(&self) -> NamespaceBindingsIter<'_> {
822        NamespaceBindingsIter {
823            resolver: self,
824            // Skip the two default namespaces `xml:` and `xmlns:`.
825            cursor: 2,
826        }
827    }
828
829    /// Returns all the bindings on the specified `level`, including the default
830    /// `xml` and `xmlns` bindings (which live at level 0).
831    pub const fn bindings_of(&self, level: usize) -> NamespaceBindingsOfLevelIter<'_> {
832        NamespaceBindingsOfLevelIter {
833            resolver: self,
834            cursor: 0,
835            level,
836        }
837    }
838
839    /// Returns the number of [`push`](Self::push) calls not yet followed by a
840    /// [`pop`](Self::pop).
841    pub const fn level(&self) -> usize {
842        self.nesting_level
843    }
844}
845
846////////////////////////////////////////////////////////////////////////////////////////////////////
847
848/// Iterator over the currently declared namespace bindings, yielding
849/// _(prefix, namespace)_ pairs. See [`NamespaceResolver::bindings`].
850#[derive(Debug, Clone)]
851pub struct NamespaceBindingsIter<'a> {
852    resolver: &'a NamespaceResolver,
853    cursor: usize,
854}
855
856impl<'a> Iterator for NamespaceBindingsIter<'a> {
857    type Item = (PrefixDeclaration<'a>, Namespace<'a>);
858
859    fn next(&mut self) -> Option<(PrefixDeclaration<'a>, Namespace<'a>)> {
860        while let Some(binding) = self.resolver.bindings.get(self.cursor) {
861            self.cursor += 1;
862
863            // Skip a binding whose prefix was overridden by a later binding.
864            let prefix = binding.prefix(&self.resolver.buffer);
865            if self.resolver.bindings[self.cursor..]
866                .iter()
867                .any(|ne| prefix == ne.prefix(&self.resolver.buffer))
868            {
869                continue;
870            }
871            if let ResolveResult::Bound(namespace) = binding.namespace(&self.resolver.buffer) {
872                let prefix = match prefix {
873                    Some(Prefix(prefix)) => PrefixDeclaration::Named(prefix),
874                    None => PrefixDeclaration::Default,
875                };
876                return Some((prefix, namespace));
877            }
878        }
879        None
880    }
881
882    fn size_hint(&self) -> (usize, Option<usize>) {
883        (0, Some(self.resolver.bindings.len() - self.cursor))
884    }
885}
886
887impl<'a> FusedIterator for NamespaceBindingsIter<'a> {}
888
889/// Iterator over the namespace bindings on a specific level, yielding
890/// _(prefix, namespace)_ pairs. See [`NamespaceResolver::bindings_of`].
891#[derive(Debug, Clone)]
892pub struct NamespaceBindingsOfLevelIter<'a> {
893    resolver: &'a NamespaceResolver,
894    cursor: usize,
895    level: usize,
896}
897
898impl<'a> Iterator for NamespaceBindingsOfLevelIter<'a> {
899    type Item = (PrefixDeclaration<'a>, Namespace<'a>);
900
901    fn next(&mut self) -> Option<(PrefixDeclaration<'a>, Namespace<'a>)> {
902        while let Some(binding) = self.resolver.bindings.get(self.cursor) {
903            self.cursor += 1;
904            if binding.level < self.level {
905                continue;
906            }
907            if binding.level > self.level {
908                break;
909            }
910
911            if let ResolveResult::Bound(namespace) = binding.namespace(&self.resolver.buffer) {
912                let prefix = match binding.prefix(&self.resolver.buffer) {
913                    Some(Prefix(prefix)) => PrefixDeclaration::Named(prefix),
914                    None => PrefixDeclaration::Default,
915                };
916                return Some((prefix, namespace));
917            }
918        }
919        None
920    }
921
922    fn size_hint(&self) -> (usize, Option<usize>) {
923        (0, Some(self.resolver.bindings.len() - self.cursor))
924    }
925}
926
927impl<'a> FusedIterator for NamespaceBindingsOfLevelIter<'a> {}
928
929#[cfg(test)]
930mod tests;