1use serde_json::Value;
8
9#[derive(Debug, Clone)]
15pub enum JmapMethodError {
16 ServerFail(String),
18 ServerUnavailable(String),
20 InvalidArguments(String),
22 UnknownMethod(String),
24 AccountNotFound,
26 Other {
30 kind: String,
32 description: String,
34 },
35}
36
37impl JmapMethodError {
38 pub fn to_json(&self) -> Value {
40 let (kind, description) = match self {
41 JmapMethodError::ServerFail(d) => ("serverFail", d.as_str()),
42 JmapMethodError::ServerUnavailable(d) => ("serverUnavailable", d.as_str()),
43 JmapMethodError::InvalidArguments(d) => ("invalidArguments", d.as_str()),
44 JmapMethodError::UnknownMethod(d) => ("unknownMethod", d.as_str()),
45 JmapMethodError::AccountNotFound => ("accountNotFound", ""),
46 JmapMethodError::Other { kind, description } => (kind.as_str(), description.as_str()),
47 };
48 if description.is_empty() {
49 serde_json::json!({ "type": kind })
50 } else {
51 serde_json::json!({ "type": kind, "description": description })
52 }
53 }
54}
55
56impl std::fmt::Display for JmapMethodError {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 match self {
59 JmapMethodError::ServerFail(d) => write!(f, "serverFail: {d}"),
60 JmapMethodError::ServerUnavailable(d) => write!(f, "serverUnavailable: {d}"),
61 JmapMethodError::InvalidArguments(d) => write!(f, "invalidArguments: {d}"),
62 JmapMethodError::UnknownMethod(d) => write!(f, "unknownMethod: {d}"),
63 JmapMethodError::AccountNotFound => write!(f, "accountNotFound"),
64 JmapMethodError::Other { kind, description } => write!(f, "{kind}: {description}"),
65 }
66 }
67}
68
69impl std::error::Error for JmapMethodError {}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn server_fail_serialises_with_description() {
77 let err = JmapMethodError::ServerFail("boom".into());
78 let v = err.to_json();
79 assert_eq!(v["type"], "serverFail");
80 assert_eq!(v["description"], "boom");
81 }
82
83 #[test]
84 fn account_not_found_has_no_description() {
85 let err = JmapMethodError::AccountNotFound;
86 let v = err.to_json();
87 assert_eq!(v["type"], "accountNotFound");
88 assert!(v.get("description").is_none());
89 }
90
91 #[test]
92 fn other_variant_uses_kind_and_description() {
93 let err = JmapMethodError::Other {
94 kind: "tooLarge".into(),
95 description: "1 MB > 100 KB".into(),
96 };
97 let v = err.to_json();
98 assert_eq!(v["type"], "tooLarge");
99 assert_eq!(v["description"], "1 MB > 100 KB");
100 }
101}