mqute_codec/protocol/v5/
pubrec.rs

1//! # Publish Received (PubRec) Packet - MQTT v5
2//!
3//! This module implements the MQTT v5 `PubRec` packet, which is the second packet in the
4//! Quality of Service 2 (QoS 2) message delivery flow. The `PubRec` packet is sent by the
5//! receiver to acknowledge receipt of a QoS 2 PUBLISH packet.
6
7use crate::protocol::v5::reason::ReasonCode;
8use crate::protocol::v5::util::{
9    ack, ack_decode_impl, ack_encode_impl, ack_properties, ack_properties_frame_impl,
10};
11use crate::protocol::{Flags, PacketType, traits};
12
13/// Validates reason codes for `PubRec` packets
14///
15/// MQTT v5 specifies the following valid reason codes for `PubRec`:
16/// - 0x00 (Success) - Packet accepted and stored
17/// - 0x10 (No matching subscribers) - No subscribers for the topic
18/// - 0x80 (Unspecified error) - Unspecified error condition
19/// - 0x83 (Implementation specific error) - Implementation-specific error
20/// - 0x87 (Not authorized) - Client not authorized
21/// - 0x90 (Topic Name invalid) - Malformed topic name
22/// - 0x91 (Packet Identifier in use) - Duplicate packet ID
23/// - 0x97 (Quota exceeded) - Message quota exceeded
24/// - 0x99 (Payload format invalid) - Invalid payload format
25fn validate_pubrec_reason_code(code: ReasonCode) -> bool {
26    matches!(
27        code.into(),
28        0 | 16 | 128 | 131 | 135 | 144 | 145 | 151 | 153
29    )
30}
31
32// Defines properties specific to `PubRec` packets
33ack_properties!(PubRecProperties);
34
35// Implements the PropertyFrame trait for PubRecProperties
36ack_properties_frame_impl!(PubRecProperties);
37
38// Represents an MQTT v5 `PubRec` packet
39ack!(PubRec, PubRecProperties, validate_pubrec_reason_code);
40
41// Implements packet decoding for `PubRec`
42ack_decode_impl!(
43    PubRec,
44    PacketType::PubRec,
45    Flags::default(),
46    validate_pubrec_reason_code
47);
48
49// Implements packet encoding for `PubRec`
50ack_encode_impl!(PubRec, PacketType::PubRec, Flags::default());
51
52impl traits::PubRec for PubRec {}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use crate::codec::PacketCodec;
58    use crate::codec::{Decode, Encode};
59    use bytes::BytesMut;
60    use tokio_util::codec::Decoder;
61
62    #[test]
63    fn pubrec_decode() {
64        let mut codec = PacketCodec::new(None, None);
65
66        let data = &[
67            (PacketType::PubRec as u8) << 4, // Packet type
68            0x04,                            // Remaining len
69            0x12,                            // Packet ID
70            0x34,                            //
71            0x00,                            // Reason code
72            0x00,                            // Property len
73        ];
74
75        let mut stream = BytesMut::new();
76
77        stream.extend_from_slice(&data[..]);
78
79        let raw_packet = codec.decode(&mut stream).unwrap().unwrap();
80        let packet = PubRec::decode(raw_packet).unwrap();
81
82        assert_eq!(packet, PubRec::new(0x1234, ReasonCode::Success, None));
83    }
84
85    #[test]
86    fn pubrec_encode() {
87        let packet = PubRec::new(0x1234, ReasonCode::Success, None);
88
89        let mut stream = BytesMut::new();
90        packet.encode(&mut stream).unwrap();
91        assert_eq!(
92            stream,
93            vec![
94                (PacketType::PubRec as u8) << 4, // Packet type
95                0x02,                            // Remaining len
96                0x12,                            // Packet ID
97                0x34,                            //
98            ]
99        );
100    }
101}