1use crate::attrs::{AttrParser, AttrParserRef};
2use crate::jid::{Jid, JidRef};
3use crate::token;
4use bytes::Bytes;
5use compact_str::CompactString;
6use stable_deref_trait::StableDeref;
7use std::borrow::Cow;
8
9#[derive(Clone, yoke::Yokeable)]
12pub enum NodeStr<'a> {
13 Borrowed(&'a str),
14 Owned(CompactString),
15}
16
17impl NodeStr<'_> {
18 #[inline]
21 pub fn to_compact_string(&self) -> CompactString {
22 match self {
23 NodeStr::Borrowed(s) => CompactString::from(*s),
24 NodeStr::Owned(cs) => cs.clone(),
25 }
26 }
27}
28
29impl Default for NodeStr<'_> {
30 #[inline]
31 fn default() -> Self {
32 NodeStr::Borrowed("")
33 }
34}
35
36impl std::ops::Deref for NodeStr<'_> {
37 type Target = str;
38 #[inline(always)]
39 fn deref(&self) -> &str {
40 match self {
41 NodeStr::Borrowed(s) => s,
42 NodeStr::Owned(cs) => cs.as_str(),
43 }
44 }
45}
46
47impl AsRef<str> for NodeStr<'_> {
48 #[inline(always)]
49 fn as_ref(&self) -> &str {
50 self
51 }
52}
53
54impl std::fmt::Debug for NodeStr<'_> {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 std::fmt::Debug::fmt(&**self, f)
57 }
58}
59
60impl std::fmt::Display for NodeStr<'_> {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 f.write_str(self)
63 }
64}
65
66#[cfg(feature = "serde")]
67impl serde::Serialize for NodeStr<'_> {
68 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
69 serializer.serialize_str(self)
70 }
71}
72
73impl PartialEq for NodeStr<'_> {
74 #[inline]
75 fn eq(&self, other: &Self) -> bool {
76 **self == **other
77 }
78}
79
80impl Eq for NodeStr<'_> {}
81
82impl std::hash::Hash for NodeStr<'_> {
83 #[inline]
84 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
85 (**self).hash(state)
86 }
87}
88
89impl PartialEq<str> for NodeStr<'_> {
90 #[inline]
91 fn eq(&self, other: &str) -> bool {
92 &**self == other
93 }
94}
95
96impl PartialEq<&str> for NodeStr<'_> {
97 #[inline]
98 fn eq(&self, other: &&str) -> bool {
99 &**self == *other
100 }
101}
102
103impl<'a> From<&'a str> for NodeStr<'a> {
104 #[inline]
105 fn from(s: &'a str) -> Self {
106 NodeStr::Borrowed(s)
107 }
108}
109
110impl From<CompactString> for NodeStr<'_> {
111 #[inline]
112 fn from(s: CompactString) -> Self {
113 NodeStr::Owned(s)
114 }
115}
116
117#[inline]
121fn intern_cow(s: &str) -> Cow<'static, str> {
122 if let Some(kind) = token::index_of_token(s) {
123 let interned = match kind {
124 token::TokenKind::Single(idx) => token::get_single_token(idx),
125 token::TokenKind::Double(dict, idx) => token::get_double_token(dict, idx),
126 };
127 if let Some(token) = interned {
128 return Cow::Borrowed(token);
129 }
130 }
131 Cow::Owned(s.to_string())
132}
133
134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138#[derive(Debug, Clone, PartialEq)]
139pub enum NodeValue {
140 String(CompactString),
141 Jid(Jid),
142}
143
144impl Default for NodeValue {
145 fn default() -> Self {
146 NodeValue::String(CompactString::default())
147 }
148}
149
150impl NodeValue {
151 #[inline]
155 pub fn as_str(&self) -> Cow<'_, str> {
156 match self {
157 NodeValue::String(s) => Cow::Borrowed(s.as_str()),
158 NodeValue::Jid(j) => Cow::Owned(j.to_string()),
159 }
160 }
161
162 #[inline]
164 pub fn to_jid(&self) -> Option<Jid> {
165 match self {
166 NodeValue::Jid(j) => Some(j.clone()),
167 NodeValue::String(s) => s.parse().ok(),
168 }
169 }
170}
171
172use std::fmt;
173
174impl fmt::Display for NodeValue {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 match self {
177 NodeValue::String(s) => write!(f, "{}", s),
178 NodeValue::Jid(j) => write!(f, "{}", j),
179 }
180 }
181}
182
183impl PartialEq<str> for NodeValue {
184 fn eq(&self, other: &str) -> bool {
185 match self {
186 NodeValue::String(s) => s == other,
187 NodeValue::Jid(j) => {
190 use std::fmt::Write;
191 struct EqCheck<'a> {
192 target: &'a [u8],
193 pos: usize,
194 matches: bool,
195 }
196 impl fmt::Write for EqCheck<'_> {
197 fn write_str(&mut self, s: &str) -> fmt::Result {
198 if !self.matches {
199 return Ok(());
200 }
201 let bytes = s.as_bytes();
202 let end = self.pos + bytes.len();
203 if end > self.target.len() || self.target[self.pos..end] != *bytes {
204 self.matches = false;
205 }
206 self.pos = end;
207 Ok(())
208 }
209 }
210 let mut check = EqCheck {
211 target: other.as_bytes(),
212 pos: 0,
213 matches: true,
214 };
215 let _ = write!(check, "{}", j);
216 check.matches && check.pos == other.len()
217 }
218 }
219 }
220}
221
222impl PartialEq<&str> for NodeValue {
223 fn eq(&self, other: &&str) -> bool {
224 self == *other
225 }
226}
227
228impl PartialEq<String> for NodeValue {
229 fn eq(&self, other: &String) -> bool {
230 self == other.as_str()
231 }
232}
233
234impl From<String> for NodeValue {
235 #[inline]
236 fn from(s: String) -> Self {
237 NodeValue::String(CompactString::from(s))
238 }
239}
240
241impl From<&str> for NodeValue {
242 #[inline]
243 fn from(s: &str) -> Self {
244 NodeValue::String(CompactString::from(s))
245 }
246}
247
248impl From<&String> for NodeValue {
249 #[inline]
250 fn from(s: &String) -> Self {
251 NodeValue::String(CompactString::from(s.as_str()))
252 }
253}
254
255impl From<CompactString> for NodeValue {
256 #[inline]
257 fn from(s: CompactString) -> Self {
258 NodeValue::String(s)
259 }
260}
261
262impl From<Jid> for NodeValue {
263 #[inline]
264 fn from(jid: Jid) -> Self {
265 NodeValue::Jid(jid)
266 }
267}
268
269impl From<&Jid> for NodeValue {
270 #[inline]
271 fn from(jid: &Jid) -> Self {
272 NodeValue::Jid(jid.clone())
273 }
274}
275
276macro_rules! impl_from_integer_for_nodevalue {
277 ($($t:ty),* $(,)?) => {
278 $(
279 impl From<$t> for NodeValue {
280 #[inline]
281 fn from(n: $t) -> Self {
282 let mut buf = itoa::Buffer::new();
283 NodeValue::String(CompactString::from(buf.format(n)))
284 }
285 }
286 )*
287 };
288}
289
290impl_from_integer_for_nodevalue!(
291 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
292);
293
294impl From<bool> for NodeValue {
295 #[inline]
296 fn from(b: bool) -> Self {
297 NodeValue::String(CompactString::from(if b { "true" } else { "false" }))
298 }
299}
300
301#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
307#[derive(Debug, Clone, PartialEq, Default)]
308pub struct Attrs(pub Vec<(Cow<'static, str>, NodeValue)>);
309
310impl Attrs {
311 #[inline]
312 pub fn new() -> Self {
313 Self(Vec::new())
314 }
315
316 #[inline]
317 pub fn with_capacity(capacity: usize) -> Self {
318 Self(Vec::with_capacity(capacity))
319 }
320
321 #[inline]
324 pub fn get(&self, key: &str) -> Option<&NodeValue> {
325 self.0.iter().find(|(k, _)| k == key).map(|(_, v)| v)
326 }
327
328 #[inline]
330 pub fn contains_key(&self, key: &str) -> bool {
331 self.0.iter().any(|(k, _)| k == key)
332 }
333
334 #[inline]
336 pub fn insert(&mut self, key: impl Into<Cow<'static, str>>, value: impl Into<NodeValue>) {
337 let key = key.into();
338 let value = value.into();
339 if let Some(pos) = self.0.iter().position(|(k, _)| k == &key) {
340 self.0[pos].1 = value;
341 } else {
342 self.0.push((key, value));
343 }
344 }
345
346 #[inline]
347 pub fn len(&self) -> usize {
348 self.0.len()
349 }
350
351 #[inline]
352 pub fn is_empty(&self) -> bool {
353 self.0.is_empty()
354 }
355
356 #[inline]
358 pub fn iter(&self) -> impl Iterator<Item = (&Cow<'static, str>, &NodeValue)> {
359 self.0.iter().map(|(k, v)| (k, v))
360 }
361
362 #[inline]
365 pub fn push(&mut self, key: impl Into<Cow<'static, str>>, value: impl Into<NodeValue>) {
366 self.0.push((key.into(), value.into()));
367 }
368
369 #[inline]
372 pub fn push_value(&mut self, key: impl Into<Cow<'static, str>>, value: NodeValue) {
373 self.0.push((key.into(), value));
374 }
375
376 #[inline]
378 pub fn keys(&self) -> impl Iterator<Item = &Cow<'static, str>> {
379 self.0.iter().map(|(k, _)| k)
380 }
381}
382
383impl IntoIterator for Attrs {
385 type Item = (Cow<'static, str>, NodeValue);
386 type IntoIter = std::vec::IntoIter<(Cow<'static, str>, NodeValue)>;
387
388 fn into_iter(self) -> Self::IntoIter {
389 self.0.into_iter()
390 }
391}
392
393impl<'a> IntoIterator for &'a Attrs {
395 type Item = (&'a Cow<'static, str>, &'a NodeValue);
396 type IntoIter = std::iter::Map<
397 std::slice::Iter<'a, (Cow<'static, str>, NodeValue)>,
398 fn(&'a (Cow<'static, str>, NodeValue)) -> (&'a Cow<'static, str>, &'a NodeValue),
399 >;
400
401 fn into_iter(self) -> Self::IntoIter {
402 self.0.iter().map(|(k, v)| (k, v))
403 }
404}
405
406impl FromIterator<(Cow<'static, str>, NodeValue)> for Attrs {
407 fn from_iter<I: IntoIterator<Item = (Cow<'static, str>, NodeValue)>>(iter: I) -> Self {
408 Self(iter.into_iter().collect())
409 }
410}
411#[derive(Debug, Clone)]
419pub enum AttrsRef<'a> {
420 Empty,
421 Slice(Box<[(NodeStr<'a>, ValueRef<'a>)]>),
422}
423
424impl PartialEq for AttrsRef<'_> {
425 fn eq(&self, other: &Self) -> bool {
426 self.as_slice() == other.as_slice()
427 }
428}
429
430impl<'a> AttrsRef<'a> {
431 pub fn from_vec(v: Vec<(NodeStr<'a>, ValueRef<'a>)>) -> Self {
434 if v.is_empty() {
435 Self::Empty
436 } else {
437 Self::Slice(v.into_boxed_slice())
438 }
439 }
440
441 #[inline]
442 pub fn len(&self) -> usize {
443 match self {
444 Self::Empty => 0,
445 Self::Slice(s) => s.len(),
446 }
447 }
448
449 #[inline]
450 pub fn is_empty(&self) -> bool {
451 self.as_slice().is_empty()
452 }
453
454 #[inline]
455 pub fn as_slice(&self) -> &[(NodeStr<'a>, ValueRef<'a>)] {
456 match self {
457 Self::Empty => &[],
458 Self::Slice(s) => s,
459 }
460 }
461
462 #[inline]
463 pub fn iter(&self) -> impl Iterator<Item = &(NodeStr<'a>, ValueRef<'a>)> {
464 self.as_slice().iter()
465 }
466}
467
468impl<'a> FromIterator<(NodeStr<'a>, ValueRef<'a>)> for AttrsRef<'a> {
469 fn from_iter<I: IntoIterator<Item = (NodeStr<'a>, ValueRef<'a>)>>(iter: I) -> Self {
470 Self::from_vec(iter.into_iter().collect())
471 }
472}
473
474fn _assert_attrs_ref_covariant<'short, 'long: 'short>(x: AttrsRef<'long>) -> AttrsRef<'short> {
477 x
478}
479
480unsafe impl<'a> yoke::Yokeable<'a> for AttrsRef<'static> {
486 type Output = AttrsRef<'a>;
487
488 fn transform(&'a self) -> &'a Self::Output {
489 self
490 }
491
492 fn transform_owned(self) -> Self::Output {
493 self
494 }
495
496 unsafe fn make(from: Self::Output) -> Self {
497 unsafe { std::mem::transmute(from) }
498 }
499
500 fn transform_mut<F>(&'a mut self, f: F)
501 where
502 F: 'static + for<'b> FnOnce(&'b mut Self::Output),
503 {
504 unsafe { f(std::mem::transmute::<&mut Self, &mut Self::Output>(self)) }
505 }
506}
507
508#[derive(Debug, Clone, PartialEq, yoke::Yokeable)]
512pub enum ValueRef<'a> {
513 String(NodeStr<'a>),
514 Jid(JidRef<'a>),
515}
516
517#[cfg(feature = "serde")]
518impl serde::Serialize for ValueRef<'_> {
519 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
520 match self {
521 ValueRef::String(s) => {
522 serializer.serialize_newtype_variant("NodeValue", 0, "String", &**s)
523 }
524 ValueRef::Jid(j) => serializer.serialize_newtype_variant("NodeValue", 1, "Jid", j),
525 }
526 }
527}
528
529impl<'a> ValueRef<'a> {
530 pub fn encode_value<W: crate::encoder::ByteWriter>(
532 &self,
533 encoder: &mut crate::encoder::Encoder<'_, W>,
534 ) -> crate::error::Result<()> {
535 match self {
536 ValueRef::String(s) => encoder.write_string(s),
537 ValueRef::Jid(jid) => encoder.write_jid_ref(jid),
538 }
539 }
540
541 pub fn as_str(&self) -> Cow<'_, str> {
545 match self {
546 ValueRef::String(s) => Cow::Borrowed(s),
547 ValueRef::Jid(j) => Cow::Owned(j.to_string()),
548 }
549 }
550
551 pub fn as_jid(&self) -> Option<&JidRef<'a>> {
553 match self {
554 ValueRef::Jid(j) => Some(j),
555 ValueRef::String(_) => None,
556 }
557 }
558
559 pub fn to_jid(&self) -> Option<Jid> {
561 match self {
562 ValueRef::Jid(j) => Some(j.to_owned()),
563 ValueRef::String(s) => Jid::from_str(s.as_ref()).ok(),
564 }
565 }
566
567 pub fn to_node_value(&self) -> NodeValue {
569 match self {
570 ValueRef::String(s) => NodeValue::String(s.to_compact_string()),
571 ValueRef::Jid(j) => NodeValue::Jid(j.to_owned()),
572 }
573 }
574}
575
576use std::str::FromStr;
577
578impl<'a> fmt::Display for ValueRef<'a> {
579 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
580 match self {
581 ValueRef::String(s) => write!(f, "{}", s),
582 ValueRef::Jid(j) => write!(f, "{}", j),
583 }
584 }
585}
586
587pub type NodeVec<'a> = Vec<NodeRef<'a>>;
588
589#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
590#[derive(Debug, Clone, PartialEq)]
591pub enum NodeContent {
592 Bytes(Vec<u8>),
593 String(CompactString),
594 Nodes(Vec<Node>),
595}
596
597#[derive(Debug, Clone, PartialEq, yoke::Yokeable)]
598pub enum NodeContentRef<'a> {
599 Bytes(Cow<'a, [u8]>),
600 String(NodeStr<'a>),
601 Nodes(Box<[NodeRef<'a>]>),
602}
603
604#[cfg(feature = "serde")]
605impl serde::Serialize for NodeContentRef<'_> {
606 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
607 match self {
608 NodeContentRef::Bytes(b) => {
609 serializer.serialize_newtype_variant("NodeContent", 0, "Bytes", b.as_ref())
610 }
611 NodeContentRef::String(s) => {
612 serializer.serialize_newtype_variant("NodeContent", 1, "String", &**s)
613 }
614 NodeContentRef::Nodes(nodes) => {
615 serializer.serialize_newtype_variant("NodeContent", 2, "Nodes", &**nodes)
616 }
617 }
618 }
619}
620
621impl NodeContent {
622 pub fn as_content_ref(&self) -> NodeContentRef<'_> {
624 match self {
625 NodeContent::Bytes(b) => NodeContentRef::Bytes(Cow::Borrowed(b)),
626 NodeContent::String(s) => NodeContentRef::String(NodeStr::Borrowed(s.as_str())),
627 NodeContent::Nodes(nodes) => {
628 let v: Vec<_> = nodes.iter().map(|n| n.as_node_ref()).collect();
629 NodeContentRef::Nodes(v.into_boxed_slice())
630 }
631 }
632 }
633}
634
635#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
636#[derive(Debug, Clone, PartialEq, Default)]
637pub struct Node {
638 pub tag: Cow<'static, str>,
639 pub attrs: Attrs,
640 pub content: Option<NodeContent>,
641}
642
643#[derive(Debug, Clone, PartialEq, yoke::Yokeable)]
644pub struct NodeRef<'a> {
645 pub tag: NodeStr<'a>,
646 pub attrs: AttrsRef<'a>,
647 pub content: Option<Box<NodeContentRef<'a>>>,
648}
649
650impl Node {
651 pub fn new(
652 tag: impl Into<Cow<'static, str>>,
653 attrs: Attrs,
654 content: Option<NodeContent>,
655 ) -> Self {
656 Self {
657 tag: tag.into(),
658 attrs,
659 content,
660 }
661 }
662
663 pub fn as_node_ref(&self) -> NodeRef<'_> {
666 NodeRef {
667 tag: NodeStr::Borrowed(self.tag.as_ref()),
668 attrs: self
669 .attrs
670 .iter()
671 .map(|(k, v)| {
672 let value_ref = match v {
673 NodeValue::String(s) => ValueRef::String(NodeStr::Borrowed(s.as_str())),
674 NodeValue::Jid(j) => ValueRef::Jid(JidRef {
675 user: NodeStr::Borrowed(&j.user),
676 server: j.server,
677 agent: j.agent,
678 device: j.device,
679 integrator: j.integrator,
680 }),
681 };
682 (NodeStr::Borrowed(k.as_ref()), value_ref)
683 })
684 .collect(),
685 content: self.content.as_ref().map(|c| Box::new(c.as_content_ref())),
686 }
687 }
688
689 pub fn children(&self) -> Option<&[Node]> {
690 match &self.content {
691 Some(NodeContent::Nodes(nodes)) => Some(nodes),
692 _ => None,
693 }
694 }
695
696 pub fn attrs(&self) -> AttrParser<'_> {
697 AttrParser::new(self)
698 }
699
700 pub fn get_optional_child_by_tag<'a>(&'a self, tags: &[&str]) -> Option<&'a Node> {
701 let mut current_node = self;
702 for &tag in tags {
703 if let Some(children) = current_node.children() {
704 if let Some(found) = children.iter().find(|c| c.tag == tag) {
705 current_node = found;
706 } else {
707 return None;
708 }
709 } else {
710 return None;
711 }
712 }
713 Some(current_node)
714 }
715
716 pub fn get_children_by_tag<'a>(&'a self, tag: &'a str) -> impl Iterator<Item = &'a Node> {
717 self.children()
718 .into_iter()
719 .flatten()
720 .filter(move |c| c.tag == tag)
721 }
722
723 pub fn get_optional_child(&self, tag: &str) -> Option<&Node> {
724 self.children()
725 .and_then(|nodes| nodes.iter().find(|node| node.tag == tag))
726 }
727
728 pub fn content_as_string(&self) -> Option<CompactString> {
730 match &self.content {
731 Some(NodeContent::String(s)) => Some(s.clone()),
732 Some(NodeContent::Bytes(b)) => {
733 Some(CompactString::from(String::from_utf8_lossy(b).as_ref()))
734 }
735 _ => None,
736 }
737 }
738}
739
740#[cfg(feature = "serde")]
745struct AttrsRefWrapper<'a, 'b>(&'b AttrsRef<'a>);
746
747#[cfg(feature = "serde")]
748impl serde::Serialize for AttrsRefWrapper<'_, '_> {
749 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
750 serializer.serialize_newtype_struct("Attrs", self.0.as_slice())
751 }
752}
753
754#[cfg(feature = "serde")]
755impl serde::Serialize for NodeRef<'_> {
756 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
757 use serde::ser::SerializeStruct;
758 let mut s = serializer.serialize_struct("Node", 3)?;
759 s.serialize_field("tag", &*self.tag)?;
760 s.serialize_field("attrs", &AttrsRefWrapper(&self.attrs))?;
761 s.serialize_field("content", &self.content)?;
762 s.end()
763 }
764}
765
766impl<'a> NodeRef<'a> {
767 pub fn new(tag: NodeStr<'a>, attrs: AttrsRef<'a>, content: Option<NodeContentRef<'a>>) -> Self {
768 Self {
769 tag,
770 attrs,
771 content: content.map(Box::new),
772 }
773 }
774
775 pub fn attrs(&self) -> AttrParserRef<'_> {
776 AttrParserRef::new(self)
777 }
778
779 pub fn children(&self) -> Option<&[NodeRef<'a>]> {
780 match self.content.as_deref() {
781 Some(NodeContentRef::Nodes(nodes)) => Some(nodes),
782 _ => None,
783 }
784 }
785
786 pub fn get_attr(&self, key: &str) -> Option<&ValueRef<'a>> {
787 self.attrs.iter().find(|(k, _)| k == key).map(|(_, v)| v)
788 }
789
790 pub fn attrs_iter(&self) -> impl Iterator<Item = (&NodeStr<'a>, &ValueRef<'a>)> {
791 self.attrs.iter().map(|(k, v)| (k, v))
792 }
793
794 pub fn get_optional_child_by_tag(&self, tags: &[&str]) -> Option<&NodeRef<'a>> {
795 let mut current_node = self;
796 for &tag in tags {
797 if let Some(children) = current_node.children() {
798 if let Some(found) = children.iter().find(|c| c.tag == tag) {
799 current_node = found;
800 } else {
801 return None;
802 }
803 } else {
804 return None;
805 }
806 }
807 Some(current_node)
808 }
809
810 pub fn get_children_by_tag<'b>(&'b self, tag: &'b str) -> impl Iterator<Item = &'b NodeRef<'a>>
811 where
812 'a: 'b,
813 {
814 self.children()
815 .into_iter()
816 .flatten()
817 .filter(move |c| c.tag == tag)
818 }
819
820 pub fn get_optional_child(&self, tag: &str) -> Option<&NodeRef<'a>> {
821 self.children()
822 .and_then(|nodes| nodes.iter().find(|node| node.tag == tag))
823 }
824
825 pub fn content_as_string(&self) -> Option<CompactString> {
827 match self.content.as_deref() {
828 Some(NodeContentRef::String(s)) => Some(s.to_compact_string()),
829 Some(NodeContentRef::Bytes(b)) => Some(CompactString::from(
830 String::from_utf8_lossy(b.as_ref()).as_ref(),
831 )),
832 _ => None,
833 }
834 }
835
836 pub fn content_bytes(&self) -> Option<&[u8]> {
838 match self.content.as_deref() {
839 Some(NodeContentRef::Bytes(b)) => Some(b.as_ref()),
840 _ => None,
841 }
842 }
843
844 pub fn content_str(&self) -> Option<&str> {
846 match self.content.as_deref() {
847 Some(NodeContentRef::String(s)) => Some(s.as_ref()),
848 _ => None,
849 }
850 }
851
852 #[inline]
855 pub fn content_nodes(&self) -> Option<&[NodeRef<'a>]> {
856 self.children()
857 }
858
859 pub fn to_owned(&self) -> Node {
860 Node {
861 tag: intern_cow(&self.tag),
862 attrs: self
863 .attrs
864 .iter()
865 .map(|(k, v)| {
866 let value = match v {
867 ValueRef::String(s) => NodeValue::String(s.to_compact_string()),
868 ValueRef::Jid(j) => NodeValue::Jid(j.to_owned()),
869 };
870 (intern_cow(k), value)
871 })
872 .collect::<Attrs>(),
873 content: self.content.as_deref().map(|c| match c {
874 NodeContentRef::Bytes(b) => NodeContent::Bytes(b.to_vec()),
875 NodeContentRef::String(s) => NodeContent::String(s.to_compact_string()),
876 NodeContentRef::Nodes(nodes) => {
877 NodeContent::Nodes(nodes.iter().map(|n| n.to_owned()).collect())
878 }
879 }),
880 }
881 }
882}
883
884use yoke::Yoke;
889
890#[derive(Clone)]
891struct BytesCart(Bytes);
892
893impl std::ops::Deref for BytesCart {
894 type Target = [u8];
895
896 fn deref(&self) -> &Self::Target {
897 self.0.as_ref()
898 }
899}
900
901unsafe impl StableDeref for BytesCart {}
904
905pub struct OwnedNodeRef {
911 inner: Yoke<NodeRef<'static>, BytesCart>,
912}
913
914impl OwnedNodeRef {
915 pub fn new(buffer: impl Into<Bytes>) -> crate::error::Result<Self> {
919 let inner = Yoke::try_attach_to_cart(BytesCart(buffer.into()), |buf| {
920 crate::marshal::unmarshal_ref(buf)
921 })?;
922 Ok(Self { inner })
923 }
924
925 #[inline]
927 pub fn get(&self) -> &NodeRef<'_> {
928 self.inner.get()
929 }
930
931 pub fn to_owned_node(&self) -> Node {
934 self.inner.get().to_owned()
935 }
936
937 pub fn slice_bytes(&self, slice: &[u8]) -> Bytes {
940 let cart = &self.inner.backing_cart().0;
941 let base = cart.as_ptr() as usize;
942 let end = base + cart.len();
943 let ptr = slice.as_ptr() as usize;
944 assert!(
945 ptr >= base && ptr + slice.len() <= end,
946 "slice is not within the backing buffer"
947 );
948 let offset = ptr - base;
949 cart.slice(offset..offset + slice.len())
950 }
951
952 #[inline]
954 pub fn tag(&self) -> &str {
955 &self.get().tag
956 }
957
958 #[inline]
960 pub fn attrs(&self) -> AttrParserRef<'_> {
961 self.get().attrs()
962 }
963
964 #[inline]
966 pub fn get_attr(&self, key: &str) -> Option<&ValueRef<'_>> {
967 self.get().get_attr(key)
968 }
969
970 #[inline]
972 pub fn children(&self) -> Option<&[NodeRef<'_>]> {
973 self.get().children()
974 }
975
976 #[inline]
978 pub fn get_optional_child(&self, tag: &str) -> Option<&NodeRef<'_>> {
979 self.get().get_optional_child(tag)
980 }
981
982 #[inline]
984 pub fn get_optional_child_by_tag(&self, tags: &[&str]) -> Option<&NodeRef<'_>> {
985 self.get().get_optional_child_by_tag(tags)
986 }
987
988 #[inline]
990 pub fn get_children_by_tag<'b>(
991 &'b self,
992 tag: &'b str,
993 ) -> impl Iterator<Item = &'b NodeRef<'b>> {
994 self.get().get_children_by_tag(tag)
995 }
996
997 #[inline]
999 pub fn content_bytes(&self) -> Option<&[u8]> {
1000 self.get().content_bytes()
1001 }
1002
1003 #[inline]
1005 pub fn content_str(&self) -> Option<&str> {
1006 self.get().content_str()
1007 }
1008
1009 #[inline]
1011 pub fn content_nodes(&self) -> Option<&[NodeRef<'_>]> {
1012 self.get().content_nodes()
1013 }
1014
1015 #[inline]
1017 pub fn content_as_string(&self) -> Option<CompactString> {
1018 self.get().content_as_string()
1019 }
1020}
1021
1022#[cfg(feature = "serde")]
1023impl serde::Serialize for OwnedNodeRef {
1024 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1025 self.get().serialize(serializer)
1026 }
1027}
1028
1029impl std::fmt::Debug for OwnedNodeRef {
1030 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1031 self.inner.get().fmt(f)
1032 }
1033}
1034
1035#[cfg(test)]
1036#[cfg(feature = "serde")]
1037mod serde_tests {
1038 use super::*;
1039 use crate::jid::{Jid, Server};
1040
1041 #[test]
1042 fn node_ref_serializes_same_as_node() {
1043 let node = Node::new(
1044 Cow::Borrowed("message"),
1045 Attrs(vec![
1046 (Cow::Borrowed("type"), NodeValue::String("text".into())),
1047 (Cow::Borrowed("from"), NodeValue::Jid(Jid::pn("5550199999"))),
1048 ]),
1049 Some(NodeContent::String("hello".into())),
1050 );
1051 let node_ref = node.as_node_ref();
1052
1053 let owned_json = serde_json::to_value(&node).unwrap();
1054 let ref_json = serde_json::to_value(&node_ref).unwrap();
1055 assert_eq!(owned_json, ref_json);
1056 }
1057
1058 #[test]
1059 fn nested_nodes_serialize_same() {
1060 let child = Node::new(Cow::Borrowed("item"), Attrs::new(), None);
1061 let parent = Node::new(
1062 Cow::Borrowed("list"),
1063 Attrs::new(),
1064 Some(NodeContent::Nodes(vec![child])),
1065 );
1066 let parent_ref = parent.as_node_ref();
1067
1068 assert_eq!(
1069 serde_json::to_value(&parent).unwrap(),
1070 serde_json::to_value(&parent_ref).unwrap(),
1071 );
1072 }
1073
1074 #[test]
1075 fn bytes_content_serializes_same() {
1076 let node = Node::new(
1077 Cow::Borrowed("iq"),
1078 Attrs(vec![(Cow::Borrowed("id"), NodeValue::String("1".into()))]),
1079 Some(NodeContent::Bytes(vec![0xDE, 0xAD])),
1080 );
1081 let node_ref = node.as_node_ref();
1082
1083 let owned_json = serde_json::to_value(&node).unwrap();
1084 let ref_json = serde_json::to_value(&node_ref).unwrap();
1085 assert_eq!(owned_json, ref_json);
1086 }
1087
1088 #[test]
1089 fn value_ref_matches_node_value() {
1090 let string_val = NodeValue::String("hello".into());
1091 let string_ref = ValueRef::String(NodeStr::Borrowed("hello"));
1092 assert_eq!(
1093 serde_json::to_value(&string_val).unwrap(),
1094 serde_json::to_value(&string_ref).unwrap(),
1095 );
1096
1097 let jid = Jid {
1098 user: "5550199999".into(),
1099 server: Server::Group,
1100 agent: 1,
1101 device: 2,
1102 integrator: 3,
1103 };
1104 let jid_val = NodeValue::Jid(jid.clone());
1105 let jid_ref_val = ValueRef::Jid(JidRef {
1106 user: NodeStr::Borrowed("5550199999"),
1107 server: Server::Group,
1108 agent: 1,
1109 device: 2,
1110 integrator: 3,
1111 });
1112 assert_eq!(
1113 serde_json::to_value(&jid_val).unwrap(),
1114 serde_json::to_value(&jid_ref_val).unwrap(),
1115 );
1116 }
1117
1118 #[test]
1119 fn owned_node_ref_serializes_same_as_owned() {
1120 let node = Node::new(
1121 Cow::Borrowed("iq"),
1122 Attrs(vec![(Cow::Borrowed("id"), NodeValue::String("abc".into()))]),
1123 Some(NodeContent::String("payload".into())),
1124 );
1125
1126 let bytes = crate::marshal::marshal(&node).unwrap();
1127 let owned_ref = OwnedNodeRef::new(Bytes::from(bytes[1..].to_vec())).unwrap();
1129
1130 let from_ref = serde_json::to_value(&owned_ref).unwrap();
1131 let from_owned = serde_json::to_value(owned_ref.to_owned_node()).unwrap();
1132 assert_eq!(from_ref, from_owned);
1133 }
1134}