use std::io;
use super::{
BitWriter, Endianness, PhantomData, Primitive, ToByteStream, ToByteStreamUsing,
ToByteStreamWith,
};
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
}
}