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