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)]
26#[xml()]
27pub enum Stanza {
28 #[xml(transparent)]
30 Iq(Iq),
31
32 #[xml(transparent)]
34 Message(Message),
35
36 #[xml(transparent)]
38 Presence(Presence),
39}
40
41impl Stanza {
42 pub fn ensure_id(&mut self) -> &str {
44 match self {
45 Self::Iq(iq) => {
46 let id = iq.id_mut();
47 if id.is_empty() {
48 *id = make_id();
49 }
50 id
51 }
52 Self::Message(message) => message.id.get_or_insert_with(|| Id(make_id())).0.as_ref(),
53 Self::Presence(presence) => presence.id.get_or_insert_with(make_id),
54 }
55 }
56}
57
58impl From<Iq> for Stanza {
59 fn from(other: Iq) -> Self {
60 Self::Iq(other)
61 }
62}
63
64impl From<Presence> for Stanza {
65 fn from(other: Presence) -> Self {
66 Self::Presence(other)
67 }
68}
69
70impl From<Message> for Stanza {
71 fn from(other: Message) -> Self {
72 Self::Message(other)
73 }
74}
75
76impl TryFrom<Stanza> for Message {
77 type Error = Stanza;
78
79 fn try_from(other: Stanza) -> Result<Self, Self::Error> {
80 match other {
81 Stanza::Message(st) => Ok(st),
82 other => Err(other),
83 }
84 }
85}
86
87impl TryFrom<Stanza> for Presence {
88 type Error = Stanza;
89
90 fn try_from(other: Stanza) -> Result<Self, Self::Error> {
91 match other {
92 Stanza::Presence(st) => Ok(st),
93 other => Err(other),
94 }
95 }
96}
97
98impl TryFrom<Stanza> for Iq {
99 type Error = Stanza;
100
101 fn try_from(other: Stanza) -> Result<Self, Stanza> {
102 match other {
103 Stanza::Iq(st) => Ok(st),
104 other => Err(other),
105 }
106 }
107}
108
109impl From<Stanza> for XmppStreamElement {
110 fn from(other: Stanza) -> Self {
111 Self::Stanza(other)
112 }
113}
114
115#[derive(Debug)]
117pub enum Event {
118 Online {
120 bound_jid: Jid,
126 features: StreamFeatures,
128 resumed: bool,
132 },
133 Disconnected(Error),
135 Stanza(Stanza),
137}
138
139impl Event {
140 pub fn is_online(&self) -> bool {
142 matches!(&self, Event::Online { .. })
143 }
144
145 pub fn get_jid(&self) -> Option<&Jid> {
147 match *self {
148 Event::Online { ref bound_jid, .. } => Some(bound_jid),
149 _ => None,
150 }
151 }
152
153 pub fn as_stanza(&self) -> Option<&Stanza> {
155 match *self {
156 Event::Stanza(ref stanza) => Some(stanza),
157 _ => None,
158 }
159 }
160
161 pub fn into_stanza(self) -> Option<Stanza> {
163 match self {
164 Event::Stanza(stanza) => Some(stanza),
165 _ => None,
166 }
167 }
168}