Skip to main content

wavecraft_protocol/ipc/
errors.rs

1use serde::{Deserialize, Serialize};
2
3/// Error returned in IpcResponse
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct IpcError {
6    /// Error code (see error code constants)
7    pub code: i32,
8    /// Human-readable error message
9    pub message: String,
10    /// Additional error data (optional)
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub data: Option<serde_json::Value>,
13}
14
15// ============================================================================
16// Error Codes (JSON-RPC 2.0 standard codes + custom extensions)
17// ============================================================================
18
19/// JSON-RPC parse error (invalid JSON)
20pub const ERROR_PARSE: i32 = -32700;
21/// JSON-RPC invalid request (malformed structure)
22pub const ERROR_INVALID_REQUEST: i32 = -32600;
23/// JSON-RPC method not found
24pub const ERROR_METHOD_NOT_FOUND: i32 = -32601;
25/// JSON-RPC invalid method parameters
26pub const ERROR_INVALID_PARAMS: i32 = -32602;
27/// JSON-RPC internal error
28pub const ERROR_INTERNAL: i32 = -32603;
29
30// Custom application error codes (start at -32000)
31/// Parameter not found
32pub const ERROR_PARAM_NOT_FOUND: i32 = -32000;
33/// Parameter value out of valid range
34pub const ERROR_PARAM_OUT_OF_RANGE: i32 = -32001;
35
36impl IpcError {
37    /// Create a new error
38    pub fn new(code: i32, message: impl Into<String>) -> Self {
39        Self {
40            code,
41            message: message.into(),
42            data: None,
43        }
44    }
45
46    /// Try to create an error with additional data.
47    pub fn try_with_data(
48        code: i32,
49        message: impl Into<String>,
50        data: impl Serialize,
51    ) -> serde_json::Result<Self> {
52        Ok(Self {
53            code,
54            message: message.into(),
55            data: Some(serde_json::to_value(data)?),
56        })
57    }
58
59    /// Create an error with additional data
60    pub fn with_data(code: i32, message: impl Into<String>, data: impl Serialize) -> Self {
61        let message = message.into();
62        match Self::try_with_data(code, message.clone(), data) {
63            Ok(error) => error,
64            Err(_) => Self {
65                code,
66                message,
67                data: None,
68            },
69        }
70    }
71
72    /// Parse error
73    pub fn parse_error() -> Self {
74        Self::new(ERROR_PARSE, "Parse error")
75    }
76
77    /// Invalid request error
78    pub fn invalid_request(reason: impl Into<String>) -> Self {
79        Self::new(
80            ERROR_INVALID_REQUEST,
81            format!("Invalid request: {}", reason.into()),
82        )
83    }
84
85    /// Method not found error
86    pub fn method_not_found(method: impl AsRef<str>) -> Self {
87        Self::new(
88            ERROR_METHOD_NOT_FOUND,
89            format!("Method not found: {}", method.as_ref()),
90        )
91    }
92
93    /// Invalid params error
94    pub fn invalid_params(reason: impl Into<String>) -> Self {
95        Self::new(
96            ERROR_INVALID_PARAMS,
97            format!("Invalid params: {}", reason.into()),
98        )
99    }
100
101    /// Internal error
102    pub fn internal_error(reason: impl Into<String>) -> Self {
103        Self::new(ERROR_INTERNAL, format!("Internal error: {}", reason.into()))
104    }
105
106    /// Parameter not found error
107    pub fn param_not_found(id: impl AsRef<str>) -> Self {
108        Self::new(
109            ERROR_PARAM_NOT_FOUND,
110            format!("Parameter not found: {}", id.as_ref()),
111        )
112    }
113
114    /// Parameter out of range error
115    pub fn param_out_of_range(id: impl AsRef<str>, value: f32) -> Self {
116        Self::new(
117            ERROR_PARAM_OUT_OF_RANGE,
118            format!("Parameter '{}' value {} out of range", id.as_ref(), value),
119        )
120    }
121}