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