use bytes::{Buf, BufMut};
use crate::coding::{Decode, DecodeError, Encode, EncodeError, Sizer};
use super::Version;
pub trait Message: Sized + std::fmt::Debug {
const ID: u64;
fn encode_msg<W: BufMut>(&self, w: &mut W, version: Version) -> Result<(), EncodeError>;
fn decode_msg<B: Buf>(buf: &mut B, version: Version) -> Result<Self, DecodeError>;
}
impl<T: Message> Encode<Version> for T {
fn encode<W: BufMut>(&self, w: &mut W, version: Version) -> Result<(), EncodeError> {
let mut sizer = Sizer::default();
self.encode_msg(&mut sizer, version)?;
let size: u16 = sizer.size.try_into().map_err(|_| EncodeError::TooLarge)?;
size.encode(w, version)?;
self.encode_msg(w, version)
}
}
impl<T: Message> Decode<Version> for T {
fn decode<B: Buf>(buf: &mut B, version: Version) -> Result<Self, DecodeError> {
let size = u16::decode(buf, version)? as usize;
let mut limited = buf.take(size);
let result = Self::decode_msg(&mut limited, version)?;
if limited.remaining() > 0 {
return Err(DecodeError::Long);
}
Ok(result)
}
}