const_generic_wrap/
lib.rs1#![no_std]
28#![cfg_attr(feature = "unstable", feature(const_evaluatable_checked))]
29#![cfg_attr(feature = "unstable", feature(const_generics))]
30
31use core::cmp::Ordering;
32pub(crate) use seal::*;
33mod seal {
34 pub trait WrapSeal {}
36 pub trait ConstableSeal {}
38}
39
40pub trait ConstWrap:
42 Clone + Copy + Default + Eq + core::hash::Hash + PartialEq + PartialOrd + Ord + WrapSeal
43{
44 type BaseType: Constable;
46 const VALUE: Self::BaseType;
48}
49
50pub trait ConstOrValue<T>: Into<T> {
52 const IS_CONST_WRAP: bool;
54}
55
56impl<T> ConstOrValue<T> for T {
57 const IS_CONST_WRAP: bool = false;
58}
59
60pub trait Constable: ConstableSeal {}
62
63pub trait ConstIntTypes: Constable {
65 type Zero: ConstWrap;
66 type One: ConstWrap;
67}
68
69#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
71pub struct MismatchConstError;
72
73macro_rules! wrap_impl {
74 ($tb: ty, $t : ident) => {
75 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
77 pub struct $t<const T: $tb>;
78 impl ConstableSeal for $tb{}
79 impl Constable for $tb {}
80 impl<const T: $tb> WrapSeal for $t<T>{}
81 impl<const T: $tb> ConstWrap for $t<T> {
82 type BaseType = $tb;
83 const VALUE : $tb = T;
84 }
85 impl<const T: $tb> ConstOrValue<$tb> for $t<T> {
86 const IS_CONST_WRAP : bool = true;
87 }
88 impl<const T: $tb> From<$t<T>> for $tb {
89 fn from(_ : $t<T>) -> $tb { T }
90 }
91 impl<'a, const T: $tb> From<$t<T>> for &'a $tb {
92 fn from(_ : $t<T>) -> &'a $tb { &T }
93 }
94 impl<const T: $tb> core::convert::TryFrom<$tb> for $t<T> {
95 type Error = MismatchConstError;
96 fn try_from(value : $tb) -> Result<$t<T>, MismatchConstError> {
97 if value == T {
98 Ok($t)
99 }else{
100 Err(MismatchConstError)
101 }
102 }
103 }
104 impl<const T: $tb> PartialEq<$tb> for $t<T> {
105 fn eq(&self, other: &$tb) -> bool { T.eq(other)}
106 }
107 impl<const T: $tb> PartialOrd<$tb> for $t<T> {
108 fn partial_cmp(&self, other: &$tb) -> Option<Ordering> { T.partial_cmp(other)}
109 }
110 };
111 [$(($tb: ty, $t : tt)),*$(,)*] => {
112 $(
113 wrap_impl!($tb, $t);
114 )*
115 };
116}
117
118wrap_impl![
119 (u8, WrapU8),
120 (u16, WrapU16),
121 (u32, WrapU32),
122 (u64, WrapU64),
123 (usize, WrapUSIZE),
124 (i8, WrapI8),
125 (i16, WrapI16),
126 (i32, WrapI32),
127 (i64, WrapI64),
128 (isize, WrapISIZE),
129 (bool, WrapBOOL),
130 (char, WrapCHAR),
131];
132
133macro_rules! wrap_impl_ints {
134 ($tb: ty, $t : ident) => {
135 impl ConstIntTypes for $tb{
136 type Zero = $t<0>;
137 type One = $t<1>;
138 }
139 };
140 [$(($tb: ty, $t : tt)),*$(,)*] => {
141 $(
142 wrap_impl_ints!($tb, $t);
143 )*
144 };
145}
146
147wrap_impl_ints![
148 (u8, WrapU8),
149 (u16, WrapU16),
150 (u32, WrapU32),
151 (u64, WrapU64),
152 (usize, WrapUSIZE),
153 (i8, WrapI8),
154 (i16, WrapI16),
155 (i32, WrapI32),
156 (i64, WrapI64),
157 (isize, WrapISIZE),
158];
159
160#[cfg(feature = "typenum")]
161mod typenum_bridge;
162
163#[cfg(test)]
164mod tests {
165
166 use crate::*;
167 #[test]
168 fn wrap_unwrap() {
169 let n3 = WrapI32::<3>;
170 assert_eq!(0, core::mem::size_of_val(&n3));
171 let m: i32 = n3.into();
172 assert_eq!(3, m);
173 }
174}