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>(value: T) -> Option<T> {
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#[cold]
153pub fn debug_desc<T: UnsignedPrimInt>(value: T) -> DebugDesc<T> {
154 DebugDesc(value)
155}
156
157#[derive(Clone)]
159pub struct DebugDesc<T: UnsignedPrimInt>(T);
160impl<T: UnsignedPrimInt> Display for DebugDesc<T> {
161 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
162 if self.0 == T::MAX {
163 f.write_str(T::TYPE_NAME)?;
164 f.write_str("::MAX")
165 } else {
166 <T as Display>::fmt(&self.0, f)
167 }
168 }
169}
170impl<T: UnsignedPrimInt> Debug for DebugDesc<T> {
171 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
172 <Self as Display>::fmt(self, f)
173 }
174}
175
176#[inline(never)]
180#[track_caller]
181#[cold]
182pub(crate) fn invalid_id<T: UnsignedPrimInt>(id: T) -> ! {
183 panic!("Invalid id: {}", debug_desc(id))
184}