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	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;