use crate::traits::*;
#[must_use]
#[inline(always)]
pub const fn len_minimal_binary(n: u64, u: u64) -> usize {
debug_assert!(n < u);
let l = u.ilog2();
let limit = ((1_u64 << l) << 1).wrapping_sub(u);
let mut result = l as usize;
if n >= limit {
result += 1;
}
result
}
pub trait MinimalBinaryRead<E: Endianness>: BitRead<E> {
#[inline(always)]
fn read_minimal_binary(&mut self, u: u64) -> Result<u64, Self::Error> {
let l = u.ilog2();
let mut prefix = self.read_bits(l as _)?;
let limit = ((1_u64 << l) << 1).wrapping_sub(u);
Ok(if prefix < limit {
prefix
} else {
prefix <<= 1;
prefix |= self.read_bits(1)?;
prefix - limit
})
}
}
pub trait MinimalBinaryWrite<E: Endianness>: BitWrite<E> {
#[inline(always)]
fn write_minimal_binary(&mut self, n: u64, u: u64) -> Result<usize, Self::Error> {
debug_assert!(n < u);
let l = u.ilog2();
let limit = ((1_u64 << l) << 1).wrapping_sub(u);
if n < limit {
self.write_bits(n, l as _)?;
Ok(l as usize)
} else {
let to_write = n + limit;
self.write_bits(to_write >> 1, l as _)?;
self.write_bits(to_write & 1, 1)?;
Ok((l + 1) as usize)
}
}
}
impl<E: Endianness, B: BitRead<E>> MinimalBinaryRead<E> for B {}
impl<E: Endianness, B: BitWrite<E>> MinimalBinaryWrite<E> for B {}