use crate::{Error, Packet};
pub fn encode_slice(packet: &Packet, buf: &mut [u8]) -> Result<usize, Error> {
let mut offset = 0;
match packet {
Packet::Connect(connect) => connect.to_buffer(buf, &mut offset),
Packet::Connack(connack) => connack.to_buffer(buf, &mut offset),
Packet::Publish(publish) => publish.to_buffer(buf, &mut offset),
Packet::Puback(pid) => {
check_remaining(buf, &mut offset, 4)?;
let header: u8 = 0b01000000;
let length: u8 = 2;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
pid.to_buffer(buf, &mut offset)?;
Ok(4)
}
Packet::Pubrec(pid) => {
check_remaining(buf, &mut offset, 4)?;
let header: u8 = 0b01010000;
let length: u8 = 2;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
pid.to_buffer(buf, &mut offset)?;
Ok(4)
}
Packet::Pubrel(pid) => {
check_remaining(buf, &mut offset, 4)?;
let header: u8 = 0b01100010;
let length: u8 = 2;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
pid.to_buffer(buf, &mut offset)?;
Ok(4)
}
Packet::Pubcomp(pid) => {
check_remaining(buf, &mut offset, 4)?;
let header: u8 = 0b01110000;
let length: u8 = 2;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
pid.to_buffer(buf, &mut offset)?;
Ok(4)
}
Packet::Subscribe(subscribe) => subscribe.to_buffer(buf, &mut offset),
Packet::Suback(suback) => suback.to_buffer(buf, &mut offset),
Packet::Unsubscribe(unsub) => unsub.to_buffer(buf, &mut offset),
Packet::Unsuback(pid) => {
check_remaining(buf, &mut offset, 4)?;
let header: u8 = 0b10110000;
let length: u8 = 2;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
pid.to_buffer(buf, &mut offset)?;
Ok(4)
}
Packet::Pingreq => {
check_remaining(buf, &mut offset, 2)?;
let header: u8 = 0b11000000;
let length: u8 = 0;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
Ok(2)
}
Packet::Pingresp => {
check_remaining(buf, &mut offset, 2)?;
let header: u8 = 0b11010000;
let length: u8 = 0;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
Ok(2)
}
Packet::Disconnect => {
check_remaining(buf, &mut offset, 2)?;
let header: u8 = 0b11100000;
let length: u8 = 0;
write_u8(buf, &mut offset, header)?;
write_u8(buf, &mut offset, length)?;
Ok(2)
}
}
}
pub(crate) fn check_remaining(buf: &mut [u8], offset: &mut usize, len: usize) -> Result<(), Error> {
if buf[*offset..].len() < len {
Err(Error::WriteZero)
} else {
Ok(())
}
}
pub(crate) fn write_length(buf: &mut [u8], offset: &mut usize, len: usize) -> Result<usize, Error> {
let write_len = match len {
0..=127 => {
check_remaining(buf, offset, len + 1)?;
len + 1
}
128..=16383 => {
check_remaining(buf, offset, len + 2)?;
len + 2
}
16384..=2097151 => {
check_remaining(buf, offset, len + 3)?;
len + 3
}
2097152..=268435455 => {
check_remaining(buf, offset, len + 4)?;
len + 4
}
_ => return Err(Error::InvalidLength),
};
let mut done = false;
let mut x = len;
while !done {
let mut byte = (x % 128) as u8;
x = x / 128;
if x > 0 {
byte = byte | 128;
}
write_u8(buf, offset, byte)?;
done = x <= 0;
}
Ok(write_len)
}
pub(crate) fn write_u8(buf: &mut [u8], offset: &mut usize, val: u8) -> Result<(), Error> {
buf[*offset] = val;
*offset += 1;
Ok(())
}
pub(crate) fn write_u16(buf: &mut [u8], offset: &mut usize, val: u16) -> Result<(), Error> {
write_u8(buf, offset, (val >> 8) as u8)?;
write_u8(buf, offset, (val & 0xFF) as u8)
}
pub(crate) fn write_bytes(buf: &mut [u8], offset: &mut usize, bytes: &[u8]) -> Result<(), Error> {
write_u16(buf, offset, bytes.len() as u16)?;
for &byte in bytes {
write_u8(buf, offset, byte)?;
}
Ok(())
}
pub(crate) fn write_string(buf: &mut [u8], offset: &mut usize, string: &str) -> Result<(), Error> {
write_bytes(buf, offset, string.as_bytes())
}