use tlb::{
bits::{
bitvec::{order::Msb0, slice::BitSlice, vec::BitVec},
de::{args::r#as::BitUnpackAsWithArgs, BitReader, BitReaderExt},
r#as::{NBits, Unary, VarNBits},
ser::{args::r#as::BitPackAsWithArgs, BitWriter, BitWriterExt},
},
Error,
};
pub struct HmLabel;
impl BitPackAsWithArgs<BitSlice<u8, Msb0>> for HmLabel {
type Args = u32;
fn pack_as_with<W>(
source: &BitSlice<u8, Msb0>,
mut writer: W,
m: Self::Args,
) -> Result<(), W::Error>
where
W: BitWriter,
{
let n = source.len() as u32;
if n < m {
writer
.pack(false)?
.pack_as::<_, Unary>(source.len())?
.pack(source)?;
return Ok(());
}
let n_bits = m.ilog2() + 1;
let v = if source.all() {
true
} else if source.not_any() {
false
} else {
writer
.pack_as::<_, NBits<2>>(0b10)?
.pack_as_with::<_, VarNBits>(n, n_bits)?
.pack(source)?;
return Ok(());
};
writer
.pack_as::<_, NBits<2>>(0b11)?
.pack(v)?
.pack_as_with::<_, VarNBits>(n, n_bits)?;
Ok(())
}
}
impl BitUnpackAsWithArgs<BitVec<u8, Msb0>> for HmLabel {
type Args = u32;
fn unpack_as_with<R>(mut reader: R, m: Self::Args) -> Result<BitVec<u8, Msb0>, R::Error>
where
R: BitReader,
{
match reader.unpack()? {
false => {
let n: u32 = reader.unpack_as::<_, Unary>()?;
if n > m {
return Err(Error::custom("n > m"));
}
reader.unpack_with(n as usize)
}
true => match reader.unpack()? {
false => {
let n: u32 = reader.unpack_as_with::<_, VarNBits>(m.ilog2() + 1)?;
reader.unpack_with(n as usize)
}
true => {
let v: bool = reader.unpack()?;
let n: u32 = reader.unpack_as_with::<_, VarNBits>(m.ilog2() + 1)?;
Ok(BitVec::repeat(v, n as usize))
}
},
}
}
}