#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::mem::size_of;
use crate::{errors::ZeroCopyError, traits::ZeroCopyAtMut};
pub trait ZeroCopyNew<'a>
where
Self: Sized,
{
type ZeroCopyConfig;
type Output;
fn byte_len(config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError>;
fn new_zero_copy(
bytes: &'a mut [u8],
config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError>;
}
impl<'a, T> ZeroCopyNew<'a> for Option<T>
where
T: ZeroCopyNew<'a>,
{
type ZeroCopyConfig = (bool, T::ZeroCopyConfig); type Output = Option<T::Output>;
fn byte_len(config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
let (enabled, inner_config) = config;
if *enabled {
let inner_len = T::byte_len(inner_config)?;
inner_len.checked_add(1).ok_or(ZeroCopyError::Size)
} else {
Ok(1)
}
}
fn new_zero_copy(
bytes: &'a mut [u8],
config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
if bytes.is_empty() {
return Err(ZeroCopyError::ArraySize(1, bytes.len()));
}
let (enabled, inner_config) = config;
if enabled {
bytes[0] = 1; let (_, bytes) = bytes.split_at_mut(1);
let (value, bytes) = T::new_zero_copy(bytes, inner_config)?;
Ok((Some(value), bytes))
} else {
bytes[0] = 0; let (_, bytes) = bytes.split_at_mut(1);
Ok((None, bytes))
}
}
}
impl<'a> ZeroCopyNew<'a> for u64 {
type ZeroCopyConfig = ();
type Output = zerocopy::Ref<&'a mut [u8], zerocopy::little_endian::U64>;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<zerocopy::little_endian::U64>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
Ok(zerocopy::Ref::<&mut [u8], zerocopy::little_endian::U64>::from_prefix(bytes)?)
}
}
impl<'a> ZeroCopyNew<'a> for u32 {
type ZeroCopyConfig = ();
type Output = zerocopy::Ref<&'a mut [u8], zerocopy::little_endian::U32>;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<zerocopy::little_endian::U32>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
Ok(zerocopy::Ref::<&mut [u8], zerocopy::little_endian::U32>::from_prefix(bytes)?)
}
}
impl<'a> ZeroCopyNew<'a> for u16 {
type ZeroCopyConfig = ();
type Output = zerocopy::Ref<&'a mut [u8], zerocopy::little_endian::U16>;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<zerocopy::little_endian::U16>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
Ok(zerocopy::Ref::<&mut [u8], zerocopy::little_endian::U16>::from_prefix(bytes)?)
}
}
impl<'a> ZeroCopyNew<'a> for u8 {
type ZeroCopyConfig = ();
type Output = <Self as crate::traits::ZeroCopyAtMut<'a>>::ZeroCopyAtMut;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<u8>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
<Self as ZeroCopyAtMut<'a>>::zero_copy_at_mut(bytes)
}
}
impl<'a> ZeroCopyNew<'a> for bool {
type ZeroCopyConfig = ();
type Output = <u8 as crate::traits::ZeroCopyAtMut<'a>>::ZeroCopyAtMut;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<u8>()) }
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
<u8 as ZeroCopyAtMut<'a>>::zero_copy_at_mut(bytes)
}
}
impl<
'a,
T: Copy + Default + zerocopy::KnownLayout + zerocopy::Immutable + zerocopy::FromBytes,
const N: usize,
> ZeroCopyNew<'a> for [T; N]
{
type ZeroCopyConfig = ();
type Output = <Self as crate::traits::ZeroCopyAtMut<'a>>::ZeroCopyAtMut;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<Self>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
<Self as ZeroCopyAtMut<'a>>::zero_copy_at_mut(bytes)
}
}
impl<'a> ZeroCopyNew<'a> for zerocopy::little_endian::U16 {
type ZeroCopyConfig = ();
type Output = zerocopy::Ref<&'a mut [u8], zerocopy::little_endian::U16>;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<zerocopy::little_endian::U16>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
Ok(zerocopy::Ref::<&mut [u8], zerocopy::little_endian::U16>::from_prefix(bytes)?)
}
}
impl<'a> ZeroCopyNew<'a> for zerocopy::little_endian::U32 {
type ZeroCopyConfig = ();
type Output = zerocopy::Ref<&'a mut [u8], zerocopy::little_endian::U32>;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<zerocopy::little_endian::U32>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
Ok(zerocopy::Ref::<&mut [u8], zerocopy::little_endian::U32>::from_prefix(bytes)?)
}
}
impl<'a> ZeroCopyNew<'a> for zerocopy::little_endian::U64 {
type ZeroCopyConfig = ();
type Output = zerocopy::Ref<&'a mut [u8], zerocopy::little_endian::U64>;
fn byte_len(_config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
Ok(size_of::<zerocopy::little_endian::U64>())
}
fn new_zero_copy(
bytes: &'a mut [u8],
_config: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
Ok(zerocopy::Ref::<&mut [u8], zerocopy::little_endian::U64>::from_prefix(bytes)?)
}
}
#[cfg(feature = "alloc")]
impl<'a, T: ZeroCopyNew<'a>> ZeroCopyNew<'a> for Vec<T> {
type ZeroCopyConfig = Vec<T::ZeroCopyConfig>; type Output = Vec<T::Output>;
fn byte_len(config: &Self::ZeroCopyConfig) -> Result<usize, ZeroCopyError> {
let mut total = 4usize;
for element_config in config {
let element_len = T::byte_len(element_config)?;
total = total.checked_add(element_len).ok_or(ZeroCopyError::Size)?;
}
Ok(total)
}
fn new_zero_copy(
bytes: &'a mut [u8],
configs: Self::ZeroCopyConfig,
) -> Result<(Self::Output, &'a mut [u8]), ZeroCopyError> {
use zerocopy::{little_endian::U32, Ref};
let len = configs.len() as u32;
let (mut len_ref, mut bytes) = Ref::<&mut [u8], U32>::from_prefix(bytes)?;
*len_ref = U32::new(len);
let mut items = Vec::with_capacity(configs.len());
for config in configs {
let (item, remaining_bytes) = T::new_zero_copy(bytes, config)?;
bytes = remaining_bytes;
items.push(item);
}
Ok((items, bytes))
}
}