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