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