use crate::{string, vec};
use crate::{Layout, ReaderExt, Result, reader};
pub trait Decode: Sized + Layout {
fn decode(buffer: &[u8]) -> Result<Self>;
}
impl Decode for bool {
fn decode(r: &[u8]) -> Result<Self> {
let [v] = r.read_const::<1>();
Ok(v != 0)
}
}
impl Decode for i8 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(i8::from_le_bytes(r.read_const()))
}
}
impl Decode for i16 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(i16::from_le_bytes(r.read_const()))
}
}
impl Decode for i32 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(i32::from_le_bytes(r.read_const()))
}
}
impl Decode for i64 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(i64::from_le_bytes(r.read_const()))
}
}
impl Decode for u8 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(u8::from_le_bytes(r.read_const()))
}
}
impl Decode for u16 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(u16::from_le_bytes(r.read_const()))
}
}
impl Decode for u32 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(u32::from_le_bytes(r.read_const()))
}
}
impl Decode for u64 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(u64::from_le_bytes(r.read_const()))
}
}
impl Decode for f32 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(f32::from_le_bytes(r.read_const()))
}
}
impl Decode for f64 {
fn decode(r: &[u8]) -> Result<Self> {
Ok(f64::from_le_bytes(r.read_const()))
}
}
impl Decode for string::String {
fn decode(r: &[u8]) -> Result<Self> {
let (offset, len) = reader::ArrayReader::<&[u8]>::read_head(r);
let buf = r.skip(offset).read_n(len).to_vec();
Ok(string::String::from_utf8(buf).unwrap())
}
}
impl<E: Decode> Decode for vec::Vec<E> {
fn decode(r: &[u8]) -> Result<Self> {
let (offset, len) = reader::ArrayReader::<&[u8]>::read_head(r);
let mut buf = r.skip(offset);
let mut out = vec::Vec::with_capacity(len);
let item_head_bytes = E::head_size().div_ceil(8);
for _ in 0..len {
out.push(E::decode(buf)?);
buf = buf.skip(item_head_bytes);
}
Ok(out)
}
}
impl<E: Decode> Decode for Option<E> {
fn decode(buf: &[u8]) -> Result<Self> {
let [tag] = buf.read_const::<1>();
if tag == 0 {
Ok(None)
} else {
let buf = buf.skip(1);
let inner_head_size = E::head_size();
let has_ptr = inner_head_size > 32;
Ok(Some(if has_ptr {
let offset = u32::from_le_bytes(buf.read_const::<4>()) as usize;
E::decode(buf.skip(offset))?
} else {
E::decode(buf)?
}))
}
}
}
impl<T: Decode, E: Decode> Decode for core::result::Result<T, E> {
fn decode(buf: &[u8]) -> Result<Self> {
let t_head_bits = T::head_size();
let e_head_bits = E::head_size();
let max_head_bits = t_head_bits.max(e_head_bits);
let has_ptr = max_head_bits > 32;
let [tag] = buf.read_const::<1>();
let buf = buf.skip(1);
Ok(match tag {
0 => {
let t = if has_ptr {
let offset = u32::from_le_bytes(buf.read_const::<4>()) as usize;
T::decode(buf.skip(offset))?
} else {
T::decode(buf)?
};
Ok(t)
}
1 => {
let e = if has_ptr {
let offset = u32::from_le_bytes(buf.read_const::<4>()) as usize;
E::decode(buf.skip(offset))?
} else {
E::decode(buf)?
};
Err(e)
}
_ => return Err(crate::Error::InvalidData),
})
}
}
impl Decode for () {
fn decode(_buf: &[u8]) -> Result<Self> {
Ok(())
}
}
pub fn decode_enum_head(mut data: &[u8], tag_bytes: u8, has_ptr: bool) -> (u64, &[u8]) {
use crate::ReaderExt;
use bytes::Buf;
let mut tag = vec![0; 8];
data.copy_to_slice(&mut tag[0..tag_bytes as usize]);
let tag = u64::from_le_bytes(tag.try_into().unwrap()) as u64;
if has_ptr {
let offset = u32::from_le_bytes(data.read_const::<4>());
data = data.skip(offset as usize);
} else {
}
(tag, data)
}