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;