use super::*;
use serde::{Deserializer, Serializer};
macro_rules! always_valid {
($($elem: ty),*) => {
$(
unsafe impl <P> ValidCheck<P> for $elem {
const ALWAYS_VALID: bool = true;
}
)*
};
}
macro_rules! bit_counts {
($($num: ty = $count: literal),*) => {
$(
unsafe impl BitCount for $num {
const COUNT: usize = $count;
}
)*
};
}
bit_counts!(u8 = 8, u16 = 16, u32 = 32, u64 = 64, u128 = 128, bool = 1);
macro_rules! impl_field_storage {
($(($type:ty, $base:ty)),+ $(,)?) => {
$(
impl FieldStorage for $type {
type StoredType = $base;
fn inner_raw(self) -> Self::StoredType {
self.into()
}
}
)+
};
}
impl_field_storage!(
(bool, u8),
(u8, Self),
(u16, Self),
(u32, Self),
(u64, Self),
(u128, Self),
);
macro_rules! impl_signed_field_storage {
($(($type:ty, $base:ty)),+ $(,)?) => {
$(
impl FieldStorage for $type {
type StoredType = $base;
fn inner_raw(self) -> Self::StoredType {
<$base>::from_le_bytes(self.to_le_bytes())
}
}
)+
};
}
impl_signed_field_storage!((i8, u8), (i16, u16), (i32, u32), (i64, u64), (i128, u128),);
always_valid!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool);
macro_rules! new_signed_types {
(
$($name: ident($count: literal, $inner: ty, $signed: ty)),*
) => {
$(
#[doc = concat!("An unsigned integer which contains ", stringify!($count), " bits")]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct $name($inner);
always_valid!($name);
impl serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.value().serialize(serializer)
}
}
impl <'de> serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let inner = <$signed>::deserialize(deserializer)?;
$name::new(inner).ok_or(serde::de::Error::custom("invalid size"))
}
}
impl PartialOrd for $name {
fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
self.value().partial_cmp(&other.value())
}
}
impl Ord for $name {
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
self.value().cmp(&other.value())
}
}
impl Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_fmt(format_args!("{}", self.value()))
}
}
impl Display for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_fmt(format_args!("{}", self.value()))
}
}
#[doc = concat!("Produce a value of type ", stringify!($name))]
#[doc = concat!("[`", stringify!($name), "::new`] function.")]
#[macro_export]
macro_rules! $name {
($value: expr) => {
{
const VALUE: $signed = $value;
const _: () = assert!(VALUE <= $crate::$name::MAX, "The provided value is too large");
const _: () = assert!(VALUE >= $crate::$name::MIN, "The provided value is too small");
let res: $name = unsafe {$crate::$name::new_unchecked(VALUE)};
res
}
};
}
unsafe impl BitCount for $name {
const COUNT: usize = $count;
}
num_traits!($name, $signed);
impl $name {
pub const unsafe fn new_unchecked(value: $signed) -> Self {
let unsigned_value = value as $inner;
if value >= 0 {
Self(unsigned_value)
} else {
let value = unsigned_value & Self::MAX_UNSIGNED;
Self(value | Self::POLARITY_FLAG)
}
}
pub fn new(value: $signed) -> Option<Self> {
if (Self::MIN..=Self::MAX).contains(&value) {
Some(unsafe {Self::new_unchecked(value)})
} else {
None
}
}
const POLARITY_FLAG: $inner = (1 << ($count - 1));
const MAX_UNSIGNED: $inner = (1 << ($count-1)) - 1;
pub const MAX: $signed = Self::MAX_UNSIGNED as $signed;
pub const MIN: $signed = -(Self::MAX_UNSIGNED as $signed) - 1;
pub const fn value(self) -> $signed {
match self.0 >> ($count - 1) {
0 => self.0 as $signed,
_ => {
let rem = self.0 ^ Self::POLARITY_FLAG;
let amount = Self::MAX_UNSIGNED - rem;
-(amount as $signed) - 1
}
}
}
}
impl Default for $name {
fn default() -> Self {
Self(0)
}
}
impl FieldStorage for $name {
type StoredType = $inner;
fn inner_raw(self) -> Self::StoredType {
self.0
}
}
)*
};
}
macro_rules! num_traits {
($num:ident, $super_kind:ty) => {
impl Zero for $num {
fn zero() -> Self {
$num::new(0).unwrap()
}
fn is_zero(&self) -> bool {
self.0 == 0
}
}
impl Add for $num {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
$num::new(self.value() + rhs.value()).unwrap()
}
}
impl One for $num {
fn one() -> Self {
$num::new(1).unwrap()
}
}
impl Mul for $num {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
$num::new(self.value() * rhs.value()).unwrap()
}
}
impl Sub for $num {
type Output = $num;
fn sub(self, rhs: Self) -> Self::Output {
$num::new(self.value() - rhs.value()).unwrap()
}
}
impl Div for $num {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
$num::new(self.value() / rhs.value()).unwrap()
}
}
impl Rem for $num {
type Output = Self;
fn rem(self, rhs: Self) -> Self::Output {
$num::new(self.value() % rhs.value()).unwrap()
}
}
impl Num for $num {
type FromStrRadixErr = ();
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
let parse = <$super_kind>::from_str_radix(str, radix).map_err(|_| ())?;
$num::new(parse).ok_or(())
}
}
impl ::core::str::FromStr for $num {
type Err = <Self as Num>::FromStrRadixErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
<Self as Num>::from_str_radix(s, 10)
}
}
impl Shr<usize> for $num {
type Output = $num;
fn shr(self, rhs: usize) -> Self::Output {
$num::new(self.value() >> rhs).unwrap()
}
}
impl Shl<usize> for $num {
type Output = $num;
fn shl(self, rhs: usize) -> Self::Output {
$num::new(self.value() << rhs).unwrap()
}
}
impl ShrAssign<usize> for $num {
fn shr_assign(&mut self, rhs: usize) {
let got = *self >> rhs;
*self = got;
}
}
impl ShlAssign<usize> for $num {
fn shl_assign(&mut self, rhs: usize) {
let got = *self << rhs;
*self = got;
}
}
impl Bounded for $num {
fn min_value() -> Self {
$num::new(Self::MIN).unwrap()
}
fn max_value() -> Self {
$num::new(Self::MAX).unwrap()
}
}
impl BitAnd for $num {
type Output = $num;
fn bitand(self, rhs: Self) -> Self::Output {
$num(self.0 & rhs.0)
}
}
impl BitXor for $num {
type Output = $num;
fn bitxor(self, rhs: Self) -> Self::Output {
$num(self.0 ^ rhs.0)
}
}
impl BitXorAssign for $num {
fn bitxor_assign(&mut self, rhs: Self) {
self.0 ^= rhs.0
}
}
impl BitAndAssign for $num {
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0
}
}
impl BitOr for $num {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
$num(self.0 | rhs.0)
}
}
impl BitOrAssign for $num {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
};
}
macro_rules! new_unsigned_types {
(
$($name: ident($count: literal, $inner: ty)),*
) => {
$(
#[doc = concat!("An unsigned integer which contains ", stringify!($count), " bits")]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct $name($inner);
always_valid!($name);
impl Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_fmt(format_args!("{}", self.0))
}
}
impl Display for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_fmt(format_args!("{}", self.0))
}
}
impl serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.value().serialize(serializer)
}
}
impl <'de> serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let inner = <$inner>::deserialize(deserializer)?;
$name::new(inner).ok_or(serde::de::Error::custom("invalid size"))
}
}
#[doc = concat!("Produce a value of type ", stringify!($name))]
#[doc = concat!("[`", stringify!($name), "::new`] function.")]
#[macro_export]
macro_rules! $name {
($value: literal) => {
{
const VALUE: $inner = $value;
const _: () = assert!($crate::$name::MAX >= VALUE, "The provided value is too large");
unsafe {$crate::$name::new_unchecked(VALUE)}
}
};
}
unsafe impl BitCount for $name {
const COUNT: usize = $count;
}
impl $name {
pub const MAX: $inner = (1 << ($count)) - 1;
pub const MIN: $inner = 0;
#[doc = concat!("Create a new ", stringify!($name), " from an inner value")]
#[doc = concat!("use the [`", stringify!($name), "::new`] function.")]
pub const unsafe fn new_unchecked(value: $inner) -> Self {
Self(value)
}
#[doc = concat!("Create a new ", stringify!($name), " from an inner value")]
pub fn new(value: $inner) -> Option<Self> {
if (Self::MIN..=Self::MAX).contains(&value) {
Some(unsafe {Self::new_unchecked(value)})
} else {
None
}
}
pub const fn value(self) -> $inner {
self.0
}
}
impl Default for $name {
fn default() -> Self {
Self(0)
}
}
num_traits!($name, $inner);
impl FieldStorage for $name {
type StoredType = $inner;
fn inner_raw(self) -> Self::StoredType {
self.0
}
}
)*
};
}
new_signed_types!(
i2(2, u8, i8),
i3(3, u8, i8),
i4(4, u8, i8),
i5(5, u8, i8),
i6(6, u8, i8),
i7(7, u8, i8),
i9(9, u16, i16),
i10(10, u16, i16),
i11(11, u16, i16),
i12(12, u16, i16),
i13(13, u16, i16),
i14(14, u16, i16),
i15(15, u16, i16),
i17(17, u32, i32),
i18(18, u32, i32),
i19(19, u32, i32),
i20(20, u32, i32),
i21(21, u32, i32),
i22(22, u32, i32),
i23(23, u32, i32),
i24(24, u32, i32),
i25(25, u32, i32),
i26(26, u32, i32),
i27(27, u32, i32),
i28(28, u32, i32),
i29(29, u32, i32),
i30(30, u32, i32),
i31(31, u32, i32),
i33(33, u64, i64),
i34(34, u64, i64),
i35(35, u64, i64),
i36(36, u64, i64),
i37(37, u64, i64),
i38(38, u64, i64),
i39(39, u64, i64),
i40(40, u64, i64),
i41(41, u64, i64),
i42(42, u64, i64),
i43(43, u64, i64),
i44(44, u64, i64),
i45(45, u64, i64),
i46(46, u64, i64),
i47(47, u64, i64),
i48(48, u64, i64),
i49(49, u64, i64),
i50(50, u64, i64),
i51(51, u64, i64),
i52(52, u64, i64),
i53(53, u64, i64),
i54(54, u64, i64),
i55(55, u64, i64),
i56(56, u64, i64),
i57(57, u64, i64),
i58(58, u64, i64),
i59(59, u64, i64),
i60(60, u64, i64),
i61(61, u64, i64),
i62(62, u64, i64),
i63(63, u64, i64)
);
new_unsigned_types!(
u1(1, u8),
u2(2, u8),
u3(3, u8),
u4(4, u8),
u5(5, u8),
u6(6, u8),
u7(7, u8),
u9(9, u16),
u10(10, u16),
u11(11, u16),
u12(12, u16),
u13(13, u16),
u14(14, u16),
u15(15, u16),
u17(17, u32),
u18(18, u32),
u19(19, u32),
u20(20, u32),
u21(21, u32),
u22(22, u32),
u23(23, u32),
u24(24, u32),
u25(25, u32),
u26(26, u32),
u27(27, u32),
u28(28, u32),
u29(29, u32),
u30(30, u32),
u31(31, u32),
u33(33, u64),
u34(34, u64),
u35(35, u64),
u36(36, u64),
u37(37, u64),
u38(38, u64),
u39(39, u64),
u40(40, u64),
u41(41, u64),
u42(42, u64),
u43(43, u64),
u44(44, u64),
u45(45, u64),
u46(46, u64),
u47(47, u64),
u48(48, u64),
u49(49, u64),
u50(50, u64),
u51(51, u64),
u52(52, u64),
u53(53, u64),
u54(54, u64),
u55(55, u64),
u56(56, u64),
u57(57, u64),
u58(58, u64),
u59(59, u64),
u60(60, u64),
u61(61, u64),
u62(62, u64),
u63(63, u64)
);
macro_rules! byte_from_impls {
($($kind: ident: $super_kind: ty)*) => {
$(
impl $kind {
const ARR_SIZE: usize = <$kind>::COUNT / 8;
const SUPER_BYTES: usize = ::core::mem::size_of::<$super_kind>();
pub fn from_be_bytes(bytes: [u8; Self::ARR_SIZE]) -> Self {
let mut res_bytes = [0_u8; Self::SUPER_BYTES];
for (set, &get) in res_bytes.iter_mut().rev().zip(bytes.iter().rev()) {
*set = get;
}
Self(<$super_kind>::from_be_bytes(res_bytes))
}
pub fn to_be_bytes(self) -> [u8; Self::ARR_SIZE] {
let mut res = [0; Self::ARR_SIZE];
let inner_bytes = self.0.to_be_bytes();
for (&get, set) in inner_bytes.iter().rev().zip(res.iter_mut().rev()) {
*set = get;
}
res
}
pub fn from_le_bytes(bytes: [u8; Self::ARR_SIZE]) -> Self {
let mut res_bytes = [0_u8; Self::SUPER_BYTES];
for (set, &get) in res_bytes.iter_mut().zip(bytes.iter()) {
*set = get;
}
Self(<$super_kind>::from_le_bytes(res_bytes))
}
pub fn to_le_bytes(self) -> [u8; Self::ARR_SIZE] {
let mut res = [0; Self::ARR_SIZE];
let inner_bytes = self.0.to_le_bytes();
for (&get, set) in inner_bytes.iter().zip(res.iter_mut()) {
*set = get;
}
res
}
}
impl From<u8> for $kind {
fn from(byte: u8) -> Self {
let inner = <$super_kind>::from(byte);
$kind(inner)
}
}
)*
};
}
byte_from_impls! {
u24: u32
u40: u64
u48: u64
u56: u64
i24: u32
i40: u64
i48: u64
i56: u64
}
impl u1 {
pub const TRUE: Self = Self(1);
pub const FALSE: Self = Self(0);
#[must_use]
pub const fn toggle(self) -> Self {
match self {
Self::FALSE => Self::TRUE,
_ => Self::FALSE,
}
}
}
macro_rules! bits_fit_in_impl {
($basety:ty => $target:ty : from) => {
impl BitsFitIn<$target> for $basety {
fn fit(self) -> $target {
self.inner_raw().into()
}
}
};
($basety:ty => $target:ty : new_unchecked) => {
impl BitsFitIn<$target> for $basety {
fn fit(self) -> $target {
unsafe { <$target>::new_unchecked(self.inner_raw().into()) }
}
}
};
}
macro_rules! bits_fit_in_impls {
() => {};
(
// The types we generate from in this pass
($basety:ty: $funcname:ident, $extra_ty:ty)
$( ,
($first_target:ty: $target_funcname:ident $(, $extra_sources:ty)* $(,)?)
)* $(,)?
) => {
bits_fit_in_impl!($basety => $basety: $funcname);
$(
bits_fit_in_impl!($basety => $first_target: $target_funcname);
bits_fit_in_impl!($extra_ty => $first_target: $target_funcname);
)*
bits_fit_in_impls!($(($first_target: $target_funcname $(, $extra_sources)*)),*);
}
}
bits_fit_in_impls!(
(u1: new_unchecked, bool),
(u2: new_unchecked, i2),
(u3: new_unchecked, i3),
(u4: new_unchecked, i4),
(u5: new_unchecked, i5),
(u6: new_unchecked, i6),
(u7: new_unchecked, i7),
(u8: from, i8),
(u9: new_unchecked, i9),
(u10: new_unchecked, i10),
(u11: new_unchecked, i11),
(u12: new_unchecked, i12),
(u13: new_unchecked, i13),
(u14: new_unchecked, i14),
(u15: new_unchecked, i15),
(u16: from, i16),
(u17: new_unchecked, i17),
(u18: new_unchecked, i18),
(u19: new_unchecked, i19),
(u20: new_unchecked, i20),
(u21: new_unchecked, i21),
(u22: new_unchecked, i22),
(u23: new_unchecked, i23),
(u24: new_unchecked, i24),
(u25: new_unchecked, i25),
(u26: new_unchecked, i26),
(u27: new_unchecked, i27),
(u28: new_unchecked, i28),
(u29: new_unchecked, i29),
(u30: new_unchecked, i30),
(u31: new_unchecked, i31),
(u32: from, i32),
(u33: new_unchecked, i33),
(u34: new_unchecked, i34),
(u35: new_unchecked, i35),
(u36: new_unchecked, i36),
(u37: new_unchecked, i37),
(u38: new_unchecked, i38),
(u39: new_unchecked, i39),
(u40: new_unchecked, i40),
(u41: new_unchecked, i41),
(u42: new_unchecked, i42),
(u43: new_unchecked, i43),
(u44: new_unchecked, i44),
(u45: new_unchecked, i45),
(u46: new_unchecked, i46),
(u47: new_unchecked, i47),
(u48: new_unchecked, i48),
(u49: new_unchecked, i49),
(u50: new_unchecked, i50),
(u51: new_unchecked, i51),
(u52: new_unchecked, i52),
(u53: new_unchecked, i53),
(u54: new_unchecked, i54),
(u55: new_unchecked, i55),
(u56: new_unchecked, i56),
(u57: new_unchecked, i57),
(u58: new_unchecked, i58),
(u59: new_unchecked, i59),
(u60: new_unchecked, i60),
(u61: new_unchecked, i61),
(u62: new_unchecked, i62),
(u63: new_unchecked, i63),
(u64: from, i64),
);