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