1use crate::conversions::ConversionError;
2use std::error::Error as StdError;
3use std::fmt;
4
5type Source = Box<dyn StdError + Send + Sync + 'static>;
6
7pub struct Error {
8 inner: ErrorImpl,
9}
10
11struct ErrorImpl {
12 kind: Kind,
13 source: Option<Source>,
14}
15
16#[derive(Debug)]
17enum Kind {
18 Request,
19 Conversion,
20}
21
22impl Error {
23 fn new(kind: Kind) -> Self {
24 Self {
25 inner: ErrorImpl { kind, source: None },
26 }
27 }
28
29 pub(crate) fn with(mut self, source: impl Into<Source>) -> Self {
30 self.inner.source = Some(source.into());
31 self
32 }
33
34 pub(crate) fn request(source: impl Into<Source>) -> Self {
35 Error::new(Kind::Request).with(source)
36 }
37
38 pub(crate) fn conversion(source: impl Into<Source>) -> Self {
39 Error::new(Kind::Conversion).with(source)
40 }
41
42 fn description(&self) -> &str {
43 match &self.inner.kind {
44 Kind::Request => "request failed",
45 Kind::Conversion => "failed to convert between types",
46 }
47 }
48}
49
50impl fmt::Debug for Error {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 let mut f = f.debug_tuple("ark_grpc::Error");
53
54 f.field(&self.inner.kind);
55
56 if let Some(source) = &self.inner.source {
57 f.field(source);
58 }
59
60 f.finish()
61 }
62}
63
64impl fmt::Display for Error {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 f.write_str(self.description())
67 }
68}
69
70impl StdError for Error {
71 fn source(&self) -> Option<&(dyn StdError + 'static)> {
72 self.inner
73 .source
74 .as_ref()
75 .map(|source| &**source as &(dyn StdError + 'static))
76 }
77}
78
79impl From<ConversionError> for Error {
80 fn from(value: ConversionError) -> Self {
81 Error::conversion(value)
82 }
83}