use crate::stream::Writes;
use super::{CodecError, DataHeader, Format};
pub trait Encodable {
const FORMAT: Format;
fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError>;
#[inline(always)]
fn encode_header(
&self,
writer: &mut (impl WritesEncodable + ?Sized),
) -> Result<(), CodecError> {
match Self::FORMAT {
Format::Blob(_) => Ok(()),
Format::Data(format) => DataHeader { count: 1, format }.encode(writer),
Format::Fluid => {
unimplemented!("fluid formats must manually implement `encode_header`")
}
}
}
}
pub trait WritesEncodable: Writes {
fn write_data<T: Encodable + ?Sized>(&mut self, data: &T) -> Result<(), CodecError> {
data.encode_header(self)?;
data.encode(self)?;
Ok(())
}
}
impl<T: Writes + ?Sized> WritesEncodable for T {}
#[cfg(test)]
mod tests {
use super::*;
use crate::codec::tests::*;
#[test]
fn encodes() -> Result<(), CodecError> {
let mut bytes = Vec::new();
let test_data = TestData::default();
bytes.write_data(&DataHeader {
count: 1,
format: TestData::FORMAT.as_data_format(),
})?;
bytes.write_data(&test_data.num_a)?;
bytes.write_data(&test_data.num_b)?;
bytes.write_data(&test_data.text)?;
let mut expected = Vec::new();
encode_test_data(&mut expected);
assert_eq!(expected, bytes);
Ok(())
}
}