tonic/transport/
error.rs
1use std::{error::Error as StdError, fmt};
2
3type Source = Box<dyn StdError + Send + Sync + 'static>;
4
5pub 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}