1use core::alloc::Layout;
2use core::any::type_name;
3use core::fmt;
4use core::ops::{Range, RangeFrom};
5use core::str::Utf8Error;
6
7mod sealed {
8 pub trait Sealed {}
9 impl Sealed for () {}
10}
11
12pub trait IntoRepr: self::sealed::Sealed {
14 #[doc(hidden)]
15 fn into_repr(self) -> Repr;
16}
17
18impl IntoRepr for () {
19 fn into_repr(self) -> Repr {
20 Repr {
21 kind: ReprKind::Unit,
22 }
23 }
24}
25
26macro_rules! impl_into_repr {
27 ($($ty:ty, $repr:ident),* $(,)?) => {
28 $(
29 impl self::sealed::Sealed for $ty {
30 }
31
32 impl IntoRepr for $ty {
33 fn into_repr(self) -> Repr {
34 Repr {
35 kind: ReprKind::$repr(self),
36 }
37 }
38 }
39 )*
40 }
41}
42
43impl_into_repr! {
44 u8, U8,
45 u16, U16,
46 u32, U32,
47 u64, U64,
48 u128, U128,
49 usize, Usize,
50 i8, I8,
51 i16, I16,
52 i32, I32,
53 i64, I64,
54 i128, I128,
55 isize, Isize,
56}
57
58#[derive(Debug)]
59#[cfg_attr(test, derive(PartialEq))]
60enum ReprKind {
61 Unit,
62 U8(u8),
63 U16(u16),
64 U32(u32),
65 U64(u64),
66 U128(u128),
67 I8(i8),
68 I16(i16),
69 I32(i32),
70 I64(i64),
71 I128(i128),
72 Usize(usize),
73 Isize(isize),
74}
75
76#[derive(Debug)]
78#[cfg_attr(test, derive(PartialEq))]
79#[non_exhaustive]
80pub struct Repr {
81 kind: ReprKind,
82}
83
84impl fmt::Display for Repr {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match &self.kind {
87 ReprKind::Unit => write!(f, "()"),
88 ReprKind::U8(value) => write!(f, "{value}u8"),
89 ReprKind::U16(value) => write!(f, "{value}u16"),
90 ReprKind::U32(value) => write!(f, "{value}u32"),
91 ReprKind::U64(value) => write!(f, "{value}u64"),
92 ReprKind::U128(value) => write!(f, "{value}u128"),
93 ReprKind::I8(value) => write!(f, "{value}i8"),
94 ReprKind::I16(value) => write!(f, "{value}i16"),
95 ReprKind::I32(value) => write!(f, "{value}i32"),
96 ReprKind::I64(value) => write!(f, "{value}i64"),
97 ReprKind::I128(value) => write!(f, "{value}i128"),
98 ReprKind::Usize(value) => write!(f, "{value}usize"),
99 ReprKind::Isize(value) => write!(f, "{value}isize"),
100 }
101 }
102}
103
104#[derive(Debug)]
106#[cfg_attr(test, derive(PartialEq))]
107pub struct Error {
108 kind: ErrorKind,
109}
110
111impl Error {
112 #[inline]
113 pub(crate) const fn new(kind: ErrorKind) -> Self {
114 Self { kind }
115 }
116
117 #[inline(always)]
118 #[doc(hidden)]
119 pub fn __illegal_enum_discriminant<T>(discriminant: impl IntoRepr) -> Self {
120 Self::new(ErrorKind::IllegalDiscriminant {
121 name: type_name::<T>(),
122 discriminant: discriminant.into_repr(),
123 })
124 }
125}
126
127impl fmt::Display for Error {
128 #[inline]
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 self.kind.fmt(f)
131 }
132}
133
134impl core::error::Error for Error {
135 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
136 match &self.kind {
137 ErrorKind::Utf8Error { error } => Some(error),
138 _ => None,
139 }
140 }
141}
142
143#[derive(Debug)]
144#[cfg_attr(test, derive(PartialEq))]
145#[non_exhaustive]
146pub(crate) enum ErrorKind {
147 InvalidOffsetRange {
148 offset: Repr,
149 max: Repr,
150 },
151 InvalidMetadataRange {
152 metadata: Repr,
153 max: Repr,
154 },
155 LengthOverflow {
156 len: usize,
157 size: usize,
158 },
159 AlignmentRangeMismatch {
160 addr: usize,
161 range: Range<usize>,
162 align: usize,
163 },
164 AlignmentRangeFromMismatch {
165 range: RangeFrom<usize>,
166 align: usize,
167 },
168 LayoutMismatch {
169 range: Range<usize>,
170 layout: Layout,
171 },
172 OutOfRangeBounds {
173 range: Range<usize>,
174 len: usize,
175 },
176 OutOfRangeFromBounds {
177 range: RangeFrom<usize>,
178 len: usize,
179 },
180 NonZeroZeroed {
181 range: Range<usize>,
182 },
183 IndexOutOfBounds {
184 index: usize,
185 len: usize,
186 },
187 ControlRangeOutOfBounds {
188 range: Range<usize>,
189 len: usize,
190 },
191 StrideOutOfBounds {
192 index: usize,
193 len: usize,
194 },
195 IllegalDiscriminant {
196 name: &'static str,
197 discriminant: Repr,
198 },
199 IllegalChar {
200 repr: u32,
201 },
202 IllegalBool {
203 repr: u8,
204 },
205 Utf8Error {
206 error: Utf8Error,
207 },
208 Underflow {
209 at: usize,
210 len: usize,
211 },
212 Overflow {
213 at: usize,
214 len: usize,
215 },
216 StackOverflow {
217 capacity: usize,
218 },
219 #[cfg(feature = "alloc")]
220 CapacityError,
221 #[cfg(feature = "alloc")]
222 FailedPhf,
223}
224
225impl fmt::Display for ErrorKind {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 match self {
228 ErrorKind::InvalidOffsetRange { offset, max } => {
229 write!(f, "Offset {offset} not in legal range 0-{max}",)
230 }
231 ErrorKind::InvalidMetadataRange { metadata, max } => {
232 write!(f, "Metadata {metadata} not in legal range 0-{max}")
233 }
234 ErrorKind::LengthOverflow { len, size } => {
235 write!(
236 f,
237 "Length overflowed when trying to take {len} elements of size {size}"
238 )
239 }
240 ErrorKind::AlignmentRangeMismatch { addr, range, align } => {
241 write!(
242 f,
243 "Alignment mismatch, expected alignment {align} for range {range:?} at address {addr:x}"
244 )
245 }
246 ErrorKind::AlignmentRangeFromMismatch { range, align } => {
247 write!(
248 f,
249 "Alignment mismatch, expected alignment {align} for range {range:?}"
250 )
251 }
252 ErrorKind::LayoutMismatch { range, layout } => {
253 write!(
254 f,
255 "Layout mismatch, expected {layout:?} for range {range:?}"
256 )
257 }
258 ErrorKind::OutOfRangeBounds { range, len } => {
259 write!(f, "Range {range:?} out of bound 0-{len}")
260 }
261 ErrorKind::OutOfRangeFromBounds { range, len } => {
262 write!(f, "Range {range:?} out of bound 0-{len}")
263 }
264 ErrorKind::NonZeroZeroed { range } => {
265 write!(f, "Expected non-zero range at {range:?}")
266 }
267 ErrorKind::IndexOutOfBounds { index, len } => {
268 write!(f, "Index {index} out of bound 0-{len}")
269 }
270 ErrorKind::ControlRangeOutOfBounds { range, len } => {
271 write!(f, "Control range {range:?} out of bound 0-{len}")
272 }
273 ErrorKind::StrideOutOfBounds { index, len } => {
274 write!(f, "Stride at index {index} out of bound 0-{len}")
275 }
276 ErrorKind::IllegalDiscriminant { name, discriminant } => {
277 write!(f, "Illegal discriminant {discriminant} for enum {name}")
278 }
279 ErrorKind::IllegalChar { repr } => {
280 write!(f, "Illegal char representation {repr}")
281 }
282 ErrorKind::IllegalBool { repr } => {
283 write!(f, "Illegal bool representation {repr}")
284 }
285 ErrorKind::Underflow { at, len } => {
286 write!(f, "Arithmetic underflow calculating {at} - {len}")
287 }
288 ErrorKind::Overflow { at, len } => {
289 write!(f, "Arithmetic overflow calculating {at} + {len}")
290 }
291 ErrorKind::StackOverflow { capacity } => {
292 write!(f, "Stack with capacity {capacity} overflowed")
293 }
294 ErrorKind::Utf8Error { error } => error.fmt(f),
295 #[cfg(feature = "alloc")]
296 ErrorKind::CapacityError => {
297 write!(f, "Out of capacity")
298 }
299 #[cfg(feature = "alloc")]
300 ErrorKind::FailedPhf => {
301 write!(f, "Failed to construct perfect hash for map")
302 }
303 }
304 }
305}