use crate::{Bitstream, DecodeFailed, DecoderState, Tree};
const FOOTER_BITS: [u8; 289] = [
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
];
const BASE_POSITION: [u32; 290] = [
0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536,
2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, 65536, 98304, 131072, 196608,
262144, 393216, 524288, 655360, 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864,
1703936, 1835008, 1966080, 2097152, 2228224, 2359296, 2490368, 2621440, 2752512, 2883584,
3014656, 3145728, 3276800, 3407872, 3538944, 3670016, 3801088, 3932160, 4063232, 4194304,
4325376, 4456448, 4587520, 4718592, 4849664, 4980736, 5111808, 5242880, 5373952, 5505024,
5636096, 5767168, 5898240, 6029312, 6160384, 6291456, 6422528, 6553600, 6684672, 6815744,
6946816, 7077888, 7208960, 7340032, 7471104, 7602176, 7733248, 7864320, 7995392, 8126464,
8257536, 8388608, 8519680, 8650752, 8781824, 8912896, 9043968, 9175040, 9306112, 9437184,
9568256, 9699328, 9830400, 9961472, 10092544, 10223616, 10354688, 10485760, 10616832, 10747904,
10878976, 11010048, 11141120, 11272192, 11403264, 11534336, 11665408, 11796480, 11927552,
12058624, 12189696, 12320768, 12451840, 12582912, 12713984, 12845056, 12976128, 13107200,
13238272, 13369344, 13500416, 13631488, 13762560, 13893632, 14024704, 14155776, 14286848,
14417920, 14548992, 14680064, 14811136, 14942208, 15073280, 15204352, 15335424, 15466496,
15597568, 15728640, 15859712, 15990784, 16121856, 16252928, 16384000, 16515072, 16646144,
16777216, 16908288, 17039360, 17170432, 17301504, 17432576, 17563648, 17694720, 17825792,
17956864, 18087936, 18219008, 18350080, 18481152, 18612224, 18743296, 18874368, 19005440,
19136512, 19267584, 19398656, 19529728, 19660800, 19791872, 19922944, 20054016, 20185088,
20316160, 20447232, 20578304, 20709376, 20840448, 20971520, 21102592, 21233664, 21364736,
21495808, 21626880, 21757952, 21889024, 22020096, 22151168, 22282240, 22413312, 22544384,
22675456, 22806528, 22937600, 23068672, 23199744, 23330816, 23461888, 23592960, 23724032,
23855104, 23986176, 24117248, 24248320, 24379392, 24510464, 24641536, 24772608, 24903680,
25034752, 25165824, 25296896, 25427968, 25559040, 25690112, 25821184, 25952256, 26083328,
26214400, 26345472, 26476544, 26607616, 26738688, 26869760, 27000832, 27131904, 27262976,
27394048, 27525120, 27656192, 27787264, 27918336, 28049408, 28180480, 28311552, 28442624,
28573696, 28704768, 28835840, 28966912, 29097984, 29229056, 29360128, 29491200, 29622272,
29753344, 29884416, 30015488, 30146560, 30277632, 30408704, 30539776, 30670848, 30801920,
30932992, 31064064, 31195136, 31326208, 31457280, 31588352, 31719424, 31850496, 31981568,
32112640, 32243712, 32374784, 32505856, 32636928, 32768000, 32899072, 33030144, 33161216,
33292288, 33423360,
];
struct DecodeInfo<'a> {
aligned_offset_tree: Option<&'a Tree>,
main_tree: &'a Tree,
length_tree: Option<&'a Tree>,
}
#[derive(Debug)]
pub enum Decoded {
Single(u8),
Match { offset: usize, length: usize },
Read(usize),
}
#[derive(Debug)]
pub enum Kind {
Verbatim {
main_tree: Tree,
length_tree: Option<Tree>,
},
AlignedOffset {
aligned_offset_tree: Tree,
main_tree: Tree,
length_tree: Option<Tree>,
},
Uncompressed {
r: [u32; 3],
},
}
pub struct Block {
pub remaining: u32,
pub size: u32,
pub kind: Kind,
}
fn read_main_and_length_trees(
bitstream: &mut Bitstream,
state: &mut DecoderState,
) -> Result<(), DecodeFailed> {
state
.main_tree
.update_range_with_pretree(bitstream, 0..256)?;
state
.main_tree
.update_range_with_pretree(bitstream, 256..256 + 8 * state.window_size.position_slots())?;
state
.length_tree
.update_range_with_pretree(bitstream, 0..249)?;
Ok(())
}
fn decode_element(
bitstream: &mut Bitstream,
r: &mut [u32; 3],
DecodeInfo {
aligned_offset_tree,
main_tree,
length_tree,
}: DecodeInfo,
) -> Result<Decoded, DecodeFailed> {
let main_element = main_tree.decode_element(bitstream)?;
Ok(if main_element < 256 {
Decoded::Single(main_element as u8)
} else {
let length_header = (main_element - 256) & 7;
let match_length = if length_header == 7 {
length_tree
.ok_or(DecodeFailed::EmptyTree)?
.decode_element(bitstream)?
+ 7
+ 2
} else {
length_header + 2 };
assert_ne!(match_length, 0);
let position_slot = (main_element - 256) >> 3;
let match_offset;
if position_slot == 0 {
match_offset = r[0];
} else if position_slot == 1 {
match_offset = r[1];
r.swap(0, 1);
} else if position_slot == 2 {
match_offset = r[2];
r.swap(0, 2);
} else {
let offset_bits = FOOTER_BITS[position_slot as usize];
let formatted_offset = if let Some(aligned_offset_tree) = aligned_offset_tree.as_ref() {
let verbatim_bits;
let aligned_bits;
if offset_bits >= 3 {
verbatim_bits = bitstream.read_bits(offset_bits - 3)? << 3;
aligned_bits = aligned_offset_tree.decode_element(bitstream)?;
} else {
verbatim_bits = bitstream.read_bits(offset_bits)?;
aligned_bits = 0;
}
BASE_POSITION[position_slot as usize] + verbatim_bits + aligned_bits as u32
} else {
let verbatim_bits = bitstream.read_bits(offset_bits)?;
BASE_POSITION[position_slot as usize] + verbatim_bits
};
match_offset = formatted_offset - 2;
r[2] = r[1];
r[1] = r[0];
r[0] = match_offset;
}
Decoded::Match {
offset: match_offset as usize,
length: match_length as usize,
}
})
}
impl Block {
pub(crate) fn read(
bitstream: &mut Bitstream,
state: &mut DecoderState,
) -> Result<Self, DecodeFailed> {
let kind = bitstream.read_bits(3)? as u8;
let size = bitstream.read_u24_be()?;
if size == 0 {
return Err(DecodeFailed::InvalidBlockSize(size));
}
let kind = match kind {
0b001 => {
read_main_and_length_trees(bitstream, state)?;
Kind::Verbatim {
main_tree: state.main_tree.create_instance()?,
length_tree: state.length_tree.create_instance_allow_empty()?,
}
}
0b010 => {
let aligned_offset_tree = {
let mut path_lengths = Vec::with_capacity(8);
for _ in 0..8 {
path_lengths.push(bitstream.read_bits(3)? as u8);
}
Tree::from_path_lengths(path_lengths)?
};
read_main_and_length_trees(bitstream, state)?;
Kind::AlignedOffset {
aligned_offset_tree,
main_tree: state.main_tree.create_instance()?,
length_tree: state.length_tree.create_instance_allow_empty()?,
}
}
0b011 => {
bitstream.align()?;
Kind::Uncompressed {
r: [
bitstream.read_u32_le()?,
bitstream.read_u32_le()?,
bitstream.read_u32_le()?,
],
}
}
_ => return Err(DecodeFailed::InvalidBlock(kind)),
};
Ok(Block {
remaining: size,
size,
kind,
})
}
pub(crate) fn decode_element(
&self,
bitstream: &mut Bitstream,
r: &mut [u32; 3],
) -> Result<Decoded, DecodeFailed> {
match &self.kind {
Kind::Verbatim {
main_tree,
length_tree,
} => decode_element(
bitstream,
r,
DecodeInfo {
aligned_offset_tree: None,
main_tree,
length_tree: length_tree.as_ref(),
},
),
Kind::AlignedOffset {
aligned_offset_tree,
main_tree,
length_tree,
} => decode_element(
bitstream,
r,
DecodeInfo {
aligned_offset_tree: Some(aligned_offset_tree),
main_tree,
length_tree: length_tree.as_ref(),
},
),
Kind::Uncompressed { r: new_r } => {
r.copy_from_slice(new_r);
Ok(Decoded::Read(self.remaining as usize))
}
}
}
}