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