use serde_json::Value;
#[derive(Debug, Clone)]
pub enum JmapMethodError {
ServerFail(String),
ServerUnavailable(String),
InvalidArguments(String),
UnknownMethod(String),
AccountNotFound,
Other {
kind: String,
description: String,
},
}
impl JmapMethodError {
pub fn to_json(&self) -> Value {
let (kind, description) = match self {
JmapMethodError::ServerFail(d) => ("serverFail", d.as_str()),
JmapMethodError::ServerUnavailable(d) => ("serverUnavailable", d.as_str()),
JmapMethodError::InvalidArguments(d) => ("invalidArguments", d.as_str()),
JmapMethodError::UnknownMethod(d) => ("unknownMethod", d.as_str()),
JmapMethodError::AccountNotFound => ("accountNotFound", ""),
JmapMethodError::Other { kind, description } => (kind.as_str(), description.as_str()),
};
if description.is_empty() {
serde_json::json!({ "type": kind })
} else {
serde_json::json!({ "type": kind, "description": description })
}
}
}
impl std::fmt::Display for JmapMethodError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
JmapMethodError::ServerFail(d) => write!(f, "serverFail: {d}"),
JmapMethodError::ServerUnavailable(d) => write!(f, "serverUnavailable: {d}"),
JmapMethodError::InvalidArguments(d) => write!(f, "invalidArguments: {d}"),
JmapMethodError::UnknownMethod(d) => write!(f, "unknownMethod: {d}"),
JmapMethodError::AccountNotFound => write!(f, "accountNotFound"),
JmapMethodError::Other { kind, description } => write!(f, "{kind}: {description}"),
}
}
}
impl std::error::Error for JmapMethodError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn server_fail_serialises_with_description() {
let err = JmapMethodError::ServerFail("boom".into());
let v = err.to_json();
assert_eq!(v["type"], "serverFail");
assert_eq!(v["description"], "boom");
}
#[test]
fn account_not_found_has_no_description() {
let err = JmapMethodError::AccountNotFound;
let v = err.to_json();
assert_eq!(v["type"], "accountNotFound");
assert!(v.get("description").is_none());
}
#[test]
fn other_variant_uses_kind_and_description() {
let err = JmapMethodError::Other {
kind: "tooLarge".into(),
description: "1 MB > 100 KB".into(),
};
let v = err.to_json();
assert_eq!(v["type"], "tooLarge");
assert_eq!(v["description"], "1 MB > 100 KB");
}
}