tonic/transport/
error.rs

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