mqtt4bytes/packets/
suback.rs1use super::*;
2use crate::*;
3use alloc::vec::Vec;
4use bytes::{Buf, BufMut, Bytes, BytesMut};
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct SubAck {
9 pub pkid: u16,
10 pub return_codes: Vec<SubscribeReturnCodes>,
11}
12
13impl SubAck {
14 pub fn new(pkid: u16, return_codes: Vec<SubscribeReturnCodes>) -> SubAck {
15 SubAck { pkid, return_codes }
16 }
17
18 pub(crate) fn assemble(fixed_header: FixedHeader, mut bytes: Bytes) -> Result<Self, Error> {
19 let variable_header_index = fixed_header.fixed_len;
20 bytes.advance(variable_header_index);
21
22 let pkid = bytes.get_u16();
23 let mut payload_bytes = fixed_header.remaining_len - 2;
24 let mut return_codes = Vec::with_capacity(payload_bytes);
25
26 while payload_bytes > 0 {
27 let return_code = bytes.get_u8();
28 if return_code >> 7 == 1 {
29 return_codes.push(SubscribeReturnCodes::Failure)
30 } else {
31 return_codes.push(SubscribeReturnCodes::Success(qos(return_code & 0x3)?));
32 }
33 payload_bytes -= 1
34 }
35 let suback = SubAck { pkid, return_codes };
36
37 Ok(suback)
38 }
39
40 pub fn write(&self, payload: &mut BytesMut) -> Result<usize, Error> {
41 payload.put_u8(0x90);
42 let remaining_len = self.return_codes.len() + 2;
43 let remaining_len_bytes = write_remaining_length(payload, remaining_len)?;
44 payload.put_u16(self.pkid);
45 let p: Vec<u8> = self
46 .return_codes
47 .iter()
48 .map(|&code| match code {
49 SubscribeReturnCodes::Success(qos) => qos as u8,
50 SubscribeReturnCodes::Failure => 0x80,
51 })
52 .collect();
53
54 payload.extend_from_slice(&p);
55 Ok(1 + remaining_len_bytes + remaining_len)
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub enum SubscribeReturnCodes {
62 Success(QoS),
63 Failure,
64}
65
66#[cfg(test)]
67mod test {
68 use super::*;
69 use alloc::vec;
70 use bytes::BytesMut;
71 use pretty_assertions::assert_eq;
72
73 #[test]
74 fn suback_stitching_works_correctly() {
75 let stream = vec![
76 0x90, 4, 0x00, 0x0F, 0x01, 0x80, 0xDE, 0xAD, 0xBE, 0xEF, ];
81 let mut stream = BytesMut::from(&stream[..]);
82
83 let packet = mqtt_read(&mut stream, 100).unwrap();
84 let packet = match packet {
85 Packet::SubAck(packet) => packet,
86 packet => panic!("Invalid packet = {:?}", packet),
87 };
88
89 assert_eq!(
90 packet,
91 SubAck {
92 pkid: 15,
93 return_codes: vec![
94 SubscribeReturnCodes::Success(QoS::AtLeastOnce),
95 SubscribeReturnCodes::Failure
96 ]
97 }
98 );
99 }
100}