#![no_std]
#![cfg_attr(feature = "unstable", feature(const_evaluatable_checked))]
#![cfg_attr(feature = "unstable", feature(const_generics))]
use core::cmp::Ordering;
pub(crate) use seal::*;
mod seal {
pub trait WrapSeal {}
pub trait ConstableSeal {}
}
pub trait ConstWrap:
Clone + Copy + Default + Eq + core::hash::Hash + PartialEq + PartialOrd + Ord + WrapSeal
{
type BaseType: Constable;
const VALUE: Self::BaseType;
}
pub trait ConstOrValue<T>: Into<T> {
const IS_CONST_WRAP: bool;
}
impl<T> ConstOrValue<T> for T {
const IS_CONST_WRAP: bool = false;
}
pub trait Constable: ConstableSeal {}
pub trait ConstIntTypes: Constable {
type Zero: ConstWrap;
type One: ConstWrap;
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct MismatchConstError;
macro_rules! wrap_impl {
($tb: ty, $t : ident) => {
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct $t<const T: $tb>;
impl ConstableSeal for $tb{}
impl Constable for $tb {}
impl<const T: $tb> WrapSeal for $t<T>{}
impl<const T: $tb> ConstWrap for $t<T> {
type BaseType = $tb;
const VALUE : $tb = T;
}
impl<const T: $tb> ConstOrValue<$tb> for $t<T> {
const IS_CONST_WRAP : bool = true;
}
impl<const T: $tb> From<$t<T>> for $tb {
fn from(_ : $t<T>) -> $tb { T }
}
impl<'a, const T: $tb> From<$t<T>> for &'a $tb {
fn from(_ : $t<T>) -> &'a $tb { &T }
}
impl<const T: $tb> core::convert::TryFrom<$tb> for $t<T> {
type Error = MismatchConstError;
fn try_from(value : $tb) -> Result<$t<T>, MismatchConstError> {
if value == T {
Ok($t)
}else{
Err(MismatchConstError)
}
}
}
impl<const T: $tb> PartialEq<$tb> for $t<T> {
fn eq(&self, other: &$tb) -> bool { T.eq(other)}
}
impl<const T: $tb> PartialOrd<$tb> for $t<T> {
fn partial_cmp(&self, other: &$tb) -> Option<Ordering> { T.partial_cmp(other)}
}
};
[$(($tb: ty, $t : tt)),*$(,)*] => {
$(
wrap_impl!($tb, $t);
)*
};
}
wrap_impl![
(u8, WrapU8),
(u16, WrapU16),
(u32, WrapU32),
(u64, WrapU64),
(usize, WrapUSIZE),
(i8, WrapI8),
(i16, WrapI16),
(i32, WrapI32),
(i64, WrapI64),
(isize, WrapISIZE),
(bool, WrapBOOL),
(char, WrapCHAR),
];
macro_rules! wrap_impl_ints {
($tb: ty, $t : ident) => {
impl ConstIntTypes for $tb{
type Zero = $t<0>;
type One = $t<1>;
}
};
[$(($tb: ty, $t : tt)),*$(,)*] => {
$(
wrap_impl_ints!($tb, $t);
)*
};
}
wrap_impl_ints![
(u8, WrapU8),
(u16, WrapU16),
(u32, WrapU32),
(u64, WrapU64),
(usize, WrapUSIZE),
(i8, WrapI8),
(i16, WrapI16),
(i32, WrapI32),
(i64, WrapI64),
(isize, WrapISIZE),
];
#[cfg(feature = "typenum")]
mod typenum_bridge;
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn wrap_unwrap() {
let n3 = WrapI32::<3>;
assert_eq!(0, core::mem::size_of_val(&n3));
let m: i32 = n3.into();
assert_eq!(3, m);
}
}