1#![allow(dead_code)]
5
6use std::{error::Error as StdError, fmt};
7
8type Source = Box<dyn StdError + Send + Sync + 'static>;
9
10pub 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}