1use xmpp_parsers::{
8 iq::Iq,
9 jid::Jid,
10 message::{Id, Message},
11 presence::Presence,
12};
13use xso::{AsXml, FromXml};
14
15use crate::xmlstream::XmppStreamElement;
16use crate::Error;
17
18pub(crate) fn make_id() -> String {
19 let id: u64 = rand::random();
20 format!("{}", id)
21}
22
23#[derive(FromXml, AsXml, Debug, PartialEq)]
28#[xml()]
29pub enum Stanza {
30 #[xml(transparent)]
32 Iq(Iq),
33
34 #[xml(transparent)]
36 Message(Message),
37
38 #[xml(transparent)]
40 Presence(Presence),
41}
42
43impl Stanza {
44 pub fn ensure_id(&mut self) -> &str {
46 match self {
47 Self::Iq(iq) => {
48 let id = iq.id_mut();
49 if id.is_empty() {
50 *id = make_id();
51 }
52 id
53 }
54 Self::Message(message) => message.id.get_or_insert_with(|| Id(make_id())).0.as_ref(),
55 Self::Presence(presence) => presence.id.get_or_insert_with(make_id),
56 }
57 }
58}
59
60impl From<Iq> for Stanza {
61 fn from(other: Iq) -> Self {
62 Self::Iq(other)
63 }
64}
65
66impl From<Presence> for Stanza {
67 fn from(other: Presence) -> Self {
68 Self::Presence(other)
69 }
70}
71
72impl From<Message> for Stanza {
73 fn from(other: Message) -> Self {
74 Self::Message(other)
75 }
76}
77
78impl TryFrom<Stanza> for Message {
79 type Error = Stanza;
80
81 fn try_from(other: Stanza) -> Result<Self, Self::Error> {
82 match other {
83 Stanza::Message(st) => Ok(st),
84 other => Err(other),
85 }
86 }
87}
88
89impl TryFrom<Stanza> for Presence {
90 type Error = Stanza;
91
92 fn try_from(other: Stanza) -> Result<Self, Self::Error> {
93 match other {
94 Stanza::Presence(st) => Ok(st),
95 other => Err(other),
96 }
97 }
98}
99
100impl TryFrom<Stanza> for Iq {
101 type Error = Stanza;
102
103 fn try_from(other: Stanza) -> Result<Self, Stanza> {
104 match other {
105 Stanza::Iq(st) => Ok(st),
106 other => Err(other),
107 }
108 }
109}
110
111impl From<Stanza> for XmppStreamElement {
112 fn from(other: Stanza) -> Self {
113 Self::Stanza(other)
114 }
115}
116
117#[derive(Debug)]
119pub enum Event {
120 Online {
122 bound_jid: Jid,
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}