use serde::*;
use std::str::FromStr;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ErrorCode {
code: u32,
}
impl ErrorCode {
pub const BAD_REQUEST: Self = Self::new(100400);
pub const UNAUTHORIZED: Self = Self::new(100401);
pub const PAYMENT_REQUIRED: Self = Self::new(100402);
pub const FORBIDDEN: Self = Self::new(100403);
pub const NOT_FOUND: Self = Self::new(100404);
pub const METHOD_NOT_ALLOWED: Self = Self::new(100405);
pub const NOT_ACCEPTABLE: Self = Self::new(100406);
pub const PROXY_AUTHENTICATION_REQUIRED: Self = Self::new(100407);
pub const REQUEST_TIMEOUT: Self = Self::new(100408);
pub const CONFLICT: Self = Self::new(100409);
pub const GONE: Self = Self::new(100410);
pub const LENGTH_REQUIRED: Self = Self::new(100411);
pub const PRECONDITION_FAILED: Self = Self::new(100412);
pub const PAYLOAD_TOO_LARGE: Self = Self::new(100413);
pub const URI_TOO_LONG: Self = Self::new(100414);
pub const UNSUPPORTED_MEDIA_TYPE: Self = Self::new(100415);
pub const RANGE_NOT_SATISFIABLE: Self = Self::new(100416);
pub const EXPECTATION_FAILED: Self = Self::new(100417);
pub const IM_A_TEAPOT: Self = Self::new(100418);
pub const MISDIRECTED_REQUEST: Self = Self::new(100421);
pub const UNPROCESSABLE_ENTITY: Self = Self::new(100422);
pub const LOCKED: Self = Self::new(100423);
pub const FAILED_DEPENDENCY: Self = Self::new(100424);
pub const UPGRADE_REQUIRED: Self = Self::new(100426);
pub const PRECONDITION_REQUIRED: Self = Self::new(100428);
pub const TOO_MANY_REQUESTS: Self = Self::new(100429);
pub const REQUEST_HEADER_FIELDS_TOO_LARGE: Self = Self::new(100431);
pub const UNAVAILABLE_FOR_LEGAL_REASONS: Self = Self::new(100451);
pub const INTERNAL_ERROR: Self = Self::new(100500);
pub const NOT_IMPLEMENTED: Self = Self::new(100501);
pub const BAD_GATEWAY: Self = Self::new(100502);
pub const SERVICE_UNAVAILABLE: Self = Self::new(100503);
pub const GATEWAY_TIMEOUT: Self = Self::new(100504);
pub const HTTP_VERSION_NOT_SUPPORTED: Self = Self::new(100505);
pub const VARIANT_ALSO_NEGOTIATES: Self = Self::new(100506);
pub const INSUFFICIENT_STORAGE: Self = Self::new(100507);
pub const LOOP_DETECTED: Self = Self::new(100508);
pub const NOT_EXTENDED: Self = Self::new(100510);
pub const NETWORK_AUTHENTICATION_REQUIRED: Self = Self::new(100511);
pub const fn new(code: u32) -> Self {
Self { code }
}
pub const fn to_u32(self) -> u32 {
self.code
}
pub const fn code(self) -> u32 {
self.to_u32()
}
pub const fn kind(self) -> &'static str {
match self.code {
100400 => "BadRequest",
100401 => "Unauthorized",
100402 => "PaymentRequired",
100403 => "Forbidden",
100404 => "NotFound",
100405 => "MethodNotAllowed",
100406 => "NotAcceptable",
100407 => "ProxyAuthenticationRequired",
100408 => "RequestTimeout",
100409 => "Conflict",
100410 => "Gone",
100411 => "LengthRequired",
100412 => "PreconditionFailed",
100413 => "PayloadTooLarge",
100414 => "UriTooLong",
100415 => "UnsupportedMediaType",
100416 => "RangeNotSatisfiable",
100417 => "ExpectationFailed",
100418 => "ImATeapot",
100421 => "MisdirectedRequest",
100422 => "UnprocessableEntity",
100423 => "Locked",
100424 => "FailedDependency",
100426 => "UpgradeRequired",
100428 => "PreconditionRequired",
100429 => "TooManyRequests",
100431 => "RequestHeaderFieldsTooLarge",
100451 => "UnavailableForLegalReasons",
100500 => "InternalError",
100501 => "NotImplemented",
100502 => "BadGateway",
100503 => "ServiceUnavailable",
100504 => "GatewayTimeout",
100505 => "HttpVersionNotSupported",
100506 => "VariantAlsoNegotiates",
100507 => "InsufficientStorage",
100508 => "LoopDetected",
100510 => "NotExtended",
100511 => "NetworkAuthenticationRequired",
_ => "CustomError",
}
}
pub fn from_name(name: &str) -> Option<Self> {
let normalized: String = name
.chars()
.filter(|c| c.is_ascii_alphanumeric())
.flat_map(char::to_uppercase)
.collect();
match normalized.as_str() {
"BADREQUEST" => Some(Self::BAD_REQUEST),
"UNAUTHORIZED" => Some(Self::UNAUTHORIZED),
"PAYMENTREQUIRED" => Some(Self::PAYMENT_REQUIRED),
"FORBIDDEN" => Some(Self::FORBIDDEN),
"NOTFOUND" => Some(Self::NOT_FOUND),
"METHODNOTALLOWED" => Some(Self::METHOD_NOT_ALLOWED),
"NOTACCEPTABLE" => Some(Self::NOT_ACCEPTABLE),
"PROXYAUTHENTICATIONREQUIRED" => Some(Self::PROXY_AUTHENTICATION_REQUIRED),
"REQUESTTIMEOUT" => Some(Self::REQUEST_TIMEOUT),
"CONFLICT" => Some(Self::CONFLICT),
"GONE" => Some(Self::GONE),
"LENGTHREQUIRED" => Some(Self::LENGTH_REQUIRED),
"PRECONDITIONFAILED" => Some(Self::PRECONDITION_FAILED),
"PAYLOADTOOLARGE" => Some(Self::PAYLOAD_TOO_LARGE),
"URITOOLONG" => Some(Self::URI_TOO_LONG),
"UNSUPPORTEDMEDIATYPE" => Some(Self::UNSUPPORTED_MEDIA_TYPE),
"RANGENOTSATISFIABLE" => Some(Self::RANGE_NOT_SATISFIABLE),
"EXPECTATIONFAILED" => Some(Self::EXPECTATION_FAILED),
"IMATEAPOT" => Some(Self::IM_A_TEAPOT),
"MISDIRECTEDREQUEST" => Some(Self::MISDIRECTED_REQUEST),
"UNPROCESSABLEENTITY" => Some(Self::UNPROCESSABLE_ENTITY),
"LOCKED" => Some(Self::LOCKED),
"FAILEDDEPENDENCY" => Some(Self::FAILED_DEPENDENCY),
"UPGRADEREQUIRED" => Some(Self::UPGRADE_REQUIRED),
"PRECONDITIONREQUIRED" => Some(Self::PRECONDITION_REQUIRED),
"TOOMANYREQUESTS" => Some(Self::TOO_MANY_REQUESTS),
"REQUESTHEADERFIELDSTOOLARGE" => Some(Self::REQUEST_HEADER_FIELDS_TOO_LARGE),
"UNAVAILABLEFORLEGALREASONS" => Some(Self::UNAVAILABLE_FOR_LEGAL_REASONS),
"INTERNALERROR" => Some(Self::INTERNAL_ERROR),
"NOTIMPLEMENTED" => Some(Self::NOT_IMPLEMENTED),
"BADGATEWAY" => Some(Self::BAD_GATEWAY),
"SERVICEUNAVAILABLE" => Some(Self::SERVICE_UNAVAILABLE),
"GATEWAYTIMEOUT" => Some(Self::GATEWAY_TIMEOUT),
"HTTPVERSIONNOTSUPPORTED" => Some(Self::HTTP_VERSION_NOT_SUPPORTED),
"VARIANTALSONEGOTIATES" => Some(Self::VARIANT_ALSO_NEGOTIATES),
"INSUFFICIENTSTORAGE" => Some(Self::INSUFFICIENT_STORAGE),
"LOOPDETECTED" => Some(Self::LOOP_DETECTED),
"NOTEXTENDED" => Some(Self::NOT_EXTENDED),
"NETWORKAUTHENTICATIONREQUIRED" => Some(Self::NETWORK_AUTHENTICATION_REQUIRED),
_ => None,
}
}
}
impl FromStr for ErrorCode {
type Err = ParseErrorCodeError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
if let Some(code) = Self::from_name(value) {
return Ok(code);
}
value
.parse::<u32>()
.map(Self::new)
.map_err(|_| ParseErrorCodeError)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ParseErrorCodeError;
impl std::fmt::Display for ParseErrorCodeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("invalid error code")
}
}
impl std::error::Error for ParseErrorCodeError {}