1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//! MQTT Protocol Constants
//!
//! This module defines constants for MQTT packet types and flags to avoid magic numbers
//! throughout the codebase.
use crate::PacketType;
/// Fixed header byte 1 values (packet type << 4 | flags)
pub mod fixed_header {
/// CONNECT packet fixed header (0x10)
pub const CONNECT: u8 = (super::PacketType::Connect as u8) << 4;
/// CONNACK packet fixed header (0x20)
pub const CONNACK: u8 = (super::PacketType::ConnAck as u8) << 4;
/// PUBLISH packet fixed header base (0x30) - flags vary
pub const PUBLISH_BASE: u8 = (super::PacketType::Publish as u8) << 4;
/// PUBACK packet fixed header (0x40)
pub const PUBACK: u8 = (super::PacketType::PubAck as u8) << 4;
/// PUBREC packet fixed header (0x50)
pub const PUBREC: u8 = (super::PacketType::PubRec as u8) << 4;
/// PUBREL packet fixed header (0x62) - has required flags
pub const PUBREL: u8 = (super::PacketType::PubRel as u8) << 4 | 0x02;
/// PUBCOMP packet fixed header (0x70)
pub const PUBCOMP: u8 = (super::PacketType::PubComp as u8) << 4;
/// SUBSCRIBE packet fixed header (0x82) - has required flags
pub const SUBSCRIBE: u8 = (super::PacketType::Subscribe as u8) << 4 | 0x02;
/// SUBACK packet fixed header (0x90)
pub const SUBACK: u8 = (super::PacketType::SubAck as u8) << 4;
/// UNSUBSCRIBE packet fixed header (0xA2) - has required flags
pub const UNSUBSCRIBE: u8 = (super::PacketType::Unsubscribe as u8) << 4 | 0x02;
/// UNSUBACK packet fixed header (0xB0)
pub const UNSUBACK: u8 = (super::PacketType::UnsubAck as u8) << 4;
/// PINGREQ packet fixed header (0xC0)
pub const PINGREQ: u8 = (super::PacketType::PingReq as u8) << 4;
/// PINGRESP packet fixed header (0xD0)
pub const PINGRESP: u8 = (super::PacketType::PingResp as u8) << 4;
/// DISCONNECT packet fixed header (0xE0)
pub const DISCONNECT: u8 = (super::PacketType::Disconnect as u8) << 4;
/// AUTH packet fixed header (0xF0)
pub const AUTH: u8 = (super::PacketType::Auth as u8) << 4;
}
/// Masks for extracting fields from fixed header
pub mod masks {
/// Mask for extracting packet type from fixed header byte 1 (0xF0)
pub const PACKET_TYPE: u8 = 0xF0;
/// Mask for extracting flags from fixed header byte 1 (0x0F)
pub const FLAGS: u8 = 0x0F;
/// Mask for checking continuation bit in variable byte integer (0x80)
pub const CONTINUATION_BIT: u8 = 0x80;
/// Mask for extracting value from variable byte integer (0x7F)
pub const VARIABLE_BYTE_VALUE: u8 = 0x7F;
}
/// Common packet payloads
pub mod packets {
/// PINGREQ packet as bytes
pub const PINGREQ_BYTES: [u8; 2] = [super::fixed_header::PINGREQ, 0x00];
/// PINGRESP packet as bytes
pub const PINGRESP_BYTES: [u8; 2] = [super::fixed_header::PINGRESP, 0x00];
}
/// Subscription option masks
pub mod subscription {
/// Mask for `QoS` bits (bits 0-1)
pub const QOS_MASK: u8 = 0x03;
/// Mask for No Local flag (bit 2)
pub const NO_LOCAL_MASK: u8 = 0x04;
/// Mask for Retain As Published flag (bit 3)
pub const RETAIN_AS_PUBLISHED_MASK: u8 = 0x08;
/// Mask for Retain Handling (bits 4-5)
pub const RETAIN_HANDLING_MASK: u8 = 0x30;
/// Shift for Retain Handling
pub const RETAIN_HANDLING_SHIFT: u8 = 4;
/// Mask for reserved bits (bits 6-7)
pub const RESERVED_BITS_MASK: u8 = 0xC0;
}
/// CONNECT flags masks
pub mod connect_flags {
/// Mask for clearing Will `QoS` bits (bits 3-4)
pub const WILL_QOS_CLEAR_MASK: u8 = !0x18;
/// Mask for extracting Will `QoS` (bits 3-4 shifted)
pub const WILL_QOS_MASK: u8 = 0x03;
/// Shift for Will `QoS`
pub const WILL_QOS_SHIFT: u8 = 3;
}
/// String and binary data limits
pub mod limits {
/// Maximum string length in MQTT (65535)
pub const MAX_STRING_LENGTH: u16 = u16::MAX;
/// Maximum client ID length (128 characters)
pub const MAX_CLIENT_ID_LENGTH: usize = 128;
/// Maximum packet size (256 MB)
pub const MAX_PACKET_SIZE: u32 = 268_435_456;
/// Maximum binary data length (65535, limited by 2-byte length prefix)
pub const MAX_BINARY_LENGTH: u32 = 65_535;
}
/// Time-related constants
pub mod time {
use crate::time::Duration;
/// Default session expiry interval (1 hour)
pub const DEFAULT_SESSION_EXPIRY: Duration = Duration::from_secs(3600);
/// Default keep alive interval (60 seconds)
pub const DEFAULT_KEEP_ALIVE: Duration = Duration::from_secs(60);
}
/// Buffer and capacity constants
pub mod buffer {
/// Default buffer capacity (1024 bytes)
pub const DEFAULT_CAPACITY: usize = 1024;
/// Default buffer size for encoding/decoding (2048 bytes)
pub const DEFAULT_BUFFER_SIZE: usize = 2048;
/// Large buffer size for bulk operations (4096 bytes)
pub const LARGE_BUFFER_SIZE: usize = 4096;
/// Maximum buffer size (8192 bytes)
pub const MAX_BUFFER_SIZE: usize = 8192;
/// Very large buffer for high-throughput scenarios (16384 bytes)
pub const VERY_LARGE_BUFFER_SIZE: usize = 16384;
/// Huge buffer for maximum performance (32768 bytes)
pub const HUGE_BUFFER_SIZE: usize = 32768;
}
/// Variable byte integer constants
pub mod variable_byte {
/// Maximum value for single byte (127)
pub const SINGLE_BYTE_MAX: u8 = 127;
/// Maximum value for variable byte integer (268435455)
pub const MAX_VALUE: u32 = 268_435_455;
}
/// Protocol version constants
pub mod version {
/// MQTT protocol version 5.0
pub const MQTT_V5: u8 = 5;
}
/// PUBLISH flags masks
pub mod publish_flags {
/// Mask for clearing `QoS` bits (bits 1-2)
pub const QOS_CLEAR_MASK: u8 = !0x06;
/// Mask for extracting `QoS` (bits 1-2 shifted)
pub const QOS_MASK: u8 = 0x03;
/// Shift for `QoS`
pub const QOS_SHIFT: u8 = 1;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fixed_header_values() {
assert_eq!(fixed_header::CONNECT, 0x10);
assert_eq!(fixed_header::CONNACK, 0x20);
assert_eq!(fixed_header::PUBLISH_BASE, 0x30);
assert_eq!(fixed_header::PINGREQ, 0xC0);
assert_eq!(fixed_header::PINGRESP, 0xD0);
}
#[test]
fn test_packets() {
assert_eq!(packets::PINGREQ_BYTES, [0xC0, 0x00]);
assert_eq!(packets::PINGRESP_BYTES, [0xD0, 0x00]);
}
}