1use xmpp_parsers::{
8 iq::Iq,
9 jid::Jid,
10 message::{Id, Message},
11 presence::Presence,
12 stream_features::StreamFeatures,
13};
14use xso::{AsXml, FromXml};
15
16use crate::xmlstream::XmppStreamElement;
17use crate::Error;
18
19pub(crate) fn make_id() -> String {
20 let id: u64 = rand::random();
21 format!("{}", id)
22}
23
24#[derive(FromXml, AsXml, Debug, PartialEq)]
29#[xml()]
30pub enum Stanza {
31 #[xml(transparent)]
33 Iq(Iq),
34
35 #[xml(transparent)]
37 Message(Message),
38
39 #[xml(transparent)]
41 Presence(Presence),
42}
43
44impl Stanza {
45 pub fn ensure_id(&mut self) -> &str {
47 match self {
48 Self::Iq(iq) => {
49 let id = iq.id_mut();
50 if id.is_empty() {
51 *id = make_id();
52 }
53 id
54 }
55 Self::Message(message) => message.id.get_or_insert_with(|| Id(make_id())).0.as_ref(),
56 Self::Presence(presence) => presence.id.get_or_insert_with(make_id),
57 }
58 }
59}
60
61impl From<Iq> for Stanza {
62 fn from(other: Iq) -> Self {
63 Self::Iq(other)
64 }
65}
66
67impl From<Presence> for Stanza {
68 fn from(other: Presence) -> Self {
69 Self::Presence(other)
70 }
71}
72
73impl From<Message> for Stanza {
74 fn from(other: Message) -> Self {
75 Self::Message(other)
76 }
77}
78
79impl TryFrom<Stanza> for Message {
80 type Error = Stanza;
81
82 fn try_from(other: Stanza) -> Result<Self, Self::Error> {
83 match other {
84 Stanza::Message(st) => Ok(st),
85 other => Err(other),
86 }
87 }
88}
89
90impl TryFrom<Stanza> for Presence {
91 type Error = Stanza;
92
93 fn try_from(other: Stanza) -> Result<Self, Self::Error> {
94 match other {
95 Stanza::Presence(st) => Ok(st),
96 other => Err(other),
97 }
98 }
99}
100
101impl TryFrom<Stanza> for Iq {
102 type Error = Stanza;
103
104 fn try_from(other: Stanza) -> Result<Self, Stanza> {
105 match other {
106 Stanza::Iq(st) => Ok(st),
107 other => Err(other),
108 }
109 }
110}
111
112impl From<Stanza> for XmppStreamElement {
113 fn from(other: Stanza) -> Self {
114 Self::Stanza(other)
115 }
116}
117
118#[derive(Debug)]
120pub enum Event {
121 Online {
123 bound_jid: Jid,
129 features: StreamFeatures,
131 resumed: bool,
135 },
136 Disconnected(Error),
138 Stanza(Stanza),
140}
141
142impl Event {
143 pub fn is_online(&self) -> bool {
145 matches!(&self, Event::Online { .. })
146 }
147
148 pub fn get_jid(&self) -> Option<&Jid> {
150 match *self {
151 Event::Online { ref bound_jid, .. } => Some(bound_jid),
152 _ => None,
153 }
154 }
155
156 pub fn as_stanza(&self) -> Option<&Stanza> {
158 match *self {
159 Event::Stanza(ref stanza) => Some(stanza),
160 _ => None,
161 }
162 }
163
164 pub fn into_stanza(self) -> Option<Stanza> {
166 match self {
167 Event::Stanza(stanza) => Some(stanza),
168 _ => None,
169 }
170 }
171}