Skip to main content

neva/error/
error_code.rs

1//! Represents error code tools
2
3use crate::error::Error;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use std::fmt::Display;
6
7/// Standard JSON-RPC error codes as defined in the MCP specification.
8#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
9pub enum ErrorCode {
10    /// The server received invalid JSON.
11    ParseError = -32700,
12
13    /// The JSON sent is not a valid Request object.
14    InvalidRequest = -32600,
15
16    /// The method does not exist / is not available.
17    MethodNotFound = -32601,
18
19    /// Invalid method parameter(s).
20    InvalidParams = -32602,
21
22    /// Internal JSON-RPC error.
23    #[default]
24    InternalError = -32603,
25
26    /// The resource does not exist / is not available.
27    ResourceNotFound = -32002,
28
29    /// The URL mode elicitation is required.
30    UrlElicitationRequiredError = -32042,
31
32    /// [Internal code] The request has been canceled
33    RequestCancelled = -99999,
34
35    /// [Internal code] The request has been timed out
36    Timeout = -99998,
37}
38
39impl From<ErrorCode> for i32 {
40    fn from(code: ErrorCode) -> Self {
41        code as i32
42    }
43}
44
45impl TryFrom<i32> for ErrorCode {
46    type Error = ();
47
48    #[inline]
49    fn try_from(value: i32) -> Result<Self, Self::Error> {
50        match value {
51            -32700 => Ok(ErrorCode::ParseError),
52            -32600 => Ok(ErrorCode::InvalidRequest),
53            -32601 => Ok(ErrorCode::MethodNotFound),
54            -32602 => Ok(ErrorCode::InvalidParams),
55            -32603 => Ok(ErrorCode::InternalError),
56            -32002 => Ok(ErrorCode::ResourceNotFound),
57            -32042 => Ok(ErrorCode::UrlElicitationRequiredError),
58            -99999 => Ok(ErrorCode::RequestCancelled),
59            -99998 => Ok(ErrorCode::Timeout),
60            _ => Err(()),
61        }
62    }
63}
64
65// Implement serde::Serialize
66impl Serialize for ErrorCode {
67    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68    where
69        S: Serializer,
70    {
71        let code: i32 = (*self).into();
72        serializer.serialize_i32(code)
73    }
74}
75
76// Implement serde::Deserialize
77impl<'de> Deserialize<'de> for ErrorCode {
78    fn deserialize<D>(deserializer: D) -> Result<ErrorCode, D::Error>
79    where
80        D: Deserializer<'de>,
81    {
82        let value = i32::deserialize(deserializer)?;
83        ErrorCode::try_from(value)
84            .map_err(|_| serde::de::Error::custom(format!("Invalid error code: {value}")))
85    }
86}
87
88impl Display for ErrorCode {
89    #[inline]
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        match self {
92            ErrorCode::ParseError => write!(f, "Parse error"),
93            ErrorCode::InvalidRequest => write!(f, "Invalid request"),
94            ErrorCode::MethodNotFound => write!(f, "Method not found"),
95            ErrorCode::InvalidParams => write!(f, "Invalid parameters"),
96            ErrorCode::InternalError => write!(f, "Internal error"),
97            ErrorCode::ResourceNotFound => write!(f, "Resource not found"),
98            ErrorCode::UrlElicitationRequiredError => write!(f, "URL elicitation required error"),
99            ErrorCode::RequestCancelled => write!(f, "Request cancelled"),
100            ErrorCode::Timeout => write!(f, "Request timed out"),
101        }
102    }
103}
104
105impl From<ErrorCode> for Error {
106    fn from(code: ErrorCode) -> Self {
107        Error::new(code, code.to_string())
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn it_converts_to_i32() {
117        let codes = [
118            (-32700, ErrorCode::ParseError),
119            (-32600, ErrorCode::InvalidRequest),
120            (-32601, ErrorCode::MethodNotFound),
121            (-32602, ErrorCode::InvalidParams),
122            (-32603, ErrorCode::InternalError),
123            (-32002, ErrorCode::ResourceNotFound),
124            (-32042, ErrorCode::UrlElicitationRequiredError),
125            (-99999, ErrorCode::RequestCancelled),
126            (-99998, ErrorCode::Timeout),
127        ];
128
129        for (code, val) in codes {
130            let error: ErrorCode = code.try_into().unwrap();
131            assert_eq!(error, val);
132
133            let int: i32 = val.into();
134            assert_eq!(int, code);
135        }
136    }
137
138    #[test]
139    fn it_serializes_error_codes() {
140        let codes = [
141            ("-32700", ErrorCode::ParseError),
142            ("-32600", ErrorCode::InvalidRequest),
143            ("-32601", ErrorCode::MethodNotFound),
144            ("-32602", ErrorCode::InvalidParams),
145            ("-32603", ErrorCode::InternalError),
146            ("-32002", ErrorCode::ResourceNotFound),
147            ("-32042", ErrorCode::UrlElicitationRequiredError),
148            ("-99999", ErrorCode::RequestCancelled),
149            ("-99998", ErrorCode::Timeout),
150        ];
151
152        for (code, val) in codes {
153            let error = serde_json::to_string(&val).unwrap();
154            assert_eq!(error, code);
155
156            let error_code: ErrorCode = serde_json::from_str(&error).unwrap();
157            assert_eq!(error_code, val);
158        }
159    }
160}