mqttrs/
publish.rs

1use crate::{decoder::*, encoder::*, *};
2
3/// Publish packet ([MQTT 3.3]).
4///
5/// [MQTT 3.3]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718037
6#[derive(Debug, Clone, PartialEq)]
7pub struct Publish<'a> {
8    pub dup: bool,
9    pub qospid: QosPid,
10    pub retain: bool,
11    pub topic_name: &'a str,
12    pub payload: &'a [u8],
13}
14
15impl<'a> Publish<'a> {
16    pub(crate) fn from_buffer(
17        header: &Header,
18        remaining_len: usize,
19        buf: &'a [u8],
20        offset: &mut usize,
21    ) -> Result<Self, Error> {
22        let payload_end = *offset + remaining_len;
23        let topic_name = read_str(buf, offset)?;
24
25        let qospid = match header.qos {
26            QoS::AtMostOnce => QosPid::AtMostOnce,
27            QoS::AtLeastOnce => QosPid::AtLeastOnce(Pid::from_buffer(buf, offset)?),
28            QoS::ExactlyOnce => QosPid::ExactlyOnce(Pid::from_buffer(buf, offset)?),
29        };
30
31        Ok(Publish {
32            dup: header.dup,
33            qospid,
34            retain: header.retain,
35            topic_name,
36            payload: &buf[*offset..payload_end],
37        })
38    }
39    pub(crate) fn to_buffer(&self, buf: &mut [u8], offset: &mut usize) -> Result<usize, Error> {
40        // Header
41        let mut header: u8 = match self.qospid {
42            QosPid::AtMostOnce => 0b00110000,
43            QosPid::AtLeastOnce(_) => 0b00110010,
44            QosPid::ExactlyOnce(_) => 0b00110100,
45        };
46        if self.dup {
47            header |= 0b00001000 as u8;
48        };
49        if self.retain {
50            header |= 0b00000001 as u8;
51        };
52        check_remaining(buf, offset, 1)?;
53        write_u8(buf, offset, header)?;
54
55        // Length: topic (2+len) + pid (0/2) + payload (len)
56        let length = self.topic_name.len()
57            + match self.qospid {
58                QosPid::AtMostOnce => 2,
59                _ => 4,
60            }
61            + self.payload.len();
62
63        let write_len = write_length(buf, offset, length)? + 1;
64
65        // Topic
66        write_string(buf, offset, self.topic_name)?;
67
68        // Pid
69        match self.qospid {
70            QosPid::AtMostOnce => (),
71            QosPid::AtLeastOnce(pid) => pid.to_buffer(buf, offset)?,
72            QosPid::ExactlyOnce(pid) => pid.to_buffer(buf, offset)?,
73        }
74
75        // Payload
76        for &byte in self.payload {
77            write_u8(buf, offset, byte)?;
78        }
79
80        Ok(write_len)
81    }
82}