use taped::Tape;
use crate::{DecodeError, EncodeError, Read, Vec32, Write};
#[macro_export]
macro_rules! stream {
($($data:expr),* $(,)? => $dest:expr) => {
{
let mut result;
'cases: {
$(
result = $dest.write(&$data);
if result.is_err() {
break 'cases;
}
)*
}
result
}
};
}
pub trait Serialize: Sized {
fn encode(&self, dest: &mut Vec<u8>) -> Result<(), EncodeError>;
fn decode(src: &mut Tape<'_, u8>) -> Result<Self, DecodeError>;
}
impl Serialize for bool {
fn encode(&self, dest: &mut Vec<u8>) -> Result<(), EncodeError> {
dest.push(if *self { 1u8 } else { 0u8 });
Ok(())
}
fn decode(src: &mut Tape<'_, u8>) -> Result<Self, DecodeError> {
src.next()
.ok_or(DecodeError::Exhausted { pos: src.pos })
.map(|b| b == 1)
}
}
impl Serialize for String {
fn encode(&self, dest: &mut Vec<u8>) -> Result<(), EncodeError> {
let len = self.len();
#[cfg(target_pointer_width = "64")]
if len > u32::MAX as usize {
return Err(EncodeError::LengthExceedsPrefix {
prefix_size: 32,
len,
});
}
dest.write(&len)?;
dest.extend_from_slice(self.as_bytes());
Ok(())
}
fn decode(src: &mut Tape<'_, u8>) -> Result<Self, DecodeError> {
let start = src.pos;
let data = src.read::<Vec32<u8>>()?.into_inner();
String::from_utf8(data).map_err(|e| DecodeError::Other {
pos: start,
cause: format!("Invalid UTF-8 ({e})"),
})
}
}