heapless/
len_type.rs

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