use std::io::Write;
use crc32fast::Hasher;
use crate::{types::number::SubunitNumber, GenResult};
pub trait Serializable {
fn wire_size(&self) -> GenResult<SubunitNumber>;
fn serialize<W: Write>(&self, out: &mut W) -> GenResult<()>;
}
impl<T> Serializable for Option<T>
where
T: Serializable,
{
fn wire_size(&self) -> GenResult<SubunitNumber> {
match self {
Some(inner) => inner.wire_size(),
None => SubunitNumber::new(0),
}
}
fn serialize<W: Write>(&self, out: &mut W) -> GenResult<()> {
match self {
Some(inner) => inner.serialize(out),
None => Ok(()),
}
}
}
impl<T> Serializable for Vec<T>
where
T: Serializable,
{
fn wire_size(&self) -> GenResult<SubunitNumber> {
let mut size = SubunitNumber::new(self.len() as u32)?.wire_size()?;
for item in self {
size = (size + item.wire_size()?)?;
}
Ok(size)
}
fn serialize<W: Write>(&self, out: &mut W) -> GenResult<()> {
SubunitNumber::try_from(self.len())?.serialize(out)?;
for item in self {
item.serialize(out)?;
}
Ok(())
}
}
impl<T, U> Serializable for (T, U)
where
T: Serializable,
U: Serializable,
{
fn wire_size(&self) -> GenResult<SubunitNumber> {
let (a, b) = self;
a.wire_size()? + b.wire_size()?
}
fn serialize<W: Write>(&self, out: &mut W) -> GenResult<()> {
let (a, b) = self;
a.serialize(out)?;
b.serialize(out)
}
}
impl Serializable for u8 {
fn wire_size(&self) -> GenResult<SubunitNumber> {
SubunitNumber::new(1)
}
fn serialize<W: Write>(&self, out: &mut W) -> GenResult<()> {
out.write_all(&[*self])?;
Ok(())
}
}
impl Serializable for u32 {
fn wire_size(&self) -> GenResult<SubunitNumber> {
SubunitNumber::new(4)
}
fn serialize<W: Write>(&self, out: &mut W) -> GenResult<()> {
out.write_all(&self.to_be_bytes())?;
Ok(())
}
}
impl Serializable for String {
fn wire_size(&self) -> GenResult<SubunitNumber> {
self.len() + SubunitNumber::new(self.len() as u32)?.wire_size()?
}
fn serialize<W: Write>(&self, out: &mut W) -> GenResult<()> {
SubunitNumber::try_from(self.len())?.serialize(out)?;
out.write_all(self.as_bytes())?;
Ok(())
}
}
pub struct Writer<'a, W> {
buffer: &'a mut W,
hasher: Hasher,
}
impl<'a, W> Writer<'a, W>
where
W: Write,
{
pub(crate) fn new(buffer: &'a mut W) -> Self {
Writer {
buffer,
hasher: Hasher::new(),
}
}
pub(crate) fn finalize(self) -> u32 {
self.hasher.finalize()
}
}
impl<W> Write for Writer<'_, W>
where
W: Write,
{
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.hasher.update(buf);
self.buffer.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.buffer.flush()
}
}