mod read;
mod sreader;
use crate::*;
pub use sreader::*;
pub struct PayloadHeader {
pub sig: ByteBlock,
pub crc: ByteBlock,
pub len: u32,
}
impl PayloadHeader {
pub fn new<T: PayloadSignature + PayloadSize + PayloadCrc>(
src: &T,
ctx: &mut T::Context<'_>,
) -> std::io::Result<Self> {
let len = src.size(ctx)?;
if len > u32::MAX as u64 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Size of payload cannot be bigger {} bytes", u32::MAX),
));
}
Ok(Self {
sig: src.sig(),
crc: src.crc(ctx)?,
len: len as u32,
})
}
pub fn payload_len(&self) -> usize {
self.len as usize
}
pub fn size(&self) -> usize {
1 + self.sig.size() + 1 + self.crc.size() + std::mem::size_of::<u32>()
}
pub fn ssize<T: PayloadSignature + PayloadSize + PayloadCrc>(
src: &T,
) -> std::io::Result<usize> {
Ok(1 + src.sig().size() + 1 + T::crc_size() + std::mem::size_of::<u32>())
}
pub fn as_vec(&self) -> Vec<u8> {
let sig = self.sig.as_slice();
let crc = self.crc.as_slice();
let mut buffer = Vec::new();
buffer.push(sig.len() as u8);
buffer.extend_from_slice(sig);
buffer.push(crc.len() as u8);
buffer.extend_from_slice(crc);
buffer.extend_from_slice(&self.len.to_le_bytes());
buffer
}
}
#[cfg(test)]
mod tests {
use crate::{
ByteBlock, PayloadCrc, PayloadEncode, PayloadEncodeReferred, PayloadHeader, PayloadHooks,
PayloadSchema, PayloadSignature, PayloadSize,
};
struct DemoPayload(Vec<u8>);
impl PayloadSchema for DemoPayload {
type Context<'a> = ();
}
impl PayloadHooks for DemoPayload {}
impl PayloadEncode for DemoPayload {
fn encode(&self, _: &mut Self::Context<'_>) -> std::io::Result<Vec<u8>> {
Ok(self.0.clone())
}
}
impl PayloadEncodeReferred for DemoPayload {
fn encode(&self, _: &mut Self::Context<'_>) -> std::io::Result<Option<&[u8]>> {
Ok(Some(self.0.as_slice()))
}
}
impl PayloadSignature for DemoPayload {
fn sig(&self) -> ByteBlock {
ByteBlock::Len4(*b"DEMO")
}
}
impl PayloadCrc for DemoPayload {}
impl PayloadSize for DemoPayload {}
#[test]
fn payload_header_new_size_ssize_and_as_vec() {
let payload = DemoPayload(vec![1, 2, 3, 4, 5]);
let mut ctx = ();
let header = PayloadHeader::new(&payload, &mut ctx).expect("header must be built");
assert_eq!(header.payload_len(), 5);
assert_eq!(header.sig.size(), 4);
assert_eq!(header.crc.size(), 4);
assert_eq!(
header.size(),
1 + header.sig.size() + 1 + header.crc.size() + std::mem::size_of::<u32>()
);
assert_eq!(
PayloadHeader::ssize(&payload).expect("ssize"),
1 + payload.sig().size() + 1 + DemoPayload::crc_size() + std::mem::size_of::<u32>()
);
let vec = header.as_vec();
assert_eq!(vec.len(), header.size());
assert_eq!(vec[0], 4); assert_eq!(&vec[1..5], b"DEMO");
assert_eq!(vec[5], 4); assert_eq!(&vec[vec.len() - 4..], &5_u32.to_le_bytes());
}
}