heapless/
len_type.rs

1use core::{
2    fmt::{Debug, Display},
3    ops::{Add, AddAssign, Sub, SubAssign},
4};
5
6pub trait Sealed:
7    Send
8    + Sync
9    + Copy
10    + Display
11    + Debug
12    + PartialEq
13    + Add<Output = Self>
14    + AddAssign
15    + Sub<Output = Self>
16    + SubAssign
17    + PartialOrd
18    + TryFrom<usize, Error: Debug>
19    + TryInto<usize, Error: Debug>
20{
21    /// The zero value of the integer type.
22    const ZERO: Self;
23    /// The one value of the integer type.
24    const MAX: Self;
25    /// The maximum value of this type, as a `usize`.
26    const MAX_USIZE: usize;
27
28    /// The one value of the integer type.
29    ///
30    /// It's a function instead of constant because we want to have implementation which panics for
31    /// type `ZeroLenType`
32    fn one() -> Self;
33
34    /// An infallible conversion from `usize` to `LenT`.
35    #[inline]
36    fn from_usize(val: usize) -> Self {
37        val.try_into().unwrap()
38    }
39
40    /// An infallible conversion from `LenT` to `usize`.
41    #[inline]
42    fn into_usize(self) -> usize {
43        self.try_into().unwrap()
44    }
45
46    /// Converts `LenT` into `Some(usize)`, unless it's `Self::MAX`, where it returns `None`.
47    #[inline]
48    fn to_non_max(self) -> Option<usize> {
49        if self == Self::MAX {
50            None
51        } else {
52            Some(self.into_usize())
53        }
54    }
55}
56
57macro_rules! impl_lentype {
58    ($($(#[$meta:meta])* $LenT:ty),*) => {$(
59        $(#[$meta])*
60        impl Sealed for $LenT {
61            const ZERO: Self = 0;
62            const MAX: Self = Self::MAX;
63            const MAX_USIZE: usize = Self::MAX as _;
64
65            fn one() -> Self {
66                1
67            }
68        }
69
70        $(#[$meta])*
71        impl LenType for $LenT {}
72    )*}
73}
74
75/// A sealed trait representing a valid type to use as a length for a container.
76///
77/// This cannot be implemented in user code, and is restricted to `u8`, `u16`, `u32`, and `usize`.
78pub trait LenType: Sealed {}
79
80impl_lentype!(
81    u8,
82    u16,
83    #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
84    u32,
85    usize
86);
87
88pub const fn check_capacity_fits<LenT: LenType, const N: usize>() {
89    assert!(LenT::MAX_USIZE >= N, "The capacity is larger than `LenT` can hold, increase the size of `LenT` or reduce the capacity");
90}