1#[derive(Copy, Clone, Debug)]
3pub struct Error {
4 pub source_location: ErrorLocation,
6 pub error_kind: ErrorKind,
8}
9
10impl core::fmt::Display for Error {
11 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12 write!(f, "In {}: {}", self.source_location, self.error_kind)
13 }
14}
15
16#[cfg(feature = "std")]
17impl std::error::Error for Error {
18 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
19 Some(&self.error_kind)
20 }
21}
22
23#[derive(Copy, Clone, Debug)]
25#[non_exhaustive]
26pub enum ErrorKind {
27 InvalidOffset,
29 InvalidLength,
31 UnknownEnumTag {
34 source: UnknownEnumTagKind,
36 },
37 UnknownUnionTag {
40 tag: u8,
42 },
43 InvalidVtableLength {
45 length: u16,
47 },
48 InvalidUtf8 {
50 source: core::str::Utf8Error,
52 },
53 MissingRequired,
55 MissingNullTerminator,
57}
58
59impl core::fmt::Display for ErrorKind {
60 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
61 match self {
62 ErrorKind::InvalidOffset => write!(f, "Invalid offset"),
63 ErrorKind::InvalidLength => write!(f, "Invalid length"),
64 ErrorKind::UnknownEnumTag { source } => source.fmt(f),
65 ErrorKind::UnknownUnionTag { tag } => write!(f, "Unknown union (tag = {})", tag),
66 ErrorKind::InvalidVtableLength { length } => {
67 write!(f, "Invalid vtable length (length = {})", length)
68 }
69 ErrorKind::InvalidUtf8 { source } => write!(f, "Invalid utf-8: {}", source),
70 ErrorKind::MissingRequired => write!(f, "Missing required field"),
71 ErrorKind::MissingNullTerminator => write!(f, "Missing null terminator"),
72 }
73 }
74}
75
76#[cfg(feature = "std")]
77impl std::error::Error for ErrorKind {
78 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
79 match self {
80 ErrorKind::InvalidOffset => None,
81 ErrorKind::InvalidLength => None,
82 ErrorKind::UnknownEnumTag { source } => Some(source),
83 ErrorKind::UnknownUnionTag { .. } => None,
84 ErrorKind::InvalidVtableLength { .. } => None,
85 ErrorKind::InvalidUtf8 { source } => Some(source),
86 ErrorKind::MissingRequired => None,
87 ErrorKind::MissingNullTerminator => None,
88 }
89 }
90}
91
92impl From<UnknownEnumTagKind> for ErrorKind {
93 fn from(source: UnknownEnumTagKind) -> Self {
94 ErrorKind::UnknownEnumTag { source }
95 }
96}
97
98impl From<core::str::Utf8Error> for ErrorKind {
99 fn from(source: core::str::Utf8Error) -> Self {
100 ErrorKind::InvalidUtf8 { source }
101 }
102}
103
104#[derive(Clone, Debug)]
105pub struct UnknownEnumTag {
110 pub source_location: ErrorLocation,
112 pub error_kind: UnknownEnumTagKind,
114}
115
116impl core::fmt::Display for UnknownEnumTag {
117 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118 write!(f, "In {}: {}", self.source_location, self.error_kind)
119 }
120}
121
122#[cfg(feature = "std")]
123impl std::error::Error for UnknownEnumTag {
124 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
125 Some(&self.error_kind)
126 }
127}
128
129#[derive(Copy, Clone, Debug)]
130pub struct UnknownEnumTagKind {
132 pub tag: i128,
134}
135
136impl core::fmt::Display for UnknownEnumTagKind {
137 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138 write!(f, "Unknown enum (tag = {})", self.tag)
139 }
140}
141
142#[cfg(feature = "std")]
143impl std::error::Error for UnknownEnumTagKind {}
144
145#[derive(Copy, Clone, Debug)]
146pub struct ErrorLocation {
149 pub type_: &'static str,
151 pub method: &'static str,
153 pub byte_offset: usize,
155}
156
157impl core::fmt::Display for ErrorLocation {
158 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
159 if self.byte_offset != usize::MAX {
160 write!(
161 f,
162 "<{}@{:x}>::{}()",
163 self.type_, self.byte_offset, self.method,
164 )
165 } else {
166 write!(f, "<{}>::{}()", self.type_, self.method,)
167 }
168 }
169}
170
171impl From<UnknownEnumTag> for Error {
172 fn from(error: UnknownEnumTag) -> Self {
173 Self {
174 source_location: error.source_location,
175 error_kind: error.error_kind.into(),
176 }
177 }
178}
179
180impl From<core::convert::Infallible> for Error {
181 fn from(value: core::convert::Infallible) -> Self {
182 match value {}
183 }
184}
185
186impl UnknownEnumTagKind {
187 pub fn with_error_location(
189 self,
190 type_: &'static str,
191 method: &'static str,
192 byte_offset: usize,
193 ) -> UnknownEnumTag {
194 UnknownEnumTag {
195 source_location: ErrorLocation {
196 type_,
197 method,
198 byte_offset,
199 },
200 error_kind: self,
201 }
202 }
203}
204
205impl ErrorKind {
206 pub fn with_error_location(
208 self,
209 type_: &'static str,
210 method: &'static str,
211 byte_offset: usize,
212 ) -> Error {
213 Error {
214 source_location: ErrorLocation {
215 type_,
216 method,
217 byte_offset,
218 },
219 error_kind: self,
220 }
221 }
222}