1use crate::attrs::{AttrParser, AttrParserRef};
2use crate::jid::{Jid, JidRef};
3use indexmap::IndexMap;
4use std::borrow::Cow;
5
6pub type Attrs = IndexMap<String, String>;
7pub type AttrsRef<'a> = Vec<(Cow<'a, str>, ValueRef<'a>)>;
8
9#[derive(Debug, Clone, PartialEq)]
13pub enum ValueRef<'a> {
14 String(Cow<'a, str>),
15 Jid(JidRef<'a>),
16}
17
18impl<'a> ValueRef<'a> {
19 pub fn as_str(&self) -> Option<&str> {
21 match self {
22 ValueRef::String(s) => Some(s.as_ref()),
23 ValueRef::Jid(_) => None,
24 }
25 }
26
27 pub fn as_jid(&self) -> Option<&JidRef<'a>> {
29 match self {
30 ValueRef::Jid(j) => Some(j),
31 ValueRef::String(_) => None,
32 }
33 }
34
35 pub fn to_jid(&self) -> Option<Jid> {
37 match self {
38 ValueRef::Jid(j) => Some(j.to_owned()),
39 ValueRef::String(s) => Jid::from_str(s.as_ref()).ok(),
40 }
41 }
42
43 pub fn to_string_cow(&self) -> Cow<'a, str> {
46 match self {
47 ValueRef::String(s) => s.clone(),
48 ValueRef::Jid(j) => Cow::Owned(j.to_string()),
49 }
50 }
51}
52
53use std::fmt;
54use std::str::FromStr;
55
56impl<'a> fmt::Display for ValueRef<'a> {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 ValueRef::String(s) => write!(f, "{}", s),
60 ValueRef::Jid(j) => write!(f, "{}", j),
61 }
62 }
63}
64
65pub type NodeVec<'a> = Vec<NodeRef<'a>>;
66
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68#[derive(Debug, Clone, PartialEq)]
69pub enum NodeContent {
70 Bytes(Vec<u8>),
71 String(String),
72 Nodes(Vec<Node>),
73}
74
75#[derive(Debug, Clone, PartialEq)]
76pub enum NodeContentRef<'a> {
77 Bytes(Cow<'a, [u8]>),
78 String(Cow<'a, str>),
79 Nodes(Box<NodeVec<'a>>),
80}
81
82impl NodeContent {
83 pub fn as_content_ref(&self) -> NodeContentRef<'_> {
85 match self {
86 NodeContent::Bytes(b) => NodeContentRef::Bytes(Cow::Borrowed(b)),
87 NodeContent::String(s) => NodeContentRef::String(Cow::Borrowed(s)),
88 NodeContent::Nodes(nodes) => {
89 NodeContentRef::Nodes(Box::new(nodes.iter().map(|n| n.as_node_ref()).collect()))
90 }
91 }
92 }
93}
94
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96#[derive(Debug, Clone, PartialEq, Default)]
97pub struct Node {
98 pub tag: String,
99 pub attrs: Attrs,
100 pub content: Option<NodeContent>,
101}
102
103#[derive(Debug, Clone, PartialEq)]
104pub struct NodeRef<'a> {
105 pub tag: Cow<'a, str>,
106 pub attrs: AttrsRef<'a>,
107 pub content: Option<Box<NodeContentRef<'a>>>,
108}
109
110impl Node {
111 pub fn new(tag: &str, attrs: Attrs, content: Option<NodeContent>) -> Self {
112 Self {
113 tag: tag.to_string(),
114 attrs,
115 content,
116 }
117 }
118
119 pub fn as_node_ref(&self) -> NodeRef<'_> {
122 NodeRef {
123 tag: Cow::Borrowed(&self.tag),
124 attrs: self
125 .attrs
126 .iter()
127 .map(|(k, v)| {
128 (
129 Cow::Borrowed(k.as_str()),
130 ValueRef::String(Cow::Borrowed(v.as_str())),
131 )
132 })
133 .collect(),
134 content: self.content.as_ref().map(|c| Box::new(c.as_content_ref())),
135 }
136 }
137
138 pub fn children(&self) -> Option<&[Node]> {
139 match &self.content {
140 Some(NodeContent::Nodes(nodes)) => Some(nodes),
141 _ => None,
142 }
143 }
144
145 pub fn attrs(&self) -> AttrParser<'_> {
146 AttrParser::new(self)
147 }
148
149 pub fn get_optional_child_by_tag<'a>(&'a self, tags: &[&str]) -> Option<&'a Node> {
150 let mut current_node = self;
151 for &tag in tags {
152 if let Some(children) = current_node.children() {
153 if let Some(found) = children.iter().find(|c| c.tag == tag) {
154 current_node = found;
155 } else {
156 return None;
157 }
158 } else {
159 return None;
160 }
161 }
162 Some(current_node)
163 }
164
165 pub fn get_children_by_tag(&self, tag: &str) -> Vec<&Node> {
166 if let Some(children) = self.children() {
167 children.iter().filter(|c| c.tag == tag).collect()
168 } else {
169 Vec::new()
170 }
171 }
172
173 pub fn get_optional_child(&self, tag: &str) -> Option<&Node> {
174 self.children()
175 .and_then(|nodes| nodes.iter().find(|node| node.tag == tag))
176 }
177}
178
179impl<'a> NodeRef<'a> {
180 pub fn new(
181 tag: Cow<'a, str>,
182 attrs: AttrsRef<'a>,
183 content: Option<NodeContentRef<'a>>,
184 ) -> Self {
185 Self {
186 tag,
187 attrs,
188 content: content.map(Box::new),
189 }
190 }
191
192 pub fn attr_parser(&'a self) -> AttrParserRef<'a> {
193 AttrParserRef::new(self)
194 }
195
196 pub fn children(&self) -> Option<&[NodeRef<'a>]> {
197 match self.content.as_deref() {
198 Some(NodeContentRef::Nodes(nodes)) => Some(nodes.as_slice()),
199 _ => None,
200 }
201 }
202
203 pub fn get_attr(&self, key: &str) -> Option<&ValueRef<'a>> {
204 self.attrs.iter().find(|(k, _)| k == key).map(|(_, v)| v)
205 }
206
207 pub fn attrs_iter(&self) -> impl Iterator<Item = (&Cow<'a, str>, &ValueRef<'a>)> {
208 self.attrs.iter().map(|(k, v)| (k, v))
209 }
210
211 pub fn get_optional_child_by_tag(&self, tags: &[&str]) -> Option<&NodeRef<'a>> {
212 let mut current_node = self;
213 for &tag in tags {
214 if let Some(children) = current_node.children() {
215 if let Some(found) = children.iter().find(|c| c.tag == tag) {
216 current_node = found;
217 } else {
218 return None;
219 }
220 } else {
221 return None;
222 }
223 }
224 Some(current_node)
225 }
226
227 pub fn get_children_by_tag(&self, tag: &str) -> Vec<&NodeRef<'a>> {
228 if let Some(children) = self.children() {
229 children.iter().filter(|c| c.tag == tag).collect()
230 } else {
231 Vec::new()
232 }
233 }
234
235 pub fn get_optional_child(&self, tag: &str) -> Option<&NodeRef<'a>> {
236 self.children()
237 .and_then(|nodes| nodes.iter().find(|node| node.tag == tag))
238 }
239
240 pub fn to_owned(&self) -> Node {
241 Node {
242 tag: self.tag.to_string(),
243 attrs: self
244 .attrs
245 .iter()
246 .map(|(k, v)| (k.to_string(), v.to_string_cow().into_owned()))
247 .collect::<IndexMap<String, String>>(),
248 content: self.content.as_deref().map(|c| match c {
249 NodeContentRef::Bytes(b) => NodeContent::Bytes(b.to_vec()),
250 NodeContentRef::String(s) => NodeContent::String(s.to_string()),
251 NodeContentRef::Nodes(nodes) => {
252 NodeContent::Nodes(nodes.iter().map(|n| n.to_owned()).collect())
253 }
254 }),
255 }
256 }
257}