use crate::error::{CoerceError, CoerceErrorKind};
use crate::traits::ZeroCopy;
pub type DefaultSize = u32;
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
compile_error!("musli-zerocopy is only supported on 32, 64-bit platforms");
mod sealed {
pub trait Sealed {}
impl Sealed for u8 {}
impl Sealed for u16 {}
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
impl Sealed for u32 {}
#[cfg(target_pointer_width = "64")]
impl Sealed for u64 {}
impl Sealed for usize {}
}
pub trait Size
where
Self: 'static + Copy + ZeroCopy + self::sealed::Sealed,
{
#[doc(hidden)]
const ZERO: Self;
#[doc(hidden)]
const MAX: usize;
#[doc(hidden)]
const ONE: Self;
#[doc(hidden)]
const N2: Self;
#[doc(hidden)]
const N4: Self;
#[doc(hidden)]
const N8: Self;
#[doc(hidden)]
const N16: Self;
#[doc(hidden)]
fn eq(self, other: Self) -> bool;
#[inline(always)]
fn try_from<U>(other: U) -> Result<Self, CoerceError>
where
U: Size,
{
Self::try_from_usize(other.as_usize())
}
#[doc(hidden)]
fn wrapping_mul(self, other: Self) -> Self;
#[doc(hidden)]
fn checked_mul(self, other: Self) -> Option<Self>;
#[doc(hidden)]
fn checked_add(self, other: Self) -> Option<Self>;
#[doc(hidden)]
fn checked_sub(self, other: Self) -> Option<Self>;
fn from_usize(value: usize) -> Self;
fn try_from_usize(value: usize) -> Result<Self, CoerceError>;
#[doc(hidden)]
fn as_usize(self) -> usize;
#[doc(hidden)]
fn is_zero(self) -> bool;
}
macro_rules! impl_size {
($ty:ty) => {
#[doc = concat!("Size implementation for `", stringify!($ty), "`")]
#[doc = concat!("let max = ", stringify!($ty), "::MAX;")]
impl Size for $ty {
const ZERO: Self = 0;
const MAX: usize = <$ty>::MAX as usize;
const ONE: Self = 1;
const N2: Self = 2;
const N4: Self = 4;
const N8: Self = 8;
const N16: Self = 16;
#[inline(always)]
fn eq(self, other: Self) -> bool {
self == other
}
#[inline(always)]
fn wrapping_mul(self, other: Self) -> Self {
self.wrapping_mul(other)
}
#[inline(always)]
fn checked_mul(self, other: Self) -> Option<Self> {
self.checked_mul(other)
}
#[inline(always)]
fn checked_add(self, other: Self) -> Option<Self> {
self.checked_add(other)
}
#[inline(always)]
fn checked_sub(self, other: Self) -> Option<Self> {
self.checked_sub(other)
}
#[inline(always)]
fn from_usize(value: usize) -> Self {
debug_assert!(
value <= <$ty>::MAX as usize,
"Value {value} cannot be represented on this platform"
);
value as $ty
}
#[inline(always)]
fn try_from_usize(value: usize) -> Result<Self, CoerceError> {
if value > <$ty>::MAX as usize {
Err(CoerceError::new(CoerceErrorKind::LengthOverflow {
len: value,
size: <$ty>::MAX as usize,
}))
} else {
Ok(value as $ty)
}
}
#[inline(always)]
fn as_usize(self) -> usize {
debug_assert!(
<usize as TryFrom<_>>::try_from(self).is_ok(),
"Value {self} cannot be represented on this platform"
);
self as usize
}
#[inline(always)]
fn is_zero(self) -> bool {
self == 0
}
}
};
}
impl_size!(u8);
impl_size!(u16);
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
impl_size!(u32);
#[cfg(target_pointer_width = "64")]
impl_size!(u64);
impl_size!(usize);