use core::fmt;
use crate::util::Error;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct PayloadError<T> {
payload: T,
}
impl<T> PayloadError<T> {
#[inline]
pub fn into_payload(self) -> T {
self.payload
}
}
impl<T> fmt::Debug for PayloadError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("PayloadError").finish()
}
}
impl<T> fmt::Display for PayloadError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("payload too large")
}
}
impl<T> Error for PayloadError<T> {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Payload<T>(T);
impl<T> Payload<T> {
pub const MAX_LENGTH: usize = max_payload_length();
#[inline]
pub const unsafe fn new_unchecked(payload: T) -> Self {
Self(payload)
}
#[inline]
pub fn get(&self) -> &T {
&self.0
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
&mut self.0
}
#[inline]
pub fn into_inner(self) -> T {
self.0
}
#[inline]
pub fn as_ref(&self) -> Payload<&T> {
Payload(&self.0)
}
#[inline]
pub fn as_mut(&mut self) -> Payload<&mut T> {
Payload(&mut self.0)
}
}
impl<T: AsRef<[u8]>> Payload<T> {
#[inline]
pub fn new(payload: T) -> Result<Self, PayloadError<T>> {
if payload.as_ref().len() > Self::MAX_LENGTH {
Err(PayloadError { payload })
} else {
Ok(Self(payload))
}
}
#[inline]
pub fn as_slice(&self) -> &[u8] {
self.0.as_ref()
}
#[inline]
#[allow(clippy::cast_possible_truncation)]
pub fn length(&self) -> u32 {
self.as_slice().len() as u32
}
}
impl<T: AsRef<[u8]>> AsRef<[u8]> for Payload<T> {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
const fn max_payload_length() -> usize {
let a = u32::MAX as u64;
let b = usize::MAX as u64;
#[allow(clippy::cast_possible_truncation)]
if a <= b {
a as usize
} else {
b as usize
}
}