1use core::fmt;
2
3#[cfg(feature = "alloc")]
4use alloc::boxed::Box;
5#[cfg(feature = "alloc")]
6use alloc::string::ToString;
7
8#[derive(Debug)]
10pub struct Error {
11 err: ErrorImpl,
12}
13
14impl fmt::Display for Error {
15 #[inline]
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 self.err.fmt(f)
18 }
19}
20
21#[derive(Debug)]
22enum ErrorImpl {
23 #[cfg(feature = "alloc")]
24 Message(Box<str>),
25 #[cfg(not(feature = "alloc"))]
26 Empty,
27}
28
29impl fmt::Display for ErrorImpl {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 #[cfg(feature = "alloc")]
33 ErrorImpl::Message(message) => message.fmt(f),
34 #[cfg(not(feature = "alloc"))]
35 ErrorImpl::Empty => write!(f, "Message error (see diagnostics)"),
36 }
37 }
38}
39
40#[cfg(feature = "std")]
41impl std::error::Error for Error {}
42
43impl musli_utils::context::Error for Error {
44 #[inline]
45 fn custom<T>(error: T) -> Self
46 where
47 T: fmt::Display,
48 {
49 Self::message(error)
50 }
51
52 #[inline]
53 #[allow(unused_variables)]
54 fn message<T>(message: T) -> Self
55 where
56 T: fmt::Display,
57 {
58 Self {
59 #[cfg(feature = "alloc")]
60 err: ErrorImpl::Message(message.to_string().into()),
61 #[cfg(not(feature = "alloc"))]
62 err: ErrorImpl::Empty,
63 }
64 }
65}
66
67#[derive(Debug)]
68#[non_exhaustive]
69pub(crate) enum ErrorMessage {
70 ParseFloat(lexical::Error),
71}
72
73impl fmt::Display for ErrorMessage {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 ErrorMessage::ParseFloat(error) => {
77 write!(f, "Expected float, got {error}")
78 }
79 }
80 }
81}
82
83#[cfg(feature = "std")]
84impl std::error::Error for ErrorMessage {
85 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
86 match self {
87 ErrorMessage::ParseFloat(error) => Some(error),
88 }
89 }
90}
91
92#[derive(Debug)]
93#[non_exhaustive]
94pub(crate) enum IntegerError {
95 IntegerOverflow,
96 Decimal,
97 InvalidNumeric,
98}
99
100impl fmt::Display for IntegerError {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 match self {
103 IntegerError::IntegerOverflow => write!(f, "Arithmetic overflow"),
104 IntegerError::Decimal => write!(f, "Decimal number"),
105 IntegerError::InvalidNumeric => write!(f, "Invalid numeric"),
106 }
107 }
108}