1use std::fmt;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14#[repr(i32)]
15#[non_exhaustive]
16pub enum ErrorCode {
17 OtherCause = -1,
18 InternalServerError = 1,
19 ConnectionFailed = 100,
20 ObjectNotFound = 101,
21 InvalidQuery = 102,
22 InvalidClassName = 103,
23 MissingObjectId = 104,
24 InvalidKeyName = 105,
25 InvalidPointer = 106,
26 InvalidJson = 107,
27 CommandUnavailable = 108,
28 NotInitialized = 109,
29 IncorrectType = 111,
30 InvalidChannelName = 112,
31 PushMisconfigured = 115,
32 ObjectTooLarge = 116,
33 OperationForbidden = 119,
34 CacheMiss = 120,
35 InvalidNestedKey = 121,
36 InvalidFileName = 122,
37 InvalidAcl = 123,
38 Timeout = 124,
39 InvalidEmailAddress = 125,
40 MissingContentType = 126,
41 MissingContentLength = 127,
42 InvalidContentLength = 128,
43 FileTooLarge = 129,
44 FileSaveError = 130,
45 DuplicateValue = 137,
46 InvalidRoleName = 139,
47 ExceededQuota = 140,
48 ScriptFailed = 141,
49 ValidationError = 142,
50 InvalidImageData = 143,
51 UnsavedFileError = 151,
52 InvalidPushTimeError = 152,
53 FileDeleteError = 153,
54 RequestLimitExceeded = 155,
55 DuplicateRequest = 159,
56 InvalidEventName = 160,
57 FileDeleteUnnamedError = 161,
58 InvalidValue = 162,
59 UsernameMissing = 200,
60 PasswordMissing = 201,
61 UsernameTaken = 202,
62 EmailTaken = 203,
63 EmailMissing = 204,
64 EmailNotFound = 205,
65 SessionMissing = 206,
66 MustCreateUserThroughSignup = 207,
67 AccountAlreadyLinked = 208,
68 InvalidSessionToken = 209,
69 MfaError = 210,
70 MfaTokenRequired = 211,
71 LinkedIdMissing = 250,
72 InvalidLinkedSession = 251,
73 UnsupportedService = 252,
74 InvalidSchemaOperation = 255,
75 AggregateError = 600,
76 FileReadError = 601,
77 XDomainRequest = 602,
78}
79
80impl ErrorCode {
81 pub fn as_i32(self) -> i32 {
83 self as i32
84 }
85}
86
87impl fmt::Display for ErrorCode {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 write!(f, "{}", self.as_i32())
90 }
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
100#[error("{code}: {message}")]
101pub struct ParseError {
102 pub code: ErrorCode,
103 pub message: String,
104}
105
106impl ParseError {
107 pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
108 Self {
109 code,
110 message: message.into(),
111 }
112 }
113}
114
115impl ParseError {
117 pub fn invalid_json(message: impl Into<String>) -> Self {
118 Self::new(ErrorCode::InvalidJson, message)
119 }
120 pub fn incorrect_type(message: impl Into<String>) -> Self {
121 Self::new(ErrorCode::IncorrectType, message)
122 }
123 pub fn invalid_key_name(message: impl Into<String>) -> Self {
124 Self::new(ErrorCode::InvalidKeyName, message)
125 }
126 pub fn invalid_acl(message: impl Into<String>) -> Self {
127 Self::new(ErrorCode::InvalidAcl, message)
128 }
129 pub fn invalid_query(message: impl Into<String>) -> Self {
130 Self::new(ErrorCode::InvalidQuery, message)
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn discriminants_match_upstream() {
140 assert_eq!(ErrorCode::OtherCause.as_i32(), -1);
143 assert_eq!(ErrorCode::InternalServerError.as_i32(), 1);
144 assert_eq!(ErrorCode::ObjectNotFound.as_i32(), 101);
145 assert_eq!(ErrorCode::InvalidQuery.as_i32(), 102);
146 assert_eq!(ErrorCode::IncorrectType.as_i32(), 111);
147 assert_eq!(ErrorCode::OperationForbidden.as_i32(), 119);
148 assert_eq!(ErrorCode::DuplicateValue.as_i32(), 137);
149 assert_eq!(ErrorCode::ScriptFailed.as_i32(), 141);
150 assert_eq!(ErrorCode::DuplicateRequest.as_i32(), 159);
151 assert_eq!(ErrorCode::InvalidSessionToken.as_i32(), 209);
152 assert_eq!(ErrorCode::InvalidSchemaOperation.as_i32(), 255);
153 }
156
157 #[test]
158 fn display_is_the_number() {
159 assert_eq!(ErrorCode::ObjectNotFound.to_string(), "101");
160 }
161}