1use serde_json::{Value, json};
4use thiserror::Error;
5
6use crate::Permissions;
7
8#[derive(Debug, Clone, PartialEq, Eq, Error)]
9#[error("permission denied: requires {required:?}, granted {granted:?}")]
10#[non_exhaustive]
11pub struct PermissionDenied {
12 pub required: Permissions,
13 pub granted: Permissions,
14}
15
16impl PermissionDenied {
17 pub fn new(required: Permissions, granted: Permissions) -> Self {
18 Self { required, granted }
19 }
20}
21
22#[derive(Debug, Error)]
23#[non_exhaustive]
24pub enum ToolError {
25 #[error(transparent)]
26 PermissionDenied(#[from] PermissionDenied),
27
28 #[error("invalid argument: {0}")]
29 InvalidArgument(String),
30
31 #[error("internal: {0}")]
32 Internal(String),
33}
34
35pub const ERROR_CODE_PERMISSION_DENIED: i32 = -32001;
42
43impl ToolError {
44 pub fn json_rpc_code(&self) -> i32 {
46 match self {
47 ToolError::PermissionDenied(_) => ERROR_CODE_PERMISSION_DENIED,
48 ToolError::InvalidArgument(_) => -32602,
49 ToolError::Internal(_) => -32603,
50 }
51 }
52
53 pub fn json_rpc_data(&self) -> Value {
58 match self {
59 ToolError::PermissionDenied(pd) => json!({
60 "kind": "permission_denied",
61 "required": pd.required.bits(),
62 "granted": pd.granted.bits(),
63 }),
64 ToolError::InvalidArgument(msg) => json!({
65 "kind": "invalid_argument",
66 "message": msg,
67 }),
68 ToolError::Internal(msg) => json!({
69 "kind": "internal",
70 "message": msg,
71 }),
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn permission_denied_json_rpc_data_carries_kind_and_bits() {
82 let err = ToolError::PermissionDenied(PermissionDenied {
83 required: Permissions::WRITE,
84 granted: Permissions::READ,
85 });
86 assert_eq!(err.json_rpc_code(), ERROR_CODE_PERMISSION_DENIED);
87 let data = err.json_rpc_data();
88 assert_eq!(data["kind"], "permission_denied");
89 assert_eq!(data["required"], Permissions::WRITE.bits());
90 assert_eq!(data["granted"], Permissions::READ.bits());
91 }
92}