1use std::{
2 backtrace::{Backtrace, BacktraceStatus},
3 fmt::{self, Display},
4 sync::Arc,
5};
6
7use parse_display::Display;
8use serde_json::{Map, Value};
9
10use crate::{ErrorCode, utils::downcast};
11
12use super::ErrorObject;
13
14#[derive(Clone, Debug)]
38pub struct Error {
39 code: ErrorCode,
40 message: Option<String>,
41 message_is_public: bool,
42 data: Option<Value>,
43 source: Option<Arc<dyn std::error::Error + Send + Sync>>,
44 backtrace: Arc<Backtrace>,
45}
46
47impl Error {
48 pub(crate) fn unsupported_version() -> Self {
49 Self::new(ErrorCode::INVALID_REQUEST).with_message("Unsupported JSON-RPC version", true)
50 }
51 pub(crate) fn missing_params() -> Self {
52 Self::new(ErrorCode::INVALID_PARAMS).with_message("`params` is required but missing", true)
53 }
54 pub(crate) fn invalid_params(source: impl std::error::Error + Send + Sync + 'static) -> Self {
55 Self::new(ErrorCode::INVALID_PARAMS).with_source(source)
56 }
57 pub(crate) fn invalid_json(source: impl std::error::Error + Send + Sync + 'static) -> Self {
58 Self::new(ErrorCode::PARSE_ERROR)
59 .with_message("Invalid JSON", true)
60 .with_source(source)
61 }
62 pub(crate) fn invalid_message() -> Self {
63 Self::new(ErrorCode::INVALID_REQUEST).with_message("Invalid JSON-RPC message", true)
64 }
65 pub(crate) fn request_id_reused() -> Self {
66 Self::new(ErrorCode::INVALID_REQUEST).with_message("Request ID reused", true)
67 }
68
69 pub fn new(code: ErrorCode) -> Self {
70 Self {
71 code,
72 message: None,
73 message_is_public: false,
74 data: None,
75 source: None,
76 backtrace: Arc::new(Backtrace::capture()),
77 }
78 }
79 pub fn with_message(self, message: impl Display, is_public: bool) -> Self {
80 Self {
81 message: Some(message.to_string()),
82 message_is_public: is_public,
83 ..self
84 }
85 }
86 pub fn with_source(self, source: impl std::error::Error + Send + Sync + 'static) -> Self {
87 Self {
88 source: Some(Arc::new(source)),
89 ..self
90 }
91 }
92
93 pub fn backtrace(&self) -> &Backtrace {
94 &self.backtrace
95 }
96 pub fn source(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)> {
97 Some(&**self.source.as_ref()?)
98 }
99
100 pub fn to_error_object(&self, expose_internals: bool) -> ErrorObject {
101 let mut data = self.data.clone();
102 if expose_internals && data.is_none() {
103 let mut m = Map::<String, Value>::new();
104 if let Some(source) = &self.source {
105 m.insert(
106 "source".to_string(),
107 Value::String(source.to_string().trim().to_string()),
108 );
109 }
110 if self.backtrace.status() == BacktraceStatus::Captured {
111 m.insert(
112 "backtrace".to_string(),
113 Value::String(format!("{:#?}", self.backtrace)),
114 );
115 }
116 data = Some(Value::Object(m));
117 }
118 let code = self.code;
119 let message = self.message(expose_internals);
120 ErrorObject {
121 code,
122 message,
123 data,
124 }
125 }
126 fn message(&self, expose_internals: bool) -> String {
127 let mut message = None;
128 if expose_internals || self.message_is_public {
129 message = self.message.clone();
130 }
131 if expose_internals {
132 if let Some(source) = &self.source {
133 if message.is_none() {
134 message = source
135 .to_string()
136 .lines()
137 .map(|s| s.trim().to_string())
138 .find(|s| !s.is_empty());
139 }
140 }
141 }
142 message.unwrap_or_else(|| self.code.message().to_string())
143 }
144
145 pub(crate) fn to_session_error(&self) -> SessionError {
146 RawSessionError::Error(self.clone()).into_error()
147 }
148}
149
150impl From<ErrorCode> for Error {
151 fn from(code: ErrorCode) -> Self {
152 Self::new(code)
153 }
154}
155
156impl From<ErrorObject> for Error {
157 fn from(e: ErrorObject) -> Self {
158 Self {
159 code: e.code,
160 message: Some(e.message),
161 data: e.data,
162 message_is_public: true,
163 source: None,
164 backtrace: Arc::new(Backtrace::capture()),
165 }
166 }
167}
168
169impl<E> From<E> for Error
170where
171 E: std::error::Error + Send + Sync + 'static,
172{
173 fn from(e: E) -> Self {
174 Self::from(ErrorCode::INTERNAL_ERROR).with_source(e)
175 }
176}
177
178#[derive(Debug, Clone)]
179pub struct SessionError {
180 raw: RawSessionError,
181}
182impl SessionError {
183 pub(crate) fn shutdown() -> Self {
184 RawSessionError::Shutdown.into_error()
185 }
186 pub(crate) fn serialize_failed(source: impl std::error::Error + Send + Sync + 'static) -> Self {
187 Self::from_error(source)
188 }
189 pub(crate) fn deserialize_failed(
190 source: impl std::error::Error + Send + Sync + 'static,
191 ) -> Self {
192 Self::from_error(source)
193 }
194 pub(crate) fn request_id_overflow() -> Self {
195 Self::from_message("Request ID overflow")
196 }
197 pub(crate) fn request_id_not_found() -> Self {
198 Self::from_message("Request ID not found")
199 }
200 pub fn from_error(e: impl std::error::Error + Send + Sync + 'static) -> Self {
201 match downcast::<Self, _>(e) {
202 Ok(e) => e,
203 Err(e) => RawSessionError::Error(e.into()).into_error(),
204 }
205 }
206 pub fn from_message(message: impl Display) -> Self {
207 RawSessionError::Message(message.to_string()).into_error()
208 }
209
210 pub fn kind(&self) -> SessionErrorKind {
211 self.raw.kind()
212 }
213 pub fn error_object(&self) -> Option<&ErrorObject> {
214 if let RawSessionError::ErrorObject(e) = &self.raw {
215 Some(e)
216 } else {
217 None
218 }
219 }
220}
221impl From<ErrorObject> for SessionError {
222 fn from(e: ErrorObject) -> Self {
223 RawSessionError::ErrorObject(e).into_error()
224 }
225}
226impl Display for SessionError {
227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
228 match &self.raw {
229 RawSessionError::Shutdown => write!(f, "Session shutdown"),
230 RawSessionError::ErrorObject(e) => write!(f, "{e:#}"),
231 RawSessionError::Error(e) => write!(f, "{}", e.message(true)),
232 RawSessionError::Message(message) => Display::fmt(message, f),
233 }
234 }
235}
236impl std::error::Error for SessionError {
237 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
238 match &self.raw {
239 RawSessionError::Shutdown => None,
240 RawSessionError::ErrorObject(_) => None,
241 RawSessionError::Error(e) => e.source().map(|s| s as &dyn std::error::Error),
242 RawSessionError::Message(_) => None,
243 }
244 }
245}
246
247#[derive(Debug, Copy, Clone, Display, Eq, PartialEq, Ord, PartialOrd, Hash)]
248#[non_exhaustive]
249pub enum SessionErrorKind {
250 Shutdown,
251 ErrorObject,
252 Other,
253}
254
255#[derive(Debug, Clone)]
256enum RawSessionError {
257 Shutdown,
258 ErrorObject(ErrorObject),
259 Error(Error),
260 Message(String),
261}
262impl RawSessionError {
263 fn into_error(self) -> SessionError {
264 SessionError { raw: self }
265 }
266 fn kind(&self) -> SessionErrorKind {
267 match self {
268 RawSessionError::Shutdown => SessionErrorKind::Shutdown,
269 RawSessionError::ErrorObject(_) => SessionErrorKind::ErrorObject,
270 RawSessionError::Error(_) | RawSessionError::Message(_) => SessionErrorKind::Other,
271 }
272 }
273}
274impl From<std::io::Error> for SessionError {
275 fn from(e: std::io::Error) -> Self {
276 Self::from_error(e)
277 }
278}
279
280pub type Result<T, E = Error> = std::result::Result<T, E>;
281pub type SessionResult<T> = Result<T, SessionError>;
282
283#[macro_export]
302macro_rules! bail {
303 () => {
304 return ::std::result::Result::Err($crate::Error::new($crate::ErrorCode::INTERNAL_ERROR))
305 };
306 ($fmt:literal $(,)?) => {
307 return ::std::result::Result::Err($crate::Error::new($crate::ErrorCode::INTERNAL_ERROR)
308 .with_message(::std::format!($fmt), false))
309 };
310 ($fmt:literal, $($arg:tt)*) => {
311 return ::std::result::Result::Err($crate::Error::new($crate::ErrorCode::INTERNAL_ERROR)
312 .with_message(::std::format!($fmt, $($arg)*), false))
313 };
314}
315
316#[macro_export]
336macro_rules! bail_public {
337 (_, $($arg:tt)*) => {
338 bail_public!($crate::ErrorCode::INTERNAL_ERROR, $($arg)*)
339 };
340 ($code:expr) => {
341 return ::std::result::Result::Err($crate::Error::new($code))
342 };
343 ($code:expr, $fmt:literal $(,)?) => {
344 return ::std::result::Result::Err($crate::Error::new($code)
345 .with_message(::std::format!($fmt), true))
346 };
347 ($code:expr, $fmt:literal, $($arg:tt)*) => {
348 return ::std::result::Result::Err($crate::Error::new($code)
349 .with_message(::std::format!($fmt, $($arg)*), true))
350 };
351}