1use crate::{ErrorPayload, RpcRecv};
2use serde_json::value::RawValue;
3
4#[derive(Debug, thiserror::Error)]
6pub enum RpcError<E, ErrResp = Box<RawValue>> {
7 #[error("server returned an error response: {0}")]
9 ErrorResp(ErrorPayload<ErrResp>),
10
11 #[error("server returned a null response when a non-null response was expected")]
13 NullResp,
14
15 #[error("unsupported feature: {0}")]
17 UnsupportedFeature(&'static str),
18
19 #[error("local usage error: {0}")]
22 LocalUsageError(#[source] Box<dyn std::error::Error + Send + Sync>),
23
24 #[error("serialization error: {0}")]
26 SerError(
27 #[source]
31 serde_json::Error,
32 ),
33 #[error("deserialization error: {err}")]
35 DeserError {
36 #[source]
40 err: serde_json::Error,
41 text: String,
43 },
44
45 #[error(transparent)]
49 Transport(
50 #[from]
52 E,
53 ),
54}
55
56impl<E, ErrResp> RpcError<E, ErrResp>
57where
58 ErrResp: RpcRecv,
59{
60 pub const fn err_resp(err: ErrorPayload<ErrResp>) -> Self {
62 Self::ErrorResp(err)
63 }
64
65 pub fn local_usage(err: impl std::error::Error + Send + Sync + 'static) -> Self {
67 Self::LocalUsageError(err.into())
68 }
69
70 pub fn local_usage_str(err: &str) -> Self {
72 Self::LocalUsageError(err.into())
73 }
74
75 pub fn deser_err(err: serde_json::Error, text: impl AsRef<str>) -> Self {
82 let text = text.as_ref();
83
84 if let Ok(err) = serde_json::from_str::<ErrorPayload<ErrResp>>(text) {
86 return Self::ErrorResp(err);
87 }
88
89 Self::DeserError { err, text: text.to_owned() }
90 }
91}
92
93impl<E, ErrResp> RpcError<E, ErrResp> {
94 pub const fn ser_err(err: serde_json::Error) -> Self {
97 Self::SerError(err)
98 }
99
100 pub const fn is_ser_error(&self) -> bool {
102 matches!(self, Self::SerError(_))
103 }
104
105 pub const fn is_deser_error(&self) -> bool {
107 matches!(self, Self::DeserError { .. })
108 }
109
110 pub const fn is_transport_error(&self) -> bool {
112 matches!(self, Self::Transport(_))
113 }
114
115 pub const fn is_error_resp(&self) -> bool {
117 matches!(self, Self::ErrorResp(_))
118 }
119
120 pub const fn is_null_resp(&self) -> bool {
122 matches!(self, Self::NullResp)
123 }
124
125 pub const fn is_unsupported_feature(&self) -> bool {
127 matches!(self, Self::UnsupportedFeature(_))
128 }
129
130 pub const fn is_local_usage_error(&self) -> bool {
132 matches!(self, Self::LocalUsageError(_))
133 }
134
135 pub const fn as_error_resp(&self) -> Option<&ErrorPayload<ErrResp>> {
137 match self {
138 Self::ErrorResp(err) => Some(err),
139 _ => None,
140 }
141 }
142}