use crate::base::MagicBytes;
use crate::decode::Take;
use crate::error::Error;
use crate::lz::LzWriter;
use crate::ops::{Len, Limit, ReadData, WriteData};
use crate::types::{ByteReader, ShortBuffer};
pub const RAW_HEADER_SIZE: u32 = 0x08;
#[derive(Clone, Copy, Debug, Default)]
pub struct RawBlock {
n_raw_bytes: u32,
}
impl RawBlock {
#[inline(always)]
pub fn new(n_raw_bytes: u32) -> Self {
Self { n_raw_bytes }
}
pub fn load_short<I: Copy + ShortBuffer>(&mut self, mut src: I) -> crate::Result<u32> {
assert!(RAW_HEADER_SIZE <= I::SHORT_LIMIT);
self.load(src.take(RAW_HEADER_SIZE)?.short_bytes())
}
pub fn load(&mut self, src: &[u8]) -> crate::Result<u32> {
let mut src = &src[..RAW_HEADER_SIZE as usize];
let magic_bytes = src.read_u32();
assert_eq!(magic_bytes, MagicBytes::Raw.into());
self.n_raw_bytes = src.read_u32();
Ok(RAW_HEADER_SIZE)
}
pub fn store(&self, mut dst: &mut [u8]) {
assert_eq!(dst.len(), RAW_HEADER_SIZE as usize);
dst.write_u32(MagicBytes::Raw.into());
dst.write_u32(self.n_raw_bytes);
}
#[inline(always)]
pub fn n_raw_bytes(&self) -> u32 {
self.n_raw_bytes
}
pub fn decode<I, O>(&mut self, dst: &mut O, src: &mut I) -> crate::Result<u32>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
let n = self.n_raw_bytes as usize;
self.copy_n(dst, src, n)?;
self.n_raw_bytes = 0;
Ok(n as u32)
}
pub fn decode_n<I, O>(&mut self, dst: &mut O, src: &mut I, n: u32) -> crate::Result<bool>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
let n = n.min(self.n_raw_bytes);
self.copy_n(dst, src, n as usize)?;
self.n_raw_bytes -= n;
Ok(self.n_raw_bytes != 0)
}
#[inline(always)]
fn copy_n<I, O>(&mut self, dst: &mut O, src: &mut I, mut n: usize) -> crate::Result<()>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
loop {
debug_assert!(n <= self.n_raw_bytes as usize);
src.fill()?;
let mut view = src.view();
view.limit(n);
dst.write_bytes_long(view)?;
let view_len = view.len();
n -= view_len;
src.skip(view_len);
if n == 0 {
break;
}
if src.is_eof() {
return Err(Error::PayloadUnderflow);
}
}
Ok(())
}
}