mqute_codec/protocol/v4/
suback.rs

1//! # SubAck Packet V4
2//!
3//! This module initializes the `SubAck` packet for MQTT protocol.
4//! It uses the `suback!` macro to define the `SubAck` packet structure.
5
6use crate::protocol::common::suback;
7use crate::protocol::QoS;
8use crate::Error;
9
10/// Represents the return codes for a `SubAck` packet.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum ReturnCode {
13    /// Indicates a successful subscription with the granted QoS level.
14    Success(QoS),
15
16    /// Indicates that the subscription failed.
17    Failure,
18}
19
20impl TryFrom<u8> for ReturnCode {
21    type Error = Error;
22
23    /// Converts a `u8` value into a `ReturnCode`.
24    fn try_from(value: u8) -> Result<Self, Self::Error> {
25        let code = match value {
26            0x0 => ReturnCode::Success(QoS::AtMostOnce),
27            0x1 => ReturnCode::Success(QoS::AtLeastOnce),
28            0x2 => ReturnCode::Success(QoS::ExactlyOnce),
29            0x80 => ReturnCode::Failure,
30            _ => return Err(Error::InvalidReasonCode(value)),
31        };
32
33        Ok(code)
34    }
35}
36
37impl From<ReturnCode> for u8 {
38    /// Converts a `ReturnCode` into a `u8` value.
39    fn from(value: ReturnCode) -> Self {
40        match value {
41            ReturnCode::Success(qos) => qos as u8,
42            ReturnCode::Failure => 0x80,
43        }
44    }
45}
46
47// Defines the `SubAck` packet
48suback!(ReturnCode);
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53    use crate::codec::{Decode, Encode, PacketCodec};
54    use crate::protocol::PacketType;
55    use bytes::BytesMut;
56    use tokio_util::codec::Decoder;
57
58    #[test]
59    fn suback_decode() {
60        let mut codec = PacketCodec::new(None, None);
61
62        let data = &[
63            (PacketType::SubAck as u8) << 4, // Packet type
64            0x04,                            // Remaining len
65            0x12,                            // Packet ID
66            0x34,
67            0x02, // Success
68            0x80, // Failure
69        ];
70
71        let mut stream = BytesMut::new();
72
73        stream.extend_from_slice(&data[..]);
74
75        let raw_packet = codec.decode(&mut stream).unwrap().unwrap();
76        let packet = SubAck::decode(raw_packet).unwrap();
77
78        assert_eq!(
79            packet,
80            SubAck::new(
81                0x1234,
82                vec![ReturnCode::Success(QoS::ExactlyOnce), ReturnCode::Failure]
83            )
84        );
85    }
86
87    #[test]
88    fn suback_encode() {
89        let packet = SubAck::new(
90            0x1234,
91            vec![ReturnCode::Success(QoS::ExactlyOnce), ReturnCode::Failure],
92        );
93
94        let mut stream = BytesMut::new();
95        packet.encode(&mut stream).unwrap();
96        assert_eq!(
97            stream,
98            vec![
99                (PacketType::SubAck as u8) << 4,
100                0x04,
101                0x12,
102                0x34,
103                0x02,
104                0x80
105            ]
106        );
107    }
108}