use alloc::vec::Vec;
pub trait Parse<'a>: Sized {
type Error;
fn parse(bytes: &'a [u8]) -> Result<Self, Self::Error>;
}
pub trait Serialize {
type Error;
fn serialized_len(&self) -> usize;
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, Self::Error>;
fn try_to_bytes(&self) -> Result<Vec<u8>, Self::Error> {
let mut v = alloc::vec![0u8; self.serialized_len()];
let written = self.serialize_into(&mut v)?;
if written != v.len() {
v.truncate(written);
}
Ok(v)
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::fmt;
#[derive(Debug, PartialEq)]
struct TestError;
impl fmt::Display for TestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("test serializer error")
}
}
struct Flagged {
fail: bool,
written: usize,
}
impl Serialize for Flagged {
type Error = TestError;
fn serialized_len(&self) -> usize {
4
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if self.fail {
return Err(TestError);
}
let n = self.written.min(buf.len());
buf[..n].copy_from_slice(&[1, 2, 3, 4][..n]);
Ok(n)
}
}
#[test]
fn try_to_bytes_returns_serializer_error() {
assert_eq!(
Flagged {
fail: true,
written: 0
}
.try_to_bytes(),
Err(TestError)
);
}
#[test]
fn try_to_bytes_truncates_when_serializer_writes_less_than_promised() {
let v = Flagged {
fail: false,
written: 3,
}
.try_to_bytes()
.unwrap();
assert_eq!(v, vec![1, 2, 3]);
}
#[test]
fn try_to_bytes_happy_path_fills_buffer() {
let ok = Flagged {
fail: false,
written: 4,
};
assert_eq!(ok.try_to_bytes().unwrap(), vec![1, 2, 3, 4]);
}
}