zulip_api/message/response/
error_code.rs1use serde::{Deserialize, Serialize};
2use zeroize::Zeroize;
3
4use crate::error::Error;
5use crate::result::Result;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize, Zeroize)]
9#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
10pub enum ErrorCode {
11 BadRequest,
13 InvalidApiKey,
15 RequestVariableMissing,
17 UserDeactivated,
19 RealmDeactivated,
21 RateLimitHit,
23 StreamDoesNotExist,
25 BadNarrow,
27}
28
29impl ErrorCode {
30 pub const BAD_REQUEST: &str = "BAD_REQUEST";
32 pub const INVALID_API_KEY: &str = "INVALID_API_KEY";
34 pub const REQUEST_VARIABLE_MISSING: &str = "REQUEST_VARIABLE_MISSING";
36 pub const USER_DEACTIVATED: &str = "USER_DEACTIVATED";
38 pub const REALM_DEACTIVATED: &str = "REALM_DEACTIVATED";
40 pub const RATE_LIMIT_HIT: &str = "RATE_LIMIT_HIT";
42 pub const STREAM_DOES_NOT_EXIST: &str = "STREAM_DOES_NOT_EXIST";
44 pub const BAD_NARROW: &str = "BAD_NARROW";
46
47 pub const fn new() -> Self {
49 Self::BadRequest
50 }
51
52 pub const fn as_str(&self) -> &'static str {
54 match self {
55 Self::BadRequest => Self::BAD_REQUEST,
56 Self::InvalidApiKey => Self::INVALID_API_KEY,
57 Self::RequestVariableMissing => Self::REQUEST_VARIABLE_MISSING,
58 Self::UserDeactivated => Self::USER_DEACTIVATED,
59 Self::RealmDeactivated => Self::REALM_DEACTIVATED,
60 Self::RateLimitHit => Self::RATE_LIMIT_HIT,
61 Self::StreamDoesNotExist => Self::STREAM_DOES_NOT_EXIST,
62 Self::BadNarrow => Self::BAD_NARROW,
63 }
64 }
65
66 pub fn try_from_str<S: Into<String>>(val: S) -> Result<Self> {
68 match val.into().to_uppercase().as_str() {
69 Self::BAD_REQUEST => Ok(Self::BadRequest),
70 Self::INVALID_API_KEY => Ok(Self::InvalidApiKey),
71 Self::REQUEST_VARIABLE_MISSING => Ok(Self::RequestVariableMissing),
72 Self::USER_DEACTIVATED => Ok(Self::UserDeactivated),
73 Self::REALM_DEACTIVATED => Ok(Self::RealmDeactivated),
74 Self::RATE_LIMIT_HIT => Ok(Self::RateLimitHit),
75 Self::STREAM_DOES_NOT_EXIST => Ok(Self::StreamDoesNotExist),
76 Self::BAD_NARROW => Ok(Self::BadNarrow),
77 s => Err(Error::io_other(format!("invalid ErrorCode: {s}"))),
78 }
79 }
80}
81
82impl Default for ErrorCode {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl From<ErrorCode> for &'static str {
89 fn from(val: ErrorCode) -> Self {
90 val.as_str()
91 }
92}
93
94impl From<ErrorCode> for String {
95 fn from(val: ErrorCode) -> Self {
96 val.as_str().to_string()
97 }
98}
99
100impl TryFrom<&str> for ErrorCode {
101 type Error = Error;
102
103 fn try_from(val: &str) -> Result<Self> {
104 Self::try_from_str(val)
105 }
106}
107
108impl TryFrom<String> for ErrorCode {
109 type Error = Error;
110
111 fn try_from(val: String) -> Result<Self> {
112 Self::try_from_str(val)
113 }
114}
115
116impl std::fmt::Display for ErrorCode {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 write!(f, "{}", self.as_str())
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_error_code() {
128 [
129 (ErrorCode::BadRequest, ErrorCode::BAD_REQUEST),
130 (ErrorCode::InvalidApiKey, ErrorCode::INVALID_API_KEY),
131 (
132 ErrorCode::RequestVariableMissing,
133 ErrorCode::REQUEST_VARIABLE_MISSING,
134 ),
135 (ErrorCode::UserDeactivated, ErrorCode::USER_DEACTIVATED),
136 (ErrorCode::RealmDeactivated, ErrorCode::REALM_DEACTIVATED),
137 (ErrorCode::RateLimitHit, ErrorCode::RATE_LIMIT_HIT),
138 (
139 ErrorCode::StreamDoesNotExist,
140 ErrorCode::STREAM_DOES_NOT_EXIST,
141 ),
142 (ErrorCode::BadNarrow, ErrorCode::BAD_NARROW),
143 ]
144 .into_iter()
145 .for_each(|(code, code_str)| {
146 let code_json = format!(r#""{code}""#);
147 assert_eq!(code.as_str(), code_str);
148
149 assert_eq!(<&str>::from(code), code_str);
150 assert_eq!(String::from(code), code_str.to_string());
151
152 assert_eq!(ErrorCode::try_from_str(code_str), Ok(code));
153 assert_eq!(ErrorCode::try_from(code_str), Ok(code));
154 assert_eq!(ErrorCode::try_from(code_str.to_string()), Ok(code));
155
156 assert_eq!(serde_json::to_string(&code).unwrap(), code_json);
157 assert_eq!(serde_json::from_str::<ErrorCode>(&code_json).unwrap(), code);
158 });
159 }
160}