#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use crate::codec::types::PacketType;
use crate::error::{Error, Result};
const VARIABLE_INT_MAX: u32 = 268_435_455;
pub fn encode_variable_int(buf: &mut Vec<u8>, mut value: u32) -> Result<()> {
if value > VARIABLE_INT_MAX {
return Err(Error::PacketTooLarge);
}
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value > 0 {
byte |= 0x80;
}
buf.push(byte);
if value == 0 {
break;
}
}
Ok(())
}
pub fn variable_int_len(value: u32) -> usize {
match value {
0..=127 => 1,
128..=16_383 => 2,
16_384..=2_097_151 => 3,
_ => 4,
}
}
pub fn encode_string(buf: &mut Vec<u8>, s: &str) -> Result<()> {
let len = s.len();
if len > 65_535 {
return Err(Error::StringTooLong(len));
}
buf.extend_from_slice(&(len as u16).to_be_bytes());
buf.extend_from_slice(s.as_bytes());
Ok(())
}
pub fn encode_binary(buf: &mut Vec<u8>, data: &[u8]) -> Result<()> {
let len = data.len();
if len > 65_535 {
return Err(Error::StringTooLong(len));
}
buf.extend_from_slice(&(len as u16).to_be_bytes());
buf.extend_from_slice(data);
Ok(())
}
pub fn encode_u16(buf: &mut Vec<u8>, val: u16) {
buf.extend_from_slice(&val.to_be_bytes());
}
pub fn encode_fixed_header(
buf: &mut Vec<u8>,
packet_type: PacketType,
flags: u8,
remaining_length: u32,
) -> Result<()> {
let type_byte = ((packet_type as u8) << 4) | (flags & 0x0F);
buf.push(type_byte);
encode_variable_int(buf, remaining_length)
}
pub fn string_len(s: &str) -> usize {
2 + s.len()
}
pub fn binary_len(data: &[u8]) -> usize {
2 + data.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn variable_int_single_byte() {
let mut buf = Vec::new();
encode_variable_int(&mut buf, 0).unwrap();
assert_eq!(buf, [0x00]);
buf.clear();
encode_variable_int(&mut buf, 127).unwrap();
assert_eq!(buf, [0x7F]);
}
#[test]
fn variable_int_two_bytes() {
let mut buf = Vec::new();
encode_variable_int(&mut buf, 128).unwrap();
assert_eq!(buf, [0x80, 0x01]);
buf.clear();
encode_variable_int(&mut buf, 16_383).unwrap();
assert_eq!(buf, [0xFF, 0x7F]);
}
#[test]
fn variable_int_four_bytes() {
let mut buf = Vec::new();
encode_variable_int(&mut buf, VARIABLE_INT_MAX).unwrap();
assert_eq!(buf, [0xFF, 0xFF, 0xFF, 0x7F]);
}
#[test]
fn variable_int_too_large() {
let mut buf = Vec::new();
assert!(encode_variable_int(&mut buf, VARIABLE_INT_MAX + 1).is_err());
}
#[test]
fn string_encoding() {
let mut buf = Vec::new();
encode_string(&mut buf, "hello").unwrap();
assert_eq!(buf, [0x00, 0x05, b'h', b'e', b'l', b'l', b'o']);
}
#[test]
fn empty_string() {
let mut buf = Vec::new();
encode_string(&mut buf, "").unwrap();
assert_eq!(buf, [0x00, 0x00]);
}
#[test]
fn binary_encoding() {
let mut buf = Vec::new();
encode_binary(&mut buf, &[0xDE, 0xAD]).unwrap();
assert_eq!(buf, [0x00, 0x02, 0xDE, 0xAD]);
}
#[test]
fn fixed_header_encoding() {
let mut buf = Vec::new();
encode_fixed_header(&mut buf, PacketType::Connect, 0, 10).unwrap();
assert_eq!(buf, [0x10, 0x0A]);
}
}