use crate::error::{MqttError, Result};
use crate::prelude::{format, ToString};
use bytes::{Buf, BufMut, Bytes};
pub fn encode_binary<B: BufMut>(buf: &mut B, data: &[u8]) -> Result<()> {
if data.len() > crate::constants::limits::MAX_STRING_LENGTH as usize {
return Err(MqttError::MalformedPacket(format!(
"Binary data length {} exceeds maximum {}",
data.len(),
crate::constants::limits::MAX_STRING_LENGTH
)));
}
#[allow(clippy::cast_possible_truncation)]
buf.put_u16(data.len() as u16);
buf.put_slice(data);
Ok(())
}
pub fn decode_binary<B: Buf>(buf: &mut B) -> Result<Bytes> {
if buf.remaining() < 2 {
return Err(MqttError::MalformedPacket(
"Insufficient bytes for binary data length".to_string(),
));
}
let len = buf.get_u16() as usize;
if buf.remaining() < len {
return Err(MqttError::MalformedPacket(format!(
"Insufficient bytes for binary data: expected {}, got {}",
len,
buf.remaining()
)));
}
Ok(buf.copy_to_bytes(len))
}
pub fn encode_optional_binary<B: BufMut>(buf: &mut B, data: Option<&[u8]>) -> Result<()> {
if let Some(data) = data {
encode_binary(buf, data)?;
}
Ok(())
}
#[must_use]
pub fn binary_len(data: &[u8]) -> usize {
2 + data.len()
}
#[must_use]
pub fn optional_binary_len(data: Option<&[u8]>) -> usize {
data.map_or(0, binary_len)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::{vec, Vec};
use bytes::BytesMut;
#[test]
fn test_encode_decode_binary() {
let mut buf = BytesMut::new();
let test_data = [
vec![],
vec![0x00],
vec![0x01, 0x02, 0x03],
vec![0xFF; 100],
(0..=255).collect::<Vec<u8>>(),
];
for data in &test_data {
buf.clear();
encode_binary(&mut buf, data).unwrap();
let decoded = decode_binary(&mut buf).unwrap();
assert_eq!(&decoded[..], data.as_slice());
}
}
#[test]
fn test_encode_binary_too_long() {
let mut buf = BytesMut::new();
let data = vec![0u8; crate::constants::limits::MAX_BINARY_LENGTH as usize + 1];
let result = encode_binary(&mut buf, &data);
assert!(result.is_err());
}
#[test]
fn test_decode_insufficient_length_bytes() {
let mut buf = BytesMut::new();
buf.put_u8(0);
let result = decode_binary(&mut buf);
assert!(result.is_err());
}
#[test]
fn test_decode_insufficient_data_bytes() {
let mut buf = BytesMut::new();
buf.put_u16(10); buf.put_slice(&[1, 2, 3, 4, 5]);
let result = decode_binary(&mut buf);
assert!(result.is_err());
}
#[test]
fn test_encode_optional_binary() {
let mut buf = BytesMut::new();
encode_optional_binary(&mut buf, None).unwrap();
assert_eq!(buf.len(), 0);
buf.clear();
encode_optional_binary(&mut buf, Some(&[1, 2, 3])).unwrap();
assert_eq!(buf.len(), 5); }
#[test]
fn test_binary_len() {
assert_eq!(binary_len(&[]), 2);
assert_eq!(binary_len(&[1, 2, 3]), 5);
assert_eq!(binary_len(&[0u8; 100]), 102);
}
#[test]
fn test_optional_binary_len() {
assert_eq!(optional_binary_len(None), 0);
assert_eq!(optional_binary_len(Some(&[])), 2);
assert_eq!(optional_binary_len(Some(&[1, 2, 3])), 5);
}
#[test]
fn test_empty_binary() {
let mut buf = BytesMut::new();
encode_binary(&mut buf, &[]).unwrap();
assert_eq!(buf.len(), 2);
assert_eq!(buf[0], 0);
assert_eq!(buf[1], 0);
let decoded = decode_binary(&mut buf).unwrap();
assert_eq!(decoded.len(), 0);
}
}