mqute_codec/protocol/v3/
suback.rs

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