1use crate::attrs::{AttrParser, AttrParserRef};
2use crate::jid::{Jid, JidRef};
3use std::borrow::Cow;
4
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Debug, Clone, PartialEq)]
10pub enum NodeValue {
11 String(String),
12 Jid(Jid),
13}
14
15impl Default for NodeValue {
16 fn default() -> Self {
17 NodeValue::String(String::new())
18 }
19}
20
21impl NodeValue {
22 #[inline]
24 pub fn as_str(&self) -> Option<&str> {
25 match self {
26 NodeValue::String(s) => Some(s.as_ref()),
27 NodeValue::Jid(_) => None,
28 }
29 }
30
31 #[inline]
33 pub fn as_jid(&self) -> Option<&Jid> {
34 match self {
35 NodeValue::Jid(j) => Some(j),
36 NodeValue::String(_) => None,
37 }
38 }
39
40 #[inline]
42 pub fn to_jid(&self) -> Option<Jid> {
43 match self {
44 NodeValue::Jid(j) => Some(j.clone()),
45 NodeValue::String(s) => s.parse().ok(),
46 }
47 }
48
49 #[inline]
51 pub fn to_string_value(&self) -> String {
52 match self {
53 NodeValue::String(s) => s.clone(),
54 NodeValue::Jid(j) => j.to_string(),
55 }
56 }
57}
58
59use std::fmt;
60
61impl fmt::Display for NodeValue {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 match self {
64 NodeValue::String(s) => write!(f, "{}", s),
65 NodeValue::Jid(j) => write!(f, "{}", j),
66 }
67 }
68}
69
70impl PartialEq<str> for NodeValue {
71 fn eq(&self, other: &str) -> bool {
72 match self {
73 NodeValue::String(s) => s == other,
74 NodeValue::Jid(j) => j.to_string() == other,
77 }
78 }
79}
80
81impl PartialEq<&str> for NodeValue {
82 fn eq(&self, other: &&str) -> bool {
83 self == *other
84 }
85}
86
87impl PartialEq<String> for NodeValue {
88 fn eq(&self, other: &String) -> bool {
89 self == other.as_str()
90 }
91}
92
93impl From<String> for NodeValue {
94 #[inline]
95 fn from(s: String) -> Self {
96 NodeValue::String(s)
97 }
98}
99
100impl From<&str> for NodeValue {
101 #[inline]
102 fn from(s: &str) -> Self {
103 NodeValue::String(s.to_string())
104 }
105}
106
107impl From<Jid> for NodeValue {
108 #[inline]
109 fn from(jid: Jid) -> Self {
110 NodeValue::Jid(jid)
111 }
112}
113
114#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118#[derive(Debug, Clone, PartialEq, Default)]
119pub struct Attrs(pub Vec<(String, NodeValue)>);
120
121impl Attrs {
122 #[inline]
123 pub fn new() -> Self {
124 Self(Vec::new())
125 }
126
127 #[inline]
128 pub fn with_capacity(capacity: usize) -> Self {
129 Self(Vec::with_capacity(capacity))
130 }
131
132 #[inline]
135 pub fn get(&self, key: &str) -> Option<&NodeValue> {
136 self.0.iter().find(|(k, _)| k == key).map(|(_, v)| v)
137 }
138
139 #[inline]
141 pub fn contains_key(&self, key: &str) -> bool {
142 self.0.iter().any(|(k, _)| k == key)
143 }
144
145 #[inline]
147 pub fn insert(&mut self, key: String, value: impl Into<NodeValue>) {
148 let value = value.into();
149 if let Some(pos) = self.0.iter().position(|(k, _)| k == &key) {
150 self.0[pos].1 = value;
151 } else {
152 self.0.push((key, value));
153 }
154 }
155
156 #[inline]
157 pub fn len(&self) -> usize {
158 self.0.len()
159 }
160
161 #[inline]
162 pub fn is_empty(&self) -> bool {
163 self.0.is_empty()
164 }
165
166 #[inline]
168 pub fn iter(&self) -> impl Iterator<Item = (&String, &NodeValue)> {
169 self.0.iter().map(|(k, v)| (k, v))
170 }
171
172 #[inline]
175 pub fn push(&mut self, key: String, value: impl Into<NodeValue>) {
176 self.0.push((key, value.into()));
177 }
178
179 #[inline]
182 pub fn push_value(&mut self, key: String, value: NodeValue) {
183 self.0.push((key, value));
184 }
185
186 #[inline]
188 pub fn keys(&self) -> impl Iterator<Item = &String> {
189 self.0.iter().map(|(k, _)| k)
190 }
191}
192
193impl IntoIterator for Attrs {
195 type Item = (String, NodeValue);
196 type IntoIter = std::vec::IntoIter<(String, NodeValue)>;
197
198 fn into_iter(self) -> Self::IntoIter {
199 self.0.into_iter()
200 }
201}
202
203impl<'a> IntoIterator for &'a Attrs {
205 type Item = (&'a String, &'a NodeValue);
206 type IntoIter = std::iter::Map<
207 std::slice::Iter<'a, (String, NodeValue)>,
208 fn(&'a (String, NodeValue)) -> (&'a String, &'a NodeValue),
209 >;
210
211 fn into_iter(self) -> Self::IntoIter {
212 self.0.iter().map(|(k, v)| (k, v))
213 }
214}
215
216impl FromIterator<(String, NodeValue)> for Attrs {
217 fn from_iter<I: IntoIterator<Item = (String, NodeValue)>>(iter: I) -> Self {
218 Self(iter.into_iter().collect())
219 }
220}
221pub type AttrsRef<'a> = Vec<(Cow<'a, str>, ValueRef<'a>)>;
222
223#[derive(Debug, Clone, PartialEq)]
227pub enum ValueRef<'a> {
228 String(Cow<'a, str>),
229 Jid(JidRef<'a>),
230}
231
232impl<'a> ValueRef<'a> {
233 pub fn as_str(&self) -> Option<&str> {
235 match self {
236 ValueRef::String(s) => Some(s.as_ref()),
237 ValueRef::Jid(_) => None,
238 }
239 }
240
241 pub fn as_jid(&self) -> Option<&JidRef<'a>> {
243 match self {
244 ValueRef::Jid(j) => Some(j),
245 ValueRef::String(_) => None,
246 }
247 }
248
249 pub fn to_jid(&self) -> Option<Jid> {
251 match self {
252 ValueRef::Jid(j) => Some(j.to_owned()),
253 ValueRef::String(s) => Jid::from_str(s.as_ref()).ok(),
254 }
255 }
256
257 pub fn to_string_cow(&self) -> Cow<'a, str> {
260 match self {
261 ValueRef::String(s) => s.clone(),
262 ValueRef::Jid(j) => Cow::Owned(j.to_string()),
263 }
264 }
265}
266
267use std::str::FromStr;
268
269impl<'a> fmt::Display for ValueRef<'a> {
270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271 match self {
272 ValueRef::String(s) => write!(f, "{}", s),
273 ValueRef::Jid(j) => write!(f, "{}", j),
274 }
275 }
276}
277
278pub type NodeVec<'a> = Vec<NodeRef<'a>>;
279
280#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
281#[derive(Debug, Clone, PartialEq)]
282pub enum NodeContent {
283 Bytes(Vec<u8>),
284 String(String),
285 Nodes(Vec<Node>),
286}
287
288#[derive(Debug, Clone, PartialEq)]
289pub enum NodeContentRef<'a> {
290 Bytes(Cow<'a, [u8]>),
291 String(Cow<'a, str>),
292 Nodes(Box<NodeVec<'a>>),
293}
294
295impl NodeContent {
296 pub fn as_content_ref(&self) -> NodeContentRef<'_> {
298 match self {
299 NodeContent::Bytes(b) => NodeContentRef::Bytes(Cow::Borrowed(b)),
300 NodeContent::String(s) => NodeContentRef::String(Cow::Borrowed(s)),
301 NodeContent::Nodes(nodes) => {
302 NodeContentRef::Nodes(Box::new(nodes.iter().map(|n| n.as_node_ref()).collect()))
303 }
304 }
305 }
306}
307
308#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
309#[derive(Debug, Clone, PartialEq, Default)]
310pub struct Node {
311 pub tag: String,
312 pub attrs: Attrs,
313 pub content: Option<NodeContent>,
314}
315
316#[derive(Debug, Clone, PartialEq)]
317pub struct NodeRef<'a> {
318 pub tag: Cow<'a, str>,
319 pub attrs: AttrsRef<'a>,
320 pub content: Option<Box<NodeContentRef<'a>>>,
321}
322
323impl Node {
324 pub fn new(tag: &str, attrs: Attrs, content: Option<NodeContent>) -> Self {
325 Self {
326 tag: tag.to_string(),
327 attrs,
328 content,
329 }
330 }
331
332 pub fn as_node_ref(&self) -> NodeRef<'_> {
335 NodeRef {
336 tag: Cow::Borrowed(&self.tag),
337 attrs: self
338 .attrs
339 .iter()
340 .map(|(k, v)| {
341 let value_ref = match v {
342 NodeValue::String(s) => ValueRef::String(Cow::Borrowed(s.as_str())),
343 NodeValue::Jid(j) => ValueRef::Jid(JidRef {
344 user: Cow::Borrowed(&j.user),
345 server: Cow::Borrowed(&j.server),
346 agent: j.agent,
347 device: j.device,
348 integrator: j.integrator,
349 }),
350 };
351 (Cow::Borrowed(k.as_str()), value_ref)
352 })
353 .collect(),
354 content: self.content.as_ref().map(|c| Box::new(c.as_content_ref())),
355 }
356 }
357
358 pub fn children(&self) -> Option<&[Node]> {
359 match &self.content {
360 Some(NodeContent::Nodes(nodes)) => Some(nodes),
361 _ => None,
362 }
363 }
364
365 pub fn attrs(&self) -> AttrParser<'_> {
366 AttrParser::new(self)
367 }
368
369 pub fn get_optional_child_by_tag<'a>(&'a self, tags: &[&str]) -> Option<&'a Node> {
370 let mut current_node = self;
371 for &tag in tags {
372 if let Some(children) = current_node.children() {
373 if let Some(found) = children.iter().find(|c| c.tag == tag) {
374 current_node = found;
375 } else {
376 return None;
377 }
378 } else {
379 return None;
380 }
381 }
382 Some(current_node)
383 }
384
385 pub fn get_children_by_tag<'a>(&'a self, tag: &'a str) -> impl Iterator<Item = &'a Node> {
386 self.children()
387 .into_iter()
388 .flatten()
389 .filter(move |c| c.tag == tag)
390 }
391
392 pub fn get_optional_child(&self, tag: &str) -> Option<&Node> {
393 self.children()
394 .and_then(|nodes| nodes.iter().find(|node| node.tag == tag))
395 }
396}
397
398impl<'a> NodeRef<'a> {
399 pub fn new(
400 tag: Cow<'a, str>,
401 attrs: AttrsRef<'a>,
402 content: Option<NodeContentRef<'a>>,
403 ) -> Self {
404 Self {
405 tag,
406 attrs,
407 content: content.map(Box::new),
408 }
409 }
410
411 pub fn attr_parser(&'a self) -> AttrParserRef<'a> {
412 AttrParserRef::new(self)
413 }
414
415 pub fn children(&self) -> Option<&[NodeRef<'a>]> {
416 match self.content.as_deref() {
417 Some(NodeContentRef::Nodes(nodes)) => Some(nodes.as_slice()),
418 _ => None,
419 }
420 }
421
422 pub fn get_attr(&self, key: &str) -> Option<&ValueRef<'a>> {
423 self.attrs.iter().find(|(k, _)| k == key).map(|(_, v)| v)
424 }
425
426 pub fn attrs_iter(&self) -> impl Iterator<Item = (&Cow<'a, str>, &ValueRef<'a>)> {
427 self.attrs.iter().map(|(k, v)| (k, v))
428 }
429
430 pub fn get_optional_child_by_tag(&self, tags: &[&str]) -> Option<&NodeRef<'a>> {
431 let mut current_node = self;
432 for &tag in tags {
433 if let Some(children) = current_node.children() {
434 if let Some(found) = children.iter().find(|c| c.tag == tag) {
435 current_node = found;
436 } else {
437 return None;
438 }
439 } else {
440 return None;
441 }
442 }
443 Some(current_node)
444 }
445
446 pub fn get_children_by_tag<'b>(&'b self, tag: &'b str) -> impl Iterator<Item = &'b NodeRef<'a>>
447 where
448 'a: 'b,
449 {
450 self.children()
451 .into_iter()
452 .flatten()
453 .filter(move |c| c.tag == tag)
454 }
455
456 pub fn get_optional_child(&self, tag: &str) -> Option<&NodeRef<'a>> {
457 self.children()
458 .and_then(|nodes| nodes.iter().find(|node| node.tag == tag))
459 }
460
461 pub fn to_owned(&self) -> Node {
462 Node {
463 tag: self.tag.to_string(),
464 attrs: self
465 .attrs
466 .iter()
467 .map(|(k, v)| {
468 let value = match v {
469 ValueRef::String(s) => NodeValue::String(s.to_string()),
470 ValueRef::Jid(j) => NodeValue::Jid(j.to_owned()),
471 };
472 (k.to_string(), value)
473 })
474 .collect::<Attrs>(),
475 content: self.content.as_deref().map(|c| match c {
476 NodeContentRef::Bytes(b) => NodeContent::Bytes(b.to_vec()),
477 NodeContentRef::String(s) => NodeContent::String(s.to_string()),
478 NodeContentRef::Nodes(nodes) => {
479 NodeContent::Nodes(nodes.iter().map(|n| n.to_owned()).collect())
480 }
481 }),
482 }
483 }
484}