use crate::base::MagicBytes;
use crate::error::Error;
use crate::fse::FseCore;
use crate::lz::LzWriter;
use crate::raw::RawBlock;
use crate::types::ByteReader;
use crate::vn::VnCore;
use std::convert::TryInto;
use std::fmt;
#[derive(Default)]
pub struct LzfseDecoder {
pub(super) fse_core: FseCore,
n_payload_bytes: u64,
dst_mark: u64,
}
impl LzfseDecoder {
pub fn decode_bytes(&mut self, mut src: &[u8], dst: &mut Vec<u8>) -> crate::Result<u64> {
let src_len = src.len();
let dst_len = dst.len();
self.execute(dst, &mut src).map(|u| {
debug_assert_eq!(u.0, src_len as u64);
debug_assert_eq!(dst_len as u64 + u.1, dst.len() as u64);
u.1
})
}
#[inline(always)]
pub(super) fn execute<I: for<'a> ByteReader<'a>, O: LzWriter>(
&mut self,
dst: &mut O,
src: &mut I,
) -> crate::Result<(u64, u64)> {
self.n_payload_bytes = 0;
self.dst_mark = dst.n_raw_bytes();
loop {
src.fill()?;
if src.len() < 4 {
return Err(Error::PayloadUnderflow);
}
let magic_bytes: MagicBytes = src.peek_u32().try_into()?;
match magic_bytes {
MagicBytes::Vx1 => self.vx1(dst, src)?,
MagicBytes::Vx2 => self.vx2(dst, src)?,
MagicBytes::Vxn => self.vxn(dst, src)?,
MagicBytes::Raw => self.raw(dst, src)?,
MagicBytes::Eos => break,
}
}
if src.len() != 4 || !src.is_eof() {
return Err(Error::PayloadOverflow);
}
src.skip(4);
self.n_payload_bytes += 4;
Ok((self.n_payload_bytes, dst.n_raw_bytes() - self.dst_mark))
}
#[cold]
fn vx1<I, O>(&mut self, dst: &mut O, src: &mut I) -> crate::Result<()>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
let view = src.view();
let n = self.fse_core.load_v1(view)?;
src.skip(n as usize);
self.n_payload_bytes += n as u64;
self.vx1_vx2_cont(dst, src)
}
#[cold]
fn vx2<I, O>(&mut self, dst: &mut O, src: &mut I) -> crate::Result<()>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
let view = src.view();
let n = self.fse_core.load_v2(view)?;
src.skip(n as usize);
self.n_payload_bytes += n as u64;
self.vx1_vx2_cont(dst, src)
}
fn vx1_vx2_cont<I, O>(&mut self, dst: &mut O, src: &mut I) -> crate::Result<()>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
let view = src.view();
let n = self.fse_core.load_literals(view)?;
src.skip(n as usize);
self.n_payload_bytes += n as u64;
let view = src.view();
let n = self.fse_core.decode(dst, view)?;
src.skip(n as usize);
self.n_payload_bytes += n as u64;
Ok(())
}
#[cold]
fn vxn<I, O>(&mut self, dst: &mut O, src: &mut I) -> crate::Result<()>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
let mut core = VnCore::default();
let view = src.view();
let n = core.load_short(view)?;
src.skip(n as usize);
self.n_payload_bytes += n as u64;
let n = core.decode(dst, src)?;
self.n_payload_bytes += n as u64;
Ok(())
}
#[cold]
fn raw<I, O>(&mut self, dst: &mut O, src: &mut I) -> crate::Result<()>
where
I: for<'a> ByteReader<'a>,
O: LzWriter,
{
let mut block = RawBlock::default();
let view = src.view();
let n = block.load_short(view)?;
src.skip(n as usize);
self.n_payload_bytes += n as u64;
let n = block.decode(dst, src)?;
self.n_payload_bytes += n as u64;
Ok(())
}
}
impl fmt::Debug for LzfseDecoder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LzfseDecoder").finish()
}
}