use core::convert::TryInto;
use std::io;
use super::{BitWrite, BitsWritten, ByteWrite, Counter, Endianness, Overflowed, Primitive};
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
}
}