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