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 InvalidUri, 19 InvalidUserAgent, 20 } 21 22 impl Error { new(kind: Kind) -> Self23 pub(crate) fn new(kind: Kind) -> Self { 24 Self { 25 inner: ErrorImpl { kind, source: None }, 26 } 27 } 28 with(mut self, source: impl Into<Source>) -> Self29 pub(crate) fn with(mut self, source: impl Into<Source>) -> Self { 30 self.inner.source = Some(source.into()); 31 self 32 } 33 from_source(source: impl Into<crate::Error>) -> Self34 pub(crate) fn from_source(source: impl Into<crate::Error>) -> Self { 35 Error::new(Kind::Transport).with(source) 36 } 37 new_invalid_uri() -> Self38 pub(crate) fn new_invalid_uri() -> Self { 39 Error::new(Kind::InvalidUri) 40 } 41 new_invalid_user_agent() -> Self42 pub(crate) fn new_invalid_user_agent() -> Self { 43 Error::new(Kind::InvalidUserAgent) 44 } 45 description(&self) -> &str46 fn description(&self) -> &str { 47 match &self.inner.kind { 48 Kind::Transport => "transport error", 49 Kind::InvalidUri => "invalid URI", 50 Kind::InvalidUserAgent => "user agent is not a valid header value", 51 } 52 } 53 } 54 55 impl fmt::Debug for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 57 let mut f = f.debug_tuple("tonic::transport::Error"); 58 59 f.field(&self.inner.kind); 60 61 if let Some(source) = &self.inner.source { 62 f.field(source); 63 } 64 65 f.finish() 66 } 67 } 68 69 impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 71 f.write_str(self.description()) 72 } 73 } 74 75 impl StdError for Error { source(&self) -> Option<&(dyn StdError + 'static)>76 fn source(&self) -> Option<&(dyn StdError + 'static)> { 77 self.inner 78 .source 79 .as_ref() 80 .map(|source| &**source as &(dyn StdError + 'static)) 81 } 82 } 83