use core::slice::Iter;
use crate::MqttError;
pub(crate) fn read_str<'a>(buf: &'a [u8], offset: &mut usize) -> Result<&'a str, MqttError> {
core::str::from_utf8(read_bytes(buf, offset)?).map_err(MqttError::InvalidString)
}
pub(crate) fn read_bytes<'a>(buf: &'a [u8], offset: &mut usize) -> Result<&'a [u8], MqttError> {
if buf[*offset..].len() < 2 {
return Err(MqttError::InvalidLength);
}
let len = ((buf[*offset] as usize) << 8) | buf[*offset + 1] as usize;
*offset += 2;
if len > buf[*offset..].len() {
Err(MqttError::InvalidLength)
} else {
let bytes = &buf[*offset..*offset + len];
*offset += len;
Ok(bytes)
}
}
pub(crate) fn check_remaining(
buf: &mut [u8],
offset: &mut usize,
len: usize,
) -> Result<(), MqttError> {
if buf[*offset..].len() < len {
Err(MqttError::InsufficientBufferSize)
} else {
Ok(())
}
}
pub(crate) fn write_length(
buf: &mut [u8],
offset: &mut usize,
len: usize,
) -> Result<usize, MqttError> {
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(MqttError::InvalidLength),
};
let mut done = false;
let mut x = len;
while !done {
let mut byte = (x % 128) as u8;
x /= 128;
if x > 0 {
byte |= 128;
}
write_u8(buf, offset, byte);
done = x == 0;
}
Ok(write_len)
}
pub(crate) fn write_remaining_length(
buf: &mut [u8],
offset: &mut usize,
len: usize,
) -> Result<usize, MqttError> {
if len > 268_435_455 {
return Err(MqttError::PayloadTooLong);
}
let mut done = false;
let mut x = len;
let mut count = 0;
while !done {
let mut byte = (x % 128) as u8;
x /= 128;
if x > 0 {
byte |= 128;
}
write_u8(buf, offset, byte);
count += 1;
done = x == 0;
}
Ok(count)
}
pub(crate) fn write_u8(buf: &mut [u8], offset: &mut usize, val: u8) {
buf[*offset] = val;
*offset += 1;
}
pub(crate) fn write_u16(buf: &mut [u8], offset: &mut usize, val: u16) {
write_u8(buf, offset, (val >> 8) as u8);
write_u8(buf, offset, (val & 0xFF) as u8);
}
pub(crate) fn write_bytes_with_len(buf: &mut [u8], offset: &mut usize, bytes: &[u8]) {
write_u16(buf, offset, bytes.len() as u16);
for &byte in bytes {
write_u8(buf, offset, byte);
}
}
pub(crate) fn write_bytes(buf: &mut [u8], offset: &mut usize, bytes: &[u8]) {
for &byte in bytes {
write_u8(buf, offset, byte);
}
}
pub(crate) fn read_u16(buf: &[u8], offset: usize) -> u16 {
u16::from_be_bytes([buf[offset], buf[offset + 1]])
}
pub(crate) fn read_u32(buf: &[u8], offset: usize) -> u32 {
u32::from_be_bytes([
buf[offset],
buf[offset + 1],
buf[offset + 2],
buf[offset + 3],
])
}
pub(crate) fn len_len(len: usize) -> usize {
if len >= 2_097_152 {
4
} else if len >= 16_384 {
3
} else if len >= 128 {
2
} else {
1
}
}
pub(crate) fn varint_length(stream: Iter<u8>) -> Result<(usize, usize), MqttError> {
let mut len: usize = 0;
let mut len_len = 0;
let mut done = false;
let mut shift = 0;
for byte in stream {
len_len += 1;
let byte = *byte as usize;
len += (byte & 0x7F) << shift;
done = (byte & 0x80) == 0;
if done {
break;
}
shift += 7;
if shift > 21 {
return Err(MqttError::MalformedRemainingLength);
}
}
if !done {
return Err(MqttError::InsufficientBytes);
}
Ok((len_len, len))
}