use alloc::string::String;
use alloc::vec::Vec;
pub struct Invalid;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[allow(dead_code)]
pub enum ByteOrder {
#[default]
Little,
Big,
}
pub trait Length {
fn len(&self) -> usize;
}
impl Length for &[u8] {
fn len(&self) -> usize {
(*self).len()
}
}
pub trait Parser<T>: Length {
type Arg;
fn parse(&mut self, arg: Self::Arg) -> Result<T, Invalid>;
fn finish(&mut self, arg: Self::Arg) -> Result<T, Invalid> {
let output = self.parse(arg)?;
if self.len() != 0 {
return Err(Invalid);
}
Ok(output)
}
}
impl Parser<Vec<u8>> for &[u8] {
type Arg = usize;
fn parse(&mut self, len: usize) -> Result<Vec<u8>, Invalid> {
let (head, tail) = self.split_at_checked(len).ok_or(Invalid)?;
*self = tail;
Ok(head.to_vec())
}
}
impl<const N: usize> Parser<[u8; N]> for &[u8] {
type Arg = ();
fn parse(&mut self, _arg: ()) -> Result<[u8; N], Invalid> {
let (head, tail) = self.split_at_checked(N).ok_or(Invalid)?;
*self = tail;
let array: &[u8; N] = head.try_into().map_err(|_| Invalid)?;
Ok(*array)
}
}
impl Parser<u8> for &[u8] {
type Arg = ();
fn parse(&mut self, _arg: ()) -> Result<u8, Invalid> {
let bytes: [u8; 1] = self.parse(())?;
Ok(bytes[0])
}
}
impl Parser<u16> for &[u8] {
type Arg = ByteOrder;
fn parse(&mut self, arg: ByteOrder) -> Result<u16, Invalid> {
Ok(match arg {
ByteOrder::Little => u16::from_le_bytes(self.parse(())?),
ByteOrder::Big => u16::from_be_bytes(self.parse(())?),
})
}
}
impl Parser<u32> for &[u8] {
type Arg = ByteOrder;
fn parse(&mut self, arg: ByteOrder) -> Result<u32, Invalid> {
Ok(match arg {
ByteOrder::Little => u32::from_le_bytes(self.parse(())?),
ByteOrder::Big => u32::from_be_bytes(self.parse(())?),
})
}
}
impl Parser<u64> for &[u8] {
type Arg = ByteOrder;
fn parse(&mut self, arg: ByteOrder) -> Result<u64, Invalid> {
Ok(match arg {
ByteOrder::Little => u64::from_le_bytes(self.parse(())?),
ByteOrder::Big => u64::from_be_bytes(self.parse(())?),
})
}
}
impl Parser<u128> for &[u8] {
type Arg = ByteOrder;
fn parse(&mut self, arg: ByteOrder) -> Result<u128, Invalid> {
Ok(match arg {
ByteOrder::Little => u128::from_le_bytes(self.parse(())?),
ByteOrder::Big => u128::from_be_bytes(self.parse(())?),
})
}
}
pub enum Format {
Utf16(Option<usize>),
Utf8(Option<usize>),
}
impl Parser<String> for &[u8] {
type Arg = Format;
fn parse(&mut self, format: Format) -> Result<String, Invalid> {
match format {
Format::Utf16(Some(len)) if len % 2 == 1 => Err(Invalid),
Format::Utf16(Some(len)) => {
let mut chars = alloc::vec::Vec::with_capacity(len);
for _ in 0..len / 2 {
chars.push(self.parse(ByteOrder::Little)?);
}
String::from_utf16(&chars).map_err(|_| Invalid)
}
Format::Utf16(None) => {
let mut chars = alloc::vec::Vec::new();
loop {
let c = self.parse(ByteOrder::Little)?;
if c == 0 {
break;
}
chars.push(c);
}
String::from_utf16(&chars).map_err(|_| Invalid)
}
Format::Utf8(Some(len)) => {
let mut bytes: Vec<u8> = self.parse(len)?;
if len > 0 && bytes[len - 1] == 0 {
bytes.truncate(len - 1);
}
String::from_utf8(bytes).map_err(|_| Invalid)
}
Format::Utf8(None) => {
let len = self.iter().position(|&b| b == 0).ok_or(Invalid)?;
let string = String::from_utf8(self.parse(len)?).map_err(|_| Invalid)?;
let _: u8 = self.parse(())?; Ok(string)
}
}
}
}
impl Parser<bool> for &[u8] {
type Arg = ();
fn parse(&mut self, _arg: ()) -> Result<bool, Invalid> {
let byte: u8 = self.parse(())?;
Ok(byte != 0)
}
}