1use std::cmp::Ordering;
4
5use std::io::{self, Read, Write};
6
7use byteorder::{ReadBytesExt, WriteBytesExt};
8
9use crate::control::variable_header::PacketIdentifier;
10use crate::control::{ControlType, FixedHeader, PacketType};
11use crate::packet::{DecodablePacket, PacketError};
12use crate::qos::QualityOfService;
13use crate::{Decodable, Encodable};
14
15#[repr(u8)]
17#[derive(Debug, Eq, PartialEq, Copy, Clone)]
18pub enum SubscribeReturnCode {
19 MaximumQoSLevel0 = 0x00,
20 MaximumQoSLevel1 = 0x01,
21 MaximumQoSLevel2 = 0x02,
22 Failure = 0x80,
23}
24
25impl PartialOrd for SubscribeReturnCode {
26 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
27 use self::SubscribeReturnCode::*;
28 match (self, other) {
29 (&Failure, _) => None,
30 (_, &Failure) => None,
31 (&MaximumQoSLevel0, &MaximumQoSLevel0) => Some(Ordering::Equal),
32 (&MaximumQoSLevel1, &MaximumQoSLevel1) => Some(Ordering::Equal),
33 (&MaximumQoSLevel2, &MaximumQoSLevel2) => Some(Ordering::Equal),
34 (&MaximumQoSLevel0, _) => Some(Ordering::Less),
35 (&MaximumQoSLevel1, &MaximumQoSLevel0) => Some(Ordering::Greater),
36 (&MaximumQoSLevel1, &MaximumQoSLevel2) => Some(Ordering::Less),
37 (&MaximumQoSLevel2, _) => Some(Ordering::Greater),
38 }
39 }
40}
41
42impl From<QualityOfService> for SubscribeReturnCode {
43 fn from(qos: QualityOfService) -> Self {
44 match qos {
45 QualityOfService::Level0 => SubscribeReturnCode::MaximumQoSLevel0,
46 QualityOfService::Level1 => SubscribeReturnCode::MaximumQoSLevel1,
47 QualityOfService::Level2 => SubscribeReturnCode::MaximumQoSLevel2,
48 }
49 }
50}
51
52#[derive(Debug, Eq, PartialEq, Clone)]
54pub struct SubackPacket {
55 fixed_header: FixedHeader,
56 packet_identifier: PacketIdentifier,
57 payload: SubackPacketPayload,
58}
59
60encodable_packet!(SubackPacket(packet_identifier, payload));
61
62impl SubackPacket {
63 pub fn new(pkid: u16, subscribes: Vec<SubscribeReturnCode>) -> SubackPacket {
64 let mut pk = SubackPacket {
65 fixed_header: FixedHeader::new(PacketType::with_default(ControlType::SubscribeAcknowledgement), 0),
66 packet_identifier: PacketIdentifier(pkid),
67 payload: SubackPacketPayload::new(subscribes),
68 };
69 pk.fix_header_remaining_len();
70 pk
71 }
72
73 pub fn packet_identifier(&self) -> u16 {
74 self.packet_identifier.0
75 }
76
77 pub fn set_packet_identifier(&mut self, pkid: u16) {
78 self.packet_identifier.0 = pkid;
79 }
80
81 pub fn subscribes(&self) -> &[SubscribeReturnCode] {
82 &self.payload.subscribes[..]
83 }
84}
85
86impl DecodablePacket for SubackPacket {
87 type DecodePacketError = SubackPacketError;
88
89 fn decode_packet<R: Read>(reader: &mut R, fixed_header: FixedHeader) -> Result<Self, PacketError<Self>> {
90 let packet_identifier = PacketIdentifier::decode(reader)?;
91 let payload: SubackPacketPayload = SubackPacketPayload::decode_with(
92 reader,
93 fixed_header.remaining_length - packet_identifier.encoded_length(),
94 )
95 .map_err(PacketError::PayloadError)?;
96 Ok(SubackPacket {
97 fixed_header,
98 packet_identifier,
99 payload,
100 })
101 }
102}
103
104#[derive(Debug, Eq, PartialEq, Clone)]
105struct SubackPacketPayload {
106 subscribes: Vec<SubscribeReturnCode>,
107}
108
109impl SubackPacketPayload {
110 pub fn new(subs: Vec<SubscribeReturnCode>) -> SubackPacketPayload {
111 SubackPacketPayload { subscribes: subs }
112 }
113}
114
115impl Encodable for SubackPacketPayload {
116 fn encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
117 for code in self.subscribes.iter() {
118 writer.write_u8(*code as u8)?;
119 }
120
121 Ok(())
122 }
123
124 fn encoded_length(&self) -> u32 {
125 self.subscribes.len() as u32
126 }
127}
128
129impl Decodable for SubackPacketPayload {
130 type Error = SubackPacketError;
131 type Cond = u32;
132
133 fn decode_with<R: Read>(reader: &mut R, payload_len: u32) -> Result<SubackPacketPayload, SubackPacketError> {
134 let mut subs = Vec::new();
135
136 for _ in 0..payload_len {
137 let retcode = match reader.read_u8()? {
138 0x00 => SubscribeReturnCode::MaximumQoSLevel0,
139 0x01 => SubscribeReturnCode::MaximumQoSLevel1,
140 0x02 => SubscribeReturnCode::MaximumQoSLevel2,
141 0x80 => SubscribeReturnCode::Failure,
142 code => return Err(SubackPacketError::InvalidSubscribeReturnCode(code)),
143 };
144
145 subs.push(retcode);
146 }
147
148 Ok(SubackPacketPayload::new(subs))
149 }
150}
151
152#[derive(Debug, thiserror::Error)]
153pub enum SubackPacketError {
154 #[error(transparent)]
155 IoError(#[from] io::Error),
156 #[error("invalid subscribe return code {0}")]
157 InvalidSubscribeReturnCode(u8),
158}