use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;
use std::sync::LazyLock;
use super::error::{Error, Result};
impl AsRef<str> for Header {
#[inline]
fn as_ref(&self) -> &str {
self.name()
}
}
impl fmt::Display for Header {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.name())
}
}
macro_rules! define_and_impl {
(
$(
// Header group
$(#[$_:meta])*
$group:ident:
{
$(
// Header definition
$(#[$comment:meta])*
$name:ident = $header:expr
),+
$(,)?
}
)+
) => {
#[allow(dead_code)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Header {
$(
$(
$(#[$comment])*
$name,
)+
)+
}
impl Header {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
$(
$(
Header::$name => $header,
)+
)+
}
}
}
static HEADER_LOOKUP_TABLE: LazyLock<HashMap<String, Header>> =
LazyLock::new(|| {
HashMap::from_iter([
$(
$(
($header.to_lowercase(), Header::$name),
)+
)+
])
});
impl FromStr for Header {
type Err = Error;
fn from_str(value: &str) -> Result<Self> {
HEADER_LOOKUP_TABLE
.get(&value.to_lowercase())
.copied()
.ok_or_else(|| Error::Header(value.to_string()))
}
}
}
}
define_and_impl! {
General: {
Accept = "Accept",
AcceptCharset = "Accept-Charset",
AcceptEncoding = "Accept-Encoding",
AcceptLanguage = "Accept-Language",
AcceptRanges = "Accept-Ranges",
Age = "Age",
Allow = "Allow",
AltSvc = "Alt-Svc",
Authorization = "Authorization",
CacheControl = "Cache-Control",
Connection = "Connection",
ContentDisposition = "Content-Disposition",
ContentEncoding = "Content-Encoding",
ContentLanguage = "Content-Language",
ContentLength = "Content-Length",
ContentLocation = "Content-Location",
ContentRange = "Content-Range",
ContentSecurityPolicy = "Content-Security-Policy",
ContentType = "Content-Type",
Cookie = "Cookie",
Date = "Date",
ETag = "ETag",
Expect = "Expect",
Expires = "Expires",
Forwarded = "Forwarded",
From = "From",
Host = "Host",
IfMatch = "If-Match",
IfModifiedSince = "If-Modified-Since",
IfNoneMatch = "If-None-Match",
IfRange = "If-Range",
IfUnmodifiedSince = "If-Unmodified-Since",
KeepAlive = "Keep-Alive",
LastModified = "Last-Modified",
Link = "Link",
Location = "Location",
MaxForwards = "Max-Forwards",
Origin = "Origin",
Pragma = "Pragma",
Priority = "Priority",
ProxyAuthenticate = "Proxy-Authenticate",
ProxyAuthorization = "Proxy-Authorization",
Range = "Range",
Referer = "Referer",
ReferrerPolicy = "Referrer-Policy",
RetryAfter = "Retry-After",
Server = "Server",
SetCookie = "Set-Cookie",
StrictTransportSecurity = "Strict-Transport-Security",
TE = "TE",
Trailer = "Trailer",
TransferEncoding = "Transfer-Encoding",
Upgrade = "Upgrade",
UpgradeInsecureRequests = "Upgrade-Insecure-Requests",
UserAgent = "User-Agent",
Vary = "Vary",
Via = "Via",
Warning = "Warning",
WwwAuthenticate = "WWW-Authenticate",
}
CrossOriginResourceSharing: {
AccessControlAllowCredentials = "Access-Control-Allow-Credentials",
AccessControlAllowHeaders = "Access-Control-Allow-Headers",
AccessControlAllowMethods = "Access-Control-Allow-Methods",
AccessControlAllowOrigin = "Access-Control-Allow-Origin",
AccessControlExposeHeaders = "Access-Control-Expose-Headers",
AccessControlMaxAge = "Access-Control-Max-Age",
AccessControlRequestHeaders = "Access-Control-Request-Headers",
AccessControlRequestMethod = "Access-Control-Request-Method",
}
Security: {
XContentTypeOptions = "X-Content-Type-Options",
XDnsPrefetchControl = "X-DNS-Prefetch-Control",
XFrameOptions = "X-Frame-Options",
XXssProtection = "X-XSS-Protection",
}
Proxy: {
XForwardedFor = "X-Forwarded-For",
XForwardedHost = "X-Forwarded-Host",
XForwardedProto = "X-Forwarded-Proto",
}
Fetch: {
SecFetchDest = "Sec-Fetch-Dest",
SecFetchMode = "Sec-Fetch-Mode",
SecFetchSite = "Sec-Fetch-Site",
SecFetchUser = "Sec-Fetch-User",
SecPurpose = "Sec-Purpose",
}
ClientHint: {
AcceptClientHint = "Accept-CH",
SecClientHintUserAgent = "Sec-CH-UA",
SecClientHintUserAgentMobile = "Sec-CH-UA-Mobile",
SecClientHintUserAgentPlatform = "Sec-CH-UA-Platform",
}
WebSocket: {
SecWebSocketAccept = "Sec-WebSocket-Accept",
SecWebSocketExtensions = "Sec-WebSocket-Extensions",
SecWebSocketKey = "Sec-WebSocket-Key",
SecWebSocketProtocol = "Sec-WebSocket-Protocol",
SecWebSocketVersion = "Sec-WebSocket-Version",
}
Miscellaneous: {
XRequestedWith = "X-Requested-With",
}
}