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