use crate::types::*;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::{default::Default, mem::MaybeUninit, slice};
pub enum SeekFrom {
Start(u32),
End(i32),
Current(i32),
}
pub trait Seek {
type Err;
fn seek(&mut self, pos: SeekFrom) -> Result<u32, Self::Err>;
fn cursor_position(&self) -> u32;
}
pub trait HasSize {
fn size(&self) -> u32;
}
macro_rules! read_n_bytes {
($n:expr, $source:tt) => {{
let mut bytes: MaybeUninit<[u8; $n]> = MaybeUninit::uninit();
let write_bytes = unsafe { slice::from_raw_parts_mut(bytes.as_mut_ptr() as *mut u8, $n) };
$source.read_exact(write_bytes)?;
unsafe { bytes.assume_init() }
}};
}
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> ParseResult<usize>;
fn read_exact(&mut self, buf: &mut [u8]) -> ParseResult<()> {
let mut start = 0;
while start < buf.len() {
match self.read(&mut buf[start..]) {
Ok(0) => break,
Ok(n) => {
start += n;
}
Err(_e) => return Err(Default::default()),
}
}
if start == buf.len() {
Ok(())
} else {
Err(Default::default())
}
}
fn read_u64(&mut self) -> ParseResult<u64> {
let bytes = read_n_bytes!(8, self);
Ok(u64::from_le_bytes(bytes))
}
fn read_u32(&mut self) -> ParseResult<u32> {
let bytes = read_n_bytes!(4, self);
Ok(u32::from_le_bytes(bytes))
}
fn read_u16(&mut self) -> ParseResult<u16> {
let bytes = read_n_bytes!(2, self);
Ok(u16::from_le_bytes(bytes))
}
fn read_u8(&mut self) -> ParseResult<u8> {
let bytes = read_n_bytes!(1, self);
Ok(u8::from_le_bytes(bytes))
}
fn read_i64(&mut self) -> ParseResult<i64> {
let bytes = read_n_bytes!(8, self);
Ok(i64::from_le_bytes(bytes))
}
fn read_i32(&mut self) -> ParseResult<i32> {
let bytes = read_n_bytes!(4, self);
Ok(i32::from_le_bytes(bytes))
}
fn read_i16(&mut self) -> ParseResult<i16> {
let bytes = read_n_bytes!(2, self);
Ok(i16::from_le_bytes(bytes))
}
fn read_i8(&mut self) -> ParseResult<i8> {
let bytes = read_n_bytes!(1, self);
Ok(i8::from_le_bytes(bytes))
}
fn read_array<const N: usize>(&mut self) -> ParseResult<[u8; N]> { Ok(read_n_bytes!(N, self)) }
}
pub trait Write {
type Err: Default;
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err>;
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Err> {
let mut start = 0;
while start < buf.len() {
match self.write(&buf[start..]) {
Ok(n) if n > 0 => start += n,
_ => return Err(Default::default()),
}
}
Ok(())
}
fn write_u8(&mut self, x: u8) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
fn write_u16(&mut self, x: u16) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
fn write_u32(&mut self, x: u32) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
fn write_u64(&mut self, x: u64) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
fn write_i8(&mut self, x: i8) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
fn write_i16(&mut self, x: i16) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
fn write_i32(&mut self, x: i32) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
fn write_i64(&mut self, x: i64) -> Result<(), Self::Err> { self.write_all(&x.to_le_bytes()) }
}
impl Write for Vec<u8> {
type Err = ();
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err> {
let _ = self.extend_from_slice(buf);
Ok(buf.len())
}
}
impl Write for &mut [u8] {
type Err = ();
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err> {
let to_write = core::cmp::min(buf.len(), self.len());
let (overwrite, rest) = core::mem::replace(self, &mut []).split_at_mut(to_write);
overwrite.copy_from_slice(&buf[..to_write]);
*self = rest;
Ok(to_write)
}
}
pub trait Serial {
fn serial<W: Write>(&self, _out: &mut W) -> Result<(), W::Err>;
}
pub trait Deserial: Sized {
fn deserial<R: Read>(_source: &mut R) -> ParseResult<Self>;
}
pub trait Serialize: Serial + Deserial {}
impl<A: Deserial + Serial> Serialize for A {}
pub trait SerialCtx {
fn serial_ctx<W: Write>(
&self,
size_length: crate::schema::SizeLength,
out: &mut W,
) -> Result<(), W::Err>;
}
pub trait DeserialCtx: Sized {
fn deserial_ctx<R: Read>(
size_length: crate::schema::SizeLength,
ensure_ordered: bool,
source: &mut R,
) -> ParseResult<Self>;
}
pub trait Get<T> {
fn get(&mut self) -> ParseResult<T>;
}
impl<R: Read, T: Deserial> Get<T> for R {
#[inline(always)]
fn get(&mut self) -> ParseResult<T> { T::deserial(self) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn write_u8_slice() {
let mut xs = [0u8; 10];
let mut slice: &mut [u8] = &mut xs;
assert!(0xAAAAAAAAu32.serial(&mut slice).is_ok(), "Writing u32 should succeed.");
assert_eq!(slice.len(), 6, "The new slice should be of length 6 (= 10 - 4)");
assert!(0xBBBBBBBBu32.serial(&mut slice).is_ok(), "Writing the second u32 should succeed.");
assert_eq!(slice.len(), 2, "The new slice should be of length 2 (= 10 - 4 - 4)");
assert!(0xCCCCu16.serial(&mut slice).is_ok(), "Writing the final u16 should succeed.");
assert_eq!(slice.len(), 0, "The new slice should be of length 0 (= 10 - 4 - 4 - 2)");
assert!(0u8.serial(&mut slice).is_err(), "Writing past the end should fail.");
assert_eq!(
xs,
[0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC],
"The original array has incorrect content."
);
}
}