xpx_chain_sdk/api/service/transport/
error.rs

1/*
2 * Copyright 2018 ProximaX Limited. All rights reserved.
3 * Use of this source code is governed by the Apache 2.0
4 * license that can be found in the LICENSE file.
5 */
6
7// TODO: remove this when we use errors throughout,
8// there are some that are only used under the TLS feature
9// these probably should be scoped to a `TLSError` enum.
10#![allow(dead_code)]
11
12use std::{error::Error as StdError, fmt};
13
14type Source = Box<dyn StdError + Send + Sync + 'static>;
15
16/// Error's that originate from the client or server;
17pub struct Error {
18    inner: ErrorImpl,
19}
20
21struct ErrorImpl {
22    kind: Kind,
23    source: Option<Source>,
24}
25
26#[derive(Debug)]
27pub(crate) enum Kind {
28    Transport,
29    InvalidUri,
30    InvalidUserAgent,
31}
32
33impl Error {
34    pub(crate) fn new(kind: Kind) -> Self {
35        Self { inner: ErrorImpl { kind, source: None } }
36    }
37
38    pub(crate) fn with(mut self, source: impl Into<Source>) -> Self {
39        self.inner.source = Some(source.into());
40        self
41    }
42
43    pub(crate) fn from_source(source: impl Into<crate::api::Error>) -> Self {
44        Error::new(Kind::Transport).with(source)
45    }
46
47    pub(crate) fn new_invalid_uri() -> Self {
48        Error::new(Kind::InvalidUri)
49    }
50
51    pub(crate) fn new_invalid_user_agent() -> Self {
52        Error::new(Kind::InvalidUserAgent)
53    }
54
55    fn description(&self) -> &str {
56        match &self.inner.kind {
57            Kind::Transport => "transport error",
58            Kind::InvalidUri => "invalid URI",
59            Kind::InvalidUserAgent => "user agent is not a valid header value",
60        }
61    }
62}
63
64impl fmt::Debug for Error {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        let mut f = f.debug_tuple("api::transport::Error");
67
68        f.field(&self.inner.kind);
69
70        if let Some(source) = &self.inner.source {
71            f.field(source);
72        }
73
74        f.finish()
75    }
76}
77
78impl fmt::Display for Error {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        f.write_str(self.description())
81    }
82}
83
84impl StdError for Error {
85    fn source(&self) -> Option<&(dyn StdError + 'static)> {
86        self.inner.source.as_ref().map(|source| &**source as &(dyn StdError + 'static))
87    }
88}