embedded_mqtt/variable_header/
publish.rs1use core::{
2 convert::TryFrom,
3 result::Result,
4};
5
6use crate::{
7 fixed_header::{PacketFlags, PublishFlags},
8 codec::{self, Encodable},
9 status::Status,
10 error::{DecodeError, EncodeError},
11 qos,
12};
13
14use super::{PacketId, HeaderDecode};
15
16#[derive(Debug)]
17pub struct Publish<'a> {
18 topic_name: &'a str,
19 packet_identifier: Option<PacketId>,
20}
21
22impl<'a> Publish<'a> {
23 pub fn new(topic_name: &'a str, packet_identifier: Option<PacketId>) -> Self {
24 Self {
25 topic_name,
26 packet_identifier,
27 }
28 }
29
30 pub fn topic_name(&self) -> &'a str {
31 self.topic_name
32 }
33
34 pub fn packet_identifier(&self) -> Option<PacketId> {
35 self.packet_identifier
36 }
37}
38
39impl<'a> HeaderDecode<'a> for Publish<'a> {
40 fn decode(flags: PacketFlags, bytes: &'a [u8]) -> Result<Status<(usize, Self)>, DecodeError> {
41 let flags = PublishFlags::try_from(flags)?;
42
43 let offset = 0;
44 let (offset, topic_name) = read!(codec::string::parse_string, bytes, offset);
45
46 let (offset, packet_identifier) = if flags.qos()? != qos::QoS::AtMostOnce {
47 let (offset, packet_identifier) = read!(codec::values::parse_u16, bytes, offset);
48 (offset, Some(packet_identifier))
49 } else {
50 (offset, None)
51 };
52
53 Ok(Status::Complete((offset, Self {
54 topic_name,
55 packet_identifier
56 })))
57 }
58}
59
60impl<'a> Encodable for Publish<'a> {
61 fn encoded_len(&self) -> usize {
62 self.topic_name.encoded_len() + self.packet_identifier.map(|_| 2).unwrap_or(0)
63 }
64
65 fn encode(&self, bytes: &mut [u8]) -> Result<usize, EncodeError> {
66 let offset = 0;
67 let offset = {
68 let o = self.topic_name.encode(&mut bytes[offset..])?;
69 offset + o
70 };
71 let offset = if let Some(packet_identifier) = self.packet_identifier {
72 let o = codec::values::encode_u16(packet_identifier, &mut bytes[offset..])?;
73 offset + o
74 } else {
75 offset
76 };
77 Ok(offset)
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn encode() {
87 let header = Publish {
88 topic_name: "a/b",
89 packet_identifier: Some(1),
90 };
91
92 assert_eq!(7, header.encoded_len());
93
94 let mut buf = [0u8; 7];
95 let res = header.encode(&mut buf[..]);
96 assert_eq!(res, Ok(7));
97
98 assert_eq!(buf, [
99 0b0000_0000,
100 0b0000_0011,
101 0x61,
102 0x2f,
103 0x62,
104 0b0000_0000,
105 0b0000_0001,
106 ]);
107 }
108}