use crate::project::Projectable;
macro_rules! le_integer {
(
$(#[$meta:meta])*
$name:ident, $native:ty, $size:expr, unsigned
) => {
$(#[$meta])*
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
pub struct $name([u8; $size]);
impl $name {
pub const ZERO: Self = Self([0; $size]);
pub const MAX: Self = Self(<$native>::MAX.to_le_bytes());
#[inline(always)]
pub const fn new(v: $native) -> Self {
Self(v.to_le_bytes())
}
#[inline(always)]
pub const fn get(self) -> $native {
<$native>::from_le_bytes(self.0)
}
#[inline(always)]
pub const fn to_le_bytes(self) -> [u8; $size] {
self.0
}
#[inline(always)]
pub const fn from_le_bytes(bytes: [u8; $size]) -> Self {
Self(bytes)
}
#[inline(always)]
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
match self.get().checked_add(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
match self.get().checked_sub(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
match self.get().checked_mul(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_div(self, rhs: Self) -> Option<Self> {
match self.get().checked_div(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn saturating_add(self, rhs: Self) -> Self {
Self::new(self.get().saturating_add(rhs.get()))
}
#[inline(always)]
pub const fn saturating_sub(self, rhs: Self) -> Self {
Self::new(self.get().saturating_sub(rhs.get()))
}
#[inline(always)]
pub const fn wrapping_add(self, rhs: Self) -> Self {
Self::new(self.get().wrapping_add(rhs.get()))
}
#[inline(always)]
pub const fn wrapping_sub(self, rhs: Self) -> Self {
Self::new(self.get().wrapping_sub(rhs.get()))
}
#[inline(always)]
pub const fn is_zero(self) -> bool {
self.get() == 0
}
}
impl From<$native> for $name {
#[inline(always)]
fn from(v: $native) -> Self { Self::new(v) }
}
impl From<$name> for $native {
#[inline(always)]
fn from(v: $name) -> Self { v.get() }
}
impl PartialOrd for $name {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for $name {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.get().cmp(&other.get())
}
}
impl core::fmt::Debug for $name {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}({})", stringify!($name), self.get())
}
}
impl core::fmt::Display for $name {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.get())
}
}
unsafe impl Projectable for $name {}
$crate::__wire_arith_ops!($name, $native);
};
(
$(#[$meta:meta])*
$name:ident, $native:ty, $size:expr, signed
) => {
$(#[$meta])*
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
pub struct $name([u8; $size]);
impl $name {
pub const ZERO: Self = Self([0; $size]);
pub const MAX: Self = Self(<$native>::MAX.to_le_bytes());
pub const MIN: Self = Self(<$native>::MIN.to_le_bytes());
#[inline(always)]
pub const fn new(v: $native) -> Self {
Self(v.to_le_bytes())
}
#[inline(always)]
pub const fn get(self) -> $native {
<$native>::from_le_bytes(self.0)
}
#[inline(always)]
pub const fn to_le_bytes(self) -> [u8; $size] {
self.0
}
#[inline(always)]
pub const fn from_le_bytes(bytes: [u8; $size]) -> Self {
Self(bytes)
}
#[inline(always)]
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
match self.get().checked_add(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
match self.get().checked_sub(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
match self.get().checked_mul(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_div(self, rhs: Self) -> Option<Self> {
match self.get().checked_div(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn saturating_add(self, rhs: Self) -> Self {
Self::new(self.get().saturating_add(rhs.get()))
}
#[inline(always)]
pub const fn saturating_sub(self, rhs: Self) -> Self {
Self::new(self.get().saturating_sub(rhs.get()))
}
#[inline(always)]
pub const fn is_zero(self) -> bool {
self.get() == 0
}
#[inline(always)]
pub const fn is_negative(self) -> bool {
self.get() < 0
}
#[inline(always)]
pub const fn abs(self) -> Self {
Self::new(self.get().wrapping_abs())
}
}
impl From<$native> for $name {
#[inline(always)]
fn from(v: $native) -> Self { Self::new(v) }
}
impl From<$name> for $native {
#[inline(always)]
fn from(v: $name) -> Self { v.get() }
}
impl PartialOrd for $name {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for $name {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.get().cmp(&other.get())
}
}
impl core::fmt::Debug for $name {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}({})", stringify!($name), self.get())
}
}
impl core::fmt::Display for $name {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.get())
}
}
unsafe impl Projectable for $name {}
$crate::__wire_arith_ops!($name, $native);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __wire_arith_ops {
($name:ident, $native:ty) => {
impl core::ops::Add for $name {
type Output = Self;
#[inline(always)]
fn add(self, rhs: Self) -> Self {
Self::new(self.get() + rhs.get())
}
}
impl core::ops::Sub for $name {
type Output = Self;
#[inline(always)]
fn sub(self, rhs: Self) -> Self {
Self::new(self.get() - rhs.get())
}
}
impl core::ops::Mul for $name {
type Output = Self;
#[inline(always)]
fn mul(self, rhs: Self) -> Self {
Self::new(self.get() * rhs.get())
}
}
impl core::ops::Div for $name {
type Output = Self;
#[inline(always)]
fn div(self, rhs: Self) -> Self {
Self::new(self.get() / rhs.get())
}
}
impl core::ops::Rem for $name {
type Output = Self;
#[inline(always)]
fn rem(self, rhs: Self) -> Self {
Self::new(self.get() % rhs.get())
}
}
impl core::ops::Add<$native> for $name {
type Output = Self;
#[inline(always)]
fn add(self, rhs: $native) -> Self {
Self::new(self.get() + rhs)
}
}
impl core::ops::Sub<$native> for $name {
type Output = Self;
#[inline(always)]
fn sub(self, rhs: $native) -> Self {
Self::new(self.get() - rhs)
}
}
impl core::ops::Mul<$native> for $name {
type Output = Self;
#[inline(always)]
fn mul(self, rhs: $native) -> Self {
Self::new(self.get() * rhs)
}
}
impl core::ops::Div<$native> for $name {
type Output = Self;
#[inline(always)]
fn div(self, rhs: $native) -> Self {
Self::new(self.get() / rhs)
}
}
impl core::ops::Rem<$native> for $name {
type Output = Self;
#[inline(always)]
fn rem(self, rhs: $native) -> Self {
Self::new(self.get() % rhs)
}
}
impl core::ops::AddAssign for $name {
#[inline(always)]
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl core::ops::SubAssign for $name {
#[inline(always)]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl core::ops::MulAssign for $name {
#[inline(always)]
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl core::ops::DivAssign for $name {
#[inline(always)]
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
}
impl core::ops::RemAssign for $name {
#[inline(always)]
fn rem_assign(&mut self, rhs: Self) {
*self = *self % rhs;
}
}
impl core::ops::AddAssign<$native> for $name {
#[inline(always)]
fn add_assign(&mut self, rhs: $native) {
*self = *self + rhs;
}
}
impl core::ops::SubAssign<$native> for $name {
#[inline(always)]
fn sub_assign(&mut self, rhs: $native) {
*self = *self - rhs;
}
}
impl core::ops::MulAssign<$native> for $name {
#[inline(always)]
fn mul_assign(&mut self, rhs: $native) {
*self = *self * rhs;
}
}
impl core::ops::DivAssign<$native> for $name {
#[inline(always)]
fn div_assign(&mut self, rhs: $native) {
*self = *self / rhs;
}
}
impl core::ops::RemAssign<$native> for $name {
#[inline(always)]
fn rem_assign(&mut self, rhs: $native) {
*self = *self % rhs;
}
}
impl PartialEq<$native> for $name {
#[inline(always)]
fn eq(&self, other: &$native) -> bool {
self.get() == *other
}
}
impl PartialOrd<$native> for $name {
#[inline(always)]
fn partial_cmp(&self, other: &$native) -> Option<core::cmp::Ordering> {
Some(self.get().cmp(other))
}
}
};
}
le_integer! {
LeU64, u64, 8, unsigned
}
le_integer! {
LeU32, u32, 4, unsigned
}
le_integer! {
LeU16, u16, 2, unsigned
}
le_integer! {
LeI64, i64, 8, signed
}
le_integer! {
LeI32, i32, 4, signed
}
le_integer! {
LeI16, i16, 2, signed
}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
pub struct LeBool(u8);
impl LeBool {
pub const TRUE: Self = Self(1);
pub const FALSE: Self = Self(0);
#[inline(always)]
pub const fn new(v: bool) -> Self {
Self(v as u8)
}
#[inline(always)]
pub const fn get(self) -> bool {
self.0 != 0
}
#[inline(always)]
pub const fn raw(self) -> u8 {
self.0
}
#[inline(always)]
pub const fn is_canonical(self) -> bool {
self.0 == 0 || self.0 == 1
}
}
impl From<bool> for LeBool {
#[inline(always)]
fn from(v: bool) -> Self {
Self::new(v)
}
}
impl From<LeBool> for bool {
#[inline(always)]
fn from(v: LeBool) -> Self {
v.get()
}
}
impl core::fmt::Debug for LeBool {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "LeBool({})", self.get())
}
}
impl core::fmt::Display for LeBool {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.get())
}
}
unsafe impl Projectable for LeBool {}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
pub struct LeU128([u8; 16]);
impl LeU128 {
pub const ZERO: Self = Self([0; 16]);
pub const MAX: Self = Self(u128::MAX.to_le_bytes());
#[inline(always)]
pub const fn new(v: u128) -> Self {
Self(v.to_le_bytes())
}
#[inline(always)]
pub const fn get(self) -> u128 {
u128::from_le_bytes(self.0)
}
#[inline(always)]
pub const fn to_le_bytes(self) -> [u8; 16] {
self.0
}
#[inline(always)]
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
match self.get().checked_add(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
match self.get().checked_sub(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
match self.get().checked_mul(rhs.get()) {
Some(v) => Some(Self::new(v)),
None => None,
}
}
#[inline(always)]
pub const fn saturating_add(self, rhs: Self) -> Self {
Self::new(self.get().saturating_add(rhs.get()))
}
#[inline(always)]
pub const fn saturating_sub(self, rhs: Self) -> Self {
Self::new(self.get().saturating_sub(rhs.get()))
}
#[inline(always)]
pub const fn is_zero(self) -> bool {
self.get() == 0
}
}
impl From<u128> for LeU128 {
#[inline(always)]
fn from(v: u128) -> Self {
Self::new(v)
}
}
impl From<LeU128> for u128 {
#[inline(always)]
fn from(v: LeU128) -> Self {
v.get()
}
}
impl PartialOrd for LeU128 {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for LeU128 {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.get().cmp(&other.get())
}
}
impl core::fmt::Debug for LeU128 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "LeU128({})", self.get())
}
}
impl core::fmt::Display for LeU128 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.get())
}
}
unsafe impl Projectable for LeU128 {}
__wire_arith_ops!(LeU128, u128);