use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[repr(u8)]
enum MajorType {
Uint = 0,
Sint = 1,
Bstr = 2,
Tstr = 3,
Array = 4,
Map = 5,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[repr(u8)]
enum ArgType {
U8 = 24,
U16 = 25,
U32 = 26,
U64 = 27,
}
pub fn arg_size(arg: u64) -> (u64, u8) {
if arg <= ArgType::U8 as u64 {
(0, arg as u8)
} else if arg <= u8::MAX.into() {
(1, ArgType::U8 as u8)
} else if arg <= u16::MAX.into() {
(2, ArgType::U16 as u8)
} else if arg <= u32::MAX.into() {
(4, ArgType::U32 as u8)
} else {
(8, ArgType::U64 as u8)
}
}
fn header(kind: MajorType, arg: u64) -> Vec<u8> {
let (size, info) = arg_size(arg);
let bytes = (0..size).map(|i| ((arg >> (i * 8)) & 0xff) as u8).rev();
let mut res = vec![((kind as u8) << 5) | info];
res.extend(bytes);
res
}
pub fn int(value: i64) -> Vec<u8> {
if value >= 0 {
header(MajorType::Uint, value as u64)
} else {
header(MajorType::Sint, -(value + 1) as u64)
}
}
pub fn byte_array_header(len: u64) -> Vec<u8> {
header(MajorType::Bstr, len)
}
pub fn string_header(len: u64) -> Vec<u8> {
header(MajorType::Tstr, len)
}
pub fn array_header(len: u64) -> Vec<u8> {
header(MajorType::Array, len)
}
pub fn map_header(len: u64) -> Vec<u8> {
header(MajorType::Map, len)
}