Created
May 16, 2021 02:09
-
-
Save lachlansneff/fc2e30d7d68f1f399723581415d7c0b7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use core::{ | |
| ops::{Shr, ShrAssign, Shl, ShlAssign, BitOr, BitOrAssign}, | |
| hash::Hash, | |
| fmt, | |
| }; | |
| macro_rules! impl_uint { | |
| ($int_ty:ty: [$($bits:literal),*]) => { | |
| $( | |
| impl Uint for u<$bits> { | |
| type Inner = $int_ty; | |
| const MAX: $int_ty = ((1 as $int_ty) << $bits) - 1; | |
| const MIN: $int_ty = 0; | |
| } | |
| )* | |
| }; | |
| } | |
| impl_uint!(u8: [1, 2, 3, 4, 5, 6, 7, 8]); | |
| impl_uint!(u16: [9, 10, 11, 12, 13, 14, 15, 16]); | |
| #[allow(non_camel_case_types)] | |
| #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | |
| #[repr(transparent)] | |
| pub struct u<const N: usize>(<Self as Uint>::Inner) | |
| where | |
| Self: Uint; | |
| #[doc(hidden)] | |
| pub trait Uint { | |
| type Inner: | |
| Copy + Clone | |
| + PartialEq + Eq | |
| + PartialOrd + Ord | |
| + Hash | |
| + fmt::Debug + fmt::Display | |
| + fmt::UpperHex + fmt::LowerHex | |
| + fmt::Octal + fmt::Binary; | |
| const MAX: Self::Inner; | |
| const MIN: Self::Inner; | |
| } | |
| impl<const N: usize> u<N> where Self: Uint { | |
| /// The smallest value that can be represented by this integer type. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// assert_eq!(u::<6>::MIN, 0); | |
| /// ``` | |
| pub const MIN: Self = Self(<Self as Uint>::MIN); | |
| /// The largest value that can be represented by this integer type. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// assert_eq!(u::<6>::MAX, 0); | |
| /// ``` | |
| pub const MAX: Self = Self(<Self as Uint>::MAX); | |
| /// The size of this integer type in bits. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// assert_eq!(u::<6>::BITS, 6); | |
| /// ``` | |
| pub const BITS: u32 = N as u32; | |
| fn mask(self) -> Self { | |
| Self(self.0 & Self::MAX.0) | |
| } | |
| pub fn new(v: <Self as Uint>::Inner) -> Self { | |
| assert!(v <= Self::MAX.0, "value out of bounds"); | |
| Self(v) | |
| } | |
| pub fn wrapping_sub(self, rhs: Self) -> Self { | |
| Self(self.0.wrapping_sub(rhs.0)).mask() | |
| } | |
| pub fn wrapping_add(self, rhs: Self) -> Self { | |
| Self(self.0.wrapping_add(rhs.0)).mask() | |
| } | |
| } | |
| impl<const N: usize> fmt::Display for u<N> where Self: Uint { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| <Uint::Inner as fmt::Display>::fmt(&self.0, f) | |
| } | |
| } | |
| impl<const N: usize> fmt::Debug for u<N> where Self: Uint { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| <Uint::Inner as fmt::Debug>::fmt(&self.0, f) | |
| } | |
| } | |
| impl<const N: usize> fmt::LowerHex for u<N> where Self: Uint { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| <Uint::Inner as fmt::LowerHex>::fmt(&self.0, f) | |
| } | |
| } | |
| impl<const N: usize> fmt::UpperHex for u<N> where Self: Uint { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| <Uint::Inner as fmt::UpperHex>::fmt(&self.0, f) | |
| } | |
| } | |
| impl<const N: usize> fmt::Octal for u<N> where Self: Uint { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| <Uint::Inner as fmt::Octal>::fmt(&self.0, f) | |
| } | |
| } | |
| impl<const N: usize> fmt::Binary for u<N> where Self: Uint { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| <Uint::Inner as fmt::Binary>::fmt(&self.0, f) | |
| } | |
| } | |
| impl<T, const N: usize> Shr<T> for u<N> | |
| where | |
| Self: Uint, | |
| <Self as Uint>::Inner: Shr<T, Output=<Self as Uint>::Inner>, | |
| { | |
| type Output = Self; | |
| fn shr(self, rhs: T) -> Self { | |
| Self(self.0.shr(rhs)) | |
| } | |
| } | |
| impl<T, const N: usize> Shl<T> for u<N> | |
| where | |
| Self: Uint, | |
| <Self as Uint>::Inner: Shl<T, Output=<Self as Uint>::Inner>, | |
| { | |
| type Output = Self; | |
| fn shl(self, rhs: T) -> Self { | |
| Self(self.0.shl(rhs)).mask() | |
| } | |
| } | |
| impl<T, const N: usize> ShrAssign<T> for u<N> | |
| where | |
| Self: Uint, | |
| <Self as Uint>::Inner: ShrAssign<T>, | |
| { | |
| fn shr_assign(&mut self, rhs: T) { | |
| *self = *self >> rhs; | |
| } | |
| } | |
| impl<T, const N: usize> ShlAssign<T> for u<N> | |
| where | |
| Self: Uint, | |
| <Self as Uint>::Inner: ShlAssign<T>, | |
| { | |
| fn shl_assign(&mut self, rhs: T) { | |
| *self = (*self << rhs).mask(); | |
| } | |
| } | |
| fn main() { | |
| println!("{}", u::<6>::MAX); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment