xref: /linux/rust/kernel/num/bounded.rs (revision 2af6ad09fc7dfe9b3610100983cccf16998bf34d)
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 {
259                     assert!(fits_within!(VALUE, $type, N));
260                 }
261 
262                 // SAFETY: `fits_within` confirmed that `VALUE` can be represented within
263                 // `N` bits.
264                 unsafe { Self::__new(VALUE) }
265             }
266         }
267         )*
268     };
269 }
270 
271 impl_const_new!(
272     u8 u16 u32 u64 usize
273     i8 i16 i32 i64 isize
274 );
275 
276 impl<T, const N: u32> Bounded<T, N>
277 where
278     T: Integer,
279 {
280     /// Private constructor enforcing the type invariants.
281     ///
282     /// All instances of [`Bounded`] must be created through this method as it enforces most of the
283     /// type invariants.
284     ///
285     /// The caller remains responsible for checking, either statically or dynamically, that `value`
286     /// can be represented as a `T` using at most `N` bits.
287     ///
288     /// # Safety
289     ///
290     /// The caller must ensure that `value` can be represented within `N` bits.
291     const unsafe fn __new(value: T) -> Self {
292         // Enforce the type invariants.
293         const {
294             // `N` cannot be zero.
295             assert!(N != 0);
296             // The backing type is at least as large as `N` bits.
297             assert!(N <= T::BITS);
298         }
299 
300         Self(value)
301     }
302 
303     /// Attempts to turn `value` into a `Bounded` using `N` bits.
304     ///
305     /// Returns [`None`] if `value` doesn't fit within `N` bits.
306     ///
307     /// # Examples
308     ///
309     /// ```
310     /// use kernel::num::Bounded;
311     ///
312     /// let v = Bounded::<u8, 1>::try_new(1);
313     /// assert_eq!(v.as_deref().copied(), Some(1));
314     ///
315     /// let v = Bounded::<i8, 4>::try_new(-2);
316     /// assert_eq!(v.as_deref().copied(), Some(-2));
317     ///
318     /// // `0x1ff` doesn't fit into 8 unsigned bits.
319     /// let v = Bounded::<u32, 8>::try_new(0x1ff);
320     /// assert_eq!(v, None);
321     ///
322     /// // The range of values representable with 4 bits is `[-8..=7]`. The following tests these
323     /// // limits.
324     /// let v = Bounded::<i8, 4>::try_new(-8);
325     /// assert_eq!(v.map(Bounded::get), Some(-8));
326     /// let v = Bounded::<i8, 4>::try_new(-9);
327     /// assert_eq!(v, None);
328     /// let v = Bounded::<i8, 4>::try_new(7);
329     /// assert_eq!(v.map(Bounded::get), Some(7));
330     /// let v = Bounded::<i8, 4>::try_new(8);
331     /// assert_eq!(v, None);
332     /// ```
333     pub fn try_new(value: T) -> Option<Self> {
334         fits_within(value, N).then(|| {
335             // SAFETY: `fits_within` confirmed that `value` can be represented within `N` bits.
336             unsafe { Self::__new(value) }
337         })
338     }
339 
340     /// Checks that `expr` is valid for this type at compile-time and build a new value.
341     ///
342     /// This relies on [`build_assert!`] and guaranteed optimization to perform validation at
343     /// compile-time. If `expr` cannot be proved to be within the requested bounds at compile-time,
344     /// use the fallible [`Self::try_new`] instead.
345     ///
346     /// Limit this to simple, easily provable expressions, and prefer one of the [`Self::new`]
347     /// constructors whenever possible as they statically validate the value instead of relying on
348     /// compiler optimizations.
349     ///
350     /// # Examples
351     ///
352     /// ```
353     /// use kernel::num::Bounded;
354     /// # fn some_number() -> u32 { 0xffffffff }
355     ///
356     /// // Some undefined number.
357     /// let v: u32 = some_number();
358     ///
359     /// // Triggers a build error as `v` cannot be asserted to fit within 4 bits...
360     /// // let _ = Bounded::<u32, 4>::from_expr(v);
361     ///
362     /// // ... but this works as the compiler can assert the range from the mask.
363     /// let _ = Bounded::<u32, 4>::from_expr(v & 0xf);
364     ///
365     /// // These expressions are simple enough to be proven correct, but since they are static the
366     /// // `new` constructor should be preferred.
367     /// assert_eq!(Bounded::<u8, 1>::from_expr(1).get(), 1);
368     /// assert_eq!(Bounded::<u16, 8>::from_expr(0xff).get(), 0xff);
369     /// ```
370     // Always inline to optimize out error path of `build_assert`.
371     #[inline(always)]
372     pub fn from_expr(expr: T) -> Self {
373         crate::build_assert!(
374             fits_within(expr, N),
375             "Requested value larger than maximal representable value."
376         );
377 
378         // SAFETY: `fits_within` confirmed that `expr` can be represented within `N` bits.
379         unsafe { Self::__new(expr) }
380     }
381 
382     /// Returns the wrapped value as the backing type.
383     ///
384     /// # Examples
385     ///
386     /// ```
387     /// use kernel::num::Bounded;
388     ///
389     /// let v = Bounded::<u32, 4>::new::<7>();
390     /// assert_eq!(v.get(), 7u32);
391     /// ```
392     pub fn get(self) -> T {
393         *self.deref()
394     }
395 
396     /// Increases the number of bits usable for `self`.
397     ///
398     /// This operation cannot fail.
399     ///
400     /// # Examples
401     ///
402     /// ```
403     /// use kernel::num::Bounded;
404     ///
405     /// let v = Bounded::<u32, 4>::new::<7>();
406     /// let larger_v = v.extend::<12>();
407     /// // The contained values are equal even though `larger_v` has a bigger capacity.
408     /// assert_eq!(larger_v, v);
409     /// ```
410     pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
411         const {
412             assert!(
413                 M >= N,
414                 "Requested number of bits is less than the current representation."
415             );
416         }
417 
418         // SAFETY: The value did fit within `N` bits, so it will all the more fit within
419         // the larger `M` bits.
420         unsafe { Bounded::__new(self.0) }
421     }
422 
423     /// Attempts to shrink the number of bits usable for `self`.
424     ///
425     /// Returns [`None`] if the value of `self` cannot be represented within `M` bits.
426     ///
427     /// # Examples
428     ///
429     /// ```
430     /// use kernel::num::Bounded;
431     ///
432     /// let v = Bounded::<u32, 12>::new::<7>();
433     ///
434     /// // `7` can be represented using 3 unsigned bits...
435     /// let smaller_v = v.try_shrink::<3>();
436     /// assert_eq!(smaller_v.as_deref().copied(), Some(7));
437     ///
438     /// // ... but doesn't fit within `2` bits.
439     /// assert_eq!(v.try_shrink::<2>(), None);
440     /// ```
441     pub fn try_shrink<const M: u32>(self) -> Option<Bounded<T, M>> {
442         Bounded::<T, M>::try_new(self.get())
443     }
444 
445     /// Casts `self` into a [`Bounded`] backed by a different storage type, but using the same
446     /// number of valid bits.
447     ///
448     /// Both `T` and `U` must be of same signedness, and `U` must be at least as large as
449     /// `N` bits, or a build error will occur.
450     ///
451     /// # Examples
452     ///
453     /// ```
454     /// use kernel::num::Bounded;
455     ///
456     /// let v = Bounded::<u32, 12>::new::<127>();
457     ///
458     /// let u16_v: Bounded<u16, 12> = v.cast();
459     /// assert_eq!(u16_v.get(), 127);
460     ///
461     /// // This won't build: a `u8` is smaller than the required 12 bits.
462     /// // let _: Bounded<u8, 12> = v.cast();
463     /// ```
464     pub fn cast<U>(self) -> Bounded<U, N>
465     where
466         U: TryFrom<T> + Integer,
467         T: Integer,
468         U: Integer<Signedness = T::Signedness>,
469     {
470         // SAFETY: The converted value is represented using `N` bits, `U` can contain `N` bits, and
471         // `U` and `T` have the same sign, hence this conversion cannot fail.
472         let value = unsafe { U::try_from(self.get()).unwrap_unchecked() };
473 
474         // SAFETY: Although the backing type has changed, the value is still represented within
475         // `N` bits, and with the same signedness.
476         unsafe { Bounded::__new(value) }
477     }
478 }
479 
480 impl<T, const N: u32> Deref for Bounded<T, N>
481 where
482     T: Integer,
483 {
484     type Target = T;
485 
486     fn deref(&self) -> &Self::Target {
487         // Enforce the invariant to inform the compiler of the bounds of the value.
488         if !fits_within(self.0, N) {
489             // SAFETY: Per the `Bounded` invariants, `fits_within` can never return `false` on the
490             // value of a valid instance.
491             unsafe { core::hint::unreachable_unchecked() }
492         }
493 
494         &self.0
495     }
496 }
497 
498 /// Trait similar to [`TryInto`] but for [`Bounded`], to avoid conflicting implementations.
499 ///
500 /// # Examples
501 ///
502 /// ```
503 /// use kernel::num::{Bounded, TryIntoBounded};
504 ///
505 /// // Succeeds because `128` fits into 8 bits.
506 /// let v: Option<Bounded<u16, 8>> = 128u32.try_into_bounded();
507 /// assert_eq!(v.as_deref().copied(), Some(128));
508 ///
509 /// // Fails because `128` doesn't fit into 6 bits.
510 /// let v: Option<Bounded<u16, 6>> = 128u32.try_into_bounded();
511 /// assert_eq!(v, None);
512 /// ```
513 pub trait TryIntoBounded<T: Integer, const N: u32> {
514     /// Attempts to convert `self` into a [`Bounded`] using `N` bits.
515     ///
516     /// Returns [`None`] if `self` does not fit into the target type.
517     fn try_into_bounded(self) -> Option<Bounded<T, N>>;
518 }
519 
520 /// Any integer value can be attempted to be converted into a [`Bounded`] of any size.
521 impl<T, U, const N: u32> TryIntoBounded<T, N> for U
522 where
523     T: Integer,
524     U: TryInto<T>,
525 {
526     fn try_into_bounded(self) -> Option<Bounded<T, N>> {
527         self.try_into().ok().and_then(Bounded::try_new)
528     }
529 }
530 
531 // Comparisons between `Bounded`s.
532 
533 impl<T, U, const N: u32, const M: u32> PartialEq<Bounded<U, M>> for Bounded<T, N>
534 where
535     T: Integer,
536     U: Integer,
537     T: PartialEq<U>,
538 {
539     fn eq(&self, other: &Bounded<U, M>) -> bool {
540         self.get() == other.get()
541     }
542 }
543 
544 impl<T, const N: u32> Eq for Bounded<T, N> where T: Integer {}
545 
546 impl<T, U, const N: u32, const M: u32> PartialOrd<Bounded<U, M>> for Bounded<T, N>
547 where
548     T: Integer,
549     U: Integer,
550     T: PartialOrd<U>,
551 {
552     fn partial_cmp(&self, other: &Bounded<U, M>) -> Option<cmp::Ordering> {
553         self.get().partial_cmp(&other.get())
554     }
555 }
556 
557 impl<T, const N: u32> Ord for Bounded<T, N>
558 where
559     T: Integer,
560     T: Ord,
561 {
562     fn cmp(&self, other: &Self) -> cmp::Ordering {
563         self.get().cmp(&other.get())
564     }
565 }
566 
567 // Comparisons between a `Bounded` and its backing type.
568 
569 impl<T, const N: u32> PartialEq<T> for Bounded<T, N>
570 where
571     T: Integer,
572     T: PartialEq,
573 {
574     fn eq(&self, other: &T) -> bool {
575         self.get() == *other
576     }
577 }
578 
579 impl<T, const N: u32> PartialOrd<T> for Bounded<T, N>
580 where
581     T: Integer,
582     T: PartialOrd,
583 {
584     fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
585         self.get().partial_cmp(other)
586     }
587 }
588 
589 // Implementations of `core::ops` for two `Bounded` with the same backing type.
590 
591 impl<T, const N: u32, const M: u32> ops::Add<Bounded<T, M>> for Bounded<T, N>
592 where
593     T: Integer,
594     T: ops::Add<Output = T>,
595 {
596     type Output = T;
597 
598     fn add(self, rhs: Bounded<T, M>) -> Self::Output {
599         self.get() + rhs.get()
600     }
601 }
602 
603 impl<T, const N: u32, const M: u32> ops::BitAnd<Bounded<T, M>> for Bounded<T, N>
604 where
605     T: Integer,
606     T: ops::BitAnd<Output = T>,
607 {
608     type Output = T;
609 
610     fn bitand(self, rhs: Bounded<T, M>) -> Self::Output {
611         self.get() & rhs.get()
612     }
613 }
614 
615 impl<T, const N: u32, const M: u32> ops::BitOr<Bounded<T, M>> for Bounded<T, N>
616 where
617     T: Integer,
618     T: ops::BitOr<Output = T>,
619 {
620     type Output = T;
621 
622     fn bitor(self, rhs: Bounded<T, M>) -> Self::Output {
623         self.get() | rhs.get()
624     }
625 }
626 
627 impl<T, const N: u32, const M: u32> ops::BitXor<Bounded<T, M>> for Bounded<T, N>
628 where
629     T: Integer,
630     T: ops::BitXor<Output = T>,
631 {
632     type Output = T;
633 
634     fn bitxor(self, rhs: Bounded<T, M>) -> Self::Output {
635         self.get() ^ rhs.get()
636     }
637 }
638 
639 impl<T, const N: u32, const M: u32> ops::Div<Bounded<T, M>> for Bounded<T, N>
640 where
641     T: Integer,
642     T: ops::Div<Output = T>,
643 {
644     type Output = T;
645 
646     fn div(self, rhs: Bounded<T, M>) -> Self::Output {
647         self.get() / rhs.get()
648     }
649 }
650 
651 impl<T, const N: u32, const M: u32> ops::Mul<Bounded<T, M>> for Bounded<T, N>
652 where
653     T: Integer,
654     T: ops::Mul<Output = T>,
655 {
656     type Output = T;
657 
658     fn mul(self, rhs: Bounded<T, M>) -> Self::Output {
659         self.get() * rhs.get()
660     }
661 }
662 
663 impl<T, const N: u32, const M: u32> ops::Rem<Bounded<T, M>> for Bounded<T, N>
664 where
665     T: Integer,
666     T: ops::Rem<Output = T>,
667 {
668     type Output = T;
669 
670     fn rem(self, rhs: Bounded<T, M>) -> Self::Output {
671         self.get() % rhs.get()
672     }
673 }
674 
675 impl<T, const N: u32, const M: u32> ops::Sub<Bounded<T, M>> for Bounded<T, N>
676 where
677     T: Integer,
678     T: ops::Sub<Output = T>,
679 {
680     type Output = T;
681 
682     fn sub(self, rhs: Bounded<T, M>) -> Self::Output {
683         self.get() - rhs.get()
684     }
685 }
686 
687 // Implementations of `core::ops` between a `Bounded` and its backing type.
688 
689 impl<T, const N: u32> ops::Add<T> for Bounded<T, N>
690 where
691     T: Integer,
692     T: ops::Add<Output = T>,
693 {
694     type Output = T;
695 
696     fn add(self, rhs: T) -> Self::Output {
697         self.get() + rhs
698     }
699 }
700 
701 impl<T, const N: u32> ops::BitAnd<T> for Bounded<T, N>
702 where
703     T: Integer,
704     T: ops::BitAnd<Output = T>,
705 {
706     type Output = T;
707 
708     fn bitand(self, rhs: T) -> Self::Output {
709         self.get() & rhs
710     }
711 }
712 
713 impl<T, const N: u32> ops::BitOr<T> for Bounded<T, N>
714 where
715     T: Integer,
716     T: ops::BitOr<Output = T>,
717 {
718     type Output = T;
719 
720     fn bitor(self, rhs: T) -> Self::Output {
721         self.get() | rhs
722     }
723 }
724 
725 impl<T, const N: u32> ops::BitXor<T> for Bounded<T, N>
726 where
727     T: Integer,
728     T: ops::BitXor<Output = T>,
729 {
730     type Output = T;
731 
732     fn bitxor(self, rhs: T) -> Self::Output {
733         self.get() ^ rhs
734     }
735 }
736 
737 impl<T, const N: u32> ops::Div<T> for Bounded<T, N>
738 where
739     T: Integer,
740     T: ops::Div<Output = T>,
741 {
742     type Output = T;
743 
744     fn div(self, rhs: T) -> Self::Output {
745         self.get() / rhs
746     }
747 }
748 
749 impl<T, const N: u32> ops::Mul<T> for Bounded<T, N>
750 where
751     T: Integer,
752     T: ops::Mul<Output = T>,
753 {
754     type Output = T;
755 
756     fn mul(self, rhs: T) -> Self::Output {
757         self.get() * rhs
758     }
759 }
760 
761 impl<T, const N: u32> ops::Neg for Bounded<T, N>
762 where
763     T: Integer,
764     T: ops::Neg<Output = T>,
765 {
766     type Output = T;
767 
768     fn neg(self) -> Self::Output {
769         -self.get()
770     }
771 }
772 
773 impl<T, const N: u32> ops::Not for Bounded<T, N>
774 where
775     T: Integer,
776     T: ops::Not<Output = T>,
777 {
778     type Output = T;
779 
780     fn not(self) -> Self::Output {
781         !self.get()
782     }
783 }
784 
785 impl<T, const N: u32> ops::Rem<T> for Bounded<T, N>
786 where
787     T: Integer,
788     T: ops::Rem<Output = T>,
789 {
790     type Output = T;
791 
792     fn rem(self, rhs: T) -> Self::Output {
793         self.get() % rhs
794     }
795 }
796 
797 impl<T, const N: u32> ops::Sub<T> for Bounded<T, N>
798 where
799     T: Integer,
800     T: ops::Sub<Output = T>,
801 {
802     type Output = T;
803 
804     fn sub(self, rhs: T) -> Self::Output {
805         self.get() - rhs
806     }
807 }
808 
809 // Proxy implementations of `core::fmt`.
810 
811 impl<T, const N: u32> fmt::Display for Bounded<T, N>
812 where
813     T: Integer,
814     T: fmt::Display,
815 {
816     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817         self.get().fmt(f)
818     }
819 }
820 
821 impl<T, const N: u32> fmt::Binary for Bounded<T, N>
822 where
823     T: Integer,
824     T: fmt::Binary,
825 {
826     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
827         self.get().fmt(f)
828     }
829 }
830 
831 impl<T, const N: u32> fmt::LowerExp for Bounded<T, N>
832 where
833     T: Integer,
834     T: fmt::LowerExp,
835 {
836     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
837         self.get().fmt(f)
838     }
839 }
840 
841 impl<T, const N: u32> fmt::LowerHex for Bounded<T, N>
842 where
843     T: Integer,
844     T: fmt::LowerHex,
845 {
846     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
847         self.get().fmt(f)
848     }
849 }
850 
851 impl<T, const N: u32> fmt::Octal for Bounded<T, N>
852 where
853     T: Integer,
854     T: fmt::Octal,
855 {
856     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
857         self.get().fmt(f)
858     }
859 }
860 
861 impl<T, const N: u32> fmt::UpperExp for Bounded<T, N>
862 where
863     T: Integer,
864     T: fmt::UpperExp,
865 {
866     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
867         self.get().fmt(f)
868     }
869 }
870 
871 impl<T, const N: u32> fmt::UpperHex for Bounded<T, N>
872 where
873     T: Integer,
874     T: fmt::UpperHex,
875 {
876     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
877         self.get().fmt(f)
878     }
879 }
880 
881 /// Implements `$trait` for all [`Bounded`] types represented using `$num_bits`.
882 ///
883 /// This is used to declare size properties as traits that we can constrain against in impl blocks.
884 macro_rules! impl_size_rule {
885     ($trait:ty, $($num_bits:literal)*) => {
886         $(
887         impl<T> $trait for Bounded<T, $num_bits> where T: Integer {}
888         )*
889     };
890 }
891 
892 /// Local trait expressing the fact that a given [`Bounded`] has at least `N` bits used for value
893 /// representation.
894 trait AtLeastXBits<const N: usize> {}
895 
896 /// Implementations for infallibly converting a primitive type into a [`Bounded`] that can contain
897 /// it.
898 ///
899 /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent
900 /// module.
901 mod atleast_impls {
902     use super::*;
903 
904     // Number of bits at least as large as 64.
905     impl_size_rule!(AtLeastXBits<64>, 64);
906 
907     // Anything 64 bits or more is also larger than 32.
908     impl<T> AtLeastXBits<32> for T where T: AtLeastXBits<64> {}
909     // Other numbers of bits at least as large as 32.
910     impl_size_rule!(AtLeastXBits<32>,
911         32 33 34 35 36 37 38 39
912         40 41 42 43 44 45 46 47
913         48 49 50 51 52 53 54 55
914         56 57 58 59 60 61 62 63
915     );
916 
917     // Anything 32 bits or more is also larger than 16.
918     impl<T> AtLeastXBits<16> for T where T: AtLeastXBits<32> {}
919     // Other numbers of bits at least as large as 16.
920     impl_size_rule!(AtLeastXBits<16>,
921         16 17 18 19 20 21 22 23
922         24 25 26 27 28 29 30 31
923     );
924 
925     // Anything 16 bits or more is also larger than 8.
926     impl<T> AtLeastXBits<8> for T where T: AtLeastXBits<16> {}
927     // Other numbers of bits at least as large as 8.
928     impl_size_rule!(AtLeastXBits<8>, 8 9 10 11 12 13 14 15);
929 }
930 
931 /// Generates `From` implementations from a primitive type into a [`Bounded`] with
932 /// enough bits to store any value of that type.
933 ///
934 /// Note: The only reason for having this macro is that if we pass `$type` as a generic
935 /// parameter, we cannot use it in the const context of [`AtLeastXBits`]'s generic parameter. This
936 /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a
937 /// regular `impl` block.
938 macro_rules! impl_from_primitive {
939     ($($type:ty)*) => {
940         $(
941         #[doc = ::core::concat!(
942             "Conversion from a [`",
943             ::core::stringify!($type),
944             "`] into a [`Bounded`] of same signedness with enough bits to store it.")]
945         impl<T, const N: u32> From<$type> for Bounded<T, N>
946         where
947             $type: Integer,
948             T: Integer<Signedness = <$type as Integer>::Signedness> + From<$type>,
949             Self: AtLeastXBits<{ <$type as Integer>::BITS as usize }>,
950         {
951             fn from(value: $type) -> Self {
952                 // SAFETY: The trait bound on `Self` guarantees that `N` bits is
953                 // enough to hold any value of the source type.
954                 unsafe { Self::__new(T::from(value)) }
955             }
956         }
957         )*
958     }
959 }
960 
961 impl_from_primitive!(
962     u8 u16 u32 u64 usize
963     i8 i16 i32 i64 isize
964 );
965 
966 /// Local trait expressing the fact that a given [`Bounded`] fits into a primitive type of `N` bits,
967 /// provided they have the same signedness.
968 trait FitsInXBits<const N: usize> {}
969 
970 /// Implementations for infallibly converting a [`Bounded`] into a primitive type that can contain
971 /// it.
972 ///
973 /// Put into their own module for readability, and to avoid cluttering the rustdoc of the parent
974 /// module.
975 mod fits_impls {
976     use super::*;
977 
978     // Number of bits that fit into a 8-bits primitive.
979     impl_size_rule!(FitsInXBits<8>, 1 2 3 4 5 6 7 8);
980 
981     // Anything that fits into 8 bits also fits into 16.
982     impl<T> FitsInXBits<16> for T where T: FitsInXBits<8> {}
983     // Other number of bits that fit into a 16-bits primitive.
984     impl_size_rule!(FitsInXBits<16>, 9 10 11 12 13 14 15 16);
985 
986     // Anything that fits into 16 bits also fits into 32.
987     impl<T> FitsInXBits<32> for T where T: FitsInXBits<16> {}
988     // Other number of bits that fit into a 32-bits primitive.
989     impl_size_rule!(FitsInXBits<32>,
990         17 18 19 20 21 22 23 24
991         25 26 27 28 29 30 31 32
992     );
993 
994     // Anything that fits into 32 bits also fits into 64.
995     impl<T> FitsInXBits<64> for T where T: FitsInXBits<32> {}
996     // Other number of bits that fit into a 64-bits primitive.
997     impl_size_rule!(FitsInXBits<64>,
998         33 34 35 36 37 38 39 40
999         41 42 43 44 45 46 47 48
1000         49 50 51 52 53 54 55 56
1001         57 58 59 60 61 62 63 64
1002     );
1003 }
1004 
1005 /// Generates [`From`] implementations from a [`Bounded`] into a primitive type that is
1006 /// guaranteed to contain it.
1007 ///
1008 /// Note: The only reason for having this macro is that if we pass `$type` as a generic
1009 /// parameter, we cannot use it in the const context of `AtLeastXBits`'s generic parameter. This
1010 /// can be fixed once the `generic_const_exprs` feature is usable, and this macro replaced by a
1011 /// regular `impl` block.
1012 macro_rules! impl_into_primitive {
1013     ($($type:ty)*) => {
1014         $(
1015         #[doc = ::core::concat!(
1016             "Conversion from a [`Bounded`] with no more bits than a [`",
1017             ::core::stringify!($type),
1018             "`] and of same signedness into [`",
1019             ::core::stringify!($type),
1020             "`]")]
1021         impl<T, const N: u32> From<Bounded<T, N>> for $type
1022         where
1023             $type: Integer + TryFrom<T>,
1024             T: Integer<Signedness = <$type as Integer>::Signedness>,
1025             Bounded<T, N>: FitsInXBits<{ <$type as Integer>::BITS as usize }>,
1026         {
1027             fn from(value: Bounded<T, N>) -> $type {
1028                 // SAFETY: The trait bound on `Bounded` ensures that any value it holds (which
1029                 // is constrained to `N` bits) can fit into the destination type, so this
1030                 // conversion cannot fail.
1031                 unsafe { <$type>::try_from(value.get()).unwrap_unchecked() }
1032             }
1033         }
1034         )*
1035     }
1036 }
1037 
1038 impl_into_primitive!(
1039     u8 u16 u32 u64 usize
1040     i8 i16 i32 i64 isize
1041 );
1042 
1043 // Single-bit `Bounded`s can be converted from/to a boolean.
1044 
1045 impl<T> From<Bounded<T, 1>> for bool
1046 where
1047     T: Integer + Zeroable,
1048 {
1049     fn from(value: Bounded<T, 1>) -> Self {
1050         value.get() != Zeroable::zeroed()
1051     }
1052 }
1053 
1054 impl<T, const N: u32> From<bool> for Bounded<T, N>
1055 where
1056     T: Integer + From<bool>,
1057 {
1058     fn from(value: bool) -> Self {
1059         // SAFETY: A boolean can be represented using a single bit, and thus fits within any
1060         // integer type for any `N` > 0.
1061         unsafe { Self::__new(T::from(value)) }
1062     }
1063 }
1064