use std::error::Error;
use std::fmt;
use std::io::{Result, Write};
use std::mem::ManuallyDrop;
pub trait BitWriter {
fn write_bit(&mut self, bit: bool) -> Result<()>;
fn write_u8(&mut self, value: u8) -> Result<()>;
fn write_i8(&mut self, value: i8) -> Result<()>;
fn write_u16(&mut self, value: u16) -> Result<()>;
fn write_i16(&mut self, value: i16) -> Result<()>;
fn write_u32(&mut self, value: u32) -> Result<()>;
fn write_i32(&mut self, value: i32) -> Result<()>;
fn write_f32(&mut self, value: f32) -> Result<()>;
fn write_u64(&mut self, value: u64) -> Result<()>;
fn write_i64(&mut self, value: i64) -> Result<()>;
fn write_f64(&mut self, value: f64) -> Result<()>;
fn write_bits(&mut self, bits: u32, value: u64) -> Result<()>;
fn write_signed_bits(&mut self, bits: u32, value: i64) -> Result<()>;
fn unaligned_bits(&self) -> u32;
fn write_bytes(&mut self, buf: &[u8]) -> Result<()>;
fn flush(&mut self) -> Result<()>;
}
#[derive(Debug)]
struct BitterWriter<W: Write, const LE: bool> {
writer: W,
bit_buf: u64,
bit_count: u32,
}
impl<W: Write, const LE: bool> BitterWriter<W, LE> {
#[inline]
pub fn new(writer: W) -> Self {
Self {
writer,
bit_buf: 0,
bit_count: 0,
}
}
#[inline]
pub fn into_inner(self) -> std::result::Result<W, IntoInnerError<BitterWriter<W, LE>>> {
let mut this = ManuallyDrop::new(self);
match this.flush_impl() {
Ok(()) => {
let writer = unsafe { std::ptr::read(&this.writer) };
Ok(writer)
}
Err(e) => {
let this = unsafe { ManuallyDrop::take(&mut this) };
Err(IntoInnerError::new(e, this))
}
}
}
#[inline]
pub fn get_ref(&self) -> &W {
&self.writer
}
#[inline]
pub fn get_mut(&mut self) -> &mut W {
&mut self.writer
}
#[inline]
fn flush_impl(&mut self) -> Result<()> {
if self.bit_count > 0 {
let remaining_bits = 8 - (self.bit_count % 8);
if remaining_bits != 8 {
self.write_bits_internal(remaining_bits, 0)?;
}
}
Ok(())
}
#[inline]
fn flush_bytes(&mut self) -> Result<()> {
let full_bytes = (self.bit_count / 8) as usize;
let flush_bits = full_bytes * 8;
if full_bytes > 0 {
let bytes = if LE {
self.bit_buf.to_le_bytes()
} else {
self.bit_buf.to_be_bytes()
};
self.writer.write_all(&bytes[..full_bytes])?;
if full_bytes < 8 {
if LE {
self.bit_buf >>= flush_bits;
} else {
self.bit_buf <<= flush_bits;
}
self.bit_count -= flush_bits as u32;
} else {
self.bit_buf = 0;
self.bit_count = 0;
}
}
Ok(())
}
#[inline]
fn write_bits_internal(&mut self, mut bits: u32, mut value: u64) -> Result<()> {
debug_assert!(bits <= 64);
debug_assert!(bits == 0 || bits == 64 || value < (1u64 << bits));
while bits > 0 {
let space_in_buf = 64 - self.bit_count;
let bits_to_write = std::cmp::min(bits, space_in_buf);
let chunk = if LE {
value
& if bits_to_write == 64 {
u64::MAX
} else {
(1u64 << bits_to_write) - 1
}
} else {
value >> (bits - bits_to_write)
};
if LE {
self.bit_buf |= chunk << self.bit_count;
if bits_to_write == 64 {
value = 0;
} else {
value >>= bits_to_write;
}
} else {
self.bit_buf |= chunk << (space_in_buf - bits_to_write);
if bits == bits_to_write {
value = 0;
} else {
value &= (1u64 << (bits - bits_to_write)) - 1;
}
}
self.bit_count += bits_to_write;
bits -= bits_to_write;
self.flush_bytes()?;
}
Ok(())
}
}
impl<W: Write, const LE: bool> Drop for BitterWriter<W, LE> {
fn drop(&mut self) {
let _ = self.flush_impl();
}
}
impl<W: Write, const LE: bool> BitWriter for BitterWriter<W, LE> {
#[inline]
fn write_bit(&mut self, bit: bool) -> Result<()> {
self.write_bits_internal(1, bit as u64)
}
#[inline]
fn write_u8(&mut self, value: u8) -> Result<()> {
self.write_bits_internal(8, value as u64)
}
#[inline]
fn write_i8(&mut self, value: i8) -> Result<()> {
self.write_bits_internal(8, value as u8 as u64)
}
#[inline]
fn write_u16(&mut self, value: u16) -> Result<()> {
self.write_bits_internal(16, value as u64)
}
#[inline]
fn write_i16(&mut self, value: i16) -> Result<()> {
self.write_bits_internal(16, value as u16 as u64)
}
#[inline]
fn write_u32(&mut self, value: u32) -> Result<()> {
self.write_bits_internal(32, value as u64)
}
#[inline]
fn write_i32(&mut self, value: i32) -> Result<()> {
self.write_bits_internal(32, value as u32 as u64)
}
#[inline]
fn write_f32(&mut self, value: f32) -> Result<()> {
self.write_bits_internal(32, value.to_bits() as u64)
}
#[inline]
fn write_u64(&mut self, value: u64) -> Result<()> {
self.write_bits_internal(64, value)
}
#[inline]
fn write_i64(&mut self, value: i64) -> Result<()> {
self.write_bits_internal(64, value as u64)
}
#[inline]
fn write_f64(&mut self, value: f64) -> Result<()> {
self.write_bits_internal(64, value.to_bits())
}
#[inline]
fn write_bits(&mut self, bits: u32, value: u64) -> Result<()> {
self.write_bits_internal(bits, value)
}
#[inline]
fn write_signed_bits(&mut self, bits: u32, value: i64) -> Result<()> {
if bits == 0 {
return Ok(());
}
let mask = if bits == 64 {
!0u64
} else {
(1u64 << bits) - 1
};
self.write_bits_internal(bits, value as u64 & mask)
}
#[inline]
fn unaligned_bits(&self) -> u32 {
self.bit_count % 8
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> Result<()> {
if self.unaligned_bits() == 0 {
self.writer.write_all(buf)?;
} else {
let mut chunks = buf.chunks_exact(8);
for c in chunks.by_ref() {
let arr = [c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]];
let value = if LE {
u64::from_le_bytes(arr)
} else {
u64::from_be_bytes(arr)
};
self.write_bits_internal(64, value)?;
}
for &byte in chunks.remainder() {
self.write_bits_internal(8, byte as u64)?;
}
}
Ok(())
}
#[inline]
fn flush(&mut self) -> Result<()> {
self.flush_impl()
}
}
#[derive(Debug)]
pub struct LittleEndianWriter<W: Write>(BitterWriter<W, true>);
impl<W: Write> LittleEndianWriter<W> {
#[inline]
pub fn new(writer: W) -> Self {
Self(BitterWriter::new(writer))
}
#[inline]
pub fn into_inner(self) -> std::result::Result<W, IntoInnerError<LittleEndianWriter<W>>> {
self.0.into_inner().map_err(|inner_error| {
IntoInnerError::new(inner_error.error, LittleEndianWriter(inner_error.writer))
})
}
#[inline]
pub fn get_ref(&self) -> &W {
self.0.get_ref()
}
#[inline]
pub fn get_mut(&mut self) -> &mut W {
self.0.get_mut()
}
}
impl<W: Write> BitWriter for LittleEndianWriter<W> {
#[inline]
fn write_bit(&mut self, bit: bool) -> Result<()> {
self.0.write_bit(bit)
}
#[inline]
fn write_u8(&mut self, value: u8) -> Result<()> {
self.0.write_u8(value)
}
#[inline]
fn write_i8(&mut self, value: i8) -> Result<()> {
self.0.write_i8(value)
}
#[inline]
fn write_u16(&mut self, value: u16) -> Result<()> {
self.0.write_u16(value)
}
#[inline]
fn write_i16(&mut self, value: i16) -> Result<()> {
self.0.write_i16(value)
}
#[inline]
fn write_u32(&mut self, value: u32) -> Result<()> {
self.0.write_u32(value)
}
#[inline]
fn write_i32(&mut self, value: i32) -> Result<()> {
self.0.write_i32(value)
}
#[inline]
fn write_f32(&mut self, value: f32) -> Result<()> {
self.0.write_f32(value)
}
#[inline]
fn write_u64(&mut self, value: u64) -> Result<()> {
self.0.write_u64(value)
}
#[inline]
fn write_i64(&mut self, value: i64) -> Result<()> {
self.0.write_i64(value)
}
#[inline]
fn write_f64(&mut self, value: f64) -> Result<()> {
self.0.write_f64(value)
}
#[inline]
fn write_bits(&mut self, bits: u32, value: u64) -> Result<()> {
self.0.write_bits(bits, value)
}
#[inline]
fn write_signed_bits(&mut self, bits: u32, value: i64) -> Result<()> {
self.0.write_signed_bits(bits, value)
}
#[inline]
fn unaligned_bits(&self) -> u32 {
self.0.unaligned_bits()
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> Result<()> {
self.0.write_bytes(buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
self.0.flush()
}
}
impl<W: Write> Write for LittleEndianWriter<W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.write_bytes(buf)?;
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> Result<()> {
BitWriter::flush(self)
}
}
#[derive(Debug)]
pub struct BigEndianWriter<W: Write>(BitterWriter<W, false>);
impl<W: Write> BigEndianWriter<W> {
#[inline]
pub fn new(writer: W) -> Self {
Self(BitterWriter::new(writer))
}
#[inline]
pub fn into_inner(self) -> std::result::Result<W, IntoInnerError<BigEndianWriter<W>>> {
self.0.into_inner().map_err(|inner_error| {
IntoInnerError::new(inner_error.error, BigEndianWriter(inner_error.writer))
})
}
#[inline]
pub fn get_ref(&self) -> &W {
self.0.get_ref()
}
#[inline]
pub fn get_mut(&mut self) -> &mut W {
self.0.get_mut()
}
}
impl<W: Write> BitWriter for BigEndianWriter<W> {
#[inline]
fn write_bit(&mut self, bit: bool) -> Result<()> {
self.0.write_bit(bit)
}
#[inline]
fn write_u8(&mut self, value: u8) -> Result<()> {
self.0.write_u8(value)
}
#[inline]
fn write_i8(&mut self, value: i8) -> Result<()> {
self.0.write_i8(value)
}
#[inline]
fn write_u16(&mut self, value: u16) -> Result<()> {
self.0.write_u16(value)
}
#[inline]
fn write_i16(&mut self, value: i16) -> Result<()> {
self.0.write_i16(value)
}
#[inline]
fn write_u32(&mut self, value: u32) -> Result<()> {
self.0.write_u32(value)
}
#[inline]
fn write_i32(&mut self, value: i32) -> Result<()> {
self.0.write_i32(value)
}
#[inline]
fn write_f32(&mut self, value: f32) -> Result<()> {
self.0.write_f32(value)
}
#[inline]
fn write_u64(&mut self, value: u64) -> Result<()> {
self.0.write_u64(value)
}
#[inline]
fn write_i64(&mut self, value: i64) -> Result<()> {
self.0.write_i64(value)
}
#[inline]
fn write_f64(&mut self, value: f64) -> Result<()> {
self.0.write_f64(value)
}
#[inline]
fn write_bits(&mut self, bits: u32, value: u64) -> Result<()> {
self.0.write_bits(bits, value)
}
#[inline]
fn write_signed_bits(&mut self, bits: u32, value: i64) -> Result<()> {
self.0.write_signed_bits(bits, value)
}
#[inline]
fn unaligned_bits(&self) -> u32 {
self.0.unaligned_bits()
}
#[inline]
fn write_bytes(&mut self, buf: &[u8]) -> Result<()> {
self.0.write_bytes(buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
self.0.flush()
}
}
impl<W: Write> Write for BigEndianWriter<W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.write_bytes(buf)?;
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> Result<()> {
BitWriter::flush(self)
}
}
#[cfg(target_endian = "little")]
pub type NativeEndianWriter<W> = LittleEndianWriter<W>;
#[cfg(target_endian = "big")]
pub type NativeEndianWriter<W> = BigEndianWriter<W>;
#[derive(Debug)]
pub struct IntoInnerError<W> {
error: std::io::Error,
writer: W,
}
impl<W> IntoInnerError<W> {
fn new(error: std::io::Error, writer: W) -> Self {
Self { error, writer }
}
pub fn error(&self) -> &std::io::Error {
&self.error
}
pub fn into_inner(self) -> W {
self.writer
}
}
impl<W> fmt::Display for IntoInnerError<W> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "failed to flush buffer in into_inner: {}", self.error)
}
}
impl<W: fmt::Debug> Error for IntoInnerError<W> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&self.error)
}
}