small_fixed_array/
length.rs1use core::{
2 fmt::{Debug, Display},
3 num::{NonZeroU16, NonZeroU32, NonZeroU8},
4};
5
6use alloc::boxed::Box;
7
8use crate::inline::get_heap_threshold;
9
10mod sealed {
11 use core::num::{NonZeroU16, NonZeroU32, NonZeroU8};
12
13 #[allow(unnameable_types)]
14 pub trait LengthSealed {}
15 impl LengthSealed for u8 {}
16 impl LengthSealed for u16 {}
17 #[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
18 impl LengthSealed for u32 {}
19
20 #[allow(unnameable_types)]
21 pub trait NonZeroSealed {}
22 impl NonZeroSealed for NonZeroU8 {}
23 impl NonZeroSealed for NonZeroU16 {}
24 #[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
25 impl NonZeroSealed for NonZeroU32 {}
26}
27
28#[derive(Debug)]
29pub struct InvalidLength<T> {
30 type_name: &'static str,
31 original: Box<[T]>,
32}
33
34impl<T> InvalidLength<T> {
35 #[cold]
36 #[track_caller]
37 pub(crate) fn new(type_name: &'static str, original: Box<[T]>) -> Self {
38 Self {
39 type_name,
40 original,
41 }
42 }
43
44 #[must_use]
46 pub fn get_inner(self) -> Box<[T]> {
47 self.original
48 }
49}
50
51#[cfg(feature = "std")]
52impl<T: Debug> std::error::Error for InvalidLength<T> {}
53
54impl<T> core::fmt::Display for InvalidLength<T> {
55 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
56 write!(
57 f,
58 "Cannot fit {} into {}",
59 self.original.len(),
60 self.type_name,
61 )
62 }
63}
64
65#[derive(Debug)]
66pub struct InvalidStrLength {
67 type_name: &'static str,
68 original: Box<str>,
69}
70
71impl InvalidStrLength {
72 #[must_use]
74 pub fn get_inner(self) -> Box<str> {
75 self.original
76 }
77}
78
79#[cfg(feature = "std")]
80impl std::error::Error for InvalidStrLength {}
81
82impl core::fmt::Display for InvalidStrLength {
83 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84 write!(
85 f,
86 "Cannot fit {} into {}",
87 self.original.len(),
88 self.type_name,
89 )
90 }
91}
92
93impl TryFrom<InvalidLength<u8>> for InvalidStrLength {
94 type Error = core::str::Utf8Error;
95
96 fn try_from(value: InvalidLength<u8>) -> Result<Self, Self::Error> {
97 let original = if let Err(err) = core::str::from_utf8(&value.original) {
98 return Err(err);
99 } else {
100 unsafe { alloc::str::from_boxed_utf8_unchecked(value.original) }
101 };
102
103 Ok(Self {
104 original,
105 type_name: value.type_name,
106 })
107 }
108}
109
110#[doc(hidden)]
111#[allow(unnameable_types)]
112pub trait NonZero<Int: ValidLength>:
113 sealed::NonZeroSealed + Into<Int> + Sized + Copy + PartialEq + Debug
114{
115 #[allow(unused)]
116 fn new(val: Int) -> Option<Self>;
117}
118
119impl NonZero<u8> for NonZeroU8 {
120 fn new(val: u8) -> Option<Self> {
121 NonZeroU8::new(val)
122 }
123}
124
125impl NonZero<u16> for NonZeroU16 {
126 fn new(val: u16) -> Option<Self> {
127 NonZeroU16::new(val)
128 }
129}
130
131impl NonZero<u32> for NonZeroU32 {
132 fn new(val: u32) -> Option<Self> {
133 NonZeroU32::new(val)
134 }
135}
136
137pub trait ValidLength:
143 sealed::LengthSealed + Copy + Display + PartialEq + From<u8> + TryFrom<usize> + Into<u32>
144{
145 const ZERO: Self;
146 const MAX: Self;
147 #[deprecated = "will be removed in the next major release"]
148 #[allow(deprecated)]
149 const DANGLING: Self::NonZero;
150
151 #[deprecated = "will be removed in the next major release"]
152 type NonZero: NonZero<Self>;
153 #[cfg(feature = "typesize")]
154 type InlineStrRepr: Copy + AsRef<[u8]> + AsMut<[u8]> + Default + typesize::TypeSize;
155 #[cfg(not(feature = "typesize"))]
156 type InlineStrRepr: Copy + AsRef<[u8]> + AsMut<[u8]> + Default;
157
158 #[must_use]
159 fn to_usize(self) -> usize;
160
161 #[must_use]
162 fn from_usize(len: usize) -> Option<Self> {
163 len.try_into().ok()
164 }
165}
166
167impl ValidLength for u8 {
168 const ZERO: Self = 0;
169 const MAX: Self = Self::MAX;
170 #[allow(deprecated)]
171 const DANGLING: Self::NonZero = Self::NonZero::MAX;
172
173 type NonZero = NonZeroU8;
174 type InlineStrRepr = [u8; get_heap_threshold::<Self>()];
175
176 fn to_usize(self) -> usize {
177 self.into()
178 }
179}
180
181impl ValidLength for u16 {
182 const ZERO: Self = 0;
183 const MAX: Self = Self::MAX;
184 #[allow(deprecated)]
185 const DANGLING: Self::NonZero = Self::NonZero::MAX;
186
187 type NonZero = NonZeroU16;
188 type InlineStrRepr = [u8; get_heap_threshold::<Self>()];
189
190 fn to_usize(self) -> usize {
191 self.into()
192 }
193}
194
195#[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
196impl ValidLength for u32 {
197 const ZERO: Self = 0;
198 const MAX: Self = Self::MAX;
199 #[allow(deprecated)]
200 const DANGLING: Self::NonZero = Self::NonZero::MAX;
201
202 type NonZero = NonZeroU32;
203 type InlineStrRepr = [u8; get_heap_threshold::<Self>()];
204
205 fn to_usize(self) -> usize {
206 self.try_into()
207 .expect("u32 can fit into usize on platforms with pointer lengths of 32 and 64")
208 }
209}
210
211#[cfg(target_pointer_width = "16")]
212pub type SmallLen = u16;
213#[cfg(not(target_pointer_width = "16"))]
214pub type SmallLen = u32;