#![warn(missing_docs)]
#[cfg(not(feature = "std"))]
use no_std_io2::io;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::{
convert::{From, TryFrom, TryInto},
fmt,
};
#[cfg(feature = "std")]
use std::io;
use super::{
BitCount, Checkable, CheckedSigned, CheckedUnsigned, Endianness, Integer, Numeric, PhantomData,
Primitive, SignedBitCount, SignedInteger, UnsignedInteger, VBRInteger,
};
#[cfg(feature = "alloc")]
pub use bit_recorder::BitRecorder;
pub struct BitWriter<W: io::Write, E: Endianness> {
writer: W,
value: u8,
bits: u32,
phantom: PhantomData<E>,
}
impl<W: io::Write, E: Endianness> BitWriter<W, E> {
pub fn new(writer: W) -> BitWriter<W, E> {
BitWriter {
writer,
value: 0,
bits: 0,
phantom: PhantomData,
}
}
pub fn endian(writer: W, _endian: E) -> BitWriter<W, E> {
BitWriter {
writer,
value: 0,
bits: 0,
phantom: PhantomData,
}
}
#[inline]
pub fn into_writer(self) -> W {
self.writer
}
#[inline]
pub fn writer(&mut self) -> Option<&mut W> {
if BitWrite::byte_aligned(self) {
Some(&mut self.writer)
} else {
None
}
}
#[inline]
pub fn aligned_writer(&mut self) -> io::Result<&mut W> {
BitWrite::byte_align(self)?;
Ok(&mut self.writer)
}
#[inline]
pub fn into_bytewriter(self) -> ByteWriter<W, E> {
ByteWriter::new(self.into_writer())
}
#[inline]
pub fn bytewriter(&mut self) -> Option<ByteWriter<&mut W, E>> {
self.writer().map(ByteWriter::new)
}
#[inline(always)]
pub fn flush(&mut self) -> io::Result<()> {
self.writer.flush()
}
}
pub trait BitWrite {
#[inline]
fn write_bit(&mut self, bit: bool) -> io::Result<()> {
self.write_unsigned::<1, u8>(u8::from(bit))
}
#[inline]
fn write<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
where
I: Integer,
{
Integer::write::<BITS, Self>(value, self)
}
#[inline]
fn write_var<I>(&mut self, bits: u32, value: I) -> io::Result<()>
where
I: Integer,
{
self.write_counted(BitCount::unknown(bits), value)
}
#[inline]
fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
self.write_unsigned_var(BITS, value)
}
fn write_unsigned_var<U>(&mut self, bits: u32, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
self.write_unsigned_counted(BitCount::unknown(bits), value)
}
fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
self.write_signed_var(BITS, value)
}
#[inline(always)]
fn write_signed_var<S>(&mut self, bits: u32, value: S) -> io::Result<()>
where
S: SignedInteger,
{
self.write_signed_counted(BitCount::unknown(bits), value)
}
fn write_count<const MAX: u32>(&mut self, BitCount { bits }: BitCount<MAX>) -> io::Result<()> {
const {
assert!(MAX > 0, "MAX value must be > 0");
}
self.write_unsigned_var(
if MAX == u32::MAX {
32
} else if (MAX + 1).is_power_of_two() {
(MAX + 1).ilog2()
} else {
(MAX + 1).ilog2() + 1
},
bits,
)
}
fn write_counted<const MAX: u32, I>(&mut self, bits: BitCount<MAX>, value: I) -> io::Result<()>
where
I: Integer + Sized,
{
I::write_var::<MAX, _>(value, self, bits)
}
fn write_unsigned_counted<const BITS: u32, U>(
&mut self,
bits: BitCount<BITS>,
value: U,
) -> io::Result<()>
where
U: UnsignedInteger;
fn write_signed_counted<const MAX: u32, S>(
&mut self,
bits: impl TryInto<SignedBitCount<MAX>>,
value: S,
) -> io::Result<()>
where
S: SignedInteger;
#[inline]
fn write_const<const BITS: u32, const VALUE: u32>(&mut self) -> io::Result<()> {
const {
assert!(
BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)),
"excessive value for bits written"
);
}
self.write::<BITS, u32>(VALUE)
}
fn write_from<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive;
fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive;
fn pad(&mut self, mut bits: u32) -> io::Result<()> {
loop {
match bits {
0 => break Ok(()),
bits @ 1..64 => break self.write_var(bits, 0u64),
_ => {
self.write::<64, u64>(0)?;
bits -= 64;
}
}
}
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
buf.iter().try_for_each(|b| self.write_unsigned::<8, _>(*b))
}
fn write_unary<const STOP_BIT: u8>(&mut self, mut value: u32) -> io::Result<()> {
const {
assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1");
}
const MAX: BitCount<32> = BitCount::new::<32>();
match STOP_BIT {
0 => {
while value > 0 {
let to_write = MAX.min(value);
self.write_checked(to_write.all::<u32>())?;
value -= u32::from(to_write);
}
self.write_bit(false)
}
1 => {
while value > 0 {
let to_write = MAX.min(value);
self.write_checked(to_write.none::<u32>())?;
value -= u32::from(to_write);
}
self.write_bit(true)
}
_ => unreachable!(),
}
}
fn write_checked<C: Checkable>(&mut self, value: C) -> io::Result<()> {
value.write(self)
}
fn build<T: ToBitStream>(&mut self, build: &T) -> Result<(), T::Error> {
build.to_writer(self)
}
fn build_with<'a, T: ToBitStreamWith<'a>>(
&mut self,
build: &T,
context: &T::Context,
) -> Result<(), T::Error> {
build.to_writer(self, context)
}
fn build_using<T: ToBitStreamUsing>(
&mut self,
build: &T,
context: T::Context,
) -> Result<(), T::Error> {
build.to_writer(self, context)
}
fn byte_aligned(&self) -> bool;
fn byte_align(&mut self) -> io::Result<()> {
while !BitWrite::byte_aligned(self) {
self.write_bit(false)?;
}
Ok(())
}
fn write_huffman<T>(&mut self, value: T::Symbol) -> io::Result<()>
where
T: crate::huffman::ToBits,
{
T::to_bits(value, |b| self.write_bit(b))
}
fn write_unsigned_vbr<const FIELD_SIZE: u32, U: UnsignedInteger>(
&mut self,
value: U,
) -> io::Result<()> {
const { assert!(FIELD_SIZE >= 2 && FIELD_SIZE < U::BITS_SIZE) };
let payload_bits = FIELD_SIZE - 1;
let continuation_bit = U::ONE.shl(payload_bits);
let payload_mask = continuation_bit.sub(U::ONE);
let mut value = value;
loop {
let payload = value & payload_mask;
value >>= payload_bits;
if value != U::ZERO {
self.write_unsigned::<FIELD_SIZE, U>(payload | continuation_bit)?;
} else {
self.write_unsigned::<FIELD_SIZE, U>(payload)?;
break;
}
}
Ok(())
}
#[inline]
fn write_signed_vbr<const FIELD_SIZE: u32, I: SignedInteger>(
&mut self,
value: I,
) -> io::Result<()> {
let zig_zag = value.shl(1).bitxor(value.shr(I::BITS_SIZE - 1));
self.write_unsigned_vbr::<FIELD_SIZE, _>(zig_zag.as_non_negative())
}
#[inline]
fn write_vbr<const FIELD_SIZE: u32, I: VBRInteger>(&mut self, value: I) -> io::Result<()> {
I::write_vbr::<FIELD_SIZE, _>(value, self)
}
#[inline]
fn by_ref(&mut self) -> &mut Self {
self
}
}
impl<W: BitWrite + ?Sized> BitWrite for &mut W {
#[inline]
fn write_bit(&mut self, bit: bool) -> io::Result<()> {
(**self).write_bit(bit)
}
#[inline]
fn write<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
where
I: Integer,
{
(**self).write::<BITS, I>(value)
}
#[inline]
fn write_const<const BITS: u32, const VALUE: u32>(&mut self) -> io::Result<()> {
(**self).write_const::<BITS, VALUE>()
}
#[inline]
fn write_var<I>(&mut self, bits: u32, value: I) -> io::Result<()>
where
I: Integer,
{
(**self).write_var(bits, value)
}
#[inline]
fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
(**self).write_unsigned::<BITS, U>(value)
}
#[inline]
fn write_unsigned_var<U>(&mut self, bits: u32, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
(**self).write_unsigned_var(bits, value)
}
#[inline]
fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
(**self).write_signed::<BITS, S>(value)
}
#[inline(always)]
fn write_signed_var<S>(&mut self, bits: u32, value: S) -> io::Result<()>
where
S: SignedInteger,
{
(**self).write_signed_var(bits, value)
}
#[inline]
fn write_count<const MAX: u32>(&mut self, count: BitCount<MAX>) -> io::Result<()> {
(**self).write_count::<MAX>(count)
}
#[inline]
fn write_counted<const MAX: u32, I>(&mut self, bits: BitCount<MAX>, value: I) -> io::Result<()>
where
I: Integer + Sized,
{
(**self).write_counted::<MAX, I>(bits, value)
}
#[inline]
fn write_unsigned_counted<const BITS: u32, U>(
&mut self,
bits: BitCount<BITS>,
value: U,
) -> io::Result<()>
where
U: UnsignedInteger,
{
(**self).write_unsigned_counted::<BITS, U>(bits, value)
}
#[inline]
fn write_signed_counted<const MAX: u32, S>(
&mut self,
bits: impl TryInto<SignedBitCount<MAX>>,
value: S,
) -> io::Result<()>
where
S: SignedInteger,
{
(**self).write_signed_counted::<MAX, S>(bits, value)
}
#[inline]
fn write_from<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive,
{
(**self).write_from::<V>(value)
}
#[inline]
fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive,
{
(**self).write_as_from::<F, V>(value)
}
#[inline]
fn pad(&mut self, bits: u32) -> io::Result<()> {
(**self).pad(bits)
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
(**self).write_bytes(buf)
}
#[inline]
fn write_unary<const STOP_BIT: u8>(&mut self, value: u32) -> io::Result<()> {
(**self).write_unary::<STOP_BIT>(value)
}
#[inline]
fn write_checked<C: Checkable>(&mut self, value: C) -> io::Result<()> {
(**self).write_checked(value)
}
#[inline]
fn build<T: ToBitStream>(&mut self, build: &T) -> Result<(), T::Error> {
(**self).build(build)
}
#[inline]
fn build_with<'a, T: ToBitStreamWith<'a>>(
&mut self,
build: &T,
context: &T::Context,
) -> Result<(), T::Error> {
(**self).build_with(build, context)
}
#[inline]
fn byte_aligned(&self) -> bool {
(**self).byte_aligned()
}
#[inline]
fn byte_align(&mut self) -> io::Result<()> {
(**self).byte_align()
}
#[inline]
fn write_huffman<T>(&mut self, value: T::Symbol) -> io::Result<()>
where
T: crate::huffman::ToBits,
{
(**self).write_huffman::<T>(value)
}
}
pub trait BitWrite2 {
fn write_bit(&mut self, bit: bool) -> io::Result<()> {
self.write_unsigned_out::<1, u8>(u8::from(bit))
}
fn write<I>(&mut self, bits: u32, value: I) -> io::Result<()>
where
I: Integer;
fn write_out<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
where
I: Integer;
fn write_unsigned<U>(&mut self, bits: u32, value: U) -> io::Result<()>
where
U: UnsignedInteger;
#[inline]
fn write_unsigned_out<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
self.write_unsigned(BITS, value)
}
fn write_signed<S>(&mut self, bits: u32, value: S) -> io::Result<()>
where
S: SignedInteger;
fn write_signed_out<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
self.write_signed(BITS, value)
}
fn write_from<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive;
fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive;
fn pad(&mut self, mut bits: u32) -> io::Result<()> {
loop {
match bits {
0 => break Ok(()),
bits @ 1..64 => break self.write(bits, 0u64),
_ => {
self.write_out::<64, u64>(0)?;
bits -= 64;
}
}
}
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
buf.iter()
.try_for_each(|b| self.write_unsigned_out::<8, _>(*b))
}
fn write_unary0(&mut self, value: u32) -> io::Result<()>;
fn write_unary1(&mut self, value: u32) -> io::Result<()>;
fn build<T: ToBitStream>(&mut self, build: &T) -> Result<(), T::Error>
where
Self: BitWrite,
{
build.to_writer(self)
}
fn build_with<'a, T: ToBitStreamWith<'a>>(
&mut self,
build: &T,
context: &T::Context,
) -> Result<(), T::Error>
where
Self: BitWrite,
{
build.to_writer(self, context)
}
fn byte_aligned(&self) -> bool;
fn byte_align(&mut self) -> io::Result<()> {
while !self.byte_aligned() {
self.write_bit(false)?;
}
Ok(())
}
fn write_huffman<T>(&mut self, value: T::Symbol) -> io::Result<()>
where
T: crate::huffman::ToBits,
{
T::to_bits(value, |b| self.write_bit(b))
}
}
impl<W: BitWrite> BitWrite2 for W {
#[inline]
fn write_bit(&mut self, bit: bool) -> io::Result<()> {
BitWrite::write_bit(self, bit)
}
#[inline]
fn write<I>(&mut self, bits: u32, value: I) -> io::Result<()>
where
I: Integer,
{
BitWrite::write_var(self, bits, value)
}
#[inline]
fn write_out<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
where
I: Integer,
{
BitWrite::write::<BITS, I>(self, value)
}
#[inline]
fn write_unsigned<U>(&mut self, bits: u32, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
BitWrite::write_unsigned_var::<U>(self, bits, value)
}
#[inline]
fn write_unsigned_out<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
BitWrite::write_unsigned::<BITS, U>(self, value)
}
#[inline]
fn write_signed<S>(&mut self, bits: u32, value: S) -> io::Result<()>
where
S: SignedInteger,
{
BitWrite::write_signed_var::<S>(self, bits, value)
}
#[inline]
fn write_signed_out<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
BitWrite::write_signed::<BITS, S>(self, value)
}
#[inline]
fn write_from<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive,
{
BitWrite::write_from(self, value)
}
#[inline]
fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive,
{
BitWrite::write_as_from::<F, V>(self, value)
}
#[inline]
fn pad(&mut self, bits: u32) -> io::Result<()> {
BitWrite::pad(self, bits)
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
BitWrite::write_bytes(self, buf)
}
#[inline]
fn write_unary0(&mut self, value: u32) -> io::Result<()> {
BitWrite::write_unary::<0>(self, value)
}
#[inline]
fn write_unary1(&mut self, value: u32) -> io::Result<()> {
BitWrite::write_unary::<1>(self, value)
}
#[inline]
fn byte_aligned(&self) -> bool {
BitWrite::byte_aligned(self)
}
#[inline]
fn byte_align(&mut self) -> io::Result<()> {
BitWrite::byte_align(self)
}
}
impl<W: io::Write, E: Endianness> BitWrite for BitWriter<W, E> {
fn write_bit(&mut self, bit: bool) -> io::Result<()> {
match E::push_bit_flush(&mut self.value, &mut self.bits, bit) {
None => Ok(()),
Some(byte) => write_byte(&mut self.writer, byte),
}
}
#[inline(always)]
fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
let Self {
value: queue_value,
bits: queue_bits,
writer,
..
} = self;
E::write_bits_checked(
writer,
queue_value,
queue_bits,
CheckedUnsigned::<BITS, U>::new_fixed::<BITS>(value)?,
)
}
fn write_unsigned_counted<const BITS: u32, U>(
&mut self,
count: BitCount<BITS>,
value: U,
) -> io::Result<()>
where
U: UnsignedInteger,
{
let Self {
value: queue_value,
bits: queue_bits,
writer,
..
} = self;
E::write_bits_checked(
writer,
queue_value,
queue_bits,
CheckedUnsigned::new(count, value)?,
)
}
#[inline(always)]
fn write_signed_counted<const BITS: u32, S>(
&mut self,
bits: impl TryInto<SignedBitCount<BITS>>,
value: S,
) -> io::Result<()>
where
S: SignedInteger,
{
E::write_signed_bits_checked(
&mut self.writer,
&mut self.value,
&mut self.bits,
CheckedSigned::new(
bits.try_into().map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"signed writes need at least 1 bit for sign",
)
})?,
value,
)?,
)
}
#[inline]
fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
E::write_signed_bits_checked(
&mut self.writer,
&mut self.value,
&mut self.bits,
CheckedSigned::<BITS, _>::new_fixed::<BITS>(value)?,
)
}
#[inline]
fn write_from<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive,
{
E::write_bytes::<8, _>(
&mut self.writer,
&mut self.value,
self.bits,
E::primitive_to_bytes(value).as_ref(),
)
}
#[inline]
fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive,
{
F::write_bytes::<8, _>(
&mut self.writer,
&mut self.value,
self.bits,
F::primitive_to_bytes(value).as_ref(),
)
}
#[inline]
fn write_checked<C: Checkable>(&mut self, value: C) -> io::Result<()> {
value.write_endian::<E, _>(&mut self.writer, &mut self.value, &mut self.bits)
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
E::write_bytes::<1024, _>(&mut self.writer, &mut self.value, self.bits, buf)
}
#[inline(always)]
fn byte_aligned(&self) -> bool {
self.bits == 0
}
}
#[derive(Copy, Clone, Debug)]
pub struct Overflowed;
impl fmt::Display for Overflowed {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"overflow occured in counter".fmt(f)
}
}
impl core::error::Error for Overflowed {}
impl From<Overflowed> for io::Error {
fn from(Overflowed: Overflowed) -> Self {
io::Error::new(
#[cfg(feature = "std")]
{
io::ErrorKind::StorageFull
},
#[cfg(not(feature = "std"))]
{
io::ErrorKind::Other
},
"bitstream accumulator overflow",
)
}
}
pub trait Counter: Default + Sized + From<u8> + TryFrom<u32> + TryFrom<usize> {
fn checked_add_assign(&mut self, rhs: Self) -> Result<(), Overflowed>;
fn checked_mul(self, rhs: Self) -> Result<Self, Overflowed>;
fn byte_aligned(&self) -> bool;
}
macro_rules! define_counter {
($t:ty) => {
impl Counter for $t {
fn checked_add_assign(&mut self, rhs: Self) -> Result<(), Overflowed> {
*self = <$t>::checked_add(*self, rhs).ok_or(Overflowed)?;
Ok(())
}
fn checked_mul(self, rhs: Self) -> Result<Self, Overflowed> {
<$t>::checked_mul(self, rhs).ok_or(Overflowed)
}
fn byte_aligned(&self) -> bool {
self % 8 == 0
}
}
};
}
define_counter!(u8);
define_counter!(u16);
define_counter!(u32);
define_counter!(u64);
define_counter!(u128);
#[derive(Default)]
pub struct BitsWritten<N> {
bits: N,
}
impl<N: Default> BitsWritten<N> {
#[inline]
pub fn new() -> Self {
Self { bits: N::default() }
}
}
impl<N: Copy> BitsWritten<N> {
#[inline]
pub fn written(&self) -> N {
self.bits
}
}
impl<N> BitsWritten<N> {
#[inline]
pub fn into_written(self) -> N {
self.bits
}
}
impl<N: Counter> BitWrite for BitsWritten<N> {
#[inline]
fn write_bit(&mut self, _bit: bool) -> io::Result<()> {
self.bits.checked_add_assign(1u8.into())?;
Ok(())
}
#[inline]
fn write_const<const BITS: u32, const VALUE: u32>(&mut self) -> io::Result<()> {
const {
assert!(
BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)),
"excessive value for bits written"
);
}
self.bits
.checked_add_assign(BITS.try_into().map_err(|_| Overflowed)?)?;
Ok(())
}
#[inline]
fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
const {
assert!(BITS <= U::BITS_SIZE, "excessive bits for type written");
}
if BITS == 0 {
Ok(())
} else if value <= (U::ALL >> (U::BITS_SIZE - BITS)) {
self.bits
.checked_add_assign(BITS.try_into().map_err(|_| Overflowed)?)?;
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive value for bits written",
))
}
}
#[inline]
fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
let SignedBitCount {
bits: BitCount { bits },
unsigned,
} = const {
assert!(BITS <= S::BITS_SIZE, "excessive bits for type written");
let count = BitCount::<BITS>::new::<BITS>().signed_count();
assert!(
count.is_some(),
"signed writes need at least 1 bit for sign"
);
count.unwrap()
};
self.bits.checked_add_assign(1u8.into())?;
self.write_unsigned_counted(
unsigned,
if value.is_negative() {
value.as_negative(bits)
} else {
value.as_non_negative()
},
)
}
#[inline]
fn write_unsigned_counted<const MAX: u32, U>(
&mut self,
BitCount { bits }: BitCount<MAX>,
value: U,
) -> io::Result<()>
where
U: UnsignedInteger,
{
if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE {
if bits == 0 {
Ok(())
} else if value <= U::ALL >> (U::BITS_SIZE - bits) {
self.bits
.checked_add_assign(bits.try_into().map_err(|_| Overflowed)?)?;
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive value for bits written",
))
}
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive bits for type written",
))
}
}
#[inline]
fn write_signed_counted<const MAX: u32, S>(
&mut self,
bits: impl TryInto<SignedBitCount<MAX>>,
value: S,
) -> io::Result<()>
where
S: SignedInteger,
{
let SignedBitCount {
bits: BitCount { bits },
unsigned,
} = bits.try_into().map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"signed writes need at least 1 bit for sign",
)
})?;
if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE {
self.bits.checked_add_assign(1u8.into())?;
self.write_unsigned_counted(
unsigned,
if value.is_negative() {
value.as_negative(bits)
} else {
value.as_non_negative()
},
)
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive bits for type written",
))
}
}
#[inline]
fn write_from<V>(&mut self, _: V) -> io::Result<()>
where
V: Primitive,
{
self.bits.checked_add_assign(
N::try_from(core::mem::size_of::<V>())
.map_err(|_| Overflowed)?
.checked_mul(8u8.into())?,
)?;
Ok(())
}
#[inline]
fn write_as_from<F, V>(&mut self, _: V) -> io::Result<()>
where
F: Endianness,
V: Primitive,
{
self.bits.checked_add_assign(
N::try_from(core::mem::size_of::<V>())
.map_err(|_| Overflowed)?
.checked_mul(8u8.into())?,
)?;
Ok(())
}
#[inline]
fn pad(&mut self, bits: u32) -> io::Result<()> {
self.bits
.checked_add_assign(bits.try_into().map_err(|_| Overflowed)?)?;
Ok(())
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
self.bits.checked_add_assign(
N::try_from(buf.len())
.map_err(|_| Overflowed)?
.checked_mul(8u8.into())?,
)?;
Ok(())
}
fn write_unary<const STOP_BIT: u8>(&mut self, value: u32) -> io::Result<()> {
const {
assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1");
}
self.bits
.checked_add_assign(value.try_into().map_err(|_| Overflowed)?)?;
self.bits.checked_add_assign(1u8.into())?;
Ok(())
}
fn write_checked<C: Checkable>(&mut self, value: C) -> io::Result<()> {
Ok(self
.bits
.checked_add_assign(value.written_bits().try_into().map_err(|_| Overflowed)?)?)
}
#[inline]
fn byte_aligned(&self) -> bool {
self.bits.byte_aligned()
}
}
#[derive(Default)]
#[deprecated(since = "4.0.0", note = "use of BitsWritten is preferred")]
pub struct BitCounter<N, E: Endianness> {
bits: BitsWritten<N>,
phantom: PhantomData<E>,
}
#[allow(deprecated)]
impl<N: Default, E: Endianness> BitCounter<N, E> {
#[inline]
pub fn new() -> Self {
BitCounter {
bits: BitsWritten::new(),
phantom: PhantomData,
}
}
}
#[allow(deprecated)]
impl<N: Copy, E: Endianness> BitCounter<N, E> {
#[inline]
pub fn written(&self) -> N {
self.bits.written()
}
}
#[allow(deprecated)]
impl<N, E: Endianness> BitCounter<N, E> {
#[inline]
pub fn into_written(self) -> N {
self.bits.into_written()
}
}
#[allow(deprecated)]
impl<N, E> BitWrite for BitCounter<N, E>
where
E: Endianness,
N: Counter,
{
#[inline]
fn write_bit(&mut self, bit: bool) -> io::Result<()> {
BitWrite::write_bit(&mut self.bits, bit)
}
#[inline]
fn write_const<const BITS: u32, const VALUE: u32>(&mut self) -> io::Result<()> {
BitWrite::write_const::<BITS, VALUE>(&mut self.bits)
}
#[inline]
fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
BitWrite::write_unsigned::<BITS, U>(&mut self.bits, value)
}
#[inline]
fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
BitWrite::write_signed::<BITS, S>(&mut self.bits, value)
}
#[inline]
fn write_unsigned_counted<const MAX: u32, U>(
&mut self,
count: BitCount<MAX>,
value: U,
) -> io::Result<()>
where
U: UnsignedInteger,
{
BitWrite::write_unsigned_counted::<MAX, U>(&mut self.bits, count, value)
}
#[inline]
fn write_signed_counted<const MAX: u32, S>(
&mut self,
bits: impl TryInto<SignedBitCount<MAX>>,
value: S,
) -> io::Result<()>
where
S: SignedInteger,
{
BitWrite::write_signed_counted::<MAX, S>(&mut self.bits, bits, value)
}
#[inline]
fn write_from<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive,
{
BitWrite::write_from(&mut self.bits, value)
}
#[inline]
fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive,
{
BitWrite::write_as_from::<F, V>(&mut self.bits, value)
}
#[inline]
fn pad(&mut self, bits: u32) -> io::Result<()> {
BitWrite::pad(&mut self.bits, bits)
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
BitWrite::write_bytes(&mut self.bits, buf)
}
fn write_unary<const STOP_BIT: u8>(&mut self, value: u32) -> io::Result<()> {
BitWrite::write_unary::<STOP_BIT>(&mut self.bits, value)
}
#[inline]
fn byte_aligned(&self) -> bool {
BitWrite::byte_aligned(&self.bits)
}
}
#[cfg(feature = "alloc")]
mod bit_recorder {
use super::*;
pub struct BitRecorder<N, E: Endianness> {
writer: BitWriter<Vec<u8>, E>,
phantom: PhantomData<N>,
}
impl<N: Counter, E: Endianness> BitRecorder<N, E> {
#[inline]
pub fn new() -> Self {
BitRecorder {
writer: BitWriter::new(Vec::new()),
phantom: PhantomData,
}
}
#[inline]
pub fn with_capacity(bytes: usize) -> Self {
BitRecorder {
writer: BitWriter::new(Vec::with_capacity(bytes)),
phantom: PhantomData,
}
}
#[inline]
pub fn endian(endian: E) -> Self {
BitRecorder {
writer: BitWriter::endian(Vec::new(), endian),
phantom: PhantomData,
}
}
#[inline]
pub fn written(&self) -> N {
self.written_checked().unwrap()
}
#[inline]
pub fn written_checked(&self) -> Result<N, Overflowed> {
let mut written = N::try_from(self.writer.writer.len())
.map_err(|_| Overflowed)?
.checked_mul(8u8.into())?;
written.checked_add_assign(N::try_from(self.writer.bits).map_err(|_| Overflowed)?)?;
Ok(written)
}
#[inline]
pub fn playback<W: BitWrite>(&self, writer: &mut W) -> io::Result<()> {
writer.write_bytes(self.writer.writer.as_slice())?;
writer.write_var(self.writer.bits, self.writer.value)?;
Ok(())
}
#[inline]
pub fn clear(&mut self) {
self.writer = BitWriter::new({
let mut v = core::mem::take(&mut self.writer.writer);
v.clear();
v
});
}
}
impl<N: Counter, E: Endianness> Default for BitRecorder<N, E> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<N, E> BitWrite for BitRecorder<N, E>
where
E: Endianness,
N: Counter,
{
#[inline]
fn write_bit(&mut self, bit: bool) -> io::Result<()> {
BitWrite::write_bit(&mut self.writer, bit)
}
#[inline]
fn write<const BITS: u32, I>(&mut self, value: I) -> io::Result<()>
where
I: Integer,
{
BitWrite::write::<BITS, I>(&mut self.writer, value)
}
#[inline]
fn write_const<const BITS: u32, const VALUE: u32>(&mut self) -> io::Result<()> {
self.writer.write_const::<BITS, VALUE>()
}
#[inline]
fn write_var<I>(&mut self, bits: u32, value: I) -> io::Result<()>
where
I: Integer,
{
self.writer.write_var(bits, value)
}
#[inline]
fn write_unsigned<const BITS: u32, U>(&mut self, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
BitWrite::write_unsigned::<BITS, U>(&mut self.writer, value)
}
#[inline]
fn write_unsigned_var<U>(&mut self, bits: u32, value: U) -> io::Result<()>
where
U: UnsignedInteger,
{
self.writer.write_unsigned_var(bits, value)
}
#[inline]
fn write_signed<const BITS: u32, S>(&mut self, value: S) -> io::Result<()>
where
S: SignedInteger,
{
BitWrite::write_signed::<BITS, S>(&mut self.writer, value)
}
#[inline(always)]
fn write_signed_var<S>(&mut self, bits: u32, value: S) -> io::Result<()>
where
S: SignedInteger,
{
self.writer.write_signed_var(bits, value)
}
#[inline]
fn write_count<const MAX: u32>(&mut self, count: BitCount<MAX>) -> io::Result<()> {
self.writer.write_count::<MAX>(count)
}
#[inline]
fn write_counted<const MAX: u32, I>(
&mut self,
bits: BitCount<MAX>,
value: I,
) -> io::Result<()>
where
I: Integer + Sized,
{
self.writer.write_counted::<MAX, I>(bits, value)
}
#[inline]
fn write_unsigned_counted<const BITS: u32, U>(
&mut self,
bits: BitCount<BITS>,
value: U,
) -> io::Result<()>
where
U: UnsignedInteger,
{
self.writer.write_unsigned_counted::<BITS, U>(bits, value)
}
#[inline]
fn write_signed_counted<const MAX: u32, S>(
&mut self,
bits: impl TryInto<SignedBitCount<MAX>>,
value: S,
) -> io::Result<()>
where
S: SignedInteger,
{
self.writer.write_signed_counted::<MAX, S>(bits, value)
}
#[inline]
fn write_from<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive,
{
BitWrite::write_from::<V>(&mut self.writer, value)
}
#[inline]
fn write_as_from<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive,
{
BitWrite::write_as_from::<F, V>(&mut self.writer, value)
}
#[inline]
fn pad(&mut self, bits: u32) -> io::Result<()> {
BitWrite::pad(&mut self.writer, bits)
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
BitWrite::write_bytes(&mut self.writer, buf)
}
#[inline]
fn write_unary<const STOP_BIT: u8>(&mut self, value: u32) -> io::Result<()> {
self.writer.write_unary::<STOP_BIT>(value)
}
#[inline]
fn build<T: ToBitStream>(&mut self, build: &T) -> Result<(), T::Error> {
BitWrite::build(&mut self.writer, build)
}
#[inline]
fn build_with<'a, T: ToBitStreamWith<'a>>(
&mut self,
build: &T,
context: &T::Context,
) -> Result<(), T::Error> {
BitWrite::build_with(&mut self.writer, build, context)
}
#[inline]
fn byte_aligned(&self) -> bool {
BitWrite::byte_aligned(&self.writer)
}
#[inline]
fn byte_align(&mut self) -> io::Result<()> {
BitWrite::byte_align(&mut self.writer)
}
#[inline]
fn write_huffman<T>(&mut self, value: T::Symbol) -> io::Result<()>
where
T: crate::huffman::ToBits,
{
BitWrite::write_huffman::<T>(&mut self.writer, value)
}
}
impl<N: PartialOrd + Counter + Copy, E: Endianness> BitRecorder<N, E> {
pub fn best<F>(
mut self,
candidate: &mut Self,
f: impl FnOnce(&mut Self) -> Result<(), F>,
) -> Result<Self, F> {
candidate.clear();
f(candidate)?;
if candidate.written() < self.written() {
core::mem::swap(&mut self, candidate);
}
Ok(self)
}
}
}
#[inline]
fn write_byte<W>(mut writer: W, byte: u8) -> io::Result<()>
where
W: io::Write,
{
writer.write_all(core::slice::from_ref(&byte))
}
pub struct ByteWriter<W: io::Write, E: Endianness> {
phantom: PhantomData<E>,
writer: W,
}
impl<W: io::Write, E: Endianness> ByteWriter<W, E> {
pub fn new(writer: W) -> ByteWriter<W, E> {
ByteWriter {
phantom: PhantomData,
writer,
}
}
pub fn endian(writer: W, _endian: E) -> ByteWriter<W, E> {
ByteWriter {
phantom: PhantomData,
writer,
}
}
#[inline]
pub fn into_writer(self) -> W {
self.writer
}
#[inline]
pub fn writer(&mut self) -> &mut W {
&mut self.writer
}
#[inline]
pub fn into_bitwriter(self) -> BitWriter<W, E> {
BitWriter::new(self.into_writer())
}
#[inline]
pub fn bitwriter(&mut self) -> BitWriter<&mut W, E> {
BitWriter::new(self.writer())
}
}
pub trait ByteWrite {
fn write<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive;
fn write_as<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive;
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()>;
fn pad(&mut self, bytes: u32) -> io::Result<()>;
fn build<T: ToByteStream>(&mut self, build: &T) -> Result<(), T::Error> {
build.to_writer(self)
}
fn build_with<'a, T: ToByteStreamWith<'a>>(
&mut self,
build: &T,
context: &T::Context,
) -> Result<(), T::Error> {
build.to_writer(self, context)
}
fn build_using<T: ToByteStreamUsing>(
&mut self,
build: &T,
context: T::Context,
) -> Result<(), T::Error> {
build.to_writer(self, context)
}
fn writer_ref(&mut self) -> &mut dyn io::Write;
}
impl<W: io::Write, E: Endianness> ByteWrite for ByteWriter<W, E> {
#[inline]
fn write<V>(&mut self, value: V) -> io::Result<()>
where
V: Primitive,
{
self.writer.write_all(E::primitive_to_bytes(value).as_ref())
}
#[inline]
fn write_as<F, V>(&mut self, value: V) -> io::Result<()>
where
F: Endianness,
V: Primitive,
{
self.writer.write_all(F::primitive_to_bytes(value).as_ref())
}
#[inline]
fn pad(&mut self, mut bytes: u32) -> io::Result<()> {
let buf = [0u8; 8];
while bytes > 0 {
let to_write = bytes.min(8);
self.write_bytes(&buf[0..to_write as usize])?;
bytes -= to_write;
}
Ok(())
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
self.writer.write_all(buf)
}
#[inline]
fn writer_ref(&mut self) -> &mut dyn io::Write {
&mut self.writer
}
}
pub trait ToBitStream {
type Error;
fn to_writer<W: BitWrite + ?Sized>(&self, w: &mut W) -> Result<(), Self::Error>
where
Self: Sized;
fn bits<C: Counter>(&self) -> Result<C, Self::Error>
where
Self: Sized,
{
let mut c: BitsWritten<C> = BitsWritten::default();
self.to_writer(&mut c)?;
Ok(c.into_written())
}
#[deprecated(since = "4.0.0", note = "use of bits() is preferred")]
#[inline]
fn bits_len<C: Counter, E: Endianness>(&self) -> Result<C, Self::Error>
where
Self: Sized,
{
self.bits()
}
}
pub trait ToBitStreamWith<'a> {
type Context: 'a;
type Error;
fn to_writer<W: BitWrite + ?Sized>(
&self,
w: &mut W,
context: &Self::Context,
) -> Result<(), Self::Error>
where
Self: Sized;
fn bits<C: Counter>(&self, context: &Self::Context) -> Result<C, Self::Error>
where
Self: Sized,
{
let mut c: BitsWritten<C> = BitsWritten::default();
self.to_writer(&mut c, context)?;
Ok(c.into_written())
}
#[deprecated(since = "4.0.0", note = "use of len() is preferred")]
#[inline]
fn bits_len<C: Counter, E: Endianness>(&self, context: &Self::Context) -> Result<C, Self::Error>
where
Self: Sized,
{
self.bits(context)
}
}
pub trait ToBitStreamUsing {
type Context;
type Error;
fn to_writer<W: BitWrite + ?Sized>(
&self,
w: &mut W,
context: Self::Context,
) -> Result<(), Self::Error>
where
Self: Sized;
fn bits<C: Counter>(&self, context: Self::Context) -> Result<C, Self::Error>
where
Self: Sized,
{
let mut c: BitsWritten<C> = BitsWritten::default();
self.to_writer(&mut c, context)?;
Ok(c.into_written())
}
}
pub trait ToByteStream {
type Error;
fn to_writer<W: ByteWrite + ?Sized>(&self, w: &mut W) -> Result<(), Self::Error>
where
Self: Sized;
fn bytes<C: Counter>(&self) -> Result<C, Self::Error>
where
Self: Sized,
{
let mut counter = ByteCount::default();
self.to_writer(&mut counter)?;
Ok(counter.writer.count)
}
}
pub trait ToByteStreamWith<'a> {
type Context: 'a;
type Error;
fn to_writer<W: ByteWrite + ?Sized>(
&self,
w: &mut W,
context: &Self::Context,
) -> Result<(), Self::Error>
where
Self: Sized;
fn bytes<C: Counter>(&self, context: &Self::Context) -> Result<C, Self::Error>
where
Self: Sized,
{
let mut counter = ByteCount::default();
self.to_writer(&mut counter, context)?;
Ok(counter.writer.count)
}
}
pub trait ToByteStreamUsing {
type Context;
type Error;
fn to_writer<W: ByteWrite + ?Sized>(
&self,
w: &mut W,
context: Self::Context,
) -> Result<(), Self::Error>
where
Self: Sized;
fn bytes<C: Counter>(&self, context: Self::Context) -> Result<C, Self::Error>
where
Self: Sized,
{
let mut counter = ByteCount::default();
self.to_writer(&mut counter, context)?;
Ok(counter.writer.count)
}
}
#[derive(Default)]
struct ByteCounterWriter<C> {
count: C,
}
impl<C: Counter> io::Write for ByteCounterWriter<C> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.count
.checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?;
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[derive(Default)]
struct ByteCount<C> {
writer: ByteCounterWriter<C>,
}
impl<C: Counter> ByteWrite for ByteCount<C> {
fn write<V: Primitive>(&mut self, _value: V) -> io::Result<()> {
self.writer.count.checked_add_assign(
V::buffer()
.as_ref()
.len()
.try_into()
.map_err(|_| Overflowed)?,
)?;
Ok(())
}
fn write_as<F: Endianness, V: Primitive>(&mut self, _value: V) -> io::Result<()> {
self.writer.count.checked_add_assign(
V::buffer()
.as_ref()
.len()
.try_into()
.map_err(|_| Overflowed)?,
)?;
Ok(())
}
fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> {
self.writer
.count
.checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?;
Ok(())
}
fn pad(&mut self, bytes: u32) -> io::Result<()> {
self.writer
.count
.checked_add_assign(bytes.try_into().map_err(|_| Overflowed)?)?;
Ok(())
}
fn writer_ref(&mut self) -> &mut dyn io::Write {
&mut self.writer
}
}