1use serde::*;
2use std::str::FromStr;
3
4#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
6pub struct ErrorCode {
7 code: u32,
9}
10
11impl ErrorCode {
12 pub const BAD_REQUEST: Self = Self::new(100400);
14
15 pub const UNAUTHORIZED: Self = Self::new(100401);
17
18 pub const PAYMENT_REQUIRED: Self = Self::new(100402);
20
21 pub const FORBIDDEN: Self = Self::new(100403);
23
24 pub const NOT_FOUND: Self = Self::new(100404);
26
27 pub const METHOD_NOT_ALLOWED: Self = Self::new(100405);
29
30 pub const NOT_ACCEPTABLE: Self = Self::new(100406);
32
33 pub const PROXY_AUTHENTICATION_REQUIRED: Self = Self::new(100407);
35
36 pub const REQUEST_TIMEOUT: Self = Self::new(100408);
38
39 pub const CONFLICT: Self = Self::new(100409);
41
42 pub const GONE: Self = Self::new(100410);
44
45 pub const LENGTH_REQUIRED: Self = Self::new(100411);
47
48 pub const PRECONDITION_FAILED: Self = Self::new(100412);
50
51 pub const PAYLOAD_TOO_LARGE: Self = Self::new(100413);
53
54 pub const URI_TOO_LONG: Self = Self::new(100414);
56
57 pub const UNSUPPORTED_MEDIA_TYPE: Self = Self::new(100415);
59
60 pub const RANGE_NOT_SATISFIABLE: Self = Self::new(100416);
62
63 pub const EXPECTATION_FAILED: Self = Self::new(100417);
65
66 pub const IM_A_TEAPOT: Self = Self::new(100418);
68
69 pub const MISDIRECTED_REQUEST: Self = Self::new(100421);
71
72 pub const UNPROCESSABLE_ENTITY: Self = Self::new(100422);
74
75 pub const LOCKED: Self = Self::new(100423);
77
78 pub const FAILED_DEPENDENCY: Self = Self::new(100424);
80
81 pub const UPGRADE_REQUIRED: Self = Self::new(100426);
83
84 pub const PRECONDITION_REQUIRED: Self = Self::new(100428);
86
87 pub const TOO_MANY_REQUESTS: Self = Self::new(100429);
89
90 pub const REQUEST_HEADER_FIELDS_TOO_LARGE: Self = Self::new(100431);
92
93 pub const UNAVAILABLE_FOR_LEGAL_REASONS: Self = Self::new(100451);
95
96 pub const INTERNAL_ERROR: Self = Self::new(100500);
98
99 pub const NOT_IMPLEMENTED: Self = Self::new(100501);
101
102 pub const BAD_GATEWAY: Self = Self::new(100502);
104
105 pub const SERVICE_UNAVAILABLE: Self = Self::new(100503);
107
108 pub const GATEWAY_TIMEOUT: Self = Self::new(100504);
110
111 pub const HTTP_VERSION_NOT_SUPPORTED: Self = Self::new(100505);
113
114 pub const VARIANT_ALSO_NEGOTIATES: Self = Self::new(100506);
116
117 pub const INSUFFICIENT_STORAGE: Self = Self::new(100507);
119
120 pub const LOOP_DETECTED: Self = Self::new(100508);
122
123 pub const NOT_EXTENDED: Self = Self::new(100510);
125
126 pub const NETWORK_AUTHENTICATION_REQUIRED: Self = Self::new(100511);
128
129 pub const fn new(code: u32) -> Self {
131 Self { code }
132 }
133
134 pub const fn to_u32(self) -> u32 {
137 self.code
138 }
139
140 pub const fn code(self) -> u32 {
142 self.to_u32()
143 }
144
145 pub const fn kind(self) -> &'static str {
146 match self.code {
147 100400 => "BadRequest",
148 100401 => "Unauthorized",
149 100402 => "PaymentRequired",
150 100403 => "Forbidden",
151 100404 => "NotFound",
152 100405 => "MethodNotAllowed",
153 100406 => "NotAcceptable",
154 100407 => "ProxyAuthenticationRequired",
155 100408 => "RequestTimeout",
156 100409 => "Conflict",
157 100410 => "Gone",
158 100411 => "LengthRequired",
159 100412 => "PreconditionFailed",
160 100413 => "PayloadTooLarge",
161 100414 => "UriTooLong",
162 100415 => "UnsupportedMediaType",
163 100416 => "RangeNotSatisfiable",
164 100417 => "ExpectationFailed",
165 100418 => "ImATeapot",
166 100421 => "MisdirectedRequest",
167 100422 => "UnprocessableEntity",
168 100423 => "Locked",
169 100424 => "FailedDependency",
170 100426 => "UpgradeRequired",
171 100428 => "PreconditionRequired",
172 100429 => "TooManyRequests",
173 100431 => "RequestHeaderFieldsTooLarge",
174 100451 => "UnavailableForLegalReasons",
175 100500 => "InternalError",
176 100501 => "NotImplemented",
177 100502 => "BadGateway",
178 100503 => "ServiceUnavailable",
179 100504 => "GatewayTimeout",
180 100505 => "HttpVersionNotSupported",
181 100506 => "VariantAlsoNegotiates",
182 100507 => "InsufficientStorage",
183 100508 => "LoopDetected",
184 100510 => "NotExtended",
185 100511 => "NetworkAuthenticationRequired",
186 _ => "CustomError",
187 }
188 }
189
190 pub fn from_name(name: &str) -> Option<Self> {
191 let normalized: String = name
192 .chars()
193 .filter(|c| c.is_ascii_alphanumeric())
194 .flat_map(char::to_uppercase)
195 .collect();
196
197 match normalized.as_str() {
198 "BADREQUEST" => Some(Self::BAD_REQUEST),
199 "UNAUTHORIZED" => Some(Self::UNAUTHORIZED),
200 "PAYMENTREQUIRED" => Some(Self::PAYMENT_REQUIRED),
201 "FORBIDDEN" => Some(Self::FORBIDDEN),
202 "NOTFOUND" => Some(Self::NOT_FOUND),
203 "METHODNOTALLOWED" => Some(Self::METHOD_NOT_ALLOWED),
204 "NOTACCEPTABLE" => Some(Self::NOT_ACCEPTABLE),
205 "PROXYAUTHENTICATIONREQUIRED" => Some(Self::PROXY_AUTHENTICATION_REQUIRED),
206 "REQUESTTIMEOUT" => Some(Self::REQUEST_TIMEOUT),
207 "CONFLICT" => Some(Self::CONFLICT),
208 "GONE" => Some(Self::GONE),
209 "LENGTHREQUIRED" => Some(Self::LENGTH_REQUIRED),
210 "PRECONDITIONFAILED" => Some(Self::PRECONDITION_FAILED),
211 "PAYLOADTOOLARGE" => Some(Self::PAYLOAD_TOO_LARGE),
212 "URITOOLONG" => Some(Self::URI_TOO_LONG),
213 "UNSUPPORTEDMEDIATYPE" => Some(Self::UNSUPPORTED_MEDIA_TYPE),
214 "RANGENOTSATISFIABLE" => Some(Self::RANGE_NOT_SATISFIABLE),
215 "EXPECTATIONFAILED" => Some(Self::EXPECTATION_FAILED),
216 "IMATEAPOT" => Some(Self::IM_A_TEAPOT),
217 "MISDIRECTEDREQUEST" => Some(Self::MISDIRECTED_REQUEST),
218 "UNPROCESSABLEENTITY" => Some(Self::UNPROCESSABLE_ENTITY),
219 "LOCKED" => Some(Self::LOCKED),
220 "FAILEDDEPENDENCY" => Some(Self::FAILED_DEPENDENCY),
221 "UPGRADEREQUIRED" => Some(Self::UPGRADE_REQUIRED),
222 "PRECONDITIONREQUIRED" => Some(Self::PRECONDITION_REQUIRED),
223 "TOOMANYREQUESTS" => Some(Self::TOO_MANY_REQUESTS),
224 "REQUESTHEADERFIELDSTOOLARGE" => Some(Self::REQUEST_HEADER_FIELDS_TOO_LARGE),
225 "UNAVAILABLEFORLEGALREASONS" => Some(Self::UNAVAILABLE_FOR_LEGAL_REASONS),
226 "INTERNALERROR" => Some(Self::INTERNAL_ERROR),
227 "NOTIMPLEMENTED" => Some(Self::NOT_IMPLEMENTED),
228 "BADGATEWAY" => Some(Self::BAD_GATEWAY),
229 "SERVICEUNAVAILABLE" => Some(Self::SERVICE_UNAVAILABLE),
230 "GATEWAYTIMEOUT" => Some(Self::GATEWAY_TIMEOUT),
231 "HTTPVERSIONNOTSUPPORTED" => Some(Self::HTTP_VERSION_NOT_SUPPORTED),
232 "VARIANTALSONEGOTIATES" => Some(Self::VARIANT_ALSO_NEGOTIATES),
233 "INSUFFICIENTSTORAGE" => Some(Self::INSUFFICIENT_STORAGE),
234 "LOOPDETECTED" => Some(Self::LOOP_DETECTED),
235 "NOTEXTENDED" => Some(Self::NOT_EXTENDED),
236 "NETWORKAUTHENTICATIONREQUIRED" => Some(Self::NETWORK_AUTHENTICATION_REQUIRED),
237 _ => None,
238 }
239 }
240}
241
242impl FromStr for ErrorCode {
243 type Err = ParseErrorCodeError;
244
245 fn from_str(value: &str) -> Result<Self, Self::Err> {
246 if let Some(code) = Self::from_name(value) {
247 return Ok(code);
248 }
249
250 value
251 .parse::<u32>()
252 .map(Self::new)
253 .map_err(|_| ParseErrorCodeError)
254 }
255}
256
257#[derive(Debug, Clone, Copy, PartialEq, Eq)]
258pub struct ParseErrorCodeError;
259
260impl std::fmt::Display for ParseErrorCodeError {
261 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
262 f.write_str("invalid error code")
263 }
264}
265
266impl std::error::Error for ParseErrorCodeError {}