smol_jsonrpc/
error.rs

1//! Error types for the library
2
3use crate::std::{self, fmt};
4use alloc::{format, string::String};
5use serde::{ser::SerializeStruct, Serializer};
6use serde_json::json;
7
8/// Convenience alias for the library's [Result](std::result::Result) type.
9pub type Result<T> = std::result::Result<T, Error>;
10
11/// Error type for JSON-RPC specific errors.
12#[repr(C)]
13#[derive(Clone, Debug, Default, serde::Deserialize)]
14pub struct Error {
15    code: ErrorCode,
16    message: String,
17    data: serde_json::Value,
18}
19
20impl PartialEq for Error {
21    fn eq(&self, oth: &Self) -> bool {
22        self.code == oth.code && self.message == oth.message
23    }
24}
25
26impl serde::Serialize for Error {
27    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
28    where
29        S: Serializer,
30    {
31        let mut s = serializer.serialize_struct("Error", 3)?;
32
33        s.serialize_field("code", &i32::from(self.code))?;
34        s.serialize_field("message", self.message.as_str())?;
35        s.serialize_field("data", &self.data)?;
36        s.end()
37    }
38}
39
40impl Error {
41    /// Creates a new [Error].
42    pub fn new() -> Self {
43        Self {
44            code: ErrorCode::new(),
45            message: String::new(),
46            data: serde_json::Value::Null,
47        }
48    }
49
50    /// Gets the [ErrorCode].
51    pub fn code(&self) -> ErrorCode {
52        self.code
53    }
54
55    /// Sets the [ErrorCode].
56    pub fn set_code(&mut self, code: ErrorCode) {
57        self.code = code;
58    }
59
60    /// Builder function to set the [ErrorCode].
61    pub fn with_code(mut self, code: ErrorCode) -> Self {
62        self.code = code;
63        self
64    }
65
66    /// Gets the [Error] message string.
67    pub fn message(&self) -> &str {
68        self.message.as_str()
69    }
70
71    /// Sets the [Error] message string.
72    pub fn set_message(&mut self, message: &str) {
73        self.message = String::from(message);
74    }
75
76    /// Builder function to set the [Error] message string.
77    pub fn with_message(mut self, message: &str) -> Self {
78        self.message = String::from(message);
79        self
80    }
81
82    /// Gets the [Error] data.
83    ///
84    /// The data is an extra field, and may be [null](serde_json::Value::Null).
85    pub fn data(&self) -> &serde_json::Value {
86        &self.data
87    }
88
89    /// Sets the [Error] data.
90    pub fn set_data<T: serde::Serialize>(&mut self, data: T) {
91        self.data = json!(data);
92    }
93
94    /// Builder function to set the [Error] data.
95    pub fn with_data<T: serde::Serialize>(mut self, data: T) -> Self {
96        self.data = json!(data);
97        self
98    }
99}
100
101impl From<serde_json::Error> for Error {
102    fn from(err: serde_json::Error) -> Self {
103        Self {
104            code: ErrorCode::ParseError,
105            message: format!("{err}"),
106            data: serde_json::Value::Null,
107        }
108    }
109}
110
111impl fmt::Display for Error {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        let code = self.code();
114        let message = self.message();
115        let data = self.data();
116
117        if data.is_null() {
118            write!(f, r#""code": {code}, "message": "{message}""#)
119        } else {
120            write!(
121                f,
122                r#""code": {code}, "message": "{message}", "data": {data}"#
123            )
124        }
125    }
126}
127
128/// Error codes defined by the JSON-RPC 2.0 spec: <https://www.jsonrpc.org/specification#error_object>
129///
130/// Non-exhaustive, additional types for server-specific codes may be defined in the future.
131#[repr(i32)]
132#[non_exhaustive]
133#[derive(Clone, Copy, Debug, Default, PartialEq)]
134pub enum ErrorCode {
135    /// A parsing error occurred.
136    #[default]
137    ParseError = -32700,
138    /// An invalid request was made.
139    InvalidRequest = -32600,
140    /// Method is not supported by the server.
141    MethodNotFound = -32601,
142    /// Invalid request parameters.
143    InvalidParams = -32602,
144    /// Internal server error occurred.
145    InternalError = -32603,
146    /// Unknown error occured.
147    UnknownError = -32999,
148}
149
150impl ErrorCode {
151    /// Creates a new [ErrorCode].
152    pub const fn new() -> Self {
153        Self::ParseError
154    }
155}
156
157impl From<ErrorCode> for i32 {
158    fn from(err: ErrorCode) -> Self {
159        err as i32
160    }
161}
162
163impl From<&ErrorCode> for i32 {
164    fn from(err: &ErrorCode) -> Self {
165        (*err).into()
166    }
167}
168
169impl From<ErrorCode> for &'static str {
170    fn from(err: ErrorCode) -> Self {
171        match err {
172            ErrorCode::ParseError => "Parse error",
173            ErrorCode::InvalidRequest => "Invalid request",
174            ErrorCode::MethodNotFound => "Method not found",
175            ErrorCode::InvalidParams => "Invalid params",
176            ErrorCode::InternalError => "Internal error",
177            ErrorCode::UnknownError => "Unknown error",
178        }
179    }
180}
181
182impl From<&ErrorCode> for &'static str {
183    fn from(err: &ErrorCode) -> Self {
184        (*err).into()
185    }
186}
187
188impl From<i32> for ErrorCode {
189    fn from(val: i32) -> Self {
190        match val {
191            v if v == -32700 => Self::ParseError,
192            v if v == -32600 => Self::InvalidRequest,
193            v if v == -32601 => Self::MethodNotFound,
194            v if v == -32602 => Self::InvalidParams,
195            v if v == -32603 => Self::InternalError,
196            _ => Self::UnknownError,
197        }
198    }
199}
200
201impl From<&str> for ErrorCode {
202    fn from(val: &str) -> Self {
203        if let Ok(err) = val.parse::<i32>() {
204            err.into()
205        } else {
206            match val.to_lowercase().as_str() {
207                "parse error" => Self::ParseError,
208                "invalid request" => Self::InvalidRequest,
209                "method not found" => Self::MethodNotFound,
210                "invalid params" => Self::InvalidParams,
211                "internal error" => Self::InternalError,
212                _ => Self::UnknownError,
213            }
214        }
215    }
216}
217
218impl fmt::Display for ErrorCode {
219    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220        write!(f, "{} ({})", <&'static str>::from(self), i32::from(self))
221    }
222}
223
224impl serde::Serialize for ErrorCode {
225    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
226    where
227        S: serde::Serializer,
228    {
229        let val = i32::from(self);
230        serde::Serialize::serialize(&val, serializer)
231    }
232}
233
234impl<'de> serde::Deserialize<'de> for ErrorCode {
235    fn deserialize<D>(deserializer: D) -> std::result::Result<ErrorCode, D::Error>
236    where
237        D: serde::de::Deserializer<'de>,
238    {
239        let val = <i32 as serde::Deserialize>::deserialize(deserializer)?;
240        Ok(val.into())
241    }
242}