mqtt5_protocol/encoding/
mqtt_binary.rs1use crate::error::{MqttError, Result};
6use crate::prelude::{format, ToString, Vec};
7use bebytes::BeBytes;
8use bytes::Bytes;
9
10#[derive(Debug, Clone, PartialEq, Eq, BeBytes)]
12pub struct MqttBinary {
13 length: u16,
15
16 #[bebytes(size = "length")]
18 data: Vec<u8>,
19}
20
21impl MqttBinary {
22 pub fn create(data: &[u8]) -> Result<Self> {
27 let len = data.len();
28 if len > u16::MAX as usize {
29 return Err(MqttError::MalformedPacket(format!(
30 "Binary data length {} exceeds maximum {}",
31 len,
32 u16::MAX
33 )));
34 }
35
36 Ok(Self {
37 #[allow(clippy::cast_possible_truncation)]
38 length: len as u16, data: data.to_vec(),
40 })
41 }
42
43 pub fn from_bytes(bytes: &Bytes) -> Result<Self> {
48 Self::create(bytes)
49 }
50
51 #[must_use]
53 pub fn as_slice(&self) -> &[u8] {
54 &self.data
55 }
56
57 #[must_use]
59 pub fn into_vec(self) -> Vec<u8> {
60 self.data
61 }
62
63 #[must_use]
65 pub fn into_bytes(self) -> Bytes {
66 Bytes::from(self.data)
67 }
68
69 #[must_use]
71 pub fn encoded_size(&self) -> usize {
72 2 + self.data.len()
73 }
74}
75
76impl TryFrom<&[u8]> for MqttBinary {
77 type Error = MqttError;
78
79 fn try_from(data: &[u8]) -> Result<Self> {
80 Self::create(data)
81 }
82}
83
84impl TryFrom<Vec<u8>> for MqttBinary {
85 type Error = MqttError;
86
87 fn try_from(data: Vec<u8>) -> Result<Self> {
88 Self::create(&data)
89 }
90}
91
92impl TryFrom<Bytes> for MqttBinary {
93 type Error = MqttError;
94
95 fn try_from(bytes: Bytes) -> Result<Self> {
96 Self::from_bytes(&bytes)
97 }
98}
99
100pub fn encode_binary<B: bytes::BufMut>(buf: &mut B, data: &[u8]) -> Result<()> {
109 let mqtt_binary = MqttBinary::create(data)?;
110 let encoded = mqtt_binary.to_be_bytes();
111 buf.put_slice(&encoded);
112 Ok(())
113}
114
115pub fn decode_binary<B: bytes::Buf>(buf: &mut B) -> Result<Bytes> {
124 if buf.remaining() < 2 {
125 return Err(MqttError::MalformedPacket(
126 "Insufficient bytes for binary data length".to_string(),
127 ));
128 }
129
130 let len = buf.get_u16() as usize;
131
132 if buf.remaining() < len {
133 return Err(MqttError::MalformedPacket(format!(
134 "Insufficient bytes for binary data: expected {}, got {}",
135 len,
136 buf.remaining()
137 )));
138 }
139
140 Ok(buf.copy_to_bytes(len))
141}
142
143pub fn encode_optional_binary<B: bytes::BufMut>(buf: &mut B, data: Option<&[u8]>) -> Result<()> {
151 if let Some(data) = data {
152 encode_binary(buf, data)?;
153 }
154 Ok(())
155}
156
157#[must_use]
159pub fn binary_len(data: &[u8]) -> usize {
160 2 + data.len()
161}
162
163#[must_use]
165pub fn optional_binary_len(data: Option<&[u8]>) -> usize {
166 data.map_or(0, binary_len)
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172 use crate::prelude::vec;
173 use bytes::BytesMut;
174
175 #[test]
176 fn test_mqtt_binary_encoding() {
177 let mqtt_bin = MqttBinary::create(&[0x01, 0x02, 0x03]).unwrap();
178 let bytes = mqtt_bin.to_be_bytes();
179
180 assert_eq!(bytes, vec![0x00, 0x03, 0x01, 0x02, 0x03]);
182 }
183
184 #[test]
185 fn test_mqtt_binary_decoding() {
186 let data = vec![0x00, 0x03, 0x01, 0x02, 0x03];
187 let (mqtt_bin, consumed) = MqttBinary::try_from_be_bytes(&data).unwrap();
188
189 assert_eq!(mqtt_bin.as_slice(), &[0x01, 0x02, 0x03]);
190 assert_eq!(consumed, 5);
191 }
192
193 #[test]
194 fn test_mqtt_binary_round_trip() {
195 let original = MqttBinary::create(&[0xFF, 0x00, 0xAB]).unwrap();
196 let bytes = original.to_be_bytes();
197 let (decoded, _) = MqttBinary::try_from_be_bytes(&bytes).unwrap();
198
199 assert_eq!(original, decoded);
200 }
201
202 #[test]
203 fn test_empty_binary() {
204 let mqtt_bin = MqttBinary::create(&[]).unwrap();
205 let bytes = mqtt_bin.to_be_bytes();
206
207 assert_eq!(bytes, vec![0x00, 0x00]);
208 }
209
210 #[test]
211 fn test_binary_too_long() {
212 let long_data = vec![0u8; 65536];
213 let result = MqttBinary::create(&long_data);
214
215 assert!(result.is_err());
216 }
217
218 #[test]
219 fn test_compatibility_functions() {
220 let mut buf = BytesMut::new();
221 let test_data = vec![0x01, 0x02, 0x03];
222
223 encode_binary(&mut buf, &test_data).unwrap();
225 let decoded = decode_binary(&mut buf).unwrap();
226
227 assert_eq!(&decoded[..], &test_data[..]);
228 }
229}