101e345e8SAlexandre Courbot // SPDX-License-Identifier: GPL-2.0
201e345e8SAlexandre Courbot
301e345e8SAlexandre Courbot //! Implementation of [`Bounded`], a wrapper around integer types limiting the number of bits
401e345e8SAlexandre Courbot //! usable for value representation.
501e345e8SAlexandre Courbot
601e345e8SAlexandre Courbot use core::{
701e345e8SAlexandre Courbot cmp,
801e345e8SAlexandre Courbot fmt,
901e345e8SAlexandre Courbot ops::{
1001e345e8SAlexandre Courbot self,
1101e345e8SAlexandre Courbot Deref, //
1201e345e8SAlexandre Courbot }, //,
1301e345e8SAlexandre Courbot };
1401e345e8SAlexandre Courbot
1501e345e8SAlexandre Courbot use kernel::{
1601e345e8SAlexandre Courbot num::Integer,
1701e345e8SAlexandre Courbot prelude::*, //
1801e345e8SAlexandre Courbot };
1901e345e8SAlexandre Courbot
2001e345e8SAlexandre Courbot /// Evaluates to `true` if `$value` can be represented using at most `$n` bits in a `$type`.
2101e345e8SAlexandre Courbot ///
2201e345e8SAlexandre Courbot /// `expr` must be of type `type`, or the result will be incorrect.
2301e345e8SAlexandre Courbot ///
2401e345e8SAlexandre Courbot /// Can be used in const context.
2501e345e8SAlexandre Courbot macro_rules! fits_within {
2601e345e8SAlexandre Courbot ($value:expr, $type:ty, $n:expr) => {{
2701e345e8SAlexandre Courbot let shift: u32 = <$type>::BITS - $n;
2801e345e8SAlexandre Courbot
2901e345e8SAlexandre Courbot // `value` fits within `$n` bits if shifting it left by the number of unused bits, then
3001e345e8SAlexandre Courbot // right by the same number, doesn't change it.
3101e345e8SAlexandre Courbot //
3201e345e8SAlexandre Courbot // This method has the benefit of working for both unsigned and signed values.
3301e345e8SAlexandre Courbot ($value << shift) >> shift == $value
3401e345e8SAlexandre Courbot }};
3501e345e8SAlexandre Courbot }
3601e345e8SAlexandre Courbot
3701e345e8SAlexandre Courbot /// Returns `true` if `value` can be represented with at most `N` bits in a `T`.
38bc197e24SAlexandre Courbot #[inline(always)]
fits_within<T: Integer>(value: T, num_bits: u32) -> bool3901e345e8SAlexandre Courbot fn fits_within<T: Integer>(value: T, num_bits: u32) -> bool {
4001e345e8SAlexandre Courbot fits_within!(value, T, num_bits)
4101e345e8SAlexandre Courbot }
4201e345e8SAlexandre Courbot
43f6b8d4b7SNakamura Shuta /// An integer value that requires only the `N` least significant bits of the wrapped type to be
4401e345e8SAlexandre Courbot /// encoded.
4501e345e8SAlexandre Courbot ///
4601e345e8SAlexandre Courbot /// This limits the number of usable bits in the wrapped integer type, and thus the stored value to
4701e345e8SAlexandre Courbot /// a narrower range, which provides guarantees that can be useful when working within e.g.
4801e345e8SAlexandre Courbot /// bitfields.
4901e345e8SAlexandre Courbot ///
5001e345e8SAlexandre Courbot /// # Invariants
5101e345e8SAlexandre Courbot ///
5201e345e8SAlexandre Courbot /// - `N` is greater than `0`.
5301e345e8SAlexandre Courbot /// - `N` is less than or equal to `T::BITS`.
5401e345e8SAlexandre Courbot /// - Stored values can be represented with at most `N` bits.
5501e345e8SAlexandre Courbot ///
5601e345e8SAlexandre Courbot /// # Examples
5701e345e8SAlexandre Courbot ///
5801e345e8SAlexandre Courbot /// The preferred way to create values is through constants and the [`Bounded::new`] family of
59f6b8d4b7SNakamura Shuta /// constructors, as they trigger a build error if the type invariants cannot be upheld.
6001e345e8SAlexandre Courbot ///
6101e345e8SAlexandre Courbot /// ```
6201e345e8SAlexandre Courbot /// use kernel::num::Bounded;
6301e345e8SAlexandre Courbot ///
6401e345e8SAlexandre Courbot /// // An unsigned 8-bit integer, of which only the 4 LSBs are used.
6501e345e8SAlexandre Courbot /// // The value `15` is statically validated to fit that constraint at build time.
6601e345e8SAlexandre Courbot /// let v = Bounded::<u8, 4>::new::<15>();
6701e345e8SAlexandre Courbot /// assert_eq!(v.get(), 15);
6801e345e8SAlexandre Courbot ///
6901e345e8SAlexandre Courbot /// // Same using signed values.
7001e345e8SAlexandre Courbot /// let v = Bounded::<i8, 4>::new::<-8>();
7101e345e8SAlexandre Courbot /// assert_eq!(v.get(), -8);
7201e345e8SAlexandre Courbot ///
7301e345e8SAlexandre Courbot /// // This doesn't build: a `u8` is smaller than the requested 9 bits.
7401e345e8SAlexandre Courbot /// // let _ = Bounded::<u8, 9>::new::<10>();
7501e345e8SAlexandre Courbot ///
7601e345e8SAlexandre Courbot /// // This also doesn't build: the requested value doesn't fit within 4 signed bits.
7701e345e8SAlexandre Courbot /// // let _ = Bounded::<i8, 4>::new::<8>();
7801e345e8SAlexandre Courbot /// ```
7901e345e8SAlexandre Courbot ///
8001e345e8SAlexandre Courbot /// Values can also be validated at runtime with [`Bounded::try_new`].
8101e345e8SAlexandre Courbot ///
8201e345e8SAlexandre Courbot /// ```
8301e345e8SAlexandre Courbot /// use kernel::num::Bounded;
8401e345e8SAlexandre Courbot ///
8501e345e8SAlexandre Courbot /// // This succeeds because `15` can be represented with 4 unsigned bits.
8601e345e8SAlexandre Courbot /// assert!(Bounded::<u8, 4>::try_new(15).is_some());
8701e345e8SAlexandre Courbot ///
8801e345e8SAlexandre Courbot /// // This fails because `16` cannot be represented with 4 unsigned bits.
8901e345e8SAlexandre Courbot /// assert!(Bounded::<u8, 4>::try_new(16).is_none());
9001e345e8SAlexandre Courbot /// ```
9101e345e8SAlexandre Courbot ///
9201e345e8SAlexandre Courbot /// Non-constant expressions can be validated at build-time thanks to compiler optimizations. This
9301e345e8SAlexandre Courbot /// should be used with caution, on simple expressions only.
9401e345e8SAlexandre Courbot ///
9501e345e8SAlexandre Courbot /// ```
9601e345e8SAlexandre Courbot /// use kernel::num::Bounded;
9701e345e8SAlexandre Courbot /// # fn some_number() -> u32 { 0xffffffff }
9801e345e8SAlexandre Courbot ///
9901e345e8SAlexandre Courbot /// // Here the compiler can infer from the mask that the type invariants are not violated, even
10001e345e8SAlexandre Courbot /// // though the value returned by `some_number` is not statically known.
10101e345e8SAlexandre Courbot /// let v = Bounded::<u32, 4>::from_expr(some_number() & 0xf);
10201e345e8SAlexandre Courbot /// ```
10301e345e8SAlexandre Courbot ///
10401e345e8SAlexandre Courbot /// Comparison and arithmetic operations are supported on [`Bounded`]s with a compatible backing
10501e345e8SAlexandre Courbot /// type, regardless of their number of valid bits.
10601e345e8SAlexandre Courbot ///
10701e345e8SAlexandre Courbot /// ```
10801e345e8SAlexandre Courbot /// use kernel::num::Bounded;
10901e345e8SAlexandre Courbot ///
11001e345e8SAlexandre Courbot /// let v1 = Bounded::<u32, 8>::new::<4>();
11101e345e8SAlexandre Courbot /// let v2 = Bounded::<u32, 4>::new::<15>();
11201e345e8SAlexandre Courbot ///
11301e345e8SAlexandre Courbot /// assert!(v1 != v2);
11401e345e8SAlexandre Courbot /// assert!(v1 < v2);
11501e345e8SAlexandre Courbot /// assert_eq!(v1 + v2, 19);
11601e345e8SAlexandre Courbot /// assert_eq!(v2 % v1, 3);
11701e345e8SAlexandre Courbot /// ```
11801e345e8SAlexandre Courbot ///
11901e345e8SAlexandre Courbot /// These operations are also supported between a [`Bounded`] and its backing type.
12001e345e8SAlexandre Courbot ///
12101e345e8SAlexandre Courbot /// ```
12201e345e8SAlexandre Courbot /// use kernel::num::Bounded;
12301e345e8SAlexandre Courbot ///
12401e345e8SAlexandre Courbot /// let v = Bounded::<u8, 4>::new::<15>();
12501e345e8SAlexandre Courbot ///
12601e345e8SAlexandre Courbot /// assert!(v == 15);
12701e345e8SAlexandre Courbot /// assert!(v > 12);
12801e345e8SAlexandre Courbot /// assert_eq!(v + 5, 20);
12901e345e8SAlexandre Courbot /// assert_eq!(v / 3, 5);
13001e345e8SAlexandre Courbot /// ```
13101e345e8SAlexandre Courbot ///
13201e345e8SAlexandre Courbot /// A change of backing types is possible using [`Bounded::cast`], and the number of valid bits can
13301e345e8SAlexandre Courbot /// be extended or reduced with [`Bounded::extend`] and [`Bounded::try_shrink`].
13401e345e8SAlexandre Courbot ///
13501e345e8SAlexandre Courbot /// ```
13601e345e8SAlexandre Courbot /// use kernel::num::Bounded;
13701e345e8SAlexandre Courbot ///
13801e345e8SAlexandre Courbot /// let v = Bounded::<u32, 12>::new::<127>();
13901e345e8SAlexandre Courbot ///
14001e345e8SAlexandre Courbot /// // Changes backing type from `u32` to `u16`.
14101e345e8SAlexandre Courbot /// let _: Bounded<u16, 12> = v.cast();
14201e345e8SAlexandre Courbot ///
14301e345e8SAlexandre Courbot /// // This does not build, as `u8` is smaller than 12 bits.
14401e345e8SAlexandre Courbot /// // let _: Bounded<u8, 12> = v.cast();
14501e345e8SAlexandre Courbot ///
14601e345e8SAlexandre Courbot /// // We can safely extend the number of bits...
14701e345e8SAlexandre Courbot /// let _ = v.extend::<15>();
14801e345e8SAlexandre Courbot ///
14901e345e8SAlexandre Courbot /// // ... to the limits of the backing type. This doesn't build as a `u32` cannot contain 33 bits.
15001e345e8SAlexandre Courbot /// // let _ = v.extend::<33>();
15101e345e8SAlexandre Courbot ///
15201e345e8SAlexandre Courbot /// // Reducing the number of bits is validated at runtime. This works because `127` can be
15301e345e8SAlexandre Courbot /// // represented with 8 bits.
15401e345e8SAlexandre Courbot /// assert!(v.try_shrink::<8>().is_some());
15501e345e8SAlexandre Courbot ///
15601e345e8SAlexandre Courbot /// // ... but not with 6, so this fails.
15701e345e8SAlexandre Courbot /// assert!(v.try_shrink::<6>().is_none());
15801e345e8SAlexandre Courbot /// ```
15901e345e8SAlexandre Courbot ///
16001e345e8SAlexandre Courbot /// Infallible conversions from a primitive integer to a large-enough [`Bounded`] are supported.
16101e345e8SAlexandre Courbot ///
16201e345e8SAlexandre Courbot /// ```
16301e345e8SAlexandre Courbot /// use kernel::num::Bounded;
16401e345e8SAlexandre Courbot ///
16501e345e8SAlexandre Courbot /// // This unsigned `Bounded` has 8 bits, so it can represent any `u8`.
16601e345e8SAlexandre Courbot /// let v = Bounded::<u32, 8>::from(128u8);
16701e345e8SAlexandre Courbot /// assert_eq!(v.get(), 128);
16801e345e8SAlexandre Courbot ///
16901e345e8SAlexandre Courbot /// // This signed `Bounded` has 8 bits, so it can represent any `i8`.
17001e345e8SAlexandre Courbot /// let v = Bounded::<i32, 8>::from(-128i8);
17101e345e8SAlexandre Courbot /// assert_eq!(v.get(), -128);
17201e345e8SAlexandre Courbot ///
17301e345e8SAlexandre Courbot /// // This doesn't build, as this 6-bit `Bounded` does not have enough capacity to represent a
17401e345e8SAlexandre Courbot /// // `u8` (regardless of the passed value).
17501e345e8SAlexandre Courbot /// // let _ = Bounded::<u32, 6>::from(10u8);
17601e345e8SAlexandre Courbot ///
17701e345e8SAlexandre Courbot /// // Booleans can be converted into single-bit `Bounded`s.
17801e345e8SAlexandre Courbot ///
17901e345e8SAlexandre Courbot /// let v = Bounded::<u64, 1>::from(false);
18001e345e8SAlexandre Courbot /// assert_eq!(v.get(), 0);
18101e345e8SAlexandre Courbot ///
18201e345e8SAlexandre Courbot /// let v = Bounded::<u64, 1>::from(true);
18301e345e8SAlexandre Courbot /// assert_eq!(v.get(), 1);
18401e345e8SAlexandre Courbot /// ```
18501e345e8SAlexandre Courbot ///
18601e345e8SAlexandre Courbot /// Infallible conversions from a [`Bounded`] to a primitive integer are also supported, and
18701e345e8SAlexandre Courbot /// dependent on the number of bits used for value representation, not on the backing type.
18801e345e8SAlexandre Courbot ///
18901e345e8SAlexandre Courbot /// ```
19001e345e8SAlexandre Courbot /// use kernel::num::Bounded;
19101e345e8SAlexandre Courbot ///
19201e345e8SAlexandre Courbot /// // Even though its backing type is `u32`, this `Bounded` only uses 6 bits and thus can safely
19301e345e8SAlexandre Courbot /// // be converted to a `u8`.
19401e345e8SAlexandre Courbot /// let v = Bounded::<u32, 6>::new::<63>();
19501e345e8SAlexandre Courbot /// assert_eq!(u8::from(v), 63);
19601e345e8SAlexandre Courbot ///
19701e345e8SAlexandre Courbot /// // Same using signed values.
19801e345e8SAlexandre Courbot /// let v = Bounded::<i32, 8>::new::<-128>();
19901e345e8SAlexandre Courbot /// assert_eq!(i8::from(v), -128);
20001e345e8SAlexandre Courbot ///
20101e345e8SAlexandre Courbot /// // This however does not build, as 10 bits won't fit into a `u8` (regardless of the actually
20201e345e8SAlexandre Courbot /// // contained value).
20301e345e8SAlexandre Courbot /// let _v = Bounded::<u32, 10>::new::<10>();
20401e345e8SAlexandre Courbot /// // assert_eq!(u8::from(_v), 10);
20501e345e8SAlexandre Courbot ///
20601e345e8SAlexandre Courbot /// // Single-bit `Bounded`s can be converted into a boolean.
20701e345e8SAlexandre Courbot /// let v = Bounded::<u8, 1>::new::<1>();
20801e345e8SAlexandre Courbot /// assert_eq!(bool::from(v), true);
20901e345e8SAlexandre Courbot ///
21001e345e8SAlexandre Courbot /// let v = Bounded::<u8, 1>::new::<0>();
21101e345e8SAlexandre Courbot /// assert_eq!(bool::from(v), false);
21201e345e8SAlexandre Courbot /// ```
21301e345e8SAlexandre Courbot ///
21401e345e8SAlexandre Courbot /// Fallible conversions from any primitive integer to any [`Bounded`] are also supported using the
21501e345e8SAlexandre Courbot /// [`TryIntoBounded`] trait.
21601e345e8SAlexandre Courbot ///
21701e345e8SAlexandre Courbot /// ```
21801e345e8SAlexandre Courbot /// use kernel::num::{Bounded, TryIntoBounded};
21901e345e8SAlexandre Courbot ///
22001e345e8SAlexandre Courbot /// // Succeeds because `128` fits into 8 bits.
221841f31d2SAlexandre Courbot /// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded();
22201e345e8SAlexandre Courbot /// assert_eq!(v.as_deref().copied(), Some(128));
22301e345e8SAlexandre Courbot ///
224f6b8d4b7SNakamura Shuta /// // Fails because `128` doesn't fit into 6 bits.
225841f31d2SAlexandre Courbot /// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded();
22601e345e8SAlexandre Courbot /// assert_eq!(v, None);
22701e345e8SAlexandre Courbot /// ```
22801e345e8SAlexandre Courbot #[repr(transparent)]
22901e345e8SAlexandre Courbot #[derive(Clone, Copy, Debug, Default, Hash)]
23001e345e8SAlexandre Courbot pub struct Bounded<T: Integer, const N: u32>(T);
23101e345e8SAlexandre Courbot
23201e345e8SAlexandre Courbot /// Validating the value as a const expression cannot be done as a regular method, as the
23301e345e8SAlexandre Courbot /// arithmetic operations we rely on to check the bounds are not const. Thus, implement
23401e345e8SAlexandre Courbot /// [`Bounded::new`] using a macro.
23501e345e8SAlexandre Courbot macro_rules! impl_const_new {
23601e345e8SAlexandre Courbot ($($type:ty)*) => {
23701e345e8SAlexandre Courbot $(
23801e345e8SAlexandre Courbot impl<const N: u32> Bounded<$type, N> {
23901e345e8SAlexandre Courbot /// Creates a [`Bounded`] for the constant `VALUE`.
24001e345e8SAlexandre Courbot ///
24101e345e8SAlexandre Courbot /// Fails at build time if `VALUE` cannot be represented with `N` bits.
24201e345e8SAlexandre Courbot ///
24301e345e8SAlexandre Courbot /// This method should be preferred to [`Self::from_expr`] whenever possible.
24401e345e8SAlexandre Courbot ///
24501e345e8SAlexandre Courbot /// # Examples
24601e345e8SAlexandre Courbot ///
24701e345e8SAlexandre Courbot /// ```
24801e345e8SAlexandre Courbot /// use kernel::num::Bounded;
24901e345e8SAlexandre Courbot ///
25001e345e8SAlexandre Courbot #[doc = ::core::concat!(
25101e345e8SAlexandre Courbot "let v = Bounded::<",
25201e345e8SAlexandre Courbot ::core::stringify!($type),
25301e345e8SAlexandre Courbot ", 4>::new::<7>();")]
25401e345e8SAlexandre Courbot /// assert_eq!(v.get(), 7);
25501e345e8SAlexandre Courbot /// ```
25601e345e8SAlexandre Courbot pub const fn new<const VALUE: $type>() -> Self {
25701e345e8SAlexandre Courbot // Statically assert that `VALUE` fits within the set number of bits.
25801e345e8SAlexandre Courbot const {
25901e345e8SAlexandre Courbot assert!(fits_within!(VALUE, $type, N));
26001e345e8SAlexandre Courbot }
26101e345e8SAlexandre Courbot
2623a1ec424SHsiu Che Yu // SAFETY: `fits_within` confirmed that `VALUE` can be represented within
26301e345e8SAlexandre Courbot // `N` bits.
2643a1ec424SHsiu Che Yu unsafe { Self::__new(VALUE) }
26501e345e8SAlexandre Courbot }
26601e345e8SAlexandre Courbot }
26701e345e8SAlexandre Courbot )*
26801e345e8SAlexandre Courbot };
26901e345e8SAlexandre Courbot }
27001e345e8SAlexandre Courbot
27101e345e8SAlexandre Courbot impl_const_new!(
27201e345e8SAlexandre Courbot u8 u16 u32 u64 usize
27301e345e8SAlexandre Courbot i8 i16 i32 i64 isize
27401e345e8SAlexandre Courbot );
27501e345e8SAlexandre Courbot
27601e345e8SAlexandre Courbot impl<T, const N: u32> Bounded<T, N>
27701e345e8SAlexandre Courbot where
27801e345e8SAlexandre Courbot T: Integer,
27901e345e8SAlexandre Courbot {
28001e345e8SAlexandre Courbot /// Private constructor enforcing the type invariants.
28101e345e8SAlexandre Courbot ///
28201e345e8SAlexandre Courbot /// All instances of [`Bounded`] must be created through this method as it enforces most of the
28301e345e8SAlexandre Courbot /// type invariants.
28401e345e8SAlexandre Courbot ///
2853a1ec424SHsiu Che Yu /// # Safety
2863a1ec424SHsiu Che Yu ///
2873a1ec424SHsiu Che Yu /// The caller must ensure that `value` can be represented within `N` bits.
__new(value: T) -> Self2883a1ec424SHsiu Che Yu const unsafe fn __new(value: T) -> Self {
28901e345e8SAlexandre Courbot // Enforce the type invariants.
29001e345e8SAlexandre Courbot const {
29101e345e8SAlexandre Courbot // `N` cannot be zero.
29201e345e8SAlexandre Courbot assert!(N != 0);
29301e345e8SAlexandre Courbot // The backing type is at least as large as `N` bits.
29401e345e8SAlexandre Courbot assert!(N <= T::BITS);
29501e345e8SAlexandre Courbot }
29601e345e8SAlexandre Courbot
297*5016cae9SShivam Kalra // INVARIANT: The caller ensures `value` fits within `N` bits.
29801e345e8SAlexandre Courbot Self(value)
29901e345e8SAlexandre Courbot }
30001e345e8SAlexandre Courbot
30101e345e8SAlexandre Courbot /// Attempts to turn `value` into a `Bounded` using `N` bits.
30201e345e8SAlexandre Courbot ///
30301e345e8SAlexandre Courbot /// Returns [`None`] if `value` doesn't fit within `N` bits.
30401e345e8SAlexandre Courbot ///
30501e345e8SAlexandre Courbot /// # Examples
30601e345e8SAlexandre Courbot ///
30701e345e8SAlexandre Courbot /// ```
30801e345e8SAlexandre Courbot /// use kernel::num::Bounded;
30901e345e8SAlexandre Courbot ///
31001e345e8SAlexandre Courbot /// let v = Bounded::<u8, 1>::try_new(1);
31101e345e8SAlexandre Courbot /// assert_eq!(v.as_deref().copied(), Some(1));
31201e345e8SAlexandre Courbot ///
31301e345e8SAlexandre Courbot /// let v = Bounded::<i8, 4>::try_new(-2);
31401e345e8SAlexandre Courbot /// assert_eq!(v.as_deref().copied(), Some(-2));
31501e345e8SAlexandre Courbot ///
31601e345e8SAlexandre Courbot /// // `0x1ff` doesn't fit into 8 unsigned bits.
31701e345e8SAlexandre Courbot /// let v = Bounded::<u32, 8>::try_new(0x1ff);
31801e345e8SAlexandre Courbot /// assert_eq!(v, None);
31901e345e8SAlexandre Courbot ///
32001e345e8SAlexandre Courbot /// // The range of values representable with 4 bits is `[-8..=7]`. The following tests these
32101e345e8SAlexandre Courbot /// // limits.
32201e345e8SAlexandre Courbot /// let v = Bounded::<i8, 4>::try_new(-8);
32301e345e8SAlexandre Courbot /// assert_eq!(v.map(Bounded::get), Some(-8));
32401e345e8SAlexandre Courbot /// let v = Bounded::<i8, 4>::try_new(-9);
32501e345e8SAlexandre Courbot /// assert_eq!(v, None);
32601e345e8SAlexandre Courbot /// let v = Bounded::<i8, 4>::try_new(7);
32701e345e8SAlexandre Courbot /// assert_eq!(v.map(Bounded::get), Some(7));
32801e345e8SAlexandre Courbot /// let v = Bounded::<i8, 4>::try_new(8);
32901e345e8SAlexandre Courbot /// assert_eq!(v, None);
33001e345e8SAlexandre Courbot /// ```
try_new(value: T) -> Option<Self>33101e345e8SAlexandre Courbot pub fn try_new(value: T) -> Option<Self> {
33201e345e8SAlexandre Courbot fits_within(value, N).then(|| {
3333a1ec424SHsiu Che Yu // SAFETY: `fits_within` confirmed that `value` can be represented within `N` bits.
3343a1ec424SHsiu Che Yu unsafe { Self::__new(value) }
33501e345e8SAlexandre Courbot })
33601e345e8SAlexandre Courbot }
33701e345e8SAlexandre Courbot
33801e345e8SAlexandre Courbot /// Checks that `expr` is valid for this type at compile-time and build a new value.
33901e345e8SAlexandre Courbot ///
34001e345e8SAlexandre Courbot /// This relies on [`build_assert!`] and guaranteed optimization to perform validation at
34101e345e8SAlexandre Courbot /// compile-time. If `expr` cannot be proved to be within the requested bounds at compile-time,
34201e345e8SAlexandre Courbot /// use the fallible [`Self::try_new`] instead.
34301e345e8SAlexandre Courbot ///
34401e345e8SAlexandre Courbot /// Limit this to simple, easily provable expressions, and prefer one of the [`Self::new`]
34501e345e8SAlexandre Courbot /// constructors whenever possible as they statically validate the value instead of relying on
34601e345e8SAlexandre Courbot /// compiler optimizations.
34701e345e8SAlexandre Courbot ///
34801e345e8SAlexandre Courbot /// # Examples
34901e345e8SAlexandre Courbot ///
35001e345e8SAlexandre Courbot /// ```
35101e345e8SAlexandre Courbot /// use kernel::num::Bounded;
35201e345e8SAlexandre Courbot /// # fn some_number() -> u32 { 0xffffffff }
35301e345e8SAlexandre Courbot ///
35401e345e8SAlexandre Courbot /// // Some undefined number.
35501e345e8SAlexandre Courbot /// let v: u32 = some_number();
35601e345e8SAlexandre Courbot ///
35701e345e8SAlexandre Courbot /// // Triggers a build error as `v` cannot be asserted to fit within 4 bits...
35801e345e8SAlexandre Courbot /// // let _ = Bounded::<u32, 4>::from_expr(v);
35901e345e8SAlexandre Courbot ///
36001e345e8SAlexandre Courbot /// // ... but this works as the compiler can assert the range from the mask.
36101e345e8SAlexandre Courbot /// let _ = Bounded::<u32, 4>::from_expr(v & 0xf);
36201e345e8SAlexandre Courbot ///
36301e345e8SAlexandre Courbot /// // These expressions are simple enough to be proven correct, but since they are static the
36401e345e8SAlexandre Courbot /// // `new` constructor should be preferred.
36501e345e8SAlexandre Courbot /// assert_eq!(Bounded::<u8, 1>::from_expr(1).get(), 1);
36601e345e8SAlexandre Courbot /// assert_eq!(Bounded::<u16, 8>::from_expr(0xff).get(), 0xff);
36701e345e8SAlexandre Courbot /// ```
3682af6ad09SAlexandre Courbot // Always inline to optimize out error path of `build_assert`.
369bc197e24SAlexandre Courbot #[inline(always)]
from_expr(expr: T) -> Self37001e345e8SAlexandre Courbot pub fn from_expr(expr: T) -> Self {
37101e345e8SAlexandre Courbot crate::build_assert!(
37201e345e8SAlexandre Courbot fits_within(expr, N),
37301e345e8SAlexandre Courbot "Requested value larger than maximal representable value."
37401e345e8SAlexandre Courbot );
37501e345e8SAlexandre Courbot
3763a1ec424SHsiu Che Yu // SAFETY: `fits_within` confirmed that `expr` can be represented within `N` bits.
3773a1ec424SHsiu Che Yu unsafe { Self::__new(expr) }
37801e345e8SAlexandre Courbot }
37901e345e8SAlexandre Courbot
38001e345e8SAlexandre Courbot /// Returns the wrapped value as the backing type.
38101e345e8SAlexandre Courbot ///
38201e345e8SAlexandre Courbot /// # Examples
38301e345e8SAlexandre Courbot ///
38401e345e8SAlexandre Courbot /// ```
38501e345e8SAlexandre Courbot /// use kernel::num::Bounded;
38601e345e8SAlexandre Courbot ///
38701e345e8SAlexandre Courbot /// let v = Bounded::<u32, 4>::new::<7>();
38801e345e8SAlexandre Courbot /// assert_eq!(v.get(), 7u32);
38901e345e8SAlexandre Courbot /// ```
get(self) -> T39001e345e8SAlexandre Courbot pub fn get(self) -> T {
39101e345e8SAlexandre Courbot *self.deref()
39201e345e8SAlexandre Courbot }
39301e345e8SAlexandre Courbot
39401e345e8SAlexandre Courbot /// Increases the number of bits usable for `self`.
39501e345e8SAlexandre Courbot ///
39601e345e8SAlexandre Courbot /// This operation cannot fail.
39701e345e8SAlexandre Courbot ///
39801e345e8SAlexandre Courbot /// # Examples
39901e345e8SAlexandre Courbot ///
40001e345e8SAlexandre Courbot /// ```
40101e345e8SAlexandre Courbot /// use kernel::num::Bounded;
40201e345e8SAlexandre Courbot ///
40301e345e8SAlexandre Courbot /// let v = Bounded::<u32, 4>::new::<7>();
40401e345e8SAlexandre Courbot /// let larger_v = v.extend::<12>();
40501e345e8SAlexandre Courbot /// // The contained values are equal even though `larger_v` has a bigger capacity.
40601e345e8SAlexandre Courbot /// assert_eq!(larger_v, v);
40701e345e8SAlexandre Courbot /// ```
extend<const M: u32>(self) -> Bounded<T, M>40801e345e8SAlexandre Courbot pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
40901e345e8SAlexandre Courbot const {
41001e345e8SAlexandre Courbot assert!(
41101e345e8SAlexandre Courbot M >= N,
41201e345e8SAlexandre Courbot "Requested number of bits is less than the current representation."
41301e345e8SAlexandre Courbot );
41401e345e8SAlexandre Courbot }
41501e345e8SAlexandre Courbot
4163a1ec424SHsiu Che Yu // SAFETY: The value did fit within `N` bits, so it will all the more fit within
41701e345e8SAlexandre Courbot // the larger `M` bits.
4183a1ec424SHsiu Che Yu unsafe { Bounded::__new(self.0) }
41901e345e8SAlexandre Courbot }
42001e345e8SAlexandre Courbot
42101e345e8SAlexandre Courbot /// Attempts to shrink the number of bits usable for `self`.
42201e345e8SAlexandre Courbot ///
42301e345e8SAlexandre Courbot /// Returns [`None`] if the value of `self` cannot be represented within `M` bits.
42401e345e8SAlexandre Courbot ///
42501e345e8SAlexandre Courbot /// # Examples
42601e345e8SAlexandre Courbot ///
42701e345e8SAlexandre Courbot /// ```
42801e345e8SAlexandre Courbot /// use kernel::num::Bounded;
42901e345e8SAlexandre Courbot ///
43001e345e8SAlexandre Courbot /// let v = Bounded::<u32, 12>::new::<7>();
43101e345e8SAlexandre Courbot ///
43201e345e8SAlexandre Courbot /// // `7` can be represented using 3 unsigned bits...
43301e345e8SAlexandre Courbot /// let smaller_v = v.try_shrink::<3>();
43401e345e8SAlexandre Courbot /// assert_eq!(smaller_v.as_deref().copied(), Some(7));
43501e345e8SAlexandre Courbot ///
43601e345e8SAlexandre Courbot /// // ... but doesn't fit within `2` bits.
43701e345e8SAlexandre Courbot /// assert_eq!(v.try_shrink::<2>(), None);
43801e345e8SAlexandre Courbot /// ```
try_shrink<const M: u32>(self) -> Option<Bounded<T, M>>43901e345e8SAlexandre Courbot pub fn try_shrink<const M: u32>(self) -> Option<Bounded<T, M>> {
44001e345e8SAlexandre Courbot Bounded::<T, M>::try_new(self.get())
44101e345e8SAlexandre Courbot }
44201e345e8SAlexandre Courbot
44301e345e8SAlexandre Courbot /// Casts `self` into a [`Bounded`] backed by a different storage type, but using the same
44401e345e8SAlexandre Courbot /// number of valid bits.
44501e345e8SAlexandre Courbot ///
44601e345e8SAlexandre Courbot /// Both `T` and `U` must be of same signedness, and `U` must be at least as large as
44701e345e8SAlexandre Courbot /// `N` bits, or a build error will occur.
44801e345e8SAlexandre Courbot ///
44901e345e8SAlexandre Courbot /// # Examples
45001e345e8SAlexandre Courbot ///
45101e345e8SAlexandre Courbot /// ```
45201e345e8SAlexandre Courbot /// use kernel::num::Bounded;
45301e345e8SAlexandre Courbot ///
45401e345e8SAlexandre Courbot /// let v = Bounded::<u32, 12>::new::<127>();
45501e345e8SAlexandre Courbot ///
45601e345e8SAlexandre Courbot /// let u16_v: Bounded<u16, 12> = v.cast();
45701e345e8SAlexandre Courbot /// assert_eq!(u16_v.get(), 127);
45801e345e8SAlexandre Courbot ///
45901e345e8SAlexandre Courbot /// // This won't build: a `u8` is smaller than the required 12 bits.
46001e345e8SAlexandre Courbot /// // let _: Bounded<u8, 12> = v.cast();
46101e345e8SAlexandre Courbot /// ```
cast<U>(self) -> Bounded<U, N> where U: TryFrom<T> + Integer, T: Integer, U: Integer<Signedness = T::Signedness>,46201e345e8SAlexandre Courbot pub fn cast<U>(self) -> Bounded<U, N>
46301e345e8SAlexandre Courbot where
46401e345e8SAlexandre Courbot U: TryFrom<T> + Integer,
46501e345e8SAlexandre Courbot T: Integer,
46601e345e8SAlexandre Courbot U: Integer<Signedness = T::Signedness>,
46701e345e8SAlexandre Courbot {
46801e345e8SAlexandre Courbot // SAFETY: The converted value is represented using `N` bits, `U` can contain `N` bits, and
46901e345e8SAlexandre Courbot // `U` and `T` have the same sign, hence this conversion cannot fail.
47001e345e8SAlexandre Courbot let value = unsafe { U::try_from(self.get()).unwrap_unchecked() };
47101e345e8SAlexandre Courbot
4723a1ec424SHsiu Che Yu // SAFETY: Although the backing type has changed, the value is still represented within
47301e345e8SAlexandre Courbot // `N` bits, and with the same signedness.
4743a1ec424SHsiu Che Yu unsafe { Bounded::__new(value) }
47501e345e8SAlexandre Courbot }
47601e345e8SAlexandre Courbot }
47701e345e8SAlexandre Courbot
47801e345e8SAlexandre Courbot impl<T, const N: u32> Deref for Bounded<T, N>
47901e345e8SAlexandre Courbot where
48001e345e8SAlexandre Courbot T: Integer,
48101e345e8SAlexandre Courbot {
48201e345e8SAlexandre Courbot type Target = T;
48301e345e8SAlexandre Courbot
deref(&self) -> &Self::Target48401e345e8SAlexandre Courbot fn deref(&self) -> &Self::Target {
48501e345e8SAlexandre Courbot // Enforce the invariant to inform the compiler of the bounds of the value.
48601e345e8SAlexandre Courbot if !fits_within(self.0, N) {
48701e345e8SAlexandre Courbot // SAFETY: Per the `Bounded` invariants, `fits_within` can never return `false` on the
48801e345e8SAlexandre Courbot // value of a valid instance.
48901e345e8SAlexandre Courbot unsafe { core::hint::unreachable_unchecked() }
49001e345e8SAlexandre Courbot }
49101e345e8SAlexandre Courbot
49201e345e8SAlexandre Courbot &self.0
49301e345e8SAlexandre Courbot }
49401e345e8SAlexandre Courbot }
49501e345e8SAlexandre Courbot
49601e345e8SAlexandre Courbot /// Trait similar to [`TryInto`] but for [`Bounded`], to avoid conflicting implementations.
49701e345e8SAlexandre Courbot ///
49801e345e8SAlexandre Courbot /// # Examples
49901e345e8SAlexandre Courbot ///
50001e345e8SAlexandre Courbot /// ```
50101e345e8SAlexandre Courbot /// use kernel::num::{Bounded, TryIntoBounded};
50201e345e8SAlexandre Courbot ///
50301e345e8SAlexandre Courbot /// // Succeeds because `128` fits into 8 bits.
504841f31d2SAlexandre Courbot /// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded();
50501e345e8SAlexandre Courbot /// assert_eq!(v.as_deref().copied(), Some(128));
50601e345e8SAlexandre Courbot ///
507f6b8d4b7SNakamura Shuta /// // Fails because `128` doesn't fit into 6 bits.
508841f31d2SAlexandre Courbot /// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded();
50901e345e8SAlexandre Courbot /// assert_eq!(v, None);
51001e345e8SAlexandre Courbot /// ```
51101e345e8SAlexandre Courbot pub trait TryIntoBounded<T: Integer, const N: u32> {
51201e345e8SAlexandre Courbot /// Attempts to convert `self` into a [`Bounded`] using `N` bits.
51301e345e8SAlexandre Courbot ///
51401e345e8SAlexandre Courbot /// Returns [`None`] if `self` does not fit into the target type.
try_into_bounded(self) -> Option<Bounded<T, N>>515841f31d2SAlexandre Courbot fn try_into_bounded(self) -> Option<Bounded<T, N>>;
51601e345e8SAlexandre Courbot }
51701e345e8SAlexandre Courbot
51801e345e8SAlexandre Courbot /// Any integer value can be attempted to be converted into a [`Bounded`] of any size.
51901e345e8SAlexandre Courbot impl<T, U, const N: u32> TryIntoBounded<T, N> for U
52001e345e8SAlexandre Courbot where
52101e345e8SAlexandre Courbot T: Integer,
52201e345e8SAlexandre Courbot U: TryInto<T>,
52301e345e8SAlexandre Courbot {
try_into_bounded(self) -> Option<Bounded<T, N>>524841f31d2SAlexandre Courbot fn try_into_bounded(self) -> Option<Bounded<T, N>> {
52501e345e8SAlexandre Courbot self.try_into().ok().and_then(Bounded::try_new)
52601e345e8SAlexandre Courbot }
52701e345e8SAlexandre Courbot }
52801e345e8SAlexandre Courbot
52901e345e8SAlexandre Courbot // Comparisons between `Bounded`s.
53001e345e8SAlexandre Courbot
53101e345e8SAlexandre Courbot impl<T, U, const N: u32, const M: u32> PartialEq<Bounded<U, M>> for Bounded<T, N>
53201e345e8SAlexandre Courbot where
53301e345e8SAlexandre Courbot T: Integer,
53401e345e8SAlexandre Courbot U: Integer,
53501e345e8SAlexandre Courbot T: PartialEq<U>,
53601e345e8SAlexandre Courbot {
eq(&self, other: &Bounded<U, M>) -> bool53701e345e8SAlexandre Courbot fn eq(&self, other: &Bounded<U, M>) -> bool {
53801e345e8SAlexandre Courbot self.get() == other.get()
53901e345e8SAlexandre Courbot }
54001e345e8SAlexandre Courbot }
54101e345e8SAlexandre Courbot
54201e345e8SAlexandre Courbot impl<T, const N: u32> Eq for Bounded<T, N> where T: Integer {}
54301e345e8SAlexandre Courbot
54401e345e8SAlexandre Courbot impl<T, U, const N: u32, const M: u32> PartialOrd<Bounded<U, M>> for Bounded<T, N>
54501e345e8SAlexandre Courbot where
54601e345e8SAlexandre Courbot T: Integer,
54701e345e8SAlexandre Courbot U: Integer,
54801e345e8SAlexandre Courbot T: PartialOrd<U>,
54901e345e8SAlexandre Courbot {
partial_cmp(&self, other: &Bounded<U, M>) -> Option<cmp::Ordering>55001e345e8SAlexandre Courbot fn partial_cmp(&self, other: &Bounded<U, M>) -> Option<cmp::Ordering> {
55101e345e8SAlexandre Courbot self.get().partial_cmp(&other.get())
55201e345e8SAlexandre Courbot }
55301e345e8SAlexandre Courbot }
55401e345e8SAlexandre Courbot
55501e345e8SAlexandre Courbot impl<T, const N: u32> Ord for Bounded<T, N>
55601e345e8SAlexandre Courbot where
55701e345e8SAlexandre Courbot T: Integer,
55801e345e8SAlexandre Courbot T: Ord,
55901e345e8SAlexandre Courbot {
cmp(&self, other: &Self) -> cmp::Ordering56001e345e8SAlexandre Courbot fn cmp(&self, other: &Self) -> cmp::Ordering {
56101e345e8SAlexandre Courbot self.get().cmp(&other.get())
56201e345e8SAlexandre Courbot }
56301e345e8SAlexandre Courbot }
56401e345e8SAlexandre Courbot
56501e345e8SAlexandre Courbot // Comparisons between a `Bounded` and its backing type.
56601e345e8SAlexandre Courbot
56701e345e8SAlexandre Courbot impl<T, const N: u32> PartialEq<T> for Bounded<T, N>
56801e345e8SAlexandre Courbot where
56901e345e8SAlexandre Courbot T: Integer,
57001e345e8SAlexandre Courbot T: PartialEq,
57101e345e8SAlexandre Courbot {
eq(&self, other: &T) -> bool57201e345e8SAlexandre Courbot fn eq(&self, other: &T) -> bool {
57301e345e8SAlexandre Courbot self.get() == *other
57401e345e8SAlexandre Courbot }
57501e345e8SAlexandre Courbot }
57601e345e8SAlexandre Courbot
57701e345e8SAlexandre Courbot impl<T, const N: u32> PartialOrd<T> for Bounded<T, N>
57801e345e8SAlexandre Courbot where
57901e345e8SAlexandre Courbot T: Integer,
58001e345e8SAlexandre Courbot T: PartialOrd,
58101e345e8SAlexandre Courbot {
partial_cmp(&self, other: &T) -> Option<cmp::Ordering>58201e345e8SAlexandre Courbot fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
58301e345e8SAlexandre Courbot self.get().partial_cmp(other)
58401e345e8SAlexandre Courbot }
58501e345e8SAlexandre Courbot }
58601e345e8SAlexandre Courbot
58701e345e8SAlexandre Courbot // Implementations of `core::ops` for two `Bounded` with the same backing type.
58801e345e8SAlexandre Courbot
58901e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::Add<Bounded<T, M>> for Bounded<T, N>
59001e345e8SAlexandre Courbot where
59101e345e8SAlexandre Courbot T: Integer,
59201e345e8SAlexandre Courbot T: ops::Add<Output = T>,
59301e345e8SAlexandre Courbot {
59401e345e8SAlexandre Courbot type Output = T;
59501e345e8SAlexandre Courbot
add(self, rhs: Bounded<T, M>) -> Self::Output59601e345e8SAlexandre Courbot fn add(self, rhs: Bounded<T, M>) -> Self::Output {
59701e345e8SAlexandre Courbot self.get() + rhs.get()
59801e345e8SAlexandre Courbot }
59901e345e8SAlexandre Courbot }
60001e345e8SAlexandre Courbot
60101e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::BitAnd<Bounded<T, M>> for Bounded<T, N>
60201e345e8SAlexandre Courbot where
60301e345e8SAlexandre Courbot T: Integer,
60401e345e8SAlexandre Courbot T: ops::BitAnd<Output = T>,
60501e345e8SAlexandre Courbot {
60601e345e8SAlexandre Courbot type Output = T;
60701e345e8SAlexandre Courbot
bitand(self, rhs: Bounded<T, M>) -> Self::Output60801e345e8SAlexandre Courbot fn bitand(self, rhs: Bounded<T, M>) -> Self::Output {
60901e345e8SAlexandre Courbot self.get() & rhs.get()
61001e345e8SAlexandre Courbot }
61101e345e8SAlexandre Courbot }
61201e345e8SAlexandre Courbot
61301e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::BitOr<Bounded<T, M>> for Bounded<T, N>
61401e345e8SAlexandre Courbot where
61501e345e8SAlexandre Courbot T: Integer,
61601e345e8SAlexandre Courbot T: ops::BitOr<Output = T>,
61701e345e8SAlexandre Courbot {
61801e345e8SAlexandre Courbot type Output = T;
61901e345e8SAlexandre Courbot
bitor(self, rhs: Bounded<T, M>) -> Self::Output62001e345e8SAlexandre Courbot fn bitor(self, rhs: Bounded<T, M>) -> Self::Output {
62101e345e8SAlexandre Courbot self.get() | rhs.get()
62201e345e8SAlexandre Courbot }
62301e345e8SAlexandre Courbot }
62401e345e8SAlexandre Courbot
62501e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::BitXor<Bounded<T, M>> for Bounded<T, N>
62601e345e8SAlexandre Courbot where
62701e345e8SAlexandre Courbot T: Integer,
62801e345e8SAlexandre Courbot T: ops::BitXor<Output = T>,
62901e345e8SAlexandre Courbot {
63001e345e8SAlexandre Courbot type Output = T;
63101e345e8SAlexandre Courbot
bitxor(self, rhs: Bounded<T, M>) -> Self::Output63201e345e8SAlexandre Courbot fn bitxor(self, rhs: Bounded<T, M>) -> Self::Output {
63301e345e8SAlexandre Courbot self.get() ^ rhs.get()
63401e345e8SAlexandre Courbot }
63501e345e8SAlexandre Courbot }
63601e345e8SAlexandre Courbot
63701e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::Div<Bounded<T, M>> for Bounded<T, N>
63801e345e8SAlexandre Courbot where
63901e345e8SAlexandre Courbot T: Integer,
64001e345e8SAlexandre Courbot T: ops::Div<Output = T>,
64101e345e8SAlexandre Courbot {
64201e345e8SAlexandre Courbot type Output = T;
64301e345e8SAlexandre Courbot
div(self, rhs: Bounded<T, M>) -> Self::Output64401e345e8SAlexandre Courbot fn div(self, rhs: Bounded<T, M>) -> Self::Output {
64501e345e8SAlexandre Courbot self.get() / rhs.get()
64601e345e8SAlexandre Courbot }
64701e345e8SAlexandre Courbot }
64801e345e8SAlexandre Courbot
64901e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::Mul<Bounded<T, M>> for Bounded<T, N>
65001e345e8SAlexandre Courbot where
65101e345e8SAlexandre Courbot T: Integer,
65201e345e8SAlexandre Courbot T: ops::Mul<Output = T>,
65301e345e8SAlexandre Courbot {
65401e345e8SAlexandre Courbot type Output = T;
65501e345e8SAlexandre Courbot
mul(self, rhs: Bounded<T, M>) -> Self::Output65601e345e8SAlexandre Courbot fn mul(self, rhs: Bounded<T, M>) -> Self::Output {
65701e345e8SAlexandre Courbot self.get() * rhs.get()
65801e345e8SAlexandre Courbot }
65901e345e8SAlexandre Courbot }
66001e345e8SAlexandre Courbot
66101e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::Rem<Bounded<T, M>> for Bounded<T, N>
66201e345e8SAlexandre Courbot where
66301e345e8SAlexandre Courbot T: Integer,
66401e345e8SAlexandre Courbot T: ops::Rem<Output = T>,
66501e345e8SAlexandre Courbot {
66601e345e8SAlexandre Courbot type Output = T;
66701e345e8SAlexandre Courbot
rem(self, rhs: Bounded<T, M>) -> Self::Output66801e345e8SAlexandre Courbot fn rem(self, rhs: Bounded<T, M>) -> Self::Output {
66901e345e8SAlexandre Courbot self.get() % rhs.get()
67001e345e8SAlexandre Courbot }
67101e345e8SAlexandre Courbot }
67201e345e8SAlexandre Courbot
67301e345e8SAlexandre Courbot impl<T, const N: u32, const M: u32> ops::Sub<Bounded<T, M>> for Bounded<T, N>
67401e345e8SAlexandre Courbot where
67501e345e8SAlexandre Courbot T: Integer,
67601e345e8SAlexandre Courbot T: ops::Sub<Output = T>,
67701e345e8SAlexandre Courbot {
67801e345e8SAlexandre Courbot type Output = T;
67901e345e8SAlexandre Courbot
sub(self, rhs: Bounded<T, M>) -> Self::Output68001e345e8SAlexandre Courbot fn sub(self, rhs: Bounded<T, M>) -> Self::Output {
68101e345e8SAlexandre Courbot self.get() - rhs.get()
68201e345e8SAlexandre Courbot }
68301e345e8SAlexandre Courbot }
68401e345e8SAlexandre Courbot
68501e345e8SAlexandre Courbot // Implementations of `core::ops` between a `Bounded` and its backing type.
68601e345e8SAlexandre Courbot
68701e345e8SAlexandre Courbot impl<T, const N: u32> ops::Add<T> for Bounded<T, N>
68801e345e8SAlexandre Courbot where
68901e345e8SAlexandre Courbot T: Integer,
69001e345e8SAlexandre Courbot T: ops::Add<Output = T>,
69101e345e8SAlexandre Courbot {
69201e345e8SAlexandre Courbot type Output = T;
69301e345e8SAlexandre Courbot
add(self, rhs: T) -> Self::Output69401e345e8SAlexandre Courbot fn add(self, rhs: T) -> Self::Output {
69501e345e8SAlexandre Courbot self.get() + rhs
69601e345e8SAlexandre Courbot }
69701e345e8SAlexandre Courbot }
69801e345e8SAlexandre Courbot
69901e345e8SAlexandre Courbot impl<T, const N: u32> ops::BitAnd<T> for Bounded<T, N>
70001e345e8SAlexandre Courbot where
70101e345e8SAlexandre Courbot T: Integer,
70201e345e8SAlexandre Courbot T: ops::BitAnd<Output = T>,
70301e345e8SAlexandre Courbot {
70401e345e8SAlexandre Courbot type Output = T;
70501e345e8SAlexandre Courbot
bitand(self, rhs: T) -> Self::Output70601e345e8SAlexandre Courbot fn bitand(self, rhs: T) -> Self::Output {
70701e345e8SAlexandre Courbot self.get() & rhs
70801e345e8SAlexandre Courbot }
70901e345e8SAlexandre Courbot }
71001e345e8SAlexandre Courbot
71101e345e8SAlexandre Courbot impl<T, const N: u32> ops::BitOr<T> for Bounded<T, N>
71201e345e8SAlexandre Courbot where
71301e345e8SAlexandre Courbot T: Integer,
71401e345e8SAlexandre Courbot T: ops::BitOr<Output = T>,
71501e345e8SAlexandre Courbot {
71601e345e8SAlexandre Courbot type Output = T;
71701e345e8SAlexandre Courbot
bitor(self, rhs: T) -> Self::Output71801e345e8SAlexandre Courbot fn bitor(self, rhs: T) -> Self::Output {
71901e345e8SAlexandre Courbot self.get() | rhs
72001e345e8SAlexandre Courbot }
72101e345e8SAlexandre Courbot }
72201e345e8SAlexandre Courbot
72301e345e8SAlexandre Courbot impl<T, const N: u32> ops::BitXor<T> for Bounded<T, N>
72401e345e8SAlexandre Courbot where
72501e345e8SAlexandre Courbot T: Integer,
72601e345e8SAlexandre Courbot T: ops::BitXor<Output = T>,
72701e345e8SAlexandre Courbot {
72801e345e8SAlexandre Courbot type Output = T;
72901e345e8SAlexandre Courbot
bitxor(self, rhs: T) -> Self::Output73001e345e8SAlexandre Courbot fn bitxor(self, rhs: T) -> Self::Output {
73101e345e8SAlexandre Courbot self.get() ^ rhs
73201e345e8SAlexandre Courbot }
73301e345e8SAlexandre Courbot }
73401e345e8SAlexandre Courbot
73501e345e8SAlexandre Courbot impl<T, const N: u32> ops::Div<T> for Bounded<T, N>
73601e345e8SAlexandre Courbot where
73701e345e8SAlexandre Courbot T: Integer,
73801e345e8SAlexandre Courbot T: ops::Div<Output = T>,
73901e345e8SAlexandre Courbot {
74001e345e8SAlexandre Courbot type Output = T;
74101e345e8SAlexandre Courbot
div(self, rhs: T) -> Self::Output74201e345e8SAlexandre Courbot fn div(self, rhs: T) -> Self::Output {
74301e345e8SAlexandre Courbot self.get() / rhs
74401e345e8SAlexandre Courbot }
74501e345e8SAlexandre Courbot }
74601e345e8SAlexandre Courbot
74701e345e8SAlexandre Courbot impl<T, const N: u32> ops::Mul<T> for Bounded<T, N>
74801e345e8SAlexandre Courbot where
74901e345e8SAlexandre Courbot T: Integer,
75001e345e8SAlexandre Courbot T: ops::Mul<Output = T>,
75101e345e8SAlexandre Courbot {
75201e345e8SAlexandre Courbot type Output = T;
75301e345e8SAlexandre Courbot
mul(self, rhs: T) -> Self::Output75401e345e8SAlexandre Courbot fn mul(self, rhs: T) -> Self::Output {
75501e345e8SAlexandre Courbot self.get() * rhs
75601e345e8SAlexandre Courbot }
75701e345e8SAlexandre Courbot }
75801e345e8SAlexandre Courbot
75901e345e8SAlexandre Courbot impl<T, const N: u32> ops::Neg for Bounded<T, N>
76001e345e8SAlexandre Courbot where
76101e345e8SAlexandre Courbot T: Integer,
76201e345e8SAlexandre Courbot T: ops::Neg<Output = T>,
76301e345e8SAlexandre Courbot {
76401e345e8SAlexandre Courbot type Output = T;
76501e345e8SAlexandre Courbot
neg(self) -> Self::Output76601e345e8SAlexandre Courbot fn neg(self) -> Self::Output {
76701e345e8SAlexandre Courbot -self.get()
76801e345e8SAlexandre Courbot }
76901e345e8SAlexandre Courbot }
77001e345e8SAlexandre Courbot
77101e345e8SAlexandre Courbot impl<T, const N: u32> ops::Not for Bounded<T, N>
77201e345e8SAlexandre Courbot where
77301e345e8SAlexandre Courbot T: Integer,
77401e345e8SAlexandre Courbot T: ops::Not<Output = T>,
77501e345e8SAlexandre Courbot {
77601e345e8SAlexandre Courbot type Output = T;
77701e345e8SAlexandre Courbot
not(self) -> Self::Output77801e345e8SAlexandre Courbot fn not(self) -> Self::Output {
77901e345e8SAlexandre Courbot !self.get()
78001e345e8SAlexandre Courbot }
78101e345e8SAlexandre Courbot }
78201e345e8SAlexandre Courbot
78301e345e8SAlexandre Courbot impl<T, const N: u32> ops::Rem<T> for Bounded<T, N>
78401e345e8SAlexandre Courbot where
78501e345e8SAlexandre Courbot T: Integer,
78601e345e8SAlexandre Courbot T: ops::Rem<Output = T>,
78701e345e8SAlexandre Courbot {
78801e345e8SAlexandre Courbot type Output = T;
78901e345e8SAlexandre Courbot
rem(self, rhs: T) -> Self::Output79001e345e8SAlexandre Courbot fn rem(self, rhs: T) -> Self::Output {
79101e345e8SAlexandre Courbot self.get() % rhs
79201e345e8SAlexandre Courbot }
79301e345e8SAlexandre Courbot }
79401e345e8SAlexandre Courbot
79501e345e8SAlexandre Courbot impl<T, const N: u32> ops::Sub<T> for Bounded<T, N>
79601e345e8SAlexandre Courbot where
79701e345e8SAlexandre Courbot T: Integer,
79801e345e8SAlexandre Courbot T: ops::Sub<Output = T>,
79901e345e8SAlexandre Courbot {
80001e345e8SAlexandre Courbot type Output = T;
80101e345e8SAlexandre Courbot
sub(self, rhs: T) -> Self::Output80201e345e8SAlexandre Courbot fn sub(self, rhs: T) -> Self::Output {
80301e345e8SAlexandre Courbot self.get() - rhs
80401e345e8SAlexandre Courbot }
80501e345e8SAlexandre Courbot }
80601e345e8SAlexandre Courbot
80701e345e8SAlexandre Courbot // Proxy implementations of `core::fmt`.
80801e345e8SAlexandre Courbot
80901e345e8SAlexandre Courbot impl<T, const N: u32> fmt::Display for Bounded<T, N>
81001e345e8SAlexandre Courbot where
81101e345e8SAlexandre Courbot T: Integer,
81201e345e8SAlexandre Courbot T: fmt::Display,
81301e345e8SAlexandre Courbot {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result81401e345e8SAlexandre Courbot fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81501e345e8SAlexandre Courbot self.get().fmt(f)
81601e345e8SAlexandre Courbot }
81701e345e8SAlexandre Courbot }
81801e345e8SAlexandre Courbot
81901e345e8SAlexandre Courbot impl<T, const N: u32> fmt::Binary for Bounded<T, N>
82001e345e8SAlexandre Courbot where
82101e345e8SAlexandre Courbot T: Integer,
82201e345e8SAlexandre Courbot T: fmt::Binary,
82301e345e8SAlexandre Courbot {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result82401e345e8SAlexandre Courbot fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82501e345e8SAlexandre Courbot self.get().fmt(f)
82601e345e8SAlexandre Courbot }
82701e345e8SAlexandre Courbot }
82801e345e8SAlexandre Courbot
82901e345e8SAlexandre Courbot impl<T, const N: u32> fmt::LowerExp for Bounded<T, N>
83001e345e8SAlexandre Courbot where
83101e345e8SAlexandre Courbot T: Integer,
83201e345e8SAlexandre Courbot T: fmt::LowerExp,
83301e345e8SAlexandre Courbot {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result83401e345e8SAlexandre Courbot fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83501e345e8SAlexandre Courbot self.get().fmt(f)
83601e345e8SAlexandre Courbot }
83701e345e8SAlexandre Courbot }
83801e345e8SAlexandre Courbot
83901e345e8SAlexandre Courbot impl<T, const N: u32> fmt::LowerHex for Bounded<T, N>
84001e345e8SAlexandre Courbot where
84101e345e8SAlexandre Courbot T: Integer,
84201e345e8SAlexandre Courbot T: fmt::LowerHex,
84301e345e8SAlexandre Courbot {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84401e345e8SAlexandre Courbot fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84501e345e8SAlexandre Courbot self.get().fmt(f)
84601e345e8SAlexandre Courbot }
84701e345e8SAlexandre Courbot }
84801e345e8SAlexandre Courbot
84901e345e8SAlexandre Courbot impl<T, const N: u32> fmt::Octal for Bounded<T, N>
85001e345e8SAlexandre Courbot where
85101e345e8SAlexandre Courbot T: Integer,
85201e345e8SAlexandre Courbot T: fmt::Octal,
85301e345e8SAlexandre Courbot {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result85401e345e8SAlexandre Courbot fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85501e345e8SAlexandre Courbot self.get().fmt(f)
85601e345e8SAlexandre Courbot }
85701e345e8SAlexandre Courbot }
85801e345e8SAlexandre Courbot
85901e345e8SAlexandre Courbot impl<T, const N: u32> fmt::UpperExp for Bounded<T, N>
86001e345e8SAlexandre Courbot where
86101e345e8SAlexandre Courbot T: Integer,
86201e345e8SAlexandre Courbot T: fmt::UpperExp,
86301e345e8SAlexandre Courbot {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result86401e345e8SAlexandre Courbot fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86501e345e8SAlexandre Courbot self.get().fmt(f)
86601e345e8SAlexandre Courbot }
86701e345e8SAlexandre Courbot }
86801e345e8SAlexandre Courbot
86901e345e8SAlexandre Courbot impl<T, const N: u32> fmt::UpperHex for Bounded<T, N>
87001e345e8SAlexandre Courbot where
87101e345e8SAlexandre Courbot T: Integer,
87201e345e8SAlexandre Courbot T: fmt::UpperHex,
87301e345e8SAlexandre Courbot {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result87401e345e8SAlexandre Courbot fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87501e345e8SAlexandre Courbot self.get().fmt(f)
87601e345e8SAlexandre Courbot }
87701e345e8SAlexandre Courbot }
87801e345e8SAlexandre Courbot
87901e345e8SAlexandre Courbot /// Implements `$trait` for all [`Bounded`] types represented using `$num_bits`.
88001e345e8SAlexandre Courbot ///
88101e345e8SAlexandre Courbot /// This is used to declare size properties as traits that we can constrain against in impl blocks.
88201e345e8SAlexandre Courbot macro_rules! impl_size_rule {
88301e345e8SAlexandre Courbot ($trait:ty, $($num_bits:literal)*) => {
88401e345e8SAlexandre Courbot $(
88501e345e8SAlexandre Courbot impl<T> $trait for Bounded<T, $num_bits> where T: Integer {}
88601e345e8SAlexandre Courbot )*
88701e345e8SAlexandre Courbot };
88801e345e8SAlexandre Courbot }
88901e345e8SAlexandre Courbot
89001e345e8SAlexandre Courbot /// Local trait expressing the fact that a given [`Bounded`] has at least `N` bits used for value
89101e345e8SAlexandre Courbot /// representation.
89201e345e8SAlexandre Courbot trait AtLeastXBits<const N: usize> {}
89301e345e8SAlexandre Courbot
89401e345e8SAlexandre Courbot /// Implementations for infallibly converting a primitive type into a [`Bounded`] that can contain
89501e345e8SAlexandre Courbot /// it.
89601e345e8SAlexandre Courbot ///
89701e345e8SAlexandre Courbot /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent
89801e345e8SAlexandre Courbot /// module.
89901e345e8SAlexandre Courbot mod atleast_impls {
90001e345e8SAlexandre Courbot use super::*;
90101e345e8SAlexandre Courbot
90201e345e8SAlexandre Courbot // Number of bits at least as large as 64.
90301e345e8SAlexandre Courbot impl_size_rule!(AtLeastXBits<64>, 64);
90401e345e8SAlexandre Courbot
90501e345e8SAlexandre Courbot // Anything 64 bits or more is also larger than 32.
90601e345e8SAlexandre Courbot impl<T> AtLeastXBits<32> for T where T: AtLeastXBits<64> {}
90701e345e8SAlexandre Courbot // Other numbers of bits at least as large as 32.
90801e345e8SAlexandre Courbot impl_size_rule!(AtLeastXBits<32>,
90901e345e8SAlexandre Courbot 32 33 34 35 36 37 38 39
91001e345e8SAlexandre Courbot 40 41 42 43 44 45 46 47
91101e345e8SAlexandre Courbot 48 49 50 51 52 53 54 55
91201e345e8SAlexandre Courbot 56 57 58 59 60 61 62 63
91301e345e8SAlexandre Courbot );
91401e345e8SAlexandre Courbot
91501e345e8SAlexandre Courbot // Anything 32 bits or more is also larger than 16.
91601e345e8SAlexandre Courbot impl<T> AtLeastXBits<16> for T where T: AtLeastXBits<32> {}
91701e345e8SAlexandre Courbot // Other numbers of bits at least as large as 16.
91801e345e8SAlexandre Courbot impl_size_rule!(AtLeastXBits<16>,
91901e345e8SAlexandre Courbot 16 17 18 19 20 21 22 23
92001e345e8SAlexandre Courbot 24 25 26 27 28 29 30 31
92101e345e8SAlexandre Courbot );
92201e345e8SAlexandre Courbot
92301e345e8SAlexandre Courbot // Anything 16 bits or more is also larger than 8.
92401e345e8SAlexandre Courbot impl<T> AtLeastXBits<8> for T where T: AtLeastXBits<16> {}
92501e345e8SAlexandre Courbot // Other numbers of bits at least as large as 8.
92601e345e8SAlexandre Courbot impl_size_rule!(AtLeastXBits<8>, 8 9 10 11 12 13 14 15);
92701e345e8SAlexandre Courbot }
92801e345e8SAlexandre Courbot
92901e345e8SAlexandre Courbot /// Generates `From` implementations from a primitive type into a [`Bounded`] with
93001e345e8SAlexandre Courbot /// enough bits to store any value of that type.
93101e345e8SAlexandre Courbot ///
93201e345e8SAlexandre Courbot /// Note: The only reason for having this macro is that if we pass `$type` as a generic
93301e345e8SAlexandre Courbot /// parameter, we cannot use it in the const context of [`AtLeastXBits`]'s generic parameter. This
93401e345e8SAlexandre Courbot /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a
93501e345e8SAlexandre Courbot /// regular `impl` block.
93601e345e8SAlexandre Courbot macro_rules! impl_from_primitive {
93701e345e8SAlexandre Courbot ($($type:ty)*) => {
93801e345e8SAlexandre Courbot $(
93901e345e8SAlexandre Courbot #[doc = ::core::concat!(
94001e345e8SAlexandre Courbot "Conversion from a [`",
94101e345e8SAlexandre Courbot ::core::stringify!($type),
94201e345e8SAlexandre Courbot "`] into a [`Bounded`] of same signedness with enough bits to store it.")]
94301e345e8SAlexandre Courbot impl<T, const N: u32> From<$type> for Bounded<T, N>
94401e345e8SAlexandre Courbot where
94501e345e8SAlexandre Courbot $type: Integer,
94601e345e8SAlexandre Courbot T: Integer<Signedness = <$type as Integer>::Signedness> + From<$type>,
94701e345e8SAlexandre Courbot Self: AtLeastXBits<{ <$type as Integer>::BITS as usize }>,
94801e345e8SAlexandre Courbot {
94901e345e8SAlexandre Courbot fn from(value: $type) -> Self {
9503a1ec424SHsiu Che Yu // SAFETY: The trait bound on `Self` guarantees that `N` bits is
95101e345e8SAlexandre Courbot // enough to hold any value of the source type.
9523a1ec424SHsiu Che Yu unsafe { Self::__new(T::from(value)) }
95301e345e8SAlexandre Courbot }
95401e345e8SAlexandre Courbot }
95501e345e8SAlexandre Courbot )*
95601e345e8SAlexandre Courbot }
95701e345e8SAlexandre Courbot }
95801e345e8SAlexandre Courbot
95901e345e8SAlexandre Courbot impl_from_primitive!(
96001e345e8SAlexandre Courbot u8 u16 u32 u64 usize
96101e345e8SAlexandre Courbot i8 i16 i32 i64 isize
96201e345e8SAlexandre Courbot );
96301e345e8SAlexandre Courbot
96401e345e8SAlexandre Courbot /// Local trait expressing the fact that a given [`Bounded`] fits into a primitive type of `N` bits,
96501e345e8SAlexandre Courbot /// provided they have the same signedness.
96601e345e8SAlexandre Courbot trait FitsInXBits<const N: usize> {}
96701e345e8SAlexandre Courbot
96801e345e8SAlexandre Courbot /// Implementations for infallibly converting a [`Bounded`] into a primitive type that can contain
96901e345e8SAlexandre Courbot /// it.
97001e345e8SAlexandre Courbot ///
97101e345e8SAlexandre Courbot /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent
97201e345e8SAlexandre Courbot /// module.
97301e345e8SAlexandre Courbot mod fits_impls {
97401e345e8SAlexandre Courbot use super::*;
97501e345e8SAlexandre Courbot
97601e345e8SAlexandre Courbot // Number of bits that fit into a 8-bits primitive.
97701e345e8SAlexandre Courbot impl_size_rule!(FitsInXBits<8>, 1 2 3 4 5 6 7 8);
97801e345e8SAlexandre Courbot
97901e345e8SAlexandre Courbot // Anything that fits into 8 bits also fits into 16.
98001e345e8SAlexandre Courbot impl<T> FitsInXBits<16> for T where T: FitsInXBits<8> {}
98101e345e8SAlexandre Courbot // Other number of bits that fit into a 16-bits primitive.
98201e345e8SAlexandre Courbot impl_size_rule!(FitsInXBits<16>, 9 10 11 12 13 14 15 16);
98301e345e8SAlexandre Courbot
98401e345e8SAlexandre Courbot // Anything that fits into 16 bits also fits into 32.
98501e345e8SAlexandre Courbot impl<T> FitsInXBits<32> for T where T: FitsInXBits<16> {}
98601e345e8SAlexandre Courbot // Other number of bits that fit into a 32-bits primitive.
98701e345e8SAlexandre Courbot impl_size_rule!(FitsInXBits<32>,
98801e345e8SAlexandre Courbot 17 18 19 20 21 22 23 24
98901e345e8SAlexandre Courbot 25 26 27 28 29 30 31 32
99001e345e8SAlexandre Courbot );
99101e345e8SAlexandre Courbot
99201e345e8SAlexandre Courbot // Anything that fits into 32 bits also fits into 64.
99301e345e8SAlexandre Courbot impl<T> FitsInXBits<64> for T where T: FitsInXBits<32> {}
99401e345e8SAlexandre Courbot // Other number of bits that fit into a 64-bits primitive.
99501e345e8SAlexandre Courbot impl_size_rule!(FitsInXBits<64>,
99601e345e8SAlexandre Courbot 33 34 35 36 37 38 39 40
99701e345e8SAlexandre Courbot 41 42 43 44 45 46 47 48
99801e345e8SAlexandre Courbot 49 50 51 52 53 54 55 56
99901e345e8SAlexandre Courbot 57 58 59 60 61 62 63 64
100001e345e8SAlexandre Courbot );
100101e345e8SAlexandre Courbot }
100201e345e8SAlexandre Courbot
100301e345e8SAlexandre Courbot /// Generates [`From`] implementations from a [`Bounded`] into a primitive type that is
100401e345e8SAlexandre Courbot /// guaranteed to contain it.
100501e345e8SAlexandre Courbot ///
100601e345e8SAlexandre Courbot /// Note: The only reason for having this macro is that if we pass `$type` as a generic
100701e345e8SAlexandre Courbot /// parameter, we cannot use it in the const context of `AtLeastXBits`'s generic parameter. This
100801e345e8SAlexandre Courbot /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a
100901e345e8SAlexandre Courbot /// regular `impl` block.
101001e345e8SAlexandre Courbot macro_rules! impl_into_primitive {
101101e345e8SAlexandre Courbot ($($type:ty)*) => {
101201e345e8SAlexandre Courbot $(
101301e345e8SAlexandre Courbot #[doc = ::core::concat!(
101401e345e8SAlexandre Courbot "Conversion from a [`Bounded`] with no more bits than a [`",
101501e345e8SAlexandre Courbot ::core::stringify!($type),
101601e345e8SAlexandre Courbot "`] and of same signedness into [`",
101701e345e8SAlexandre Courbot ::core::stringify!($type),
101801e345e8SAlexandre Courbot "`]")]
101901e345e8SAlexandre Courbot impl<T, const N: u32> From<Bounded<T, N>> for $type
102001e345e8SAlexandre Courbot where
102101e345e8SAlexandre Courbot $type: Integer + TryFrom<T>,
102201e345e8SAlexandre Courbot T: Integer<Signedness = <$type as Integer>::Signedness>,
102301e345e8SAlexandre Courbot Bounded<T, N>: FitsInXBits<{ <$type as Integer>::BITS as usize }>,
102401e345e8SAlexandre Courbot {
102501e345e8SAlexandre Courbot fn from(value: Bounded<T, N>) -> $type {
102601e345e8SAlexandre Courbot // SAFETY: The trait bound on `Bounded` ensures that any value it holds (which
102701e345e8SAlexandre Courbot // is constrained to `N` bits) can fit into the destination type, so this
102801e345e8SAlexandre Courbot // conversion cannot fail.
102901e345e8SAlexandre Courbot unsafe { <$type>::try_from(value.get()).unwrap_unchecked() }
103001e345e8SAlexandre Courbot }
103101e345e8SAlexandre Courbot }
103201e345e8SAlexandre Courbot )*
103301e345e8SAlexandre Courbot }
103401e345e8SAlexandre Courbot }
103501e345e8SAlexandre Courbot
103601e345e8SAlexandre Courbot impl_into_primitive!(
103701e345e8SAlexandre Courbot u8 u16 u32 u64 usize
103801e345e8SAlexandre Courbot i8 i16 i32 i64 isize
103901e345e8SAlexandre Courbot );
104001e345e8SAlexandre Courbot
104101e345e8SAlexandre Courbot // Single-bit `Bounded`s can be converted from/to a boolean.
104201e345e8SAlexandre Courbot
104301e345e8SAlexandre Courbot impl<T> From<Bounded<T, 1>> for bool
104401e345e8SAlexandre Courbot where
104501e345e8SAlexandre Courbot T: Integer + Zeroable,
104601e345e8SAlexandre Courbot {
from(value: Bounded<T, 1>) -> Self104701e345e8SAlexandre Courbot fn from(value: Bounded<T, 1>) -> Self {
104801e345e8SAlexandre Courbot value.get() != Zeroable::zeroed()
104901e345e8SAlexandre Courbot }
105001e345e8SAlexandre Courbot }
105101e345e8SAlexandre Courbot
105201e345e8SAlexandre Courbot impl<T, const N: u32> From<bool> for Bounded<T, N>
105301e345e8SAlexandre Courbot where
105401e345e8SAlexandre Courbot T: Integer + From<bool>,
105501e345e8SAlexandre Courbot {
from(value: bool) -> Self105601e345e8SAlexandre Courbot fn from(value: bool) -> Self {
10573a1ec424SHsiu Che Yu // SAFETY: A boolean can be represented using a single bit, and thus fits within any
105801e345e8SAlexandre Courbot // integer type for any `N` > 0.
10593a1ec424SHsiu Che Yu unsafe { Self::__new(T::from(value)) }
106001e345e8SAlexandre Courbot }
106101e345e8SAlexandre Courbot }
1062