hickory_proto/serialize/txt/
errors.rs1use alloc::{fmt, string::String};
2use std::io;
3
4#[cfg(feature = "backtrace")]
5use crate::trace;
6use crate::{
7 error::{ProtoError, ProtoErrorKind},
8 rr::RecordType,
9 serialize::txt::Token,
10};
11
12#[cfg(feature = "backtrace")]
13use backtrace::Backtrace as ExtBacktrace;
14use thiserror::Error;
15
16pub type ParseResult<T> = ::core::result::Result<T, ParseError>;
18
19#[derive(Debug, Error)]
21#[non_exhaustive]
22pub enum ParseErrorKind {
23 #[error("invalid numerical character: {0}")]
25 CharToInt(char),
26
27 #[error("{0}")]
29 Message(&'static str),
30
31 #[error("token is missing: {0}")]
33 MissingToken(String),
34
35 #[error("{0}")]
37 Msg(String),
38
39 #[error("invalid time string: {0}")]
41 ParseTime(String),
42
43 #[error("unrecognized token in stream: {0:?}")]
45 UnexpectedToken(Token),
46
47 #[cfg(not(feature = "std"))]
50 #[error("network address parse error: {0}")]
51 AddrParse(#[from] core::net::AddrParseError),
52
53 #[cfg(feature = "std")]
56 #[error("network address parse error: {0}")]
57 AddrParse(#[from] std::net::AddrParseError),
58
59 #[error("data encoding error: {0}")]
61 DataEncoding(#[from] data_encoding::DecodeError),
62
63 #[cfg(feature = "std")]
65 #[error("io error: {0}")]
66 Io(#[from] std::io::Error),
67
68 #[error("lexer error: {0}")]
70 Lexer(#[from] LexerError),
71
72 #[error("error parsing number: {0}")]
74 ParseInt(#[from] core::num::ParseIntError),
75
76 #[error("proto error: {0}")]
78 Proto(#[from] ProtoError),
79
80 #[error("unknown RecordType: {0}")]
82 UnknownRecordType(u16),
83
84 #[error("unsupported RecordType: {0}")]
86 UnsupportedRecordType(RecordType),
87
88 #[error("request timed out")]
90 Timeout,
91}
92
93impl Clone for ParseErrorKind {
94 fn clone(&self) -> Self {
95 use ParseErrorKind::*;
96 match self {
97 CharToInt(c) => CharToInt(*c),
98 Message(msg) => Message(msg),
99 MissingToken(s) => MissingToken(s.clone()),
100 Msg(msg) => Msg(msg.clone()),
101 ParseTime(s) => ParseTime(s.clone()),
102 UnexpectedToken(token) => UnexpectedToken(token.clone()),
103
104 AddrParse(e) => AddrParse(e.clone()),
105 DataEncoding(e) => DataEncoding(*e),
106 #[cfg(feature = "std")]
107 Io(e) => Io(std::io::Error::from(e.kind())),
108 Lexer(e) => Lexer(e.clone()),
109 ParseInt(e) => ParseInt(e.clone()),
110 Proto(e) => Proto(e.clone()),
111 UnsupportedRecordType(ty) => UnsupportedRecordType(*ty),
112 UnknownRecordType(ty) => UnknownRecordType(*ty),
113 Timeout => Timeout,
114 }
115 }
116}
117
118#[derive(Error, Debug)]
120pub struct ParseError {
121 kind: ParseErrorKind,
122 #[cfg(feature = "backtrace")]
123 backtrack: Option<ExtBacktrace>,
124}
125
126impl ParseError {
127 pub fn kind(&self) -> &ParseErrorKind {
129 &self.kind
130 }
131}
132
133impl fmt::Display for ParseError {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 cfg_if::cfg_if! {
136 if #[cfg(feature = "backtrace")] {
137 if let Some(backtrace) = &self.backtrack {
138 fmt::Display::fmt(&self.kind, f)?;
139 fmt::Debug::fmt(backtrace, f)
140 } else {
141 fmt::Display::fmt(&self.kind, f)
142 }
143 } else {
144 fmt::Display::fmt(&self.kind, f)
145 }
146 }
147 }
148}
149
150impl From<ParseErrorKind> for ParseError {
151 fn from(kind: ParseErrorKind) -> Self {
152 Self {
153 kind,
154 #[cfg(feature = "backtrace")]
155 backtrack: trace!(),
156 }
157 }
158}
159
160impl From<&'static str> for ParseError {
161 fn from(msg: &'static str) -> Self {
162 ParseErrorKind::Message(msg).into()
163 }
164}
165
166impl From<String> for ParseError {
167 fn from(msg: String) -> Self {
168 ParseErrorKind::Msg(msg).into()
169 }
170}
171
172#[cfg(not(feature = "std"))]
173impl From<core::net::AddrParseError> for ParseError {
174 fn from(e: core::net::AddrParseError) -> Self {
175 ParseErrorKind::from(e).into()
176 }
177}
178
179#[cfg(feature = "std")]
180impl From<std::net::AddrParseError> for ParseError {
181 fn from(e: std::net::AddrParseError) -> Self {
182 ParseErrorKind::from(e).into()
183 }
184}
185
186impl From<::data_encoding::DecodeError> for ParseError {
187 fn from(e: data_encoding::DecodeError) -> Self {
188 ParseErrorKind::from(e).into()
189 }
190}
191
192impl From<io::Error> for ParseError {
193 fn from(e: io::Error) -> Self {
194 match e.kind() {
195 io::ErrorKind::TimedOut => ParseErrorKind::Timeout.into(),
196 _ => ParseErrorKind::from(e).into(),
197 }
198 }
199}
200
201impl From<LexerError> for ParseError {
202 fn from(e: LexerError) -> Self {
203 ParseErrorKind::from(e).into()
204 }
205}
206
207impl From<core::num::ParseIntError> for ParseError {
208 fn from(e: core::num::ParseIntError) -> Self {
209 ParseErrorKind::from(e).into()
210 }
211}
212
213impl From<ProtoError> for ParseError {
214 fn from(e: ProtoError) -> Self {
215 match e.kind() {
216 ProtoErrorKind::Timeout => ParseErrorKind::Timeout.into(),
217 _ => ParseErrorKind::from(e).into(),
218 }
219 }
220}
221
222impl From<core::convert::Infallible> for ParseError {
223 fn from(_e: core::convert::Infallible) -> Self {
224 panic!("infallible")
225 }
226}
227
228impl From<ParseError> for io::Error {
229 fn from(e: ParseError) -> Self {
230 match e.kind() {
231 ParseErrorKind::Timeout => Self::new(io::ErrorKind::TimedOut, e),
232 _ => Self::new(io::ErrorKind::Other, e),
233 }
234 }
235}
236
237pub(crate) type LexerResult<T> = core::result::Result<T, LexerError>;
239
240#[derive(Eq, PartialEq, Debug, Error, Clone)]
242#[non_exhaustive]
243pub enum LexerErrorKind {
244 #[error("unexpected end of input")]
246 EOF,
247
248 #[error("illegal character input: {0}")]
250 IllegalCharacter(char),
251
252 #[error("illegal state: {0}")]
254 IllegalState(&'static str),
255
256 #[error("{0}")]
258 Message(&'static str),
259
260 #[error("unclosed list, missing ')'")]
262 UnclosedList,
263
264 #[error("unclosed quoted string")]
266 UnclosedQuotedString,
267
268 #[error("unrecognized character input: {0}")]
270 UnrecognizedChar(char),
271
272 #[error("unrecognized dollar content: {0}")]
274 UnrecognizedDollar(String),
275
276 #[error("unrecognized octet: {0:x}")]
278 UnrecognizedOctet(u32),
279}
280
281#[derive(Clone, Error, Debug)]
283pub struct LexerError {
284 kind: LexerErrorKind,
285 #[cfg(feature = "backtrace")]
286 backtrack: Option<ExtBacktrace>,
287}
288
289impl LexerError {
290 pub fn kind(&self) -> &LexerErrorKind {
292 &self.kind
293 }
294}
295
296impl From<LexerErrorKind> for LexerError {
297 fn from(kind: LexerErrorKind) -> Self {
298 Self {
299 kind,
300 #[cfg(feature = "backtrace")]
301 backtrack: trace!(),
302 }
303 }
304}
305
306impl fmt::Display for LexerError {
307 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308 cfg_if::cfg_if! {
309 if #[cfg(feature = "backtrace")] {
310 if let Some(backtrace) = &self.backtrack {
311 fmt::Display::fmt(&self.kind, f)?;
312 fmt::Debug::fmt(backtrace, f)
313 } else {
314 fmt::Display::fmt(&self.kind, f)
315 }
316 } else {
317 fmt::Display::fmt(&self.kind, f)
318 }
319 }
320 }
321}