use std::{fmt::Debug, hash::Hash};
use crate::header::model::AddressHeader;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error)]
#[error(
"buffer too small for payload encoding: expected at least {expected_size} bytes, got {actual_size} bytes"
)]
pub struct BufferTooSmallError {
expected_size: usize,
actual_size: usize,
}
pub trait PayloadEncode: Debug + Send + Sync + PartialEq + PartialOrd + Hash {
fn required_size(&self, header_and_extensions_size: usize) -> usize;
unsafe fn encode_unchecked(
&self,
buf: &mut [u8],
address_header: &AddressHeader,
header_and_extensions_size: usize,
) -> usize;
#[inline]
fn try_encode(
&self,
buf: &mut [u8],
address_header: &AddressHeader,
header_and_extensions_size: usize,
) -> Result<usize, BufferTooSmallError> {
let required_size = self.required_size(header_and_extensions_size);
if buf.len() < required_size {
return Err(BufferTooSmallError {
expected_size: required_size,
actual_size: buf.len(),
});
}
Ok(unsafe { self.encode_unchecked(buf, address_header, header_and_extensions_size) })
}
fn wire_valid(&self) -> Result<(), crate::core::encode::InvalidStructureError>;
}
impl PayloadEncode for &[u8] {
#[inline]
fn required_size(&self, _header_and_extensions_size: usize) -> usize {
self.len()
}
#[inline]
unsafe fn encode_unchecked(
&self,
buf: &mut [u8],
_address_header: &AddressHeader,
_header_and_extensions_size: usize,
) -> usize {
unsafe {
std::ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
}
self.len()
}
#[inline]
fn wire_valid(&self) -> Result<(), crate::core::encode::InvalidStructureError> {
Ok(())
}
}
impl PayloadEncode for Vec<u8> {
#[inline]
fn required_size(&self, header_and_extensions_size: usize) -> usize {
self.as_slice().required_size(header_and_extensions_size)
}
#[inline]
unsafe fn encode_unchecked(
&self,
buf: &mut [u8],
address_header: &AddressHeader,
header_and_extensions_size: usize,
) -> usize {
unsafe {
self.as_slice()
.encode_unchecked(buf, address_header, header_and_extensions_size)
}
}
#[inline]
fn wire_valid(&self) -> Result<(), crate::core::encode::InvalidStructureError> {
self.as_slice().wire_valid()
}
}