1 use std::{error::Error as StdError, fmt}; 2 3 type Source = Box<dyn StdError + Send + Sync + 'static>; 4 5 /// Error's that originate from the client or server; 6 pub struct Error { 7 inner: ErrorImpl, 8 } 9 10 struct ErrorImpl { 11 kind: Kind, 12 source: Option<Source>, 13 } 14 15 #[derive(Debug)] 16 pub(crate) enum Kind { 17 Transport, 18 #[cfg(feature = "channel")] 19 InvalidUri, 20 #[cfg(feature = "channel")] 21 InvalidUserAgent, 22 } 23 24 impl Error { new(kind: Kind) -> Self25 pub(crate) fn new(kind: Kind) -> Self { 26 Self { 27 inner: ErrorImpl { kind, source: None }, 28 } 29 } 30 with(mut self, source: impl Into<Source>) -> Self31 pub(crate) fn with(mut self, source: impl Into<Source>) -> Self { 32 self.inner.source = Some(source.into()); 33 self 34 } 35 from_source(source: impl Into<crate::BoxError>) -> Self36 pub(crate) fn from_source(source: impl Into<crate::BoxError>) -> Self { 37 Error::new(Kind::Transport).with(source) 38 } 39 40 #[cfg(feature = "channel")] new_invalid_uri() -> Self41 pub(crate) fn new_invalid_uri() -> Self { 42 Error::new(Kind::InvalidUri) 43 } 44 45 #[cfg(feature = "channel")] new_invalid_user_agent() -> Self46 pub(crate) fn new_invalid_user_agent() -> Self { 47 Error::new(Kind::InvalidUserAgent) 48 } 49 description(&self) -> &str50 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 61 impl fmt::Debug for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result62 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 75 impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 77 f.write_str(self.description()) 78 } 79 } 80 81 impl StdError for Error { source(&self) -> Option<&(dyn StdError + 'static)>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 } 89