libmatrix-client/src/api/error.rs

87 lines
3.6 KiB
Rust

use serde::Deserialize;
use std::collections::HashMap;
// Various helper constants for common error codes.
pub const FORBIDDEN: &str = "M_FORBIDDEN";
pub const UNKNOWN_TOKEN: &str = "M_UNKNOWN_TOKEN";
pub const MISSING_TOKEN: &str = "M_MISSING_TOKEN";
pub const BAD_JSON: &str = "M_BAD_JSON";
pub const NOT_JSON: &str = "M_NOT_JSON";
pub const NOT_FOUND: &str = "M_NOT_FOUND";
pub const LIMIT_EXCEEDED: &str = "M_LIMIT_EXCEEDED";
pub const UNKNOWN: &str = "M_UNKNOWN";
pub const UNRECOGNIZED: &str = "M_UNRECOGNIZED";
pub const UNAUTHORIZED: &str = "M_UNAUTHORIZED";
pub const USER_IN_USE: &str = "M_USER_IN_USE";
pub const INVALID_USERNAME: &str = "M_INVALID_USERNAME";
pub const IN_USE: &str = "M_ROOM_IN_USE";
pub const STATE: &str = "M_INVALID_ROOM_STATE";
pub const THREEPID_IN_USE: &str = "M_THREEPID_IN_USE";
pub const THREEPID_NOT_FOUND: &str = "M_THREEPID_NOT_FOUND";
pub const THREEPID_AUTH_FAILED: &str = "M_THREEPID_AUTH_FAILED";
pub const THREEPID_DENIED: &str = "M_THREEPID_DENIED";
pub const SERVER_NOT_TRUSTED: &str = "M_SERVER_NOT_TRUSTED";
pub const UNSUPPORTED_ROOM_VERSION: &str = "M_UNSUPPORTED_ROOM_VERSION";
pub const INCOMPATIBLE_ROOM_VERSION: &str = "M_INCOMPATIBLE_ROOM_VERSION";
pub const BAD_STATE: &str = "M_BAD_STATE";
pub const GUEST_ACCESS_FORBIDDEN: &str = "M_GUEST_ACCESS_FORBIDDEN";
pub const CAPTCHA_NEEDED: &str = "M_CAPTCHA_NEEDED";
pub const CAPTCHA_INVALID: &str = "M_CAPTCHA_INVALID";
pub const MISSING_PARAM: &str = "M_MISSING_PARAM";
pub const INVALID_PARAM: &str = "M_INVALID_PARAM";
pub const TOO_LARGE: &str = "M_TOO_LARGE";
pub const EXCLUSIVE: &str = "M_EXCLUSIVE";
pub const RESOURCE_LIMIT_EXCEEDED: &str = "M_RESOURCE_LIMIT_EXCEEDED";
pub const CANNOT_LEAVE_SERVER_NOTICE_ROOM: &str = "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM";
/// Implements the standard error response as defined by [Section 2](https://matrix.org/docs/spec/client_server/r0.5.0#api-standards)
/// of the Client-Server API standard as a HashMap. We don't have a better way
/// of representing this class, since we need to conform to having different
/// fields for different errors.
#[derive(Deserialize)]
pub struct ApiError {
#[serde(flatten)]
pub data: HashMap<String, String>,
}
impl ApiError {
/// Helper function for obtaining the error code. Access the `errcode`
/// field, which must be present on all valid error messages.
pub fn error_code(&self) -> &str {
self.data
.get("errcode")
.expect("Error did not contain required errcode field")
}
/// Helper function for obtaining the error message, which is a
/// human-readable field that explains the issue. This accesses the `error`
/// field, which must be present on all valid error messages.
pub fn error_message(&self) -> &str {
self.data
.get("error")
.expect("Error did not contain required error field")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize_basic_error_msg() {
let test_msg = r#"{"errcode": "M_FORBIDDEN", "error": "hello"}"#;
let deserialized: ApiError = serde_json::from_str(test_msg).unwrap();
assert_eq!(deserialized.error_code(), FORBIDDEN);
assert_eq!(deserialized.error_message(), "hello");
}
#[test]
fn deserialize_error_with_custom_field() {
let test_msg = r#"{"errcode": "M_UNKNOWN", "error": "foo", "a": "b"}"#;
let deserialized: ApiError = serde_json::from_str(test_msg).unwrap();
assert_eq!(deserialized.error_code(), UNKNOWN);
assert_eq!(deserialized.error_message(), "foo");
assert_eq!(deserialized.data.get("a").unwrap(), "b");
}
}