1use core::fmt::{Debug, Display, Formatter};
7use core::hash::Hash;
8
9mod sealed;
10
11maybe_trait_bound!(
12 MaybeNumTrait,
13 cfg(feature = "num-traits"),
14 num_traits::PrimInt
15);
16maybe_trait_bound!(MaybePod, cfg(feature = "bytemuck"), bytemuck::Pod);
17maybe_trait_bound!(
18 MaybeContiguous,
19 cfg(feature = "bytemuck"),
20 bytemuck::Contiguous
21);
22#[doc(hidden)]
23pub trait ConvertPrimInts:
24 From<u8>
25 + TryFrom<u8>
26 + TryFrom<u16>
27 + TryFrom<u32>
28 + TryFrom<u64>
29 + TryFrom<u128>
30 + TryFrom<usize>
31 + TryInto<u8>
32 + TryInto<u16>
33 + TryFrom<u32>
34 + TryFrom<u64>
35 + TryInto<u128>
36 + TryInto<usize>
37{
38}
39
40pub trait UnsignedPrimInt:
47 Eq
48 + Hash
49 + Ord
50 + Copy
51 + Default
52 + Debug
53 + Display
54 + ConvertPrimInts
55 + sealed::PrivateUnsignedInt
56 + MaybeNumTrait
57 + MaybePod
58 + MaybeContiguous
59{
60}
61
62#[inline]
65pub fn checked_cast<T: UnsignedPrimInt, U: UnsignedPrimInt>(value: T) -> Option<U> {
66 sealed::PrivateUnsignedInt::checked_cast(value)
67}
68
69#[inline]
72pub fn checked_add<T: UnsignedPrimInt>(left: T, right: T) -> Option<T> {
73 sealed::PrivateUnsignedInt::checked_add(left, right)
74}
75
76#[inline]
79pub fn checked_sub<T: UnsignedPrimInt>(left: T, right: T) -> Option<T> {
80 sealed::PrivateUnsignedInt::checked_sub(left, right)
81}
82
83#[inline]
86pub fn to_usize_checked<T: UnsignedPrimInt>(val: T) -> Option<usize> {
87 T::to_usize_checked(val)
88}
89
90#[inline]
93pub fn to_usize_wrapping<T: UnsignedPrimInt>(val: T) -> usize {
94 T::to_usize_wrapping(val)
95}
96
97#[inline]
100pub fn from_usize_checked<T: UnsignedPrimInt>(val: usize) -> Option<T> {
101 T::from_usize_checked(val)
102}
103
104#[inline]
107pub fn from_usize_wrapping<T: UnsignedPrimInt>(val: usize) -> T {
108 T::from_usize_wrapping(val)
109}
110
111#[inline]
115pub const fn zero<T: UnsignedPrimInt>() -> T {
116 T::ZERO
117}
118
119#[inline]
121pub const fn one<T: UnsignedPrimInt>() -> T {
122 T::ONE
123}
124
125#[inline]
127pub const fn max_value<T: UnsignedPrimInt>() -> T {
128 T::MAX
129}
130
131#[inline]
133pub const fn bits<T: UnsignedPrimInt>() -> u32 {
134 T::BITS
135}
136
137#[inline]
141pub fn trailing_zeros<T: UnsignedPrimInt>(val: T) -> u32 {
142 sealed::PrivateUnsignedInt::trailing_zeros(val)
143}
144
145#[inline]
149pub fn leading_zeros<T: UnsignedPrimInt>(val: T) -> u32 {
150 sealed::PrivateUnsignedInt::leading_zeros(val)
151}
152
153#[inline]
157pub fn count_ones<T: UnsignedPrimInt>(val: T) -> u32 {
158 sealed::PrivateUnsignedInt::count_ones(val)
159}
160
161#[cold]
183pub fn debug_desc<T: UnsignedPrimInt>(value: T) -> DebugDesc<T> {
184 DebugDesc(value)
185}
186
187#[derive(Clone)]
189pub struct DebugDesc<T: UnsignedPrimInt>(T);
190impl<T: UnsignedPrimInt> Display for DebugDesc<T> {
191 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
192 if self.0 == T::MAX {
193 f.write_str(T::TYPE_NAME)?;
194 f.write_str("::MAX")
195 } else {
196 <T as Display>::fmt(&self.0, f)
197 }
198 }
199}
200impl<T: UnsignedPrimInt> Debug for DebugDesc<T> {
201 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
202 <Self as Display>::fmt(self, f)
203 }
204}
205
206#[inline(never)]
210#[track_caller]
211#[cold]
212pub(crate) fn invalid_id<T: UnsignedPrimInt>(id: T) -> ! {
213 panic!("Invalid id: {}", debug_desc(id))
214}