1use crate::internal_prelude::*;
4
5use super::contents::{
6 AttributeNodeStorage, CDataSectionNodeStorage, CommentNodeStorage, DocumentFragmentNodeStorage,
7 DocumentNodeStorage, DocumentTypeNodeStorage, ProcessingInstructionNodeStorage,
8 TextNodeStorage,
9};
10use super::{
11 AnyNodeStorage, Buildable, NodeCommon, NodeContentsArc, NodeContentsWeak, NodeGraphStorage,
12};
13use crate::node_list::NodeList;
14use std::convert::TryFrom;
15crate::use_behaviors!(sandbox_member);
16
17#[derive(Clone)]
18pub struct ConcreteNodeArc<S: AnyNodeStorage> {
22 pub(crate) contents: Arc<S>,
23 pub(crate) common: Arc<NodeCommon>,
24}
25
26#[derive(Clone)]
27pub struct ConcreteNodeWeak<S: AnyNodeStorage> {
31 pub(crate) contents: Weak<S>,
32 pub(crate) common: Weak<NodeCommon>,
33}
34
35macro_rules! impl_concrete {
36 ($($ti:expr => $name:ident),*) => {
37 paste::paste! {
38 $(
39 impl AnyNodeStorage for [<$name NodeStorage>] {}
40
41 #[doc = "Convenience alias for a strong reference to a(n) " $name " node"]
42 pub type [<$name NodeArc>] = ConcreteNodeArc<[<$name NodeStorage>]>;
43
44 #[doc = "Convenience alias for a weak reference to a(n) " $name " node"]
45 pub type [<$name NodeWeak>] = ConcreteNodeWeak<[<$name NodeStorage>]>;
46
47 impl ConcreteNodeArc<[<$name NodeStorage>]> {
48 pub(crate) fn new(context: Weak<Sandbox>, contents: Arc<[<$name NodeStorage>]>) ->
49 ConcreteNodeArc<[<$name NodeStorage>]> {
50 let common = Arc::new_cyclic(|construction_weak| NodeCommon {
51 node_graph: NodeGraphStorage::new(AnyNodeWeak {
52 contents: (&contents).into(),
53 common: construction_weak.clone(),
54 }),
55 context,
56 });
57
58 ConcreteNodeArc { contents, common }
59 }
60 }
61
62 impl Buildable for ConcreteNodeArc<[<$name NodeStorage>]> {
63 type Storage = [<$name NodeStorage>];
64 }
65
66 impl SandboxMemberBehavior for ConcreteNodeArc<[<$name NodeStorage>]> {
67 fn get_context(&self) -> Weak<Sandbox> {
68 self.common.context.clone()
69 }
70 }
71
72 impl TryFrom<AnyNodeArc> for ConcreteNodeArc<[<$name NodeStorage>]> {
73 type Error = AnyNodeArc;
74
75 fn try_from(value: AnyNodeArc) -> Result<Self, Self::Error> {
76 match value.contents {
77 NodeContentsArc::$name(element) => {
78 return Ok(ConcreteNodeArc {
79 contents: element,
80 common: value.common,
81 })
82 },
83 _ => Err(value),
84 }
85 }
86 }
87
88 impl TryFrom<AnyNodeWeak> for ConcreteNodeWeak<[<$name NodeStorage>]> {
89 type Error = AnyNodeWeak;
90
91 fn try_from(value: AnyNodeWeak) -> Result<Self, Self::Error> {
92 match value.contents {
93 NodeContentsWeak::$name(element) => {
94 return Ok(ConcreteNodeWeak {
95 contents: element,
96 common: value.common,
97 })
98 },
99 _ => Err(value),
100 }
101 }
102 }
103
104 impl From<ConcreteNodeArc<[<$name NodeStorage>]>> for AnyNodeArc {
105 fn from(concrete: ConcreteNodeArc<[<$name NodeStorage>]>) -> Self {
106 AnyNodeArc {
107 common: concrete.common,
108 contents: NodeContentsArc::$name(concrete.contents),
109 }
110 }
111 }
112
113 impl From<ConcreteNodeWeak<[<$name NodeStorage>]>> for AnyNodeWeak {
114 fn from(concrete: ConcreteNodeWeak<[<$name NodeStorage>]>) -> Self {
115 AnyNodeWeak {
116 common: concrete.common,
117 contents: NodeContentsWeak::$name(concrete.contents),
118 }
119 }
120 }
121
122 impl NodeBehavior for ConcreteNodeArc<[<$name NodeStorage>]> {
123 fn first_child(&self) -> Option<AnyNodeArc> {
124 self.common.node_graph.first_child()
125 }
126
127 fn last_child(&self) -> Option<AnyNodeArc> {
128 self.common.node_graph.last_child()
129 }
130
131 fn append_child(&self, other: AnyNodeArc) {
132 self.common.node_graph.append_child(other)
133 }
134
135 fn child_nodes(&self) -> Arc<NodeList> {
136 self.common.node_graph.child_nodes()
137 }
138
139 fn clone_node(&self) -> AnyNodeArc {
140 AnyNodeArc::from(self.clone()).clone_node()
141 }
142
143 fn get_node_type(&self) -> isize {
144 $ti
145 }
146 }
147 )*
148 }
149 }
150}
151
152impl_concrete! {
153 1 => Element,
154 2 => Attribute,
155 3 => Text,
156 4 => CDataSection,
157 5 => ProcessingInstruction,
158 6 => Comment,
159 7 => Document,
160 8 => DocumentType,
161 9 => DocumentFragment
162}
163
164impl DocumentNodeArc {
165 pub fn create_text_node(&self, text: String) -> TextNodeArc {
167 TextNodeArc::new(self.get_context(), Arc::new(TextNodeStorage { data: text }))
168 }
169}