1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
mod sealed {
#[doc(hidden)]
pub trait Sealed: Sized {}
}
use sealed::Sealed;
/// Converts a [`TStr`] to unsigned integers.
///
/// # Example
///
/// ```rust
/// use tstr::{ToUint, TS, ts};
///
/// type Zero = TS!(0);
/// type N8 = TS!(8);
/// type N13 = TS!(13);
/// type N15 = TS!(0xF);
/// type N16 = TS!(0b10000);
///
/// assert_eq!(Zero::USIZE, 0);
/// assert_eq!(N8::USIZE, 8);
/// assert_eq!(N13::USIZE, 13);
/// assert_eq!(N15::USIZE, 15);
/// assert_eq!(N16::USIZE, 16);
///
/// assert_eq!(ts!(0).to_u128(), 0);
/// assert_eq!(ts!(8).to_u128(), 8);
/// assert_eq!(ts!(13).to_u128(), 13);
/// assert_eq!(ts!(0xF).to_u128(), 15);
/// assert_eq!(ts!(0b10000).to_u128(), 16);
///
/// ```
///
/// [`TStr`]: ./struct.TStr.html
pub trait ToUint: Sized {
/// The `usize` value of the type.
///
/// By default this value is a saturated cast from `Self::U128`.
const USIZE: usize = u128_as_usize(Self::U128);
/// The `u128` value of the type.
const U128: u128;
#[doc(hidden)]
const DIGITS: u32;
/// Gets the usize value of this type
///
/// By default this value is a saturated cast from `Self::U128`.
fn to_usize(&self) -> usize {
Self::USIZE
}
/// Gets the u128 value of this type
fn to_u128(&self) -> u128 {
Self::U128
}
}
#[cfg(feature = "const_generics")]
macro_rules! impl_for_const {
() => {
const fn str_to_u128(s: &str) -> u128 {
let s = s.as_bytes();
let mut out = 0u128;
let mut index = 0usize;
while index < s.len() {
let digit = s[index];
// This has the effect of panicking on non to '0' to '9' characters.
#[allow(clippy::no_effect)]
["Expected all characters to be digits"]
[!(b'0' <= digit && digit <= b'9') as usize];
let digit = (digit - b'0') as u128;
out = out * 10 + digit;
index += 1;
}
out
}
impl<const N: &'static str> Sealed for crate::___<N> {}
impl<const N: &'static str> ToUint for crate::___<N> {
const U128: u128 = str_to_u128(N);
const DIGITS: u32 = N.len() as u32;
}
};
}
impl<T> Sealed for crate::TStr<T> where T: Sealed {}
impl<T> ToUint for crate::TStr<T>
where
T: ToUint,
{
// Intentionally not setting this.
// const USIZE: usize = T::USIZE;
const U128: u128 = T::U128;
const DIGITS: u32 = T::DIGITS;
}
#[cfg(feature = "const_generics")]
impl_for_const! {}
#[cfg(not(feature = "const_generics"))]
mod impl_no_const_generics;
const fn u128_as_usize(n: u128) -> usize {
const MAXU: u128 = usize::max_value() as u128;
[n, MAXU][(n > MAXU) as usize] as usize
}