bitflags_lite/util.rs
1//! Internal utilities for integer operations used by [`BitFlags`].
2//!
3//! This module is public to support the generic implementations in this crate,
4//! but its items are not intended to be used directly.
5//!
6//! [`BitFlags`]: struct.BitFlags.html
7
8use core::num::ParseIntError;
9
10/// An extension trait for integer operations used by
11/// [`BitFlags`](crate::BitFlags).
12///
13/// It abstracts over the concrete integer types so that generic code can use
14/// the same operations.
15///
16/// # Bit width limit
17///
18/// Bit indices are stored as `u8`, so implementations must report a
19/// [`BITS`](Self::BITS) value of at most `u8::MAX`.
20/// This library therefore supports storage types of up to 256 bits.
21/// All primitive integers satisfy this constraint.
22pub trait IntOpsExt: Sized {
23 /// The value `0`.
24 const ZERO: Self;
25
26 /// The value `1`.
27 const ONE: Self;
28
29 /// The number of bits in this integer type.
30 ///
31 /// For primitive integers this equals `size_of::<Self>() * 8`, but
32 /// [`IntOpsExt`] implementations must return the number of bits the type
33 /// can represent as a bit set, which may be smaller for wrapper types.
34 ///
35 /// This value is used to bound valid bit indices for
36 /// [`BitFlag`](crate::BitFlag) and [`BitFlags`](crate::BitFlags).
37 /// It must not exceed `u8::MAX`, because bit indices are stored as `u8`.
38 const BITS: u8;
39
40 /// Checked shift left.
41 /// Computes `self << rhs`, returning `None` if `rhs` is larger than or
42 /// equal to the number of bits in `self`.
43 #[must_use]
44 fn checked_shl(&self, rhs: u32) -> Option<Self>;
45
46 /// Returns the number of ones in the binary representation of `self`.
47 #[must_use]
48 fn count_ones(&self) -> u32;
49
50 /// Returns the index of the highest bit set to one in `self`, or `None`
51 /// if `self` is `0`.
52 #[must_use]
53 fn highest_one(&self) -> Option<u32>;
54
55 /// Returns the index of the lowest bit set to one in `self`, or `None`
56 /// if `self` is `0`.
57 #[must_use]
58 fn lowest_one(&self) -> Option<u32>;
59
60 /// Parses an integer from a string slice with digits in a given base.
61 ///
62 /// This is equivalent to the corresponding inherent method on the
63 /// concrete integer type.
64 ///
65 /// # Errors
66 ///
67 /// If `src` is not a valid representation of an integer in the given
68 /// radix, returns `Err(ParseIntError)`.
69 fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError>;
70}
71
72// Const traits are not stable yet, so the const methods are implemented for
73// each integer type separately via a macro.
74// See: https://github.com/rust-lang/rust/issues/143874
75macro_rules! impl_uint_opt_ext {
76 ($ty:ty) => {
77 impl IntOpsExt for $ty {
78 const ZERO: Self = 0;
79 const ONE: Self = 1;
80
81 #[expect(
82 clippy::as_conversions,
83 clippy::cast_possible_truncation,
84 reason = "supported in const context"
85 )]
86 const BITS: u8 = <$ty>::BITS as u8;
87
88 #[inline]
89 fn checked_shl(&self, rhs: u32) -> Option<Self> {
90 <$ty>::checked_shl(*self, rhs)
91 }
92
93 #[inline]
94 fn count_ones(&self) -> u32 {
95 <$ty>::count_ones(*self)
96 }
97
98 #[inline]
99 fn lowest_one(&self) -> Option<u32> {
100 <$ty>::lowest_one(*self)
101 }
102
103 #[inline]
104 fn highest_one(&self) -> Option<u32> {
105 <$ty>::highest_one(*self)
106 }
107
108 #[inline]
109 fn from_str_radix(src: &str, radix: u32) -> Result<Self, core::num::ParseIntError> {
110 <$ty>::from_str_radix(src, radix)
111 }
112 }
113 };
114}
115
116impl_uint_opt_ext!(u8);
117impl_uint_opt_ext!(u16);
118impl_uint_opt_ext!(u32);
119impl_uint_opt_ext!(u64);
120impl_uint_opt_ext!(u128);
121impl_uint_opt_ext!(usize);
122
123impl_uint_opt_ext!(i8);
124impl_uint_opt_ext!(i16);
125impl_uint_opt_ext!(i32);
126impl_uint_opt_ext!(i64);
127impl_uint_opt_ext!(i128);
128impl_uint_opt_ext!(isize);