Skip to main content

kernel/num/
bounded.rs

1// SPDX-License-Identifier: GPL-2.0
2
3//! Implementation of [`Bounded`], a wrapper around integer types limiting the number of bits
4//! usable for value representation.
5
6use core::{
7    cmp,
8    fmt,
9    ops::{
10        self,
11        Deref, //
12    }, //,
13};
14
15use kernel::{
16    num::{
17        Integer,
18        Unsigned, //
19    },
20    prelude::*, //
21};
22
23/// Evaluates to `true` if `$value` can be represented using at most `$n` bits in a `$type`.
24///
25/// `expr` must be of type `type`, or the result will be incorrect.
26///
27/// Can be used in const context.
28macro_rules! fits_within {
29    ($value:expr, $type:ty, $n:expr) => {{
30        let shift: u32 = <$type>::BITS - $n;
31
32        // `value` fits within `$n` bits if shifting it left by the number of unused bits, then
33        // right by the same number, doesn't change it.
34        //
35        // This method has the benefit of working for both unsigned and signed values.
36        ($value << shift) >> shift == $value
37    }};
38}
39
40/// Returns `true` if `value` can be represented with at most `N` bits in a `T`.
41#[inline(always)]
42fn fits_within<T: Integer>(value: T, num_bits: u32) -> bool {
43    fits_within!(value, T, num_bits)
44}
45
46/// An integer value that requires only the `N` least significant bits of the wrapped type to be
47/// encoded.
48///
49/// This limits the number of usable bits in the wrapped integer type, and thus the stored value to
50/// a narrower range, which provides guarantees that can be useful when working within e.g.
51/// bitfields.
52///
53/// # Invariants
54///
55/// - `N` is greater than `0`.
56/// - `N` is less than or equal to `T::BITS`.
57/// - Stored values can be represented with at most `N` bits.
58///
59/// # Examples
60///
61/// The preferred way to create values is through constants and the [`Bounded::new`] family of
62/// constructors, as they trigger a build error if the type invariants cannot be upheld.
63///
64/// ```
65/// use kernel::num::Bounded;
66///
67/// // An unsigned 8-bit integer, of which only the 4 LSBs are used.
68/// // The value `15` is statically validated to fit that constraint at build time.
69/// let v = Bounded::<u8, 4>::new::<15>();
70/// assert_eq!(v.get(), 15);
71///
72/// // Same using signed values.
73/// let v = Bounded::<i8, 4>::new::<-8>();
74/// assert_eq!(v.get(), -8);
75///
76/// // This doesn't build: a `u8` is smaller than the requested 9 bits.
77/// // let _ = Bounded::<u8, 9>::new::<10>();
78///
79/// // This also doesn't build: the requested value doesn't fit within 4 signed bits.
80/// // let _ = Bounded::<i8, 4>::new::<8>();
81/// ```
82///
83/// Values can also be validated at runtime with [`Bounded::try_new`].
84///
85/// ```
86/// use kernel::num::Bounded;
87///
88/// // This succeeds because `15` can be represented with 4 unsigned bits.
89/// assert!(Bounded::<u8, 4>::try_new(15).is_some());
90///
91/// // This fails because `16` cannot be represented with 4 unsigned bits.
92/// assert!(Bounded::<u8, 4>::try_new(16).is_none());
93/// ```
94///
95/// Non-constant expressions can be validated at build-time thanks to compiler optimizations. This
96/// should be used with caution, on simple expressions only.
97///
98/// ```
99/// use kernel::num::Bounded;
100/// # fn some_number() -> u32 { 0xffffffff }
101///
102/// // Here the compiler can infer from the mask that the type invariants are not violated, even
103/// // though the value returned by `some_number` is not statically known.
104/// let v = Bounded::<u32, 4>::from_expr(some_number() & 0xf);
105/// ```
106///
107/// Comparison and arithmetic operations are supported on [`Bounded`]s with a compatible backing
108/// type, regardless of their number of valid bits.
109///
110/// ```
111/// use kernel::num::Bounded;
112///
113/// let v1 = Bounded::<u32, 8>::new::<4>();
114/// let v2 = Bounded::<u32, 4>::new::<15>();
115///
116/// assert!(v1 != v2);
117/// assert!(v1 < v2);
118/// assert_eq!(v1 + v2, 19);
119/// assert_eq!(v2 % v1, 3);
120/// ```
121///
122/// These operations are also supported between a [`Bounded`] and its backing type.
123///
124/// ```
125/// use kernel::num::Bounded;
126///
127/// let v = Bounded::<u8, 4>::new::<15>();
128///
129/// assert!(v == 15);
130/// assert!(v > 12);
131/// assert_eq!(v + 5, 20);
132/// assert_eq!(v / 3, 5);
133/// ```
134///
135/// A change of backing types is possible using [`Bounded::cast`], and the number of valid bits can
136/// be extended or reduced with [`Bounded::extend`] and [`Bounded::try_shrink`].
137///
138/// ```
139/// use kernel::num::Bounded;
140///
141/// let v = Bounded::<u32, 12>::new::<127>();
142///
143/// // Changes backing type from `u32` to `u16`.
144/// let _: Bounded<u16, 12> = v.cast();
145///
146/// // This does not build, as `u8` is smaller than 12 bits.
147/// // let _: Bounded<u8, 12> = v.cast();
148///
149/// // We can safely extend the number of bits...
150/// let _ = v.extend::<15>();
151///
152/// // ... to the limits of the backing type. This doesn't build as a `u32` cannot contain 33 bits.
153/// // let _ = v.extend::<33>();
154///
155/// // Reducing the number of bits is validated at runtime. This works because `127` can be
156/// // represented with 8 bits.
157/// assert!(v.try_shrink::<8>().is_some());
158///
159/// // ... but not with 6, so this fails.
160/// assert!(v.try_shrink::<6>().is_none());
161/// ```
162///
163/// Infallible conversions from a primitive integer to a large-enough [`Bounded`] are supported.
164///
165/// ```
166/// use kernel::num::Bounded;
167///
168/// // This unsigned `Bounded` has 8 bits, so it can represent any `u8`.
169/// let v = Bounded::<u32, 8>::from(128u8);
170/// assert_eq!(v.get(), 128);
171///
172/// // This signed `Bounded` has 8 bits, so it can represent any `i8`.
173/// let v = Bounded::<i32, 8>::from(-128i8);
174/// assert_eq!(v.get(), -128);
175///
176/// // This doesn't build, as this 6-bit `Bounded` does not have enough capacity to represent a
177/// // `u8` (regardless of the passed value).
178/// // let _ = Bounded::<u32, 6>::from(10u8);
179///
180/// // Booleans can be converted into unsigned `Bounded`s.
181///
182/// let v = Bounded::<u64, 1>::from(false);
183/// assert_eq!(v.get(), 0);
184///
185/// let v = Bounded::<u64, 1>::from(true);
186/// assert_eq!(v.get(), 1);
187///
188/// // This does not build because `i8` is signed.
189/// // let _ = Bounded::<i8, 2>::from(true);
190/// ```
191///
192/// Infallible conversions from a [`Bounded`] to a primitive integer are also supported, and
193/// dependent on the number of bits used for value representation, not on the backing type.
194///
195/// ```
196/// use kernel::num::Bounded;
197///
198/// // Even though its backing type is `u32`, this `Bounded` only uses 6 bits and thus can safely
199/// // be converted to a `u8`.
200/// let v = Bounded::<u32, 6>::new::<63>();
201/// assert_eq!(u8::from(v), 63);
202///
203/// // Same using signed values.
204/// let v = Bounded::<i32, 8>::new::<-128>();
205/// assert_eq!(i8::from(v), -128);
206///
207/// // This however does not build, as 10 bits won't fit into a `u8` (regardless of the actually
208/// // contained value).
209/// let _v = Bounded::<u32, 10>::new::<10>();
210/// // assert_eq!(u8::from(_v), 10);
211///
212/// // Unsigned single-bit `Bounded`s can be converted into a boolean.
213/// let v = Bounded::<u8, 1>::new::<1>();
214/// assert_eq!(bool::from(v), true);
215///
216/// let v = Bounded::<u8, 1>::new::<0>();
217/// assert_eq!(bool::from(v), false);
218///
219/// // This does not build because `i8` is signed.
220/// // let v = Bounded::<i8, 1>::new::<-1>();
221/// // let _ = bool::from(v);
222/// ```
223///
224/// Fallible conversions from any primitive integer to any [`Bounded`] are also supported using the
225/// [`TryIntoBounded`] trait.
226///
227/// ```
228/// use kernel::num::{Bounded, TryIntoBounded};
229///
230/// // Succeeds because `128` fits into 8 bits.
231/// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded();
232/// assert_eq!(v.as_deref().copied(), Some(128));
233///
234/// // Fails because `128` doesn't fit into 6 bits.
235/// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded();
236/// assert_eq!(v, None);
237/// ```
238#[repr(transparent)]
239#[derive(Clone, Copy, Debug, Default, Hash)]
240pub struct Bounded<T: Integer, const N: u32>(T);
241
242/// Validating the value as a const expression cannot be done as a regular method, as the
243/// arithmetic operations we rely on to check the bounds are not const. Thus, implement
244/// [`Bounded::new`] using a macro.
245macro_rules! impl_const_new {
246    ($($type:ty)*) => {
247        $(
248        impl<const N: u32> Bounded<$type, N> {
249            /// Creates a [`Bounded`] for the constant `VALUE`.
250            ///
251            /// Fails at build time if `VALUE` cannot be represented with `N` bits.
252            ///
253            /// This method should be preferred to [`Self::from_expr`] whenever possible.
254            ///
255            /// # Examples
256            ///
257            /// ```
258            /// use kernel::num::Bounded;
259            ///
260            #[doc = ::core::concat!(
261                "let v = Bounded::<",
262                ::core::stringify!($type),
263                ", 4>::new::<7>();")]
264            /// assert_eq!(v.get(), 7);
265            /// ```
266            pub const fn new<const VALUE: $type>() -> Self {
267                // Statically assert that `VALUE` fits within the set number of bits.
268                const_assert!(fits_within!(VALUE, $type, N));
269
270                // SAFETY: `fits_within` confirmed that `VALUE` can be represented within
271                // `N` bits.
272                unsafe { Self::__new(VALUE) }
273            }
274        }
275        )*
276    };
277}
278
279impl_const_new!(
280    u8 u16 u32 u64 usize
281    i8 i16 i32 i64 isize
282);
283
284impl<T, const N: u32> Bounded<T, N>
285where
286    T: Integer,
287{
288    /// Private constructor enforcing the type invariants.
289    ///
290    /// All instances of [`Bounded`] must be created through this method as it enforces most of the
291    /// type invariants.
292    ///
293    /// # Safety
294    ///
295    /// The caller must ensure that `value` can be represented within `N` bits.
296    const unsafe fn __new(value: T) -> Self {
297        // Enforce the type invariants.
298        // `N` cannot be zero.
299        const_assert!(N != 0);
300        // The backing type is at least as large as `N` bits.
301        const_assert!(N <= T::BITS);
302
303        // INVARIANT: The caller ensures `value` fits within `N` bits.
304        Self(value)
305    }
306
307    /// Attempts to turn `value` into a `Bounded` using `N` bits.
308    ///
309    /// Returns [`None`] if `value` doesn't fit within `N` bits.
310    ///
311    /// # Examples
312    ///
313    /// ```
314    /// use kernel::num::Bounded;
315    ///
316    /// let v = Bounded::<u8, 1>::try_new(1);
317    /// assert_eq!(v.as_deref().copied(), Some(1));
318    ///
319    /// let v = Bounded::<i8, 4>::try_new(-2);
320    /// assert_eq!(v.as_deref().copied(), Some(-2));
321    ///
322    /// // `0x1ff` doesn't fit into 8 unsigned bits.
323    /// let v = Bounded::<u32, 8>::try_new(0x1ff);
324    /// assert_eq!(v, None);
325    ///
326    /// // The range of values representable with 4 bits is `[-8..=7]`. The following tests these
327    /// // limits.
328    /// let v = Bounded::<i8, 4>::try_new(-8);
329    /// assert_eq!(v.map(Bounded::get), Some(-8));
330    /// let v = Bounded::<i8, 4>::try_new(-9);
331    /// assert_eq!(v, None);
332    /// let v = Bounded::<i8, 4>::try_new(7);
333    /// assert_eq!(v.map(Bounded::get), Some(7));
334    /// let v = Bounded::<i8, 4>::try_new(8);
335    /// assert_eq!(v, None);
336    /// ```
337    pub fn try_new(value: T) -> Option<Self> {
338        fits_within(value, N).then(|| {
339            // SAFETY: `fits_within` confirmed that `value` can be represented within `N` bits.
340            unsafe { Self::__new(value) }
341        })
342    }
343
344    /// Checks that `expr` is valid for this type at compile-time and build a new value.
345    ///
346    /// This relies on [`build_assert!`] and guaranteed optimization to perform validation at
347    /// compile-time. If `expr` cannot be proved to be within the requested bounds at compile-time,
348    /// use the fallible [`Self::try_new`] instead.
349    ///
350    /// Limit this to simple, easily provable expressions, and prefer one of the [`Self::new`]
351    /// constructors whenever possible as they statically validate the value instead of relying on
352    /// compiler optimizations.
353    ///
354    /// # Examples
355    ///
356    /// ```
357    /// use kernel::num::Bounded;
358    /// # fn some_number() -> u32 { 0xffffffff }
359    ///
360    /// // Some undefined number.
361    /// let v: u32 = some_number();
362    ///
363    /// // Triggers a build error as `v` cannot be asserted to fit within 4 bits...
364    /// // let _ = Bounded::<u32, 4>::from_expr(v);
365    ///
366    /// // ... but this works as the compiler can assert the range from the mask.
367    /// let _ = Bounded::<u32, 4>::from_expr(v & 0xf);
368    ///
369    /// // These expressions are simple enough to be proven correct, but since they are static the
370    /// // `new` constructor should be preferred.
371    /// assert_eq!(Bounded::<u8, 1>::from_expr(1).get(), 1);
372    /// assert_eq!(Bounded::<u16, 8>::from_expr(0xff).get(), 0xff);
373    /// ```
374    // Always inline to optimize out error path of `build_assert`.
375    #[inline(always)]
376    pub fn from_expr(expr: T) -> Self {
377        crate::build_assert::build_assert!(
378            fits_within(expr, N),
379            "Requested value larger than maximal representable value."
380        );
381
382        // SAFETY: `fits_within` confirmed that `expr` can be represented within `N` bits.
383        unsafe { Self::__new(expr) }
384    }
385
386    /// Returns the wrapped value as the backing type.
387    ///
388    /// This is similar to the [`Deref`] implementation, but doesn't enforce the size invariant of
389    /// the [`Bounded`], which might produce slightly less optimal code.
390    ///
391    /// # Examples
392    ///
393    /// ```
394    /// use kernel::num::Bounded;
395    ///
396    /// let v = Bounded::<u32, 4>::new::<7>();
397    /// assert_eq!(v.get(), 7u32);
398    /// ```
399    pub const fn get(self) -> T {
400        self.0
401    }
402
403    /// Increases the number of bits usable for `self`.
404    ///
405    /// This operation cannot fail.
406    ///
407    /// # Examples
408    ///
409    /// ```
410    /// use kernel::num::Bounded;
411    ///
412    /// let v = Bounded::<u32, 4>::new::<7>();
413    /// let larger_v = v.extend::<12>();
414    /// // The contained values are equal even though `larger_v` has a bigger capacity.
415    /// assert_eq!(larger_v, v);
416    /// ```
417    pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
418        const_assert!(
419            M >= N,
420            "Requested number of bits is less than the current representation."
421        );
422
423        // SAFETY: The value did fit within `N` bits, so it will all the more fit within
424        // the larger `M` bits.
425        unsafe { Bounded::__new(self.0) }
426    }
427
428    /// Attempts to shrink the number of bits usable for `self`.
429    ///
430    /// Returns [`None`] if the value of `self` cannot be represented within `M` bits.
431    ///
432    /// # Examples
433    ///
434    /// ```
435    /// use kernel::num::Bounded;
436    ///
437    /// let v = Bounded::<u32, 12>::new::<7>();
438    ///
439    /// // `7` can be represented using 3 unsigned bits...
440    /// let smaller_v = v.try_shrink::<3>();
441    /// assert_eq!(smaller_v.as_deref().copied(), Some(7));
442    ///
443    /// // ... but doesn't fit within `2` bits.
444    /// assert_eq!(v.try_shrink::<2>(), None);
445    /// ```
446    pub fn try_shrink<const M: u32>(self) -> Option<Bounded<T, M>> {
447        Bounded::<T, M>::try_new(self.get())
448    }
449
450    /// Casts `self` into a [`Bounded`] backed by a different storage type, but using the same
451    /// number of valid bits.
452    ///
453    /// Both `T` and `U` must be of same signedness, and `U` must be at least as large as
454    /// `N` bits, or a build error will occur.
455    ///
456    /// # Examples
457    ///
458    /// ```
459    /// use kernel::num::Bounded;
460    ///
461    /// let v = Bounded::<u32, 12>::new::<127>();
462    ///
463    /// let u16_v: Bounded<u16, 12> = v.cast();
464    /// assert_eq!(u16_v.get(), 127);
465    ///
466    /// // This won't build: a `u8` is smaller than the required 12 bits.
467    /// // let _: Bounded<u8, 12> = v.cast();
468    /// ```
469    pub fn cast<U>(self) -> Bounded<U, N>
470    where
471        U: TryFrom<T> + Integer,
472        T: Integer,
473        U: Integer<Signedness = T::Signedness>,
474    {
475        // SAFETY: The converted value is represented using `N` bits, `U` can contain `N` bits, and
476        // `U` and `T` have the same sign, hence this conversion cannot fail.
477        let value = unsafe { U::try_from(self.get()).unwrap_unchecked() };
478
479        // SAFETY: Although the backing type has changed, the value is still represented within
480        // `N` bits, and with the same signedness.
481        unsafe { Bounded::__new(value) }
482    }
483
484    /// Right-shifts `self` by `SHIFT` and returns the result as a `Bounded<_, RES>`, where `RES >=
485    /// N - SHIFT`.
486    ///
487    /// # Examples
488    ///
489    /// ```
490    /// use kernel::num::Bounded;
491    ///
492    /// let v = Bounded::<u32, 16>::new::<0xff00>();
493    /// let v_shifted: Bounded::<u32, 8> = v.shr::<8, _>();
494    ///
495    /// assert_eq!(v_shifted.get(), 0xff);
496    /// ```
497    pub fn shr<const SHIFT: u32, const RES: u32>(self) -> Bounded<T, RES> {
498        const_assert!(SHIFT < T::BITS);
499        const { assert!(RES + SHIFT >= N) }
500
501        // SAFETY: We shift the value right by `SHIFT`, reducing the number of bits needed to
502        // represent the shifted value by as much, and just asserted that `RES >= N - SHIFT`.
503        unsafe { Bounded::__new(self.0 >> SHIFT) }
504    }
505
506    /// Left-shifts `self` by `SHIFT` and returns the result as a `Bounded<_, RES>`, where `RES >=
507    /// N + SHIFT`.
508    ///
509    /// # Examples
510    ///
511    /// ```
512    /// use kernel::num::Bounded;
513    ///
514    /// let v = Bounded::<u32, 8>::new::<0xff>();
515    /// let v_shifted: Bounded::<u32, 16> = v.shl::<8, _>();
516    ///
517    /// assert_eq!(v_shifted.get(), 0xff00);
518    /// ```
519    pub fn shl<const SHIFT: u32, const RES: u32>(self) -> Bounded<T, RES> {
520        const { assert!(RES >= N + SHIFT) }
521
522        // SAFETY: We shift the value left by `SHIFT`, augmenting the number of bits needed to
523        // represent the shifted value by as much, and just asserted that `RES >= N + SHIFT`.
524        unsafe { Bounded::__new(self.0 << SHIFT) }
525    }
526}
527
528impl<T, const N: u32> Deref for Bounded<T, N>
529where
530    T: Integer,
531{
532    type Target = T;
533
534    fn deref(&self) -> &Self::Target {
535        // Enforce the invariant to inform the compiler of the bounds of the value.
536        if !fits_within(self.0, N) {
537            // SAFETY: Per the `Bounded` invariants, `fits_within` can never return `false` on the
538            // value of a valid instance.
539            unsafe { core::hint::unreachable_unchecked() }
540        }
541
542        &self.0
543    }
544}
545
546/// Trait similar to [`TryInto`] but for [`Bounded`], to avoid conflicting implementations.
547///
548/// # Examples
549///
550/// ```
551/// use kernel::num::{Bounded, TryIntoBounded};
552///
553/// // Succeeds because `128` fits into 8 bits.
554/// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded();
555/// assert_eq!(v.as_deref().copied(), Some(128));
556///
557/// // Fails because `128` doesn't fit into 6 bits.
558/// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded();
559/// assert_eq!(v, None);
560/// ```
561pub trait TryIntoBounded<T: Integer, const N: u32> {
562    /// Attempts to convert `self` into a [`Bounded`] using `N` bits.
563    ///
564    /// Returns [`None`] if `self` does not fit into the target type.
565    fn try_into_bounded(self) -> Option<Bounded<T, N>>;
566}
567
568/// Any integer value can be attempted to be converted into a [`Bounded`] of any size.
569impl<T, U, const N: u32> TryIntoBounded<T, N> for U
570where
571    T: Integer,
572    U: TryInto<T>,
573{
574    fn try_into_bounded(self) -> Option<Bounded<T, N>> {
575        self.try_into().ok().and_then(Bounded::try_new)
576    }
577}
578
579// Comparisons between `Bounded`s.
580
581impl<T, U, const N: u32, const M: u32> PartialEq<Bounded<U, M>> for Bounded<T, N>
582where
583    T: Integer,
584    U: Integer,
585    T: PartialEq<U>,
586{
587    fn eq(&self, other: &Bounded<U, M>) -> bool {
588        self.get() == other.get()
589    }
590}
591
592impl<T, const N: u32> Eq for Bounded<T, N> where T: Integer {}
593
594impl<T, U, const N: u32, const M: u32> PartialOrd<Bounded<U, M>> for Bounded<T, N>
595where
596    T: Integer,
597    U: Integer,
598    T: PartialOrd<U>,
599{
600    fn partial_cmp(&self, other: &Bounded<U, M>) -> Option<cmp::Ordering> {
601        self.get().partial_cmp(&other.get())
602    }
603}
604
605impl<T, const N: u32> Ord for Bounded<T, N>
606where
607    T: Integer,
608    T: Ord,
609{
610    fn cmp(&self, other: &Self) -> cmp::Ordering {
611        self.get().cmp(&other.get())
612    }
613}
614
615// Comparisons between a `Bounded` and its backing type.
616
617impl<T, const N: u32> PartialEq<T> for Bounded<T, N>
618where
619    T: Integer,
620    T: PartialEq,
621{
622    fn eq(&self, other: &T) -> bool {
623        self.get() == *other
624    }
625}
626
627impl<T, const N: u32> PartialOrd<T> for Bounded<T, N>
628where
629    T: Integer,
630    T: PartialOrd,
631{
632    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
633        self.get().partial_cmp(other)
634    }
635}
636
637// Implementations of `core::ops` for two `Bounded` with the same backing type.
638
639impl<T, const N: u32, const M: u32> ops::Add<Bounded<T, M>> for Bounded<T, N>
640where
641    T: Integer,
642    T: ops::Add<Output = T>,
643{
644    type Output = T;
645
646    fn add(self, rhs: Bounded<T, M>) -> Self::Output {
647        self.get() + rhs.get()
648    }
649}
650
651impl<T, const N: u32, const M: u32> ops::BitAnd<Bounded<T, M>> for Bounded<T, N>
652where
653    T: Integer,
654    T: ops::BitAnd<Output = T>,
655{
656    type Output = T;
657
658    fn bitand(self, rhs: Bounded<T, M>) -> Self::Output {
659        self.get() & rhs.get()
660    }
661}
662
663impl<T, const N: u32, const M: u32> ops::BitOr<Bounded<T, M>> for Bounded<T, N>
664where
665    T: Integer,
666    T: ops::BitOr<Output = T>,
667{
668    type Output = T;
669
670    fn bitor(self, rhs: Bounded<T, M>) -> Self::Output {
671        self.get() | rhs.get()
672    }
673}
674
675impl<T, const N: u32, const M: u32> ops::BitXor<Bounded<T, M>> for Bounded<T, N>
676where
677    T: Integer,
678    T: ops::BitXor<Output = T>,
679{
680    type Output = T;
681
682    fn bitxor(self, rhs: Bounded<T, M>) -> Self::Output {
683        self.get() ^ rhs.get()
684    }
685}
686
687impl<T, const N: u32, const M: u32> ops::Div<Bounded<T, M>> for Bounded<T, N>
688where
689    T: Integer,
690    T: ops::Div<Output = T>,
691{
692    type Output = T;
693
694    fn div(self, rhs: Bounded<T, M>) -> Self::Output {
695        self.get() / rhs.get()
696    }
697}
698
699impl<T, const N: u32, const M: u32> ops::Mul<Bounded<T, M>> for Bounded<T, N>
700where
701    T: Integer,
702    T: ops::Mul<Output = T>,
703{
704    type Output = T;
705
706    fn mul(self, rhs: Bounded<T, M>) -> Self::Output {
707        self.get() * rhs.get()
708    }
709}
710
711impl<T, const N: u32, const M: u32> ops::Rem<Bounded<T, M>> for Bounded<T, N>
712where
713    T: Integer,
714    T: ops::Rem<Output = T>,
715{
716    type Output = T;
717
718    fn rem(self, rhs: Bounded<T, M>) -> Self::Output {
719        self.get() % rhs.get()
720    }
721}
722
723impl<T, const N: u32, const M: u32> ops::Sub<Bounded<T, M>> for Bounded<T, N>
724where
725    T: Integer,
726    T: ops::Sub<Output = T>,
727{
728    type Output = T;
729
730    fn sub(self, rhs: Bounded<T, M>) -> Self::Output {
731        self.get() - rhs.get()
732    }
733}
734
735// Implementations of `core::ops` between a `Bounded` and its backing type.
736
737impl<T, const N: u32> ops::Add<T> for Bounded<T, N>
738where
739    T: Integer,
740    T: ops::Add<Output = T>,
741{
742    type Output = T;
743
744    fn add(self, rhs: T) -> Self::Output {
745        self.get() + rhs
746    }
747}
748
749impl<T, const N: u32> ops::BitAnd<T> for Bounded<T, N>
750where
751    T: Integer,
752    T: ops::BitAnd<Output = T>,
753{
754    type Output = T;
755
756    fn bitand(self, rhs: T) -> Self::Output {
757        self.get() & rhs
758    }
759}
760
761impl<T, const N: u32> ops::BitOr<T> for Bounded<T, N>
762where
763    T: Integer,
764    T: ops::BitOr<Output = T>,
765{
766    type Output = T;
767
768    fn bitor(self, rhs: T) -> Self::Output {
769        self.get() | rhs
770    }
771}
772
773impl<T, const N: u32> ops::BitXor<T> for Bounded<T, N>
774where
775    T: Integer,
776    T: ops::BitXor<Output = T>,
777{
778    type Output = T;
779
780    fn bitxor(self, rhs: T) -> Self::Output {
781        self.get() ^ rhs
782    }
783}
784
785impl<T, const N: u32> ops::Div<T> for Bounded<T, N>
786where
787    T: Integer,
788    T: ops::Div<Output = T>,
789{
790    type Output = T;
791
792    fn div(self, rhs: T) -> Self::Output {
793        self.get() / rhs
794    }
795}
796
797impl<T, const N: u32> ops::Mul<T> for Bounded<T, N>
798where
799    T: Integer,
800    T: ops::Mul<Output = T>,
801{
802    type Output = T;
803
804    fn mul(self, rhs: T) -> Self::Output {
805        self.get() * rhs
806    }
807}
808
809impl<T, const N: u32> ops::Neg for Bounded<T, N>
810where
811    T: Integer,
812    T: ops::Neg<Output = T>,
813{
814    type Output = T;
815
816    fn neg(self) -> Self::Output {
817        -self.get()
818    }
819}
820
821impl<T, const N: u32> ops::Not for Bounded<T, N>
822where
823    T: Integer,
824    T: ops::Not<Output = T>,
825{
826    type Output = T;
827
828    fn not(self) -> Self::Output {
829        !self.get()
830    }
831}
832
833impl<T, const N: u32> ops::Rem<T> for Bounded<T, N>
834where
835    T: Integer,
836    T: ops::Rem<Output = T>,
837{
838    type Output = T;
839
840    fn rem(self, rhs: T) -> Self::Output {
841        self.get() % rhs
842    }
843}
844
845impl<T, const N: u32> ops::Sub<T> for Bounded<T, N>
846where
847    T: Integer,
848    T: ops::Sub<Output = T>,
849{
850    type Output = T;
851
852    fn sub(self, rhs: T) -> Self::Output {
853        self.get() - rhs
854    }
855}
856
857// Proxy implementations of `core::fmt`.
858
859impl<T, const N: u32> fmt::Display for Bounded<T, N>
860where
861    T: Integer,
862    T: fmt::Display,
863{
864    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
865        self.get().fmt(f)
866    }
867}
868
869impl<T, const N: u32> fmt::Binary for Bounded<T, N>
870where
871    T: Integer,
872    T: fmt::Binary,
873{
874    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
875        self.get().fmt(f)
876    }
877}
878
879impl<T, const N: u32> fmt::LowerExp for Bounded<T, N>
880where
881    T: Integer,
882    T: fmt::LowerExp,
883{
884    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
885        self.get().fmt(f)
886    }
887}
888
889impl<T, const N: u32> fmt::LowerHex for Bounded<T, N>
890where
891    T: Integer,
892    T: fmt::LowerHex,
893{
894    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
895        self.get().fmt(f)
896    }
897}
898
899impl<T, const N: u32> fmt::Octal for Bounded<T, N>
900where
901    T: Integer,
902    T: fmt::Octal,
903{
904    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
905        self.get().fmt(f)
906    }
907}
908
909impl<T, const N: u32> fmt::UpperExp for Bounded<T, N>
910where
911    T: Integer,
912    T: fmt::UpperExp,
913{
914    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
915        self.get().fmt(f)
916    }
917}
918
919impl<T, const N: u32> fmt::UpperHex for Bounded<T, N>
920where
921    T: Integer,
922    T: fmt::UpperHex,
923{
924    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
925        self.get().fmt(f)
926    }
927}
928
929/// Implements `$trait` for all [`Bounded`] types represented using `$num_bits`.
930///
931/// This is used to declare size properties as traits that we can constrain against in impl blocks.
932macro_rules! impl_size_rule {
933    ($trait:ty, $($num_bits:literal)*) => {
934        $(
935        impl<T> $trait for Bounded<T, $num_bits> where T: Integer {}
936        )*
937    };
938}
939
940/// Local trait expressing the fact that a given [`Bounded`] has at least `N` bits used for value
941/// representation.
942trait AtLeastXBits<const N: usize> {}
943
944/// Implementations for infallibly converting a primitive type into a [`Bounded`] that can contain
945/// it.
946///
947/// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent
948/// module.
949mod atleast_impls {
950    use super::*;
951
952    // Number of bits at least as large as 64.
953    impl_size_rule!(AtLeastXBits<64>, 64);
954
955    // Anything 64 bits or more is also larger than 32.
956    impl<T> AtLeastXBits<32> for T where T: AtLeastXBits<64> {}
957    // Other numbers of bits at least as large as 32.
958    impl_size_rule!(AtLeastXBits<32>,
959        32 33 34 35 36 37 38 39
960        40 41 42 43 44 45 46 47
961        48 49 50 51 52 53 54 55
962        56 57 58 59 60 61 62 63
963    );
964
965    // Anything 32 bits or more is also larger than 16.
966    impl<T> AtLeastXBits<16> for T where T: AtLeastXBits<32> {}
967    // Other numbers of bits at least as large as 16.
968    impl_size_rule!(AtLeastXBits<16>,
969        16 17 18 19 20 21 22 23
970        24 25 26 27 28 29 30 31
971    );
972
973    // Anything 16 bits or more is also larger than 8.
974    impl<T> AtLeastXBits<8> for T where T: AtLeastXBits<16> {}
975    // Other numbers of bits at least as large as 8.
976    impl_size_rule!(AtLeastXBits<8>, 8 9 10 11 12 13 14 15);
977}
978
979/// Generates `From` implementations from a primitive type into a [`Bounded`] with
980/// enough bits to store any value of that type.
981///
982/// Note: The only reason for having this macro is that if we pass `$type` as a generic
983/// parameter, we cannot use it in the const context of [`AtLeastXBits`]'s generic parameter. This
984/// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a
985/// regular `impl` block.
986macro_rules! impl_from_primitive {
987    ($($type:ty)*) => {
988        $(
989        #[doc = ::core::concat!(
990            "Conversion from a [`",
991            ::core::stringify!($type),
992            "`] into a [`Bounded`] of same signedness with enough bits to store it.")]
993        impl<T, const N: u32> From<$type> for Bounded<T, N>
994        where
995            $type: Integer,
996            T: Integer<Signedness = <$type as Integer>::Signedness> + From<$type>,
997            Self: AtLeastXBits<{ <$type as Integer>::BITS as usize }>,
998        {
999            fn from(value: $type) -> Self {
1000                // SAFETY: The trait bound on `Self` guarantees that `N` bits is
1001                // enough to hold any value of the source type.
1002                unsafe { Self::__new(T::from(value)) }
1003            }
1004        }
1005        )*
1006    }
1007}
1008
1009impl_from_primitive!(
1010    u8 u16 u32 u64 usize
1011    i8 i16 i32 i64 isize
1012);
1013
1014/// Local trait expressing the fact that a given [`Bounded`] fits into a primitive type of `N` bits,
1015/// provided they have the same signedness.
1016trait FitsInXBits<const N: usize> {}
1017
1018/// Implementations for infallibly converting a [`Bounded`] into a primitive type that can contain
1019/// it.
1020///
1021/// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent
1022/// module.
1023mod fits_impls {
1024    use super::*;
1025
1026    // Number of bits that fit into a 8-bits primitive.
1027    impl_size_rule!(FitsInXBits<8>, 1 2 3 4 5 6 7 8);
1028
1029    // Anything that fits into 8 bits also fits into 16.
1030    impl<T> FitsInXBits<16> for T where T: FitsInXBits<8> {}
1031    // Other number of bits that fit into a 16-bits primitive.
1032    impl_size_rule!(FitsInXBits<16>, 9 10 11 12 13 14 15 16);
1033
1034    // Anything that fits into 16 bits also fits into 32.
1035    impl<T> FitsInXBits<32> for T where T: FitsInXBits<16> {}
1036    // Other number of bits that fit into a 32-bits primitive.
1037    impl_size_rule!(FitsInXBits<32>,
1038        17 18 19 20 21 22 23 24
1039        25 26 27 28 29 30 31 32
1040    );
1041
1042    // Anything that fits into 32 bits also fits into 64.
1043    impl<T> FitsInXBits<64> for T where T: FitsInXBits<32> {}
1044    // Other number of bits that fit into a 64-bits primitive.
1045    impl_size_rule!(FitsInXBits<64>,
1046        33 34 35 36 37 38 39 40
1047        41 42 43 44 45 46 47 48
1048        49 50 51 52 53 54 55 56
1049        57 58 59 60 61 62 63 64
1050    );
1051}
1052
1053/// Generates [`From`] implementations from a [`Bounded`] into a primitive type that is
1054/// guaranteed to contain it.
1055///
1056/// Note: The only reason for having this macro is that if we pass `$type` as a generic
1057/// parameter, we cannot use it in the const context of `AtLeastXBits`'s generic parameter. This
1058/// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a
1059/// regular `impl` block.
1060macro_rules! impl_into_primitive {
1061    ($($type:ty)*) => {
1062        $(
1063        #[doc = ::core::concat!(
1064            "Conversion from a [`Bounded`] with no more bits than a [`",
1065            ::core::stringify!($type),
1066            "`] and of same signedness into [`",
1067            ::core::stringify!($type),
1068            "`]")]
1069        impl<T, const N: u32> From<Bounded<T, N>> for $type
1070        where
1071            $type: Integer + TryFrom<T>,
1072            T: Integer<Signedness = <$type as Integer>::Signedness>,
1073            Bounded<T, N>: FitsInXBits<{ <$type as Integer>::BITS as usize }>,
1074        {
1075            fn from(value: Bounded<T, N>) -> $type {
1076                // SAFETY: The trait bound on `Bounded` ensures that any value it holds (which
1077                // is constrained to `N` bits) can fit into the destination type, so this
1078                // conversion cannot fail.
1079                unsafe { <$type>::try_from(value.get()).unwrap_unchecked() }
1080            }
1081        }
1082        )*
1083    }
1084}
1085
1086impl_into_primitive!(
1087    u8 u16 u32 u64 usize
1088    i8 i16 i32 i64 isize
1089);
1090
1091// Unsigned single-bit `Bounded`s can be converted to a boolean.
1092
1093impl<T> From<Bounded<T, 1>> for bool
1094where
1095    T: Integer<Signedness = Unsigned> + Zeroable,
1096{
1097    fn from(value: Bounded<T, 1>) -> Self {
1098        value.get() != Zeroable::zeroed()
1099    }
1100}
1101
1102// Booleans can be converted to unsigned `Bounded`s.
1103
1104impl<T, const N: u32> From<bool> for Bounded<T, N>
1105where
1106    T: Integer<Signedness = Unsigned> + From<bool>,
1107{
1108    fn from(value: bool) -> Self {
1109        // SAFETY: A boolean is represented by `0` or `1`, so it fits within any valid unsigned
1110        // `Bounded` width.
1111        unsafe { Self::__new(T::from(value)) }
1112    }
1113}
1114
1115impl<T> Bounded<T, 1>
1116where
1117    T: Integer<Signedness = Unsigned> + Zeroable,
1118{
1119    /// Converts this [`Bounded`] into a [`bool`].
1120    ///
1121    /// This is a shorter way of writing `bool::from(self)`.
1122    ///
1123    /// # Examples
1124    ///
1125    /// ```
1126    /// use kernel::num::Bounded;
1127    ///
1128    /// assert_eq!(Bounded::<u8, 1>::new::<0>().into_bool(), false);
1129    /// assert_eq!(Bounded::<u8, 1>::new::<1>().into_bool(), true);
1130    /// ```
1131    pub fn into_bool(self) -> bool {
1132        self.into()
1133    }
1134}