use std::fmt;
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
UnexpectedEof,
UnexpectedConstructor {
id: u32,
},
}
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::UnexpectedEof => write!(f, "unexpected eof"),
Self::UnexpectedConstructor { id } => write!(f, "unexpected constructor: {id:08x}"),
}
}
}
pub struct Cursor<'a> {
buf: &'a [u8],
pos: usize,
}
impl<'a> Cursor<'a> {
pub fn from_slice(buf: &'a [u8]) -> Self {
Self { buf, pos: 0 }
}
pub fn pos(&self) -> usize {
self.pos
}
pub fn read_byte(&mut self) -> Result<u8> {
if self.pos < self.buf.len() {
let byte = self.buf[self.pos];
self.pos += 1;
Ok(byte)
} else {
Err(Error::UnexpectedEof)
}
}
pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
if self.pos + buf.len() > self.buf.len() {
Err(Error::UnexpectedEof)
} else {
buf.copy_from_slice(&self.buf[self.pos..self.pos + buf.len()]);
self.pos += buf.len();
Ok(())
}
}
pub fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
buf.extend(&self.buf[self.pos..]);
let old = self.pos;
self.pos = self.buf.len();
Ok(self.pos - old)
}
}
pub(crate) type Buffer<'a, 'b> = &'a mut Cursor<'b>;
pub type Result<T> = std::result::Result<T, Error>;
pub trait Deserializable {
fn deserialize(buf: Buffer) -> Result<Self>
where
Self: std::marker::Sized;
fn from_bytes(buf: &[u8]) -> Result<Self>
where
Self: std::marker::Sized,
{
Self::deserialize(&mut Cursor::from_slice(buf))
}
}
impl Deserializable for bool {
#[allow(clippy::unreadable_literal)]
fn deserialize(buf: Buffer) -> Result<Self> {
let id = u32::deserialize(buf)?;
match id {
0x997275b5u32 => Ok(true),
0xbc799737u32 => Ok(false),
_ => Err(Error::UnexpectedConstructor { id }),
}
}
}
impl Deserializable for i32 {
fn deserialize(buf: Buffer) -> Result<Self> {
let mut buffer = [0u8; 4];
buf.read_exact(&mut buffer)?;
Ok(Self::from_le_bytes(buffer))
}
}
impl Deserializable for u32 {
fn deserialize(buf: Buffer) -> Result<Self> {
let mut buffer = [0u8; 4];
buf.read_exact(&mut buffer)?;
Ok(Self::from_le_bytes(buffer))
}
}
impl Deserializable for i64 {
fn deserialize(buf: Buffer) -> Result<Self> {
let mut buffer = [0u8; 8];
buf.read_exact(&mut buffer)?;
Ok(Self::from_le_bytes(buffer))
}
}
impl Deserializable for [u8; 16] {
fn deserialize(buf: Buffer) -> Result<Self> {
let mut buffer = [0u8; 16];
buf.read_exact(&mut buffer)?;
Ok(buffer)
}
}
impl Deserializable for [u8; 32] {
fn deserialize(buf: Buffer) -> Result<Self> {
let mut buffer = [0u8; 32];
buf.read_exact(&mut buffer)?;
Ok(buffer)
}
}
impl Deserializable for f64 {
fn deserialize(buf: Buffer) -> Result<Self> {
let mut buffer = [0u8; 8];
buf.read_exact(&mut buffer)?;
Ok(Self::from_le_bytes(buffer))
}
}
impl<T: Deserializable> Deserializable for Vec<T> {
#[allow(clippy::unreadable_literal)]
fn deserialize(buf: Buffer) -> Result<Self> {
let id = u32::deserialize(buf)?;
if id != 0x1cb5c415u32 {
return Err(Error::UnexpectedConstructor { id });
}
let len = u32::deserialize(buf)?;
(0..len).map(|_| T::deserialize(buf)).collect()
}
}
impl<T: Deserializable> Deserializable for crate::RawVec<T> {
fn deserialize(buf: Buffer) -> Result<Self> {
let len = u32::deserialize(buf)?;
Ok(Self(
(0..len)
.map(|_| T::deserialize(buf))
.collect::<Result<Vec<T>>>()?,
))
}
}
impl Deserializable for String {
fn deserialize(buf: Buffer) -> Result<Self> {
Ok(String::from_utf8_lossy(&Vec::<u8>::deserialize(buf)?).into())
}
}
impl Deserializable for Vec<u8> {
fn deserialize(buf: Buffer) -> Result<Self> {
let first_byte = buf.read_byte()?;
let (len, padding) = if first_byte == 254 {
let mut buffer = [0u8; 3];
buf.read_exact(&mut buffer)?;
let len =
(buffer[0] as usize) | ((buffer[1] as usize) << 8) | ((buffer[2] as usize) << 16);
(len, len % 4)
} else {
let len = first_byte as usize;
(len, (len + 1) % 4)
};
let mut result = vec![0u8; len];
buf.read_exact(&mut result)?;
if padding > 0 {
for _ in 0..(4 - padding) {
buf.read_byte()?;
}
}
Ok(result)
}
}