Skip to main content

embedded_svc/mqtt/
client.rs

1use core::fmt::{self, Debug, Display, Formatter};
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6#[cfg(feature = "use_serde")]
7use serde::{Deserialize, Serialize};
8
9pub trait ErrorType {
10    type Error: Debug;
11}
12
13impl<E> ErrorType for &E
14where
15    E: ErrorType,
16{
17    type Error = E::Error;
18}
19
20impl<E> ErrorType for &mut E
21where
22    E: ErrorType,
23{
24    type Error = E::Error;
25}
26
27/// Quality of service
28#[repr(u8)]
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
32pub enum QoS {
33    AtMostOnce = 0,
34    AtLeastOnce = 1,
35    ExactlyOnce = 2,
36}
37
38pub type MessageId = u32;
39
40pub trait Event: ErrorType {
41    fn payload(&self) -> EventPayload<'_, Self::Error>;
42}
43
44impl<E> Event for &E
45where
46    E: Event,
47{
48    fn payload(&self) -> EventPayload<'_, Self::Error> {
49        (*self).payload()
50    }
51}
52
53impl<E> Event for &mut E
54where
55    E: Event,
56{
57    fn payload(&self) -> EventPayload<'_, Self::Error> {
58        (**self).payload()
59    }
60}
61
62#[derive(Clone, PartialEq, Eq, Debug)]
63#[cfg_attr(feature = "defmt", derive(defmt::Format))]
64pub enum EventPayload<'a, E> {
65    BeforeConnect,
66    Connected(bool),
67    Disconnected,
68    Subscribed(MessageId),
69    Unsubscribed(MessageId),
70    Published(MessageId),
71    Received {
72        id: MessageId,
73        topic: Option<&'a str>,
74        data: &'a [u8],
75        details: Details,
76    },
77    Deleted(MessageId),
78    Error(&'a E),
79}
80
81impl<E> Display for EventPayload<'_, E>
82where
83    E: Debug,
84{
85    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
86        match self {
87            Self::BeforeConnect => write!(f, "BeforeConnect"),
88            Self::Connected(session_present) => write!(f, "Connected(session: {session_present})"),
89            Self::Disconnected => write!(f, "Disconnected"),
90            Self::Subscribed(message_id) => write!(f, "Subscribed({message_id})"),
91            Self::Unsubscribed(message_id) => write!(f, "Unsubscribed({message_id})"),
92            Self::Published(message_id) => write!(f, "Published({message_id})"),
93            Self::Received {
94                id,
95                topic,
96                data,
97                details,
98            } => write!(
99                f,
100                "Received {{ id: {id}, topic: {topic:?}, data: {:?}, details: {details:?} }}",
101                core::str::from_utf8(data),
102            ),
103            Self::Deleted(message_id) => write!(f, "Deleted({message_id})"),
104            Self::Error(error) => write!(f, "Error({error:?})"),
105        }
106    }
107}
108
109#[derive(Debug, Copy, Clone, PartialEq, Eq)]
110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
111#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
112pub enum Details {
113    Complete,
114    InitialChunk(InitialChunkData),
115    SubsequentChunk(SubsequentChunkData),
116}
117
118#[derive(Debug, Copy, Clone, PartialEq, Eq)]
119#[cfg_attr(feature = "defmt", derive(defmt::Format))]
120#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
121pub struct InitialChunkData {
122    pub total_data_size: usize,
123}
124
125#[derive(Debug, Copy, Clone, PartialEq, Eq)]
126#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
128pub struct SubsequentChunkData {
129    pub current_data_offset: usize,
130    pub total_data_size: usize,
131}
132
133pub trait Client: ErrorType {
134    fn subscribe<'a>(&'a mut self, topic: &'a str, qos: QoS) -> Result<MessageId, Self::Error>;
135
136    fn unsubscribe<'a>(&'a mut self, topic: &'a str) -> Result<MessageId, Self::Error>;
137}
138
139impl<C> Client for &mut C
140where
141    C: Client,
142{
143    fn subscribe<'a>(&'a mut self, topic: &'a str, qos: QoS) -> Result<MessageId, Self::Error> {
144        (*self).subscribe(topic, qos)
145    }
146
147    fn unsubscribe<'a>(&'a mut self, topic: &'a str) -> Result<MessageId, Self::Error> {
148        (*self).unsubscribe(topic)
149    }
150}
151
152pub trait Publish: ErrorType {
153    fn publish<'a>(
154        &'a mut self,
155        topic: &'a str,
156        qos: QoS,
157        retain: bool,
158        payload: &'a [u8],
159    ) -> Result<MessageId, Self::Error>;
160}
161
162impl<P> Publish for &mut P
163where
164    P: Publish,
165{
166    fn publish<'a>(
167        &'a mut self,
168        topic: &'a str,
169        qos: QoS,
170        retain: bool,
171        payload: &'a [u8],
172    ) -> Result<MessageId, Self::Error> {
173        (*self).publish(topic, qos, retain, payload)
174    }
175}
176
177pub trait Enqueue: ErrorType {
178    fn enqueue<'a>(
179        &'a mut self,
180        topic: &'a str,
181        qos: QoS,
182        retain: bool,
183        payload: &'a [u8],
184    ) -> Result<MessageId, Self::Error>;
185}
186
187impl<E> Enqueue for &mut E
188where
189    E: Enqueue,
190{
191    fn enqueue<'a>(
192        &'a mut self,
193        topic: &'a str,
194        qos: QoS,
195        retain: bool,
196        payload: &'a [u8],
197    ) -> Result<MessageId, Self::Error> {
198        (*self).enqueue(topic, qos, retain, payload)
199    }
200}
201
202pub trait Connection: ErrorType {
203    type Event<'a>: Event
204    where
205        Self: 'a;
206
207    fn next(&mut self) -> Result<Self::Event<'_>, Self::Error>;
208}
209
210impl<C> Connection for &mut C
211where
212    C: Connection,
213{
214    type Event<'a>
215        = C::Event<'a>
216    where
217        Self: 'a;
218
219    fn next(&mut self) -> Result<Self::Event<'_>, Self::Error> {
220        (*self).next()
221    }
222}
223
224pub mod asynch {
225    pub use super::{Details, ErrorType, Event, EventPayload, MessageId, QoS};
226
227    pub trait Client: ErrorType {
228        async fn subscribe(&mut self, topic: &str, qos: QoS) -> Result<MessageId, Self::Error>;
229
230        async fn unsubscribe(&mut self, topic: &str) -> Result<MessageId, Self::Error>;
231    }
232
233    impl<C> Client for &mut C
234    where
235        C: Client,
236    {
237        async fn subscribe(&mut self, topic: &str, qos: QoS) -> Result<MessageId, Self::Error> {
238            (*self).subscribe(topic, qos).await
239        }
240
241        async fn unsubscribe(&mut self, topic: &str) -> Result<MessageId, Self::Error> {
242            (*self).unsubscribe(topic).await
243        }
244    }
245
246    pub trait Publish: ErrorType {
247        async fn publish(
248            &mut self,
249            topic: &str,
250            qos: QoS,
251            retain: bool,
252            payload: &[u8],
253        ) -> Result<MessageId, Self::Error>;
254    }
255
256    impl<P> Publish for &mut P
257    where
258        P: Publish,
259    {
260        async fn publish(
261            &mut self,
262            topic: &str,
263            qos: QoS,
264            retain: bool,
265            payload: &[u8],
266        ) -> Result<MessageId, Self::Error> {
267            (*self).publish(topic, qos, retain, payload).await
268        }
269    }
270
271    pub trait Connection: ErrorType {
272        type Event<'a>: Event
273        where
274            Self: 'a;
275
276        async fn next(&mut self) -> Result<Self::Event<'_>, Self::Error>;
277    }
278
279    impl<C> Connection for &mut C
280    where
281        C: Connection,
282    {
283        type Event<'a>
284            = C::Event<'a>
285        where
286            Self: 'a;
287
288        async fn next(&mut self) -> Result<Self::Event<'_>, Self::Error> {
289            (*self).next().await
290        }
291    }
292}