1#![deny(
2 unsafe_code,
3 missing_debug_implementations,
4 missing_copy_implementations,
5 unreachable_pub
6)]
7
8mod attributes;
9mod error;
10mod namespaces;
11mod nodes;
12mod parser;
13#[cfg(feature = "serde")]
14pub mod serde;
15mod strings;
16mod tokenizer;
17
18use std::fmt;
19use std::num::NonZeroUsize;
20
21use attributes::AttributeData;
22use namespaces::{Namespace, Namespaces, NamespacesBuilder};
23use nodes::{ElementData, NodeData};
24use strings::StringData;
25
26pub use attributes::{Attribute, Attributes};
27pub use error::{Error, ErrorKind};
28pub use nodes::{Children, Descendants, Node, NodeId};
29
30pub struct Document<'input> {
31 nodes: Box<[NodeData]>,
32 elements: Box<[ElementData<'input>]>,
33 texts: Box<[StringData<'input>]>,
34 attributes: Box<[AttributeData<'input>]>,
35 namespaces: Namespaces<'input>,
36}
37
38const fn _is_send_and_sync<T>()
39where
40 T: Send + Sync,
41{
42}
43
44const _DOCUMENT_IS_SEND_AND_SYNC: () = _is_send_and_sync::<Document>();
45
46impl Document<'_> {
47 pub fn len(&self) -> NonZeroUsize {
48 NonZeroUsize::new(self.nodes.len()).unwrap()
49 }
50}
51
52struct DocumentBuilder<'input> {
53 nodes: Vec<NodeData>,
54 elements: Vec<ElementData<'input>>,
55 texts: Vec<StringData<'input>>,
56 attributes: Vec<AttributeData<'input>>,
57 namespaces: NamespacesBuilder<'input>,
58}
59
60impl<'input> DocumentBuilder<'input> {
61 fn build(self) -> Document<'input> {
62 Document {
63 nodes: self.nodes.into_boxed_slice(),
64 elements: self.elements.into_boxed_slice(),
65 texts: self.texts.into_boxed_slice(),
66 attributes: self.attributes.into_boxed_slice(),
67 namespaces: self.namespaces.build(),
68 }
69 }
70}
71
72#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
73pub struct Name<'doc, 'input> {
74 pub namespace: Option<&'doc str>,
75 pub local: &'input str,
76}
77
78impl PartialEq<&str> for Name<'_, '_> {
90 fn eq(&self, other: &&str) -> bool {
91 self.local == *other
92 }
93}
94
95#[derive(Debug, Clone, Copy)]
96struct NameData<'input> {
97 namespace: Option<Namespace>,
98 local: &'input str,
99}
100
101const _SIZE_OF_NAME_DATA: () =
102 assert!(size_of::<NameData<'static>>() == (1 + 2) * size_of::<usize>());
103
104impl<'input> NameData<'input> {
105 fn get<'doc>(self, doc: &'doc Document) -> Name<'doc, 'input> {
106 let namespace = self
107 .namespace
108 .map(|namespace| doc.namespaces.get(namespace));
109
110 Name {
111 namespace,
112 local: self.local,
113 }
114 }
115}
116
117impl fmt::Debug for Document<'_> {
118 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
119 fmt.debug_struct("Document")
120 .field("root", &self.root())
121 .finish()
122 }
123}
124
125impl fmt::Debug for Name<'_, '_> {
126 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
127 match self.namespace {
128 Some(namespace) => write!(fmt, "\"{{{}}}{}\"", namespace, self.local),
129 None => write!(fmt, "\"{}\"", self.local),
130 }
131 }
132}