pub mod slices;
pub use slices::*;
use crate::prelude::*;
pub(crate) fn prepare_payload<'a, T>(
payload: &'a T,
ctx: &mut T::Context<'_>,
) -> std::io::Result<(PayloadHeader, EncodedPayload<'a>)>
where
T: PayloadSignature + PayloadEncoded,
{
let body = payload.encoded(ctx)?;
let len = body.len();
if len > u32::MAX as usize {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Size of payload cannot be bigger {} bytes", u32::MAX),
));
}
let mut hasher = crc32fast::Hasher::new();
hasher.update(body.as_slice());
let header = PayloadHeader {
sig: payload.sig(),
crc: ByteBlock::Len4(hasher.finalize().to_le_bytes()),
len: len as u32,
};
Ok((header, body))
}
pub trait WriteTo {
fn write<T: std::io::Write>(&self, buf: &mut T) -> std::io::Result<usize>;
fn write_all<T: std::io::Write>(&self, buf: &mut T) -> std::io::Result<()>;
}
pub trait WriteMutTo: PayloadSchema {
fn write<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<usize>;
fn write_all<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<()>;
}
pub trait WriteVectoredTo {
fn write_vectored<T: std::io::Write>(&self, buf: &mut T) -> std::io::Result<usize> {
buf.write_vectored(&self.slices()?.get())
}
fn slices(&self) -> std::io::Result<IoSlices<'_>>;
fn write_vectored_all<T: std::io::Write>(&self, buf: &mut T) -> std::io::Result<()> {
self.slices()?.write_vectored_all(buf)
}
}
pub trait WriteVectoredMutTo: PayloadSchema {
fn write_vectored<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<usize> {
buf.write_vectored(&self.slices(ctx)?.get())
}
fn slices(
&mut self,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<IoSlices<'_>>;
fn write_vectored_all<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<()> {
self.slices(ctx)?.write_vectored_all(buf)
}
}
pub trait WritePayloadWithHeaderTo
where
Self: Sized
+ PayloadEncode
+ PayloadHooks
+ PayloadEncodeReferred
+ PayloadSignature
+ PayloadCrc
+ PayloadSize,
{
fn write<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<usize> {
let (header, body) = prepare_payload(self, ctx)?;
let header = header.as_vec();
buf.write_all(&header)?;
buf.write(body.as_slice()).map(|s| s + header.len())
}
fn write_all<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<()> {
let (header, body) = prepare_payload(self, ctx)?;
buf.write_all(&header.as_vec())?;
buf.write_all(body.as_slice())
}
}
pub trait WriteVectoredPayloadWithHeaderTo
where
Self:
Sized + PayloadEncode + PayloadEncodeReferred + PayloadSignature + PayloadCrc + PayloadSize,
{
fn write_vectored<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<usize> {
buf.write_vectored(&self.slices(ctx)?.get())
}
fn slices(
&mut self,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<IoSlices<'_>> {
let mut slices = IoSlices::default();
let (header, body) = prepare_payload(self, ctx)?;
let header = header.as_vec();
slices.add_buffered(header.to_vec());
match body {
EncodedPayload::Borrowed(bytes) => slices.add_slice(bytes),
EncodedPayload::Owned(bytes) => slices.add_buffered(bytes),
}
Ok(slices)
}
fn write_vectored_all<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<()> {
self.slices(ctx)?.write_vectored_all(buf)
}
}