1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
use quick_xml::{
events::{BytesStart, BytesText, Event},
name::QName,
Reader,
};
use super::{Element, IntoElement};
use crate::{JabberError, JID};
const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind";
pub struct Bind {
pub resource: Option<String>,
pub jid: Option<JID>,
}
impl<'e> IntoElement<'e> for Bind {
fn event(&self) -> quick_xml::events::Event<'static> {
let mut bind_event = BytesStart::new("bind");
bind_event.push_attribute(("xmlns", XMLNS));
if self.resource.is_none() && self.jid.is_none() {
return Event::Empty(bind_event);
} else {
return Event::Start(bind_event);
}
}
fn children(&self) -> Option<Vec<Element<'static>>> {
if let Some(resource) = &self.resource {
let resource_event: BytesStart<'static> = BytesStart::new("resource");
let resource_child: BytesText<'static> = BytesText::new(resource).into_owned();
let resource_child: Element<'static> = Element {
event: Event::Text(resource_child),
children: None,
};
let resource_element: Element<'static> = Element {
event: Event::Start(resource_event),
children: Some(vec![resource_child]),
};
return Some(vec![resource_element]);
} else if let Some(jid) = &self.jid {
let jid_event = BytesStart::new("jid");
let jid_child = BytesText::new(&jid.to_string()).into_owned();
let jid_child = Element {
event: Event::Text(jid_child),
children: None,
};
let jid_element = Element {
event: Event::Start(jid_event),
children: Some(vec![jid_child]),
};
return Some(vec![jid_element]);
}
None
}
}
impl TryFrom<Element<'static>> for Bind {
type Error = JabberError;
fn try_from(element: Element<'static>) -> Result<Self, Self::Error> {
if let Event::Start(start) = &element.event {
let buf: Vec<u8> = Vec::new();
let reader = Reader::from_reader(buf);
if start.name() == QName(b"bind")
&& start.try_get_attribute("xmlns")?.is_some_and(|attribute| {
attribute.decode_and_unescape_value(&reader).unwrap() == XMLNS
})
{
let child: Element<'static> = element.child()?.clone();
if let Event::Start(start) = &child.event {
match start.name() {
QName(b"resource") => {
let resource_text = child.child()?;
if let Event::Text(text) = &resource_text.event {
return Ok(Self {
resource: Some(text.unescape()?.into_owned()),
jid: None,
});
}
}
QName(b"jid") => {
let jid_text = child.child()?;
if let Event::Text(text) = &jid_text.event {
return Ok(Self {
jid: Some(text.unescape()?.into_owned().try_into()?),
resource: None,
});
}
}
_ => return Err(JabberError::UnexpectedElement),
}
}
}
} else if let Event::Empty(start) = &element.event {
let buf: Vec<u8> = Vec::new();
let reader = Reader::from_reader(buf);
if start.name() == QName(b"bind")
&& start.try_get_attribute("xmlns")?.is_some_and(|attribute| {
attribute.decode_and_unescape_value(&reader).unwrap() == XMLNS
})
{
return Ok(Bind {
resource: None,
jid: None,
});
}
}
Err(JabberError::UnexpectedElement)
}
}
|