tonic/transport/
error.rs

1use std::{error::Error as StdError, fmt};
2
3type Source = Box<dyn StdError + Send + Sync + 'static>;
4
5/// Error's that originate from the client or server;
6pub struct Error {
7    inner: ErrorImpl,
8}
9
10struct ErrorImpl {
11    kind: Kind,
12    source: Option<Source>,
13}
14
15#[derive(Debug)]
16pub(crate) enum Kind {
17    Transport,
18    #[cfg(feature = "channel")]
19    InvalidUri,
20    #[cfg(feature = "channel")]
21    InvalidUserAgent,
22}
23
24impl Error {
25    pub(crate) fn new(kind: Kind) -> Self {
26        Self {
27            inner: ErrorImpl { kind, source: None },
28        }
29    }
30
31    pub(crate) fn with(mut self, source: impl Into<Source>) -> Self {
32        self.inner.source = Some(source.into());
33        self
34    }
35
36    pub(crate) fn from_source(source: impl Into<crate::Error>) -> Self {
37        Error::new(Kind::Transport).with(source)
38    }
39
40    #[cfg(feature = "channel")]
41    pub(crate) fn new_invalid_uri() -> Self {
42        Error::new(Kind::InvalidUri)
43    }
44
45    #[cfg(feature = "channel")]
46    pub(crate) fn new_invalid_user_agent() -> Self {
47        Error::new(Kind::InvalidUserAgent)
48    }
49
50    fn description(&self) -> &str {
51        match &self.inner.kind {
52            Kind::Transport => "transport error",
53            #[cfg(feature = "channel")]
54            Kind::InvalidUri => "invalid URI",
55            #[cfg(feature = "channel")]
56            Kind::InvalidUserAgent => "user agent is not a valid header value",
57        }
58    }
59}
60
61impl fmt::Debug for Error {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        let mut f = f.debug_tuple("tonic::transport::Error");
64
65        f.field(&self.inner.kind);
66
67        if let Some(source) = &self.inner.source {
68            f.field(source);
69        }
70
71        f.finish()
72    }
73}
74
75impl fmt::Display for Error {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        f.write_str(self.description())
78    }
79}
80
81impl StdError for Error {
82    fn source(&self) -> Option<&(dyn StdError + 'static)> {
83        self.inner
84            .source
85            .as_ref()
86            .map(|source| &**source as &(dyn StdError + 'static))
87    }
88}