use crate::payload::EncodedPayload;
use crate::*;
impl<B: BlockDef, P: PayloadDef<Inner>, Inner: PayloadInnerDef> WriteMutTo
for PacketDef<B, P, Inner>
{
fn write<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<usize> {
let prepared_payload = if let Some(payload) = self.payload.as_ref() {
Some(prepare_payload(payload, ctx)?)
} else {
None
};
let payload_len = prepared_payload
.as_ref()
.map(|(header, body)| (header.size() + body.len()) as u64)
.unwrap_or(0);
let blocks_len: u64 = self.blocks.iter().map(|blk| blk.size()).sum();
let header =
PacketHeader::from_lengths(blocks_len, payload_len, prepared_payload.is_some());
let mut total = header.write(buf)?;
if total < PacketHeader::SIZE as usize {
return Ok(total);
}
for blk in self.blocks.iter() {
let size = blk.size() as usize;
let written = blk.write(buf)?;
if written < size {
return Ok(total + written);
}
total += written;
}
if let Some((payload_header, payload_body)) = prepared_payload.as_ref() {
let payload_header = payload_header.as_vec();
let written = buf.write(&payload_header)?;
if written < payload_header.len() {
return Ok(total + written);
}
total += written;
let written = buf.write(payload_body.as_slice())?;
if written < payload_body.len() {
return Ok(total + written);
}
total += written;
}
Ok(total)
}
fn write_all<T: std::io::Write>(
&mut self,
buf: &mut T,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<()> {
let prepared_payload = if let Some(payload) = self.payload.as_ref() {
Some(prepare_payload(payload, ctx)?)
} else {
None
};
let payload_len = prepared_payload
.as_ref()
.map(|(header, body)| (header.size() + body.len()) as u64)
.unwrap_or(0);
let blocks_len: u64 = self.blocks.iter().map(|blk| blk.size()).sum();
let header =
PacketHeader::from_lengths(blocks_len, payload_len, prepared_payload.is_some());
header.write_all(buf)?;
for blk in self.blocks.iter() {
blk.write_all(buf)?;
}
if let Some((payload_header, payload_body)) = prepared_payload.as_ref() {
buf.write_all(&payload_header.as_vec())?;
buf.write_all(payload_body.as_slice())?;
}
Ok(())
}
}
impl<B: BlockDef, P: PayloadDef<Inner>, Inner: PayloadInnerDef> WriteVectoredMutTo
for PacketDef<B, P, Inner>
{
fn slices(
&mut self,
ctx: &mut <Self as PayloadSchema>::Context<'_>,
) -> std::io::Result<IoSlices<'_>> {
let prepared_payload = if let Some(payload) = self.payload.as_ref() {
Some(prepare_payload(payload, ctx)?)
} else {
None
};
let payload_len = prepared_payload
.as_ref()
.map(|(header, body)| (header.size() + body.len()) as u64)
.unwrap_or(0);
let blocks_len: u64 = self.blocks.iter().map(|blk| blk.size()).sum();
let header =
PacketHeader::from_lengths(blocks_len, payload_len, prepared_payload.is_some());
let mut slices = IoSlices::default();
let mut header_bytes: Vec<u8> = Vec::new();
header.write_all(&mut header_bytes)?;
slices.add_buffered(header_bytes);
for blk in self.blocks.iter() {
slices.append(blk.slices()?);
}
if let Some((payload_header, payload_body)) = prepared_payload {
slices.add_buffered(payload_header.as_vec());
match payload_body {
EncodedPayload::Borrowed(bytes) => slices.add_slice(bytes),
EncodedPayload::Owned(bytes) => slices.add_buffered(bytes),
}
}
Ok(slices)
}
}