1use std::convert::Infallible;
2
3use thiserror::Error;
4
5#[derive(Debug, Error)]
7pub enum InstrumentError {
8 #[error("instrument does not exist")]
10 NotFound,
11}
12
13#[derive(Debug, Error)]
15pub enum ExchangeError {
16 #[error("layer: {0}")]
18 Layer(#[from] Box<dyn std::error::Error + Send + Sync>),
19 #[cfg(feature = "http")]
20 #[error("http: {0}")]
22 Http(hyper::Error),
23 #[error(transparent)]
25 Other(#[from] anyhow::Error),
26 #[error("api: {0}")]
28 Api(anyhow::Error),
29 #[error("unavailable: {0}")]
31 Unavailable(anyhow::Error),
32 #[error("instrument: {0}")]
34 Instrument(InstrumentError),
35 #[error("rate limited: {0}")]
37 RateLimited(anyhow::Error),
38 #[error("key error: {0}")]
40 KeyError(anyhow::Error),
41 #[error("order not found")]
43 OrderNotFound,
44 #[error("forbidden: {0}")]
46 Forbidden(anyhow::Error),
47 #[error("unexpected response type: {0}")]
49 UnexpectedResponseType(String),
50}
51
52impl ExchangeError {
53 pub fn is_temporary(&self) -> bool {
55 #[cfg(feature = "http")]
56 {
57 matches!(
58 self,
59 Self::RateLimited(_) | Self::Unavailable(_) | Self::Http(_)
60 )
61 }
62 #[cfg(not(feature = "http"))]
63 {
64 matches!(self, Self::RateLimited(_) | Self::Unavailable(_))
65 }
66 }
67
68 pub fn flatten(self) -> Self {
70 match self {
71 Self::Layer(err) => match err.downcast::<Self>() {
72 Ok(err) => (*err).flatten(),
73 Err(err) => Self::Other(anyhow::anyhow!("{err}")),
74 },
75 err => err,
76 }
77 }
78
79 pub fn layer(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
81 match err.downcast::<Self>() {
82 Ok(err) => (*err).flatten(),
83 Err(err) => Self::Other(anyhow::anyhow!("{err}")),
84 }
85 }
86
87 pub fn unexpected_response_type(msg: impl ToString) -> Self {
89 Self::UnexpectedResponseType(msg.to_string())
90 }
91}
92
93impl From<Infallible> for ExchangeError {
94 fn from(_: Infallible) -> Self {
95 panic!("infallible")
96 }
97}