use crate::base::*;
use crate::error::Error;
use crate::io::blocking_impl::*;
use crate::*;
pub trait Element: Sized {
const ID: VInt64;
const HAS_DEFAULT_VALUE: bool = false;
fn decode_body<B: Buf>(buf: &mut B) -> crate::Result<Self>;
fn encode_body<B: BufMut>(&self, buf: &mut B) -> crate::Result<()>;
}
impl<T: Element> Decode for T {
fn decode<B: Buf>(buf: &mut B) -> crate::Result<Self> {
let header = Header::decode(buf)?;
let body_size = *header.size as usize;
if buf.remaining() < body_size {
return Err(Error::try_get_error(body_size, buf.remaining()));
}
let mut body = &buf.chunk()[..body_size];
let element = match T::decode_body(&mut body) {
Ok(e) => e,
Err(Error::TryGetError(_)) => return Err(Error::OverDecode(Self::ID)),
Err(Error::ShortRead) => return Err(Error::UnderDecode(Self::ID)),
Err(e) => return Err(e),
};
if body.has_remaining() {
return Err(Error::UnderDecode(Self::ID));
}
buf.advance(body_size);
Ok(element)
}
}
impl<T: Element> Encode for T {
fn encode<B: BufMut>(&self, buf: &mut B) -> crate::Result<()> {
let mut body_buf = Vec::new();
self.encode_body(&mut body_buf)?;
let header = Header {
id: T::ID,
size: VInt64::new(body_buf.len() as u64),
};
header.encode(buf)?;
buf.put_slice(&body_buf);
Ok(())
}
}
impl<T: Element> ReadFrom for T {
fn read_from<R: std::io::Read + ?Sized>(r: &mut R) -> crate::Result<Self> {
let header = Header::read_from(r)?;
let body = header.read_body(r)?;
let element = match T::decode_body(&mut &body[..]) {
Ok(e) => e,
Err(Error::TryGetError(_)) => return Err(Error::OverDecode(Self::ID)),
Err(Error::ShortRead) => return Err(Error::UnderDecode(Self::ID)),
Err(e) => return Err(e),
};
Ok(element)
}
}
#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
impl<T: Element> crate::io::tokio_impl::AsyncReadFrom for T {
async fn async_read_from<R: tokio::io::AsyncRead + Unpin + ?Sized>(
r: &mut R,
) -> crate::Result<Self> {
let header = Header::async_read_from(r).await?;
let body = header.read_body_tokio(r).await?;
let element = match T::decode_body(&mut &body[..]) {
Ok(e) => e,
Err(Error::TryGetError(_)) => return Err(Error::OverDecode(Self::ID)),
Err(Error::ShortRead) => return Err(Error::UnderDecode(Self::ID)),
Err(e) => return Err(e),
};
Ok(element)
}
}