hickory_proto/http/
error.rs

1// Copyright 2015-2020 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use alloc::{fmt, string::String};
9use core::num::ParseIntError;
10use std::io;
11
12use crate::error::ProtoError;
13use http::header::ToStrError;
14use thiserror::Error;
15
16#[cfg(feature = "backtrace")]
17use crate::{ExtBacktrace, trace};
18
19/// An alias for results returned by functions of this crate
20pub type Result<T> = ::core::result::Result<T, Error>;
21
22// TODO: remove this and put in ProtoError
23#[derive(Debug, Error)]
24#[non_exhaustive]
25pub enum ErrorKind {
26    /// Unable to decode header value to string
27    #[error("header decode error: {0}")]
28    Decode(#[from] ToStrError),
29
30    /// An error with an arbitrary message, referenced as &'static str
31    #[error("{0}")]
32    Message(&'static str),
33
34    /// An error with an arbitrary message, stored as String
35    #[error("{0}")]
36    Msg(String),
37
38    /// Unable to parse header value as number
39    #[error("unable to parse number: {0}")]
40    ParseInt(#[from] ParseIntError),
41
42    #[error("proto error: {0}")]
43    ProtoError(#[from] ProtoError),
44
45    #[error("h2: {0}")]
46    #[cfg(feature = "__https")]
47    H2(#[from] h2::Error),
48
49    #[error("h3: {0}")]
50    #[cfg(feature = "__h3")]
51    H3(#[from] h3::Error),
52}
53
54/// The error type for errors that get returned in the crate
55#[derive(Debug)]
56pub struct Error {
57    kind: ErrorKind,
58    #[cfg(feature = "backtrace")]
59    backtrack: Option<ExtBacktrace>,
60}
61
62impl Error {
63    /// Get the kind of the error
64    pub fn kind(&self) -> &ErrorKind {
65        &self.kind
66    }
67}
68
69impl fmt::Display for Error {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        cfg_if::cfg_if! {
72            if #[cfg(feature = "backtrace")] {
73                if let Some(backtrace) = &self.backtrack {
74                    fmt::Display::fmt(&self.kind, f)?;
75                    fmt::Debug::fmt(backtrace, f)
76                } else {
77                    fmt::Display::fmt(&self.kind, f)
78                }
79            } else {
80                fmt::Display::fmt(&self.kind, f)
81            }
82        }
83    }
84}
85
86impl From<ErrorKind> for Error {
87    fn from(kind: ErrorKind) -> Self {
88        Self {
89            kind,
90            #[cfg(feature = "backtrace")]
91            backtrack: trace!(),
92        }
93    }
94}
95
96impl From<&'static str> for Error {
97    fn from(msg: &'static str) -> Self {
98        ErrorKind::Message(msg).into()
99    }
100}
101
102impl From<String> for Error {
103    fn from(msg: String) -> Self {
104        ErrorKind::Msg(msg).into()
105    }
106}
107
108impl From<ParseIntError> for Error {
109    fn from(err: ParseIntError) -> Self {
110        ErrorKind::from(err).into()
111    }
112}
113
114impl From<ToStrError> for Error {
115    fn from(err: ToStrError) -> Self {
116        ErrorKind::from(err).into()
117    }
118}
119
120impl From<ProtoError> for Error {
121    fn from(msg: ProtoError) -> Self {
122        ErrorKind::ProtoError(msg).into()
123    }
124}
125
126#[cfg(feature = "__https")]
127impl From<h2::Error> for Error {
128    fn from(msg: h2::Error) -> Self {
129        ErrorKind::H2(msg).into()
130    }
131}
132
133#[cfg(feature = "__h3")]
134impl From<h3::Error> for Error {
135    fn from(msg: h3::Error) -> Self {
136        ErrorKind::H3(msg).into()
137    }
138}
139
140impl From<Error> for io::Error {
141    fn from(err: Error) -> Self {
142        Self::new(io::ErrorKind::Other, format!("https: {err}"))
143    }
144}