1 use crate::byte_str::ByteStr;
2 use bytes::{Bytes, BytesMut};
3 
4 use std::borrow::Borrow;
5 use std::error::Error;
6 use std::convert::{TryFrom};
7 use std::hash::{Hash, Hasher};
8 use std::str::FromStr;
9 use std::{fmt, mem};
10 
11 /// Represents an HTTP header field name
12 ///
13 /// Header field names identify the header. Header sets may include multiple
14 /// headers with the same name. The HTTP specification defines a number of
15 /// standard headers, but HTTP messages may include non-standard header names as
16 /// well as long as they adhere to the specification.
17 ///
18 /// `HeaderName` is used as the [`HeaderMap`] key. Constants are available for
19 /// all standard header names in the [`header`] module.
20 ///
21 /// # Representation
22 ///
23 /// `HeaderName` represents standard header names using an `enum`, as such they
24 /// will not require an allocation for storage. All custom header names are
25 /// lower cased upon conversion to a `HeaderName` value. This avoids the
26 /// overhead of dynamically doing lower case conversion during the hash code
27 /// computation and the comparison operation.
28 ///
29 /// [`HeaderMap`]: struct.HeaderMap.html
30 /// [`header`]: index.html
31 #[derive(Clone, Eq, PartialEq, Hash)]
32 pub struct HeaderName {
33     inner: Repr<Custom>,
34 }
35 
36 // Almost a full `HeaderName`
37 #[derive(Debug, Hash)]
38 pub struct HdrName<'a> {
39     inner: Repr<MaybeLower<'a>>,
40 }
41 
42 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
43 enum Repr<T> {
44     Standard(StandardHeader),
45     Custom(T),
46 }
47 
48 // Used to hijack the Hash impl
49 #[derive(Debug, Clone, Eq, PartialEq)]
50 struct Custom(ByteStr);
51 
52 #[derive(Debug, Clone)]
53 struct MaybeLower<'a> {
54     buf: &'a [u8],
55     lower: bool,
56 }
57 
58 /// A possible error when converting a `HeaderName` from another type.
59 pub struct InvalidHeaderName {
60     _priv: (),
61 }
62 
63 macro_rules! standard_headers {
64     (
65         $(
66             $(#[$docs:meta])*
67             ($konst:ident, $upcase:ident, $name:expr);
68         )+
69     ) => {
70         #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
71         enum StandardHeader {
72             $(
73                 $konst,
74             )+
75         }
76 
77         $(
78             $(#[$docs])*
79             pub const $upcase: HeaderName = HeaderName {
80                 inner: Repr::Standard(StandardHeader::$konst),
81             };
82         )+
83 
84         impl StandardHeader {
85             #[inline]
86             fn as_str(&self) -> &'static str {
87                 match *self {
88                     $(
89                     StandardHeader::$konst => $name,
90                     )+
91                 }
92             }
93         }
94 
95         #[cfg(test)]
96         const TEST_HEADERS: &'static [(StandardHeader, &'static str)] = &[
97             $(
98             (StandardHeader::$konst, $name),
99             )+
100         ];
101 
102         #[test]
103         fn test_parse_standard_headers() {
104             for &(std, name) in TEST_HEADERS {
105                 // Test lower case
106                 assert_eq!(HeaderName::from_bytes(name.as_bytes()).unwrap(), HeaderName::from(std));
107 
108                 // Test upper case
109                 let upper = name.to_uppercase().to_string();
110                 assert_eq!(HeaderName::from_bytes(upper.as_bytes()).unwrap(), HeaderName::from(std));
111             }
112         }
113 
114         #[test]
115         fn test_standard_headers_into_bytes() {
116             for &(std, name) in TEST_HEADERS {
117                 let std = HeaderName::from(std);
118                 // Test lower case
119                 let name_bytes = name.as_bytes();
120                 let bytes: Bytes =
121                     HeaderName::from_bytes(name_bytes).unwrap().inner.into();
122                 assert_eq!(bytes, name_bytes);
123                 assert_eq!(HeaderName::from_bytes(name_bytes).unwrap(), std);
124 
125                 // Test upper case
126                 let upper = name.to_uppercase().to_string();
127                 let bytes: Bytes =
128                     HeaderName::from_bytes(upper.as_bytes()).unwrap().inner.into();
129                 assert_eq!(bytes, name.as_bytes());
130                 assert_eq!(HeaderName::from_bytes(upper.as_bytes()).unwrap(),
131                            std);
132 
133 
134             }
135 
136         }
137     }
138 }
139 
140 // Generate constants for all standard HTTP headers. This includes a static hash
141 // code for the "fast hash" path. The hash code for static headers *do not* have
142 // to match the text representation of those headers. This is because header
143 // strings are always converted to the static values (when they match) before
144 // being hashed. This means that it is impossible to compare the static hash
145 // code of CONTENT_LENGTH with "content-length".
146 standard_headers! {
147     /// Advertises which content types the client is able to understand.
148     ///
149     /// The Accept request HTTP header advertises which content types, expressed
150     /// as MIME types, the client is able to understand. Using content
151     /// negotiation, the server then selects one of the proposals, uses it and
152     /// informs the client of its choice with the Content-Type response header.
153     /// Browsers set adequate values for this header depending of the context
154     /// where the request is done: when fetching a CSS stylesheet a different
155     /// value is set for the request than when fetching an image, video or a
156     /// script.
157     (Accept, ACCEPT, "accept");
158 
159     /// Advertises which character set the client is able to understand.
160     ///
161     /// The Accept-Charset request HTTP header advertises which character set
162     /// the client is able to understand. Using content negotiation, the server
163     /// then selects one of the proposals, uses it and informs the client of its
164     /// choice within the Content-Type response header. Browsers usually don't
165     /// set this header as the default value for each content type is usually
166     /// correct and transmitting it would allow easier fingerprinting.
167     ///
168     /// If the server cannot serve any matching character set, it can
169     /// theoretically send back a 406 (Not Acceptable) error code. But, for a
170     /// better user experience, this is rarely done and the more common way is
171     /// to ignore the Accept-Charset header in this case.
172     (AcceptCharset, ACCEPT_CHARSET, "accept-charset");
173 
174     /// Advertises which content encoding the client is able to understand.
175     ///
176     /// The Accept-Encoding request HTTP header advertises which content
177     /// encoding, usually a compression algorithm, the client is able to
178     /// understand. Using content negotiation, the server selects one of the
179     /// proposals, uses it and informs the client of its choice with the
180     /// Content-Encoding response header.
181     ///
182     /// Even if both the client and the server supports the same compression
183     /// algorithms, the server may choose not to compress the body of a
184     /// response, if the identity value is also acceptable. Two common cases
185     /// lead to this:
186     ///
187     /// * The data to be sent is already compressed and a second compression
188     /// won't lead to smaller data to be transmitted. This may the case with
189     /// some image formats;
190     ///
191     /// * The server is overloaded and cannot afford the computational overhead
192     /// induced by the compression requirement. Typically, Microsoft recommends
193     /// not to compress if a server use more than 80 % of its computational
194     /// power.
195     ///
196     /// As long as the identity value, meaning no encryption, is not explicitly
197     /// forbidden, by an identity;q=0 or a *;q=0 without another explicitly set
198     /// value for identity, the server must never send back a 406 Not Acceptable
199     /// error.
200     (AcceptEncoding, ACCEPT_ENCODING, "accept-encoding");
201 
202     /// Advertises which languages the client is able to understand.
203     ///
204     /// The Accept-Language request HTTP header advertises which languages the
205     /// client is able to understand, and which locale variant is preferred.
206     /// Using content negotiation, the server then selects one of the proposals,
207     /// uses it and informs the client of its choice with the Content-Language
208     /// response header. Browsers set adequate values for this header according
209     /// their user interface language and even if a user can change it, this
210     /// happens rarely (and is frown upon as it leads to fingerprinting).
211     ///
212     /// This header is a hint to be used when the server has no way of
213     /// determining the language via another way, like a specific URL, that is
214     /// controlled by an explicit user decision. It is recommended that the
215     /// server never overrides an explicit decision. The content of the
216     /// Accept-Language is often out of the control of the user (like when
217     /// traveling and using an Internet Cafe in a different country); the user
218     /// may also want to visit a page in another language than the locale of
219     /// their user interface.
220     ///
221     /// If the server cannot serve any matching language, it can theoretically
222     /// send back a 406 (Not Acceptable) error code. But, for a better user
223     /// experience, this is rarely done and more common way is to ignore the
224     /// Accept-Language header in this case.
225     (AcceptLanguage, ACCEPT_LANGUAGE, "accept-language");
226 
227     /// Marker used by the server to advertise partial request support.
228     ///
229     /// The Accept-Ranges response HTTP header is a marker used by the server to
230     /// advertise its support of partial requests. The value of this field
231     /// indicates the unit that can be used to define a range.
232     ///
233     /// In presence of an Accept-Ranges header, the browser may try to resume an
234     /// interrupted download, rather than to start it from the start again.
235     (AcceptRanges, ACCEPT_RANGES, "accept-ranges");
236 
237     /// Preflight response indicating if the response to the request can be
238     /// exposed to the page.
239     ///
240     /// The Access-Control-Allow-Credentials response header indicates whether
241     /// or not the response to the request can be exposed to the page. It can be
242     /// exposed when the true value is returned; it can't in other cases.
243     ///
244     /// Credentials are cookies, authorization headers or TLS client
245     /// certificates.
246     ///
247     /// When used as part of a response to a preflight request, this indicates
248     /// whether or not the actual request can be made using credentials. Note
249     /// that simple GET requests are not preflighted, and so if a request is
250     /// made for a resource with credentials, if this header is not returned
251     /// with the resource, the response is ignored by the browser and not
252     /// returned to web content.
253     ///
254     /// The Access-Control-Allow-Credentials header works in conjunction with
255     /// the XMLHttpRequest.withCredentials property or with the credentials
256     /// option in the Request() constructor of the Fetch API. Credentials must
257     /// be set on both sides (the Access-Control-Allow-Credentials header and in
258     /// the XHR or Fetch request) in order for the CORS request with credentials
259     /// to succeed.
260     (AccessControlAllowCredentials, ACCESS_CONTROL_ALLOW_CREDENTIALS, "access-control-allow-credentials");
261 
262     /// Preflight response indicating permitted HTTP headers.
263     ///
264     /// The Access-Control-Allow-Headers response header is used in response to
265     /// a preflight request to indicate which HTTP headers will be available via
266     /// Access-Control-Expose-Headers when making the actual request.
267     ///
268     /// The simple headers, Accept, Accept-Language, Content-Language,
269     /// Content-Type (but only with a MIME type of its parsed value (ignoring
270     /// parameters) of either application/x-www-form-urlencoded,
271     /// multipart/form-data, or text/plain), are always available and don't need
272     /// to be listed by this header.
273     ///
274     /// This header is required if the request has an
275     /// Access-Control-Request-Headers header.
276     (AccessControlAllowHeaders, ACCESS_CONTROL_ALLOW_HEADERS, "access-control-allow-headers");
277 
278     /// Preflight header response indicating permitted access methods.
279     ///
280     /// The Access-Control-Allow-Methods response header specifies the method or
281     /// methods allowed when accessing the resource in response to a preflight
282     /// request.
283     (AccessControlAllowMethods, ACCESS_CONTROL_ALLOW_METHODS, "access-control-allow-methods");
284 
285     /// Indicates whether the response can be shared with resources with the
286     /// given origin.
287     (AccessControlAllowOrigin, ACCESS_CONTROL_ALLOW_ORIGIN, "access-control-allow-origin");
288 
289     /// Indicates which headers can be exposed as part of the response by
290     /// listing their names.
291     (AccessControlExposeHeaders, ACCESS_CONTROL_EXPOSE_HEADERS, "access-control-expose-headers");
292 
293     /// Indicates how long the results of a preflight request can be cached.
294     (AccessControlMaxAge, ACCESS_CONTROL_MAX_AGE, "access-control-max-age");
295 
296     /// Informs the server which HTTP headers will be used when an actual
297     /// request is made.
298     (AccessControlRequestHeaders, ACCESS_CONTROL_REQUEST_HEADERS, "access-control-request-headers");
299 
300     /// Informs the server know which HTTP method will be used when the actual
301     /// request is made.
302     (AccessControlRequestMethod, ACCESS_CONTROL_REQUEST_METHOD, "access-control-request-method");
303 
304     /// Indicates the time in seconds the object has been in a proxy cache.
305     ///
306     /// The Age header is usually close to zero. If it is Age: 0, it was
307     /// probably just fetched from the origin server; otherwise It is usually
308     /// calculated as a difference between the proxy's current date and the Date
309     /// general header included in the HTTP response.
310     (Age, AGE, "age");
311 
312     /// Lists the set of methods support by a resource.
313     ///
314     /// This header must be sent if the server responds with a 405 Method Not
315     /// Allowed status code to indicate which request methods can be used. An
316     /// empty Allow header indicates that the resource allows no request
317     /// methods, which might occur temporarily for a given resource, for
318     /// example.
319     (Allow, ALLOW, "allow");
320 
321     /// Advertises the availability of alternate services to clients.
322     (AltSvc, ALT_SVC, "alt-svc");
323 
324     /// Contains the credentials to authenticate a user agent with a server.
325     ///
326     /// Usually this header is included after the server has responded with a
327     /// 401 Unauthorized status and the WWW-Authenticate header.
328     (Authorization, AUTHORIZATION, "authorization");
329 
330     /// Specifies directives for caching mechanisms in both requests and
331     /// responses.
332     ///
333     /// Caching directives are unidirectional, meaning that a given directive in
334     /// a request is not implying that the same directive is to be given in the
335     /// response.
336     (CacheControl, CACHE_CONTROL, "cache-control");
337 
338     /// Controls whether or not the network connection stays open after the
339     /// current transaction finishes.
340     ///
341     /// If the value sent is keep-alive, the connection is persistent and not
342     /// closed, allowing for subsequent requests to the same server to be done.
343     ///
344     /// Except for the standard hop-by-hop headers (Keep-Alive,
345     /// Transfer-Encoding, TE, Connection, Trailer, Upgrade, Proxy-Authorization
346     /// and Proxy-Authenticate), any hop-by-hop headers used by the message must
347     /// be listed in the Connection header, so that the first proxy knows he has
348     /// to consume them and not to forward them further. Standard hop-by-hop
349     /// headers can be listed too (it is often the case of Keep-Alive, but this
350     /// is not mandatory.
351     (Connection, CONNECTION, "connection");
352 
353     /// Indicates if the content is expected to be displayed inline.
354     ///
355     /// In a regular HTTP response, the Content-Disposition response header is a
356     /// header indicating if the content is expected to be displayed inline in
357     /// the browser, that is, as a Web page or as part of a Web page, or as an
358     /// attachment, that is downloaded and saved locally.
359     ///
360     /// In a multipart/form-data body, the HTTP Content-Disposition general
361     /// header is a header that can be used on the subpart of a multipart body
362     /// to give information about the field it applies to. The subpart is
363     /// delimited by the boundary defined in the Content-Type header. Used on
364     /// the body itself, Content-Disposition has no effect.
365     ///
366     /// The Content-Disposition header is defined in the larger context of MIME
367     /// messages for e-mail, but only a subset of the possible parameters apply
368     /// to HTTP forms and POST requests. Only the value form-data, as well as
369     /// the optional directive name and filename, can be used in the HTTP
370     /// context.
371     (ContentDisposition, CONTENT_DISPOSITION, "content-disposition");
372 
373     /// Used to compress the media-type.
374     ///
375     /// When present, its value indicates what additional content encoding has
376     /// been applied to the entity-body. It lets the client know, how to decode
377     /// in order to obtain the media-type referenced by the Content-Type header.
378     ///
379     /// It is recommended to compress data as much as possible and therefore to
380     /// use this field, but some types of resources, like jpeg images, are
381     /// already compressed.  Sometimes using additional compression doesn't
382     /// reduce payload size and can even make the payload longer.
383     (ContentEncoding, CONTENT_ENCODING, "content-encoding");
384 
385     /// Used to describe the languages intended for the audience.
386     ///
387     /// This header allows a user to differentiate according to the users' own
388     /// preferred language. For example, if "Content-Language: de-DE" is set, it
389     /// says that the document is intended for German language speakers
390     /// (however, it doesn't indicate the document is written in German. For
391     /// example, it might be written in English as part of a language course for
392     /// German speakers).
393     ///
394     /// If no Content-Language is specified, the default is that the content is
395     /// intended for all language audiences. Multiple language tags are also
396     /// possible, as well as applying the Content-Language header to various
397     /// media types and not only to textual documents.
398     (ContentLanguage, CONTENT_LANGUAGE, "content-language");
399 
400     /// Indicates the size fo the entity-body.
401     ///
402     /// The header value must be a decimal indicating the number of octets sent
403     /// to the recipient.
404     (ContentLength, CONTENT_LENGTH, "content-length");
405 
406     /// Indicates an alternate location for the returned data.
407     ///
408     /// The principal use case is to indicate the URL of the resource
409     /// transmitted as the result of content negotiation.
410     ///
411     /// Location and Content-Location are different: Location indicates the
412     /// target of a redirection (or the URL of a newly created document), while
413     /// Content-Location indicates the direct URL to use to access the resource,
414     /// without the need of further content negotiation. Location is a header
415     /// associated with the response, while Content-Location is associated with
416     /// the entity returned.
417     (ContentLocation, CONTENT_LOCATION, "content-location");
418 
419     /// Indicates where in a full body message a partial message belongs.
420     (ContentRange, CONTENT_RANGE, "content-range");
421 
422     /// Allows controlling resources the user agent is allowed to load for a
423     /// given page.
424     ///
425     /// With a few exceptions, policies mostly involve specifying server origins
426     /// and script endpoints. This helps guard against cross-site scripting
427     /// attacks (XSS).
428     (ContentSecurityPolicy, CONTENT_SECURITY_POLICY, "content-security-policy");
429 
430     /// Allows experimenting with policies by monitoring their effects.
431     ///
432     /// The HTTP Content-Security-Policy-Report-Only response header allows web
433     /// developers to experiment with policies by monitoring (but not enforcing)
434     /// their effects. These violation reports consist of JSON documents sent
435     /// via an HTTP POST request to the specified URI.
436     (ContentSecurityPolicyReportOnly, CONTENT_SECURITY_POLICY_REPORT_ONLY, "content-security-policy-report-only");
437 
438     /// Used to indicate the media type of the resource.
439     ///
440     /// In responses, a Content-Type header tells the client what the content
441     /// type of the returned content actually is. Browsers will do MIME sniffing
442     /// in some cases and will not necessarily follow the value of this header;
443     /// to prevent this behavior, the header X-Content-Type-Options can be set
444     /// to nosniff.
445     ///
446     /// In requests, (such as POST or PUT), the client tells the server what
447     /// type of data is actually sent.
448     (ContentType, CONTENT_TYPE, "content-type");
449 
450     /// Contains stored HTTP cookies previously sent by the server with the
451     /// Set-Cookie header.
452     ///
453     /// The Cookie header might be omitted entirely, if the privacy setting of
454     /// the browser are set to block them, for example.
455     (Cookie, COOKIE, "cookie");
456 
457     /// Indicates the client's tracking preference.
458     ///
459     /// This header lets users indicate whether they would prefer privacy rather
460     /// than personalized content.
461     (Dnt, DNT, "dnt");
462 
463     /// Contains the date and time at which the message was originated.
464     (Date, DATE, "date");
465 
466     /// Identifier for a specific version of a resource.
467     ///
468     /// This header allows caches to be more efficient, and saves bandwidth, as
469     /// a web server does not need to send a full response if the content has
470     /// not changed. On the other side, if the content has changed, etags are
471     /// useful to help prevent simultaneous updates of a resource from
472     /// overwriting each other ("mid-air collisions").
473     ///
474     /// If the resource at a given URL changes, a new Etag value must be
475     /// generated. Etags are therefore similar to fingerprints and might also be
476     /// used for tracking purposes by some servers. A comparison of them allows
477     /// to quickly determine whether two representations of a resource are the
478     /// same, but they might also be set to persist indefinitely by a tracking
479     /// server.
480     (Etag, ETAG, "etag");
481 
482     /// Indicates expectations that need to be fulfilled by the server in order
483     /// to properly handle the request.
484     ///
485     /// The only expectation defined in the specification is Expect:
486     /// 100-continue, to which the server shall respond with:
487     ///
488     /// * 100 if the information contained in the header is sufficient to cause
489     /// an immediate success,
490     ///
491     /// * 417 (Expectation Failed) if it cannot meet the expectation; or any
492     /// other 4xx status otherwise.
493     ///
494     /// For example, the server may reject a request if its Content-Length is
495     /// too large.
496     ///
497     /// No common browsers send the Expect header, but some other clients such
498     /// as cURL do so by default.
499     (Expect, EXPECT, "expect");
500 
501     /// Contains the date/time after which the response is considered stale.
502     ///
503     /// Invalid dates, like the value 0, represent a date in the past and mean
504     /// that the resource is already expired.
505     ///
506     /// If there is a Cache-Control header with the "max-age" or "s-max-age"
507     /// directive in the response, the Expires header is ignored.
508     (Expires, EXPIRES, "expires");
509 
510     /// Contains information from the client-facing side of proxy servers that
511     /// is altered or lost when a proxy is involved in the path of the request.
512     ///
513     /// The alternative and de-facto standard versions of this header are the
514     /// X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Proto headers.
515     ///
516     /// This header is used for debugging, statistics, and generating
517     /// location-dependent content and by design it exposes privacy sensitive
518     /// information, such as the IP address of the client. Therefore the user's
519     /// privacy must be kept in mind when deploying this header.
520     (Forwarded, FORWARDED, "forwarded");
521 
522     /// Contains an Internet email address for a human user who controls the
523     /// requesting user agent.
524     ///
525     /// If you are running a robotic user agent (e.g. a crawler), the From
526     /// header should be sent, so you can be contacted if problems occur on
527     /// servers, such as if the robot is sending excessive, unwanted, or invalid
528     /// requests.
529     (From, FROM, "from");
530 
531     /// Specifies the domain name of the server and (optionally) the TCP port
532     /// number on which the server is listening.
533     ///
534     /// If no port is given, the default port for the service requested (e.g.,
535     /// "80" for an HTTP URL) is implied.
536     ///
537     /// A Host header field must be sent in all HTTP/1.1 request messages. A 400
538     /// (Bad Request) status code will be sent to any HTTP/1.1 request message
539     /// that lacks a Host header field or contains more than one.
540     (Host, HOST, "host");
541 
542     /// Makes a request conditional based on the E-Tag.
543     ///
544     /// For GET and HEAD methods, the server will send back the requested
545     /// resource only if it matches one of the listed ETags. For PUT and other
546     /// non-safe methods, it will only upload the resource in this case.
547     ///
548     /// The comparison with the stored ETag uses the strong comparison
549     /// algorithm, meaning two files are considered identical byte to byte only.
550     /// This is weakened when the  W/ prefix is used in front of the ETag.
551     ///
552     /// There are two common use cases:
553     ///
554     /// * For GET and HEAD methods, used in combination with an Range header, it
555     /// can guarantee that the new ranges requested comes from the same resource
556     /// than the previous one. If it doesn't match, then a 416 (Range Not
557     /// Satisfiable) response is returned.
558     ///
559     /// * For other methods, and in particular for PUT, If-Match can be used to
560     /// prevent the lost update problem. It can check if the modification of a
561     /// resource that the user wants to upload will not override another change
562     /// that has been done since the original resource was fetched. If the
563     /// request cannot be fulfilled, the 412 (Precondition Failed) response is
564     /// returned.
565     (IfMatch, IF_MATCH, "if-match");
566 
567     /// Makes a request conditional based on the modification date.
568     ///
569     /// The If-Modified-Since request HTTP header makes the request conditional:
570     /// the server will send back the requested resource, with a 200 status,
571     /// only if it has been last modified after the given date. If the request
572     /// has not been modified since, the response will be a 304 without any
573     /// body; the Last-Modified header will contain the date of last
574     /// modification. Unlike If-Unmodified-Since, If-Modified-Since can only be
575     /// used with a GET or HEAD.
576     ///
577     /// When used in combination with If-None-Match, it is ignored, unless the
578     /// server doesn't support If-None-Match.
579     ///
580     /// The most common use case is to update a cached entity that has no
581     /// associated ETag.
582     (IfModifiedSince, IF_MODIFIED_SINCE, "if-modified-since");
583 
584     /// Makes a request conditional based on the E-Tag.
585     ///
586     /// The If-None-Match HTTP request header makes the request conditional. For
587     /// GET and HEAD methods, the server will send back the requested resource,
588     /// with a 200 status, only if it doesn't have an ETag matching the given
589     /// ones. For other methods, the request will be processed only if the
590     /// eventually existing resource's ETag doesn't match any of the values
591     /// listed.
592     ///
593     /// When the condition fails for GET and HEAD methods, then the server must
594     /// return HTTP status code 304 (Not Modified). For methods that apply
595     /// server-side changes, the status code 412 (Precondition Failed) is used.
596     /// Note that the server generating a 304 response MUST generate any of the
597     /// following header fields that would have been sent in a 200 (OK) response
598     /// to the same request: Cache-Control, Content-Location, Date, ETag,
599     /// Expires, and Vary.
600     ///
601     /// The comparison with the stored ETag uses the weak comparison algorithm,
602     /// meaning two files are considered identical not only if they are
603     /// identical byte to byte, but if the content is equivalent. For example,
604     /// two pages that would differ only by the date of generation in the footer
605     /// would be considered as identical.
606     ///
607     /// When used in combination with If-Modified-Since, it has precedence (if
608     /// the server supports it).
609     ///
610     /// There are two common use cases:
611     ///
612     /// * For `GET` and `HEAD` methods, to update a cached entity that has an associated ETag.
613     /// * For other methods, and in particular for `PUT`, `If-None-Match` used with
614     /// the `*` value can be used to save a file not known to exist,
615     /// guaranteeing that another upload didn't happen before, losing the data
616     /// of the previous put; this problems is the variation of the lost update
617     /// problem.
618     (IfNoneMatch, IF_NONE_MATCH, "if-none-match");
619 
620     /// Makes a request conditional based on range.
621     ///
622     /// The If-Range HTTP request header makes a range request conditional: if
623     /// the condition is fulfilled, the range request will be issued and the
624     /// server sends back a 206 Partial Content answer with the appropriate
625     /// body. If the condition is not fulfilled, the full resource is sent back,
626     /// with a 200 OK status.
627     ///
628     /// This header can be used either with a Last-Modified validator, or with
629     /// an ETag, but not with both.
630     ///
631     /// The most common use case is to resume a download, to guarantee that the
632     /// stored resource has not been modified since the last fragment has been
633     /// received.
634     (IfRange, IF_RANGE, "if-range");
635 
636     /// Makes the request conditional based on the last modification date.
637     ///
638     /// The If-Unmodified-Since request HTTP header makes the request
639     /// conditional: the server will send back the requested resource, or accept
640     /// it in the case of a POST or another non-safe method, only if it has not
641     /// been last modified after the given date. If the request has been
642     /// modified after the given date, the response will be a 412 (Precondition
643     /// Failed) error.
644     ///
645     /// There are two common use cases:
646     ///
647     /// * In conjunction non-safe methods, like POST, it can be used to
648     /// implement an optimistic concurrency control, like done by some wikis:
649     /// editions are rejected if the stored document has been modified since the
650     /// original has been retrieved.
651     ///
652     /// * In conjunction with a range request with a If-Range header, it can be
653     /// used to ensure that the new fragment requested comes from an unmodified
654     /// document.
655     (IfUnmodifiedSince, IF_UNMODIFIED_SINCE, "if-unmodified-since");
656 
657     /// Content-Types that are acceptable for the response.
658     (LastModified, LAST_MODIFIED, "last-modified");
659 
660     /// Allows the server to point an interested client to another resource
661     /// containing metadata about the requested resource.
662     (Link, LINK, "link");
663 
664     /// Indicates the URL to redirect a page to.
665     ///
666     /// The Location response header indicates the URL to redirect a page to. It
667     /// only provides a meaning when served with a 3xx status response.
668     ///
669     /// The HTTP method used to make the new request to fetch the page pointed
670     /// to by Location depends of the original method and of the kind of
671     /// redirection:
672     ///
673     /// * If 303 (See Also) responses always lead to the use of a GET method,
674     /// 307 (Temporary Redirect) and 308 (Permanent Redirect) don't change the
675     /// method used in the original request;
676     ///
677     /// * 301 (Permanent Redirect) and 302 (Found) doesn't change the method
678     /// most of the time, though older user-agents may (so you basically don't
679     /// know).
680     ///
681     /// All responses with one of these status codes send a Location header.
682     ///
683     /// Beside redirect response, messages with 201 (Created) status also
684     /// include the Location header. It indicates the URL to the newly created
685     /// resource.
686     ///
687     /// Location and Content-Location are different: Location indicates the
688     /// target of a redirection (or the URL of a newly created resource), while
689     /// Content-Location indicates the direct URL to use to access the resource
690     /// when content negotiation happened, without the need of further content
691     /// negotiation. Location is a header associated with the response, while
692     /// Content-Location is associated with the entity returned.
693     (Location, LOCATION, "location");
694 
695     /// Indicates the max number of intermediaries the request should be sent
696     /// through.
697     (MaxForwards, MAX_FORWARDS, "max-forwards");
698 
699     /// Indicates where a fetch originates from.
700     ///
701     /// It doesn't include any path information, but only the server name. It is
702     /// sent with CORS requests, as well as with POST requests. It is similar to
703     /// the Referer header, but, unlike this header, it doesn't disclose the
704     /// whole path.
705     (Origin, ORIGIN, "origin");
706 
707     /// HTTP/1.0 header usually used for backwards compatibility.
708     ///
709     /// The Pragma HTTP/1.0 general header is an implementation-specific header
710     /// that may have various effects along the request-response chain. It is
711     /// used for backwards compatibility with HTTP/1.0 caches where the
712     /// Cache-Control HTTP/1.1 header is not yet present.
713     (Pragma, PRAGMA, "pragma");
714 
715     /// Defines the authentication method that should be used to gain access to
716     /// a proxy.
717     ///
718     /// Unlike `www-authenticate`, the `proxy-authenticate` header field applies
719     /// only to the next outbound client on the response chain. This is because
720     /// only the client that chose a given proxy is likely to have the
721     /// credentials necessary for authentication. However, when multiple proxies
722     /// are used within the same administrative domain, such as office and
723     /// regional caching proxies within a large corporate network, it is common
724     /// for credentials to be generated by the user agent and passed through the
725     /// hierarchy until consumed. Hence, in such a configuration, it will appear
726     /// as if Proxy-Authenticate is being forwarded because each proxy will send
727     /// the same challenge set.
728     ///
729     /// The `proxy-authenticate` header is sent along with a `407 Proxy
730     /// Authentication Required`.
731     (ProxyAuthenticate, PROXY_AUTHENTICATE, "proxy-authenticate");
732 
733     /// Contains the credentials to authenticate a user agent to a proxy server.
734     ///
735     /// This header is usually included after the server has responded with a
736     /// 407 Proxy Authentication Required status and the Proxy-Authenticate
737     /// header.
738     (ProxyAuthorization, PROXY_AUTHORIZATION, "proxy-authorization");
739 
740     /// Associates a specific cryptographic public key with a certain server.
741     ///
742     /// This decreases the risk of MITM attacks with forged certificates. If one
743     /// or several keys are pinned and none of them are used by the server, the
744     /// browser will not accept the response as legitimate, and will not display
745     /// it.
746     (PublicKeyPins, PUBLIC_KEY_PINS, "public-key-pins");
747 
748     /// Sends reports of pinning violation to the report-uri specified in the
749     /// header.
750     ///
751     /// Unlike `Public-Key-Pins`, this header still allows browsers to connect
752     /// to the server if the pinning is violated.
753     (PublicKeyPinsReportOnly, PUBLIC_KEY_PINS_REPORT_ONLY, "public-key-pins-report-only");
754 
755     /// Indicates the part of a document that the server should return.
756     ///
757     /// Several parts can be requested with one Range header at once, and the
758     /// server may send back these ranges in a multipart document. If the server
759     /// sends back ranges, it uses the 206 Partial Content for the response. If
760     /// the ranges are invalid, the server returns the 416 Range Not Satisfiable
761     /// error. The server can also ignore the Range header and return the whole
762     /// document with a 200 status code.
763     (Range, RANGE, "range");
764 
765     /// Contains the address of the previous web page from which a link to the
766     /// currently requested page was followed.
767     ///
768     /// The Referer header allows servers to identify where people are visiting
769     /// them from and may use that data for analytics, logging, or optimized
770     /// caching, for example.
771     (Referer, REFERER, "referer");
772 
773     /// Governs which referrer information should be included with requests
774     /// made.
775     (ReferrerPolicy, REFERRER_POLICY, "referrer-policy");
776 
777     /// Informs the web browser that the current page or frame should be
778     /// refreshed.
779     (Refresh, REFRESH, "refresh");
780 
781     /// The Retry-After response HTTP header indicates how long the user agent
782     /// should wait before making a follow-up request. There are two main cases
783     /// this header is used:
784     ///
785     /// * When sent with a 503 (Service Unavailable) response, it indicates how
786     /// long the service is expected to be unavailable.
787     ///
788     /// * When sent with a redirect response, such as 301 (Moved Permanently),
789     /// it indicates the minimum time that the user agent is asked to wait
790     /// before issuing the redirected request.
791     (RetryAfter, RETRY_AFTER, "retry-after");
792 
793     /// The |Sec-WebSocket-Accept| header field is used in the WebSocket
794     /// opening handshake. It is sent from the server to the client to
795     /// confirm that the server is willing to initiate the WebSocket
796     /// connection.
797     (SecWebSocketAccept, SEC_WEBSOCKET_ACCEPT, "sec-websocket-accept");
798 
799     /// The |Sec-WebSocket-Extensions| header field is used in the WebSocket
800     /// opening handshake. It is initially sent from the client to the
801     /// server, and then subsequently sent from the server to the client, to
802     /// agree on a set of protocol-level extensions to use for the duration
803     /// of the connection.
804     (SecWebSocketExtensions, SEC_WEBSOCKET_EXTENSIONS, "sec-websocket-extensions");
805 
806     /// The |Sec-WebSocket-Key| header field is used in the WebSocket opening
807     /// handshake. It is sent from the client to the server to provide part
808     /// of the information used by the server to prove that it received a
809     /// valid WebSocket opening handshake. This helps ensure that the server
810     /// does not accept connections from non-WebSocket clients (e.g., HTTP
811     /// clients) that are being abused to send data to unsuspecting WebSocket
812     /// servers.
813     (SecWebSocketKey, SEC_WEBSOCKET_KEY, "sec-websocket-key");
814 
815     /// The |Sec-WebSocket-Protocol| header field is used in the WebSocket
816     /// opening handshake. It is sent from the client to the server and back
817     /// from the server to the client to confirm the subprotocol of the
818     /// connection.  This enables scripts to both select a subprotocol and be
819     /// sure that the server agreed to serve that subprotocol.
820     (SecWebSocketProtocol, SEC_WEBSOCKET_PROTOCOL, "sec-websocket-protocol");
821 
822     /// The |Sec-WebSocket-Version| header field is used in the WebSocket
823     /// opening handshake.  It is sent from the client to the server to
824     /// indicate the protocol version of the connection.  This enables
825     /// servers to correctly interpret the opening handshake and subsequent
826     /// data being sent from the data, and close the connection if the server
827     /// cannot interpret that data in a safe manner.
828     (SecWebSocketVersion, SEC_WEBSOCKET_VERSION, "sec-websocket-version");
829 
830     /// Contains information about the software used by the origin server to
831     /// handle the request.
832     ///
833     /// Overly long and detailed Server values should be avoided as they
834     /// potentially reveal internal implementation details that might make it
835     /// (slightly) easier for attackers to find and exploit known security
836     /// holes.
837     (Server, SERVER, "server");
838 
839     /// Used to send cookies from the server to the user agent.
840     (SetCookie, SET_COOKIE, "set-cookie");
841 
842     /// Tells the client to communicate with HTTPS instead of using HTTP.
843     (StrictTransportSecurity, STRICT_TRANSPORT_SECURITY, "strict-transport-security");
844 
845     /// Informs the server of transfer encodings willing to be accepted as part
846     /// of the response.
847     ///
848     /// See also the Transfer-Encoding response header for more details on
849     /// transfer encodings. Note that chunked is always acceptable for HTTP/1.1
850     /// recipients and you that don't have to specify "chunked" using the TE
851     /// header. However, it is useful for setting if the client is accepting
852     /// trailer fields in a chunked transfer coding using the "trailers" value.
853     (Te, TE, "te");
854 
855     /// Allows the sender to include additional fields at the end of chunked
856     /// messages.
857     (Trailer, TRAILER, "trailer");
858 
859     /// Specifies the form of encoding used to safely transfer the entity to the
860     /// client.
861     ///
862     /// `transfer-encoding` is a hop-by-hop header, that is applying to a
863     /// message between two nodes, not to a resource itself. Each segment of a
864     /// multi-node connection can use different `transfer-encoding` values. If
865     /// you want to compress data over the whole connection, use the end-to-end
866     /// header `content-encoding` header instead.
867     ///
868     /// When present on a response to a `HEAD` request that has no body, it
869     /// indicates the value that would have applied to the corresponding `GET`
870     /// message.
871     (TransferEncoding, TRANSFER_ENCODING, "transfer-encoding");
872 
873     /// Contains a string that allows identifying the requesting client's
874     /// software.
875     (UserAgent, USER_AGENT, "user-agent");
876 
877     /// Used as part of the exchange to upgrade the protocol.
878     (Upgrade, UPGRADE, "upgrade");
879 
880     /// Sends a signal to the server expressing the client’s preference for an
881     /// encrypted and authenticated response.
882     (UpgradeInsecureRequests, UPGRADE_INSECURE_REQUESTS, "upgrade-insecure-requests");
883 
884     /// Determines how to match future requests with cached responses.
885     ///
886     /// The `vary` HTTP response header determines how to match future request
887     /// headers to decide whether a cached response can be used rather than
888     /// requesting a fresh one from the origin server. It is used by the server
889     /// to indicate which headers it used when selecting a representation of a
890     /// resource in a content negotiation algorithm.
891     ///
892     /// The `vary` header should be set on a 304 Not Modified response exactly
893     /// like it would have been set on an equivalent 200 OK response.
894     (Vary, VARY, "vary");
895 
896     /// Added by proxies to track routing.
897     ///
898     /// The `via` general header is added by proxies, both forward and reverse
899     /// proxies, and can appear in the request headers and the response headers.
900     /// It is used for tracking message forwards, avoiding request loops, and
901     /// identifying the protocol capabilities of senders along the
902     /// request/response chain.
903     (Via, VIA, "via");
904 
905     /// General HTTP header contains information about possible problems with
906     /// the status of the message.
907     ///
908     /// More than one `warning` header may appear in a response. Warning header
909     /// fields can in general be applied to any message, however some warn-codes
910     /// are specific to caches and can only be applied to response messages.
911     (Warning, WARNING, "warning");
912 
913     /// Defines the authentication method that should be used to gain access to
914     /// a resource.
915     (WwwAuthenticate, WWW_AUTHENTICATE, "www-authenticate");
916 
917     /// Marker used by the server to indicate that the MIME types advertised in
918     /// the `content-type` headers should not be changed and be followed.
919     ///
920     /// This allows to opt-out of MIME type sniffing, or, in other words, it is
921     /// a way to say that the webmasters knew what they were doing.
922     ///
923     /// This header was introduced by Microsoft in IE 8 as a way for webmasters
924     /// to block content sniffing that was happening and could transform
925     /// non-executable MIME types into executable MIME types. Since then, other
926     /// browsers have introduced it, even if their MIME sniffing algorithms were
927     /// less aggressive.
928     ///
929     /// Site security testers usually expect this header to be set.
930     (XContentTypeOptions, X_CONTENT_TYPE_OPTIONS, "x-content-type-options");
931 
932     /// Controls DNS prefetching.
933     ///
934     /// The `x-dns-prefetch-control` HTTP response header controls DNS
935     /// prefetching, a feature by which browsers proactively perform domain name
936     /// resolution on both links that the user may choose to follow as well as
937     /// URLs for items referenced by the document, including images, CSS,
938     /// JavaScript, and so forth.
939     ///
940     /// This prefetching is performed in the background, so that the DNS is
941     /// likely to have been resolved by the time the referenced items are
942     /// needed. This reduces latency when the user clicks a link.
943     (XDnsPrefetchControl, X_DNS_PREFETCH_CONTROL, "x-dns-prefetch-control");
944 
945     /// Indicates whether or not a browser should be allowed to render a page in
946     /// a frame.
947     ///
948     /// Sites can use this to avoid clickjacking attacks, by ensuring that their
949     /// content is not embedded into other sites.
950     ///
951     /// The added security is only provided if the user accessing the document
952     /// is using a browser supporting `x-frame-options`.
953     (XFrameOptions, X_FRAME_OPTIONS, "x-frame-options");
954 
955     /// Stop pages from loading when an XSS attack is detected.
956     ///
957     /// The HTTP X-XSS-Protection response header is a feature of Internet
958     /// Explorer, Chrome and Safari that stops pages from loading when they
959     /// detect reflected cross-site scripting (XSS) attacks. Although these
960     /// protections are largely unnecessary in modern browsers when sites
961     /// implement a strong Content-Security-Policy that disables the use of
962     /// inline JavaScript ('unsafe-inline'), they can still provide protections
963     /// for users of older web browsers that don't yet support CSP.
964     (XXssProtection, X_XSS_PROTECTION, "x-xss-protection");
965 }
966 
967 /// Valid header name characters
968 ///
969 /// ```not_rust
970 ///       field-name     = token
971 ///       separators     = "(" | ")" | "<" | ">" | "@"
972 ///                      | "," | ";" | ":" | "\" | <">
973 ///                      | "/" | "[" | "]" | "?" | "="
974 ///                      | "{" | "}" | SP | HT
975 ///       token          = 1*tchar
976 ///       tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
977 ///                      / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
978 ///                      / DIGIT / ALPHA
979 ///                      ; any VCHAR, except delimiters
980 /// ```
981 const HEADER_CHARS: [u8; 256] = [
982     //  0      1      2      3      4      5      6      7      8      9
983         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //   x
984         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  1x
985         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  2x
986         0,     0,     0,  b'!',  b'"',  b'#',  b'$',  b'%',  b'&', b'\'', //  3x
987         0,     0,  b'*',  b'+',     0,  b'-',  b'.',     0,  b'0',  b'1', //  4x
988      b'2',  b'3',  b'4',  b'5',  b'6',  b'7',  b'8',  b'9',     0,     0, //  5x
989         0,     0,     0,     0,     0,  b'a',  b'b',  b'c',  b'd',  b'e', //  6x
990      b'f',  b'g',  b'h',  b'i',  b'j',  b'k',  b'l',  b'm',  b'n',  b'o', //  7x
991      b'p',  b'q',  b'r',  b's',  b't',  b'u',  b'v',  b'w',  b'x',  b'y', //  8x
992      b'z',     0,     0,     0,  b'^',  b'_',  b'`',  b'a',  b'b',  b'c', //  9x
993      b'd',  b'e',  b'f',  b'g',  b'h',  b'i',  b'j',  b'k',  b'l',  b'm', // 10x
994      b'n',  b'o',  b'p',  b'q',  b'r',  b's',  b't',  b'u',  b'v',  b'w', // 11x
995      b'x',  b'y',  b'z',     0,  b'|',     0,  b'~',     0,     0,     0, // 12x
996         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 13x
997         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 14x
998         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 15x
999         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 16x
1000         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 17x
1001         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 18x
1002         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 19x
1003         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 20x
1004         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 21x
1005         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 22x
1006         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 23x
1007         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 24x
1008         0,     0,     0,     0,     0,     0                              // 25x
1009 ];
1010 
1011 /// Valid header name characters for HTTP/2.0 and HTTP/3.0
1012 const HEADER_CHARS_H2: [u8; 256] = [
1013     //  0      1      2      3      4      5      6      7      8      9
1014         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //   x
1015         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  1x
1016         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  2x
1017         0,     0,     0,  b'!',  b'"',  b'#',  b'$',  b'%',  b'&', b'\'', //  3x
1018         0,     0,  b'*',  b'+',     0,  b'-',  b'.',     0,  b'0',  b'1', //  4x
1019      b'2',  b'3',  b'4',  b'5',  b'6',  b'7',  b'8',  b'9',     0,     0, //  5x
1020         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  6x
1021         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  7x
1022         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, //  8x
1023         0,     0,     0,     0,  b'^',  b'_',  b'`',  b'a',  b'b',  b'c', //  9x
1024      b'd',  b'e',  b'f',  b'g',  b'h',  b'i',  b'j',  b'k',  b'l',  b'm', // 10x
1025      b'n',  b'o',  b'p',  b'q',  b'r',  b's',  b't',  b'u',  b'v',  b'w', // 11x
1026      b'x',  b'y',  b'z',     0,  b'|',     0,  b'~',     0,     0,     0, // 12x
1027         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 13x
1028         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 14x
1029         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 15x
1030         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 16x
1031         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 17x
1032         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 18x
1033         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 19x
1034         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 20x
1035         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 21x
1036         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 22x
1037         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 23x
1038         0,     0,     0,     0,     0,     0,     0,     0,     0,     0, // 24x
1039         0,     0,     0,     0,     0,     0                              // 25x
1040 ];
1041 
1042 #[cfg(any(not(debug_assertions), not(target_arch = "wasm32")))]
1043 macro_rules! eq {
1044     (($($cmp:expr,)*) $v:ident[$n:expr] ==) => {
1045         $($cmp) && *
1046     };
1047     (($($cmp:expr,)*) $v:ident[$n:expr] == $a:tt $($rest:tt)*) => {
1048         eq!(($($cmp,)* $v[$n] == $a,) $v[$n+1] == $($rest)*)
1049     };
1050     ($v:ident == $($rest:tt)+) => {
1051         eq!(() $v[0] == $($rest)+)
1052     };
1053     ($v:ident[$n:expr] == $($rest:tt)+) => {
1054         eq!(() $v[$n] == $($rest)+)
1055     };
1056 }
1057 
1058 #[cfg(any(not(debug_assertions), not(target_arch = "wasm32")))]
1059 /// This version is best under optimized mode, however in a wasm debug compile,
1060 /// the `eq` macro expands to 1 + 1 + 1 + 1... and wasm explodes when this chain gets too long
1061 /// See https://github.com/DenisKolodin/yew/issues/478
parse_hdr<'a>( data: &'a [u8], b: &'a mut [u8; 64], table: &[u8; 256], ) -> Result<HdrName<'a>, InvalidHeaderName>1062 fn parse_hdr<'a>(
1063     data: &'a [u8],
1064     b: &'a mut [u8; 64],
1065     table: &[u8; 256],
1066 ) -> Result<HdrName<'a>, InvalidHeaderName> {
1067     use self::StandardHeader::*;
1068 
1069     let len = data.len();
1070 
1071     let validate = |buf: &'a [u8], len: usize| {
1072         let buf = &buf[..len];
1073         if buf.iter().any(|&b| b == 0) {
1074             Err(InvalidHeaderName::new())
1075         } else {
1076             Ok(HdrName::custom(buf, true))
1077         }
1078     };
1079 
1080 
1081     macro_rules! to_lower {
1082         ($d:ident, $src:ident, 1) => { $d[0] = table[$src[0] as usize]; };
1083         ($d:ident, $src:ident, 2) => { to_lower!($d, $src, 1); $d[1] = table[$src[1] as usize]; };
1084         ($d:ident, $src:ident, 3) => { to_lower!($d, $src, 2); $d[2] = table[$src[2] as usize]; };
1085         ($d:ident, $src:ident, 4) => { to_lower!($d, $src, 3); $d[3] = table[$src[3] as usize]; };
1086         ($d:ident, $src:ident, 5) => { to_lower!($d, $src, 4); $d[4] = table[$src[4] as usize]; };
1087         ($d:ident, $src:ident, 6) => { to_lower!($d, $src, 5); $d[5] = table[$src[5] as usize]; };
1088         ($d:ident, $src:ident, 7) => { to_lower!($d, $src, 6); $d[6] = table[$src[6] as usize]; };
1089         ($d:ident, $src:ident, 8) => { to_lower!($d, $src, 7); $d[7] = table[$src[7] as usize]; };
1090         ($d:ident, $src:ident, 9) => { to_lower!($d, $src, 8); $d[8] = table[$src[8] as usize]; };
1091         ($d:ident, $src:ident, 10) => { to_lower!($d, $src, 9); $d[9] = table[$src[9] as usize]; };
1092         ($d:ident, $src:ident, 11) => { to_lower!($d, $src, 10); $d[10] = table[$src[10] as usize]; };
1093         ($d:ident, $src:ident, 12) => { to_lower!($d, $src, 11); $d[11] = table[$src[11] as usize]; };
1094         ($d:ident, $src:ident, 13) => { to_lower!($d, $src, 12); $d[12] = table[$src[12] as usize]; };
1095         ($d:ident, $src:ident, 14) => { to_lower!($d, $src, 13); $d[13] = table[$src[13] as usize]; };
1096         ($d:ident, $src:ident, 15) => { to_lower!($d, $src, 14); $d[14] = table[$src[14] as usize]; };
1097         ($d:ident, $src:ident, 16) => { to_lower!($d, $src, 15); $d[15] = table[$src[15] as usize]; };
1098         ($d:ident, $src:ident, 17) => { to_lower!($d, $src, 16); $d[16] = table[$src[16] as usize]; };
1099         ($d:ident, $src:ident, 18) => { to_lower!($d, $src, 17); $d[17] = table[$src[17] as usize]; };
1100         ($d:ident, $src:ident, 19) => { to_lower!($d, $src, 18); $d[18] = table[$src[18] as usize]; };
1101         ($d:ident, $src:ident, 20) => { to_lower!($d, $src, 19); $d[19] = table[$src[19] as usize]; };
1102         ($d:ident, $src:ident, 21) => { to_lower!($d, $src, 20); $d[20] = table[$src[20] as usize]; };
1103         ($d:ident, $src:ident, 22) => { to_lower!($d, $src, 21); $d[21] = table[$src[21] as usize]; };
1104         ($d:ident, $src:ident, 23) => { to_lower!($d, $src, 22); $d[22] = table[$src[22] as usize]; };
1105         ($d:ident, $src:ident, 24) => { to_lower!($d, $src, 23); $d[23] = table[$src[23] as usize]; };
1106         ($d:ident, $src:ident, 25) => { to_lower!($d, $src, 24); $d[24] = table[$src[24] as usize]; };
1107         ($d:ident, $src:ident, 26) => { to_lower!($d, $src, 25); $d[25] = table[$src[25] as usize]; };
1108         ($d:ident, $src:ident, 27) => { to_lower!($d, $src, 26); $d[26] = table[$src[26] as usize]; };
1109         ($d:ident, $src:ident, 28) => { to_lower!($d, $src, 27); $d[27] = table[$src[27] as usize]; };
1110         ($d:ident, $src:ident, 29) => { to_lower!($d, $src, 28); $d[28] = table[$src[28] as usize]; };
1111         ($d:ident, $src:ident, 30) => { to_lower!($d, $src, 29); $d[29] = table[$src[29] as usize]; };
1112         ($d:ident, $src:ident, 31) => { to_lower!($d, $src, 30); $d[30] = table[$src[30] as usize]; };
1113         ($d:ident, $src:ident, 32) => { to_lower!($d, $src, 31); $d[31] = table[$src[31] as usize]; };
1114         ($d:ident, $src:ident, 33) => { to_lower!($d, $src, 32); $d[32] = table[$src[32] as usize]; };
1115         ($d:ident, $src:ident, 34) => { to_lower!($d, $src, 33); $d[33] = table[$src[33] as usize]; };
1116         ($d:ident, $src:ident, 35) => { to_lower!($d, $src, 34); $d[34] = table[$src[34] as usize]; };
1117     }
1118 
1119     match len {
1120         0 => Err(InvalidHeaderName::new()),
1121         2 => {
1122             to_lower!(b, data, 2);
1123 
1124             if eq!(b == b't' b'e') {
1125                 Ok(Te.into())
1126             } else {
1127                 validate(b, len)
1128             }
1129         }
1130         3 => {
1131             to_lower!(b, data, 3);
1132 
1133             if eq!(b == b'a' b'g' b'e') {
1134                 Ok(Age.into())
1135             } else if eq!(b == b'v' b'i' b'a') {
1136                 Ok(Via.into())
1137             } else if eq!(b == b'd' b'n' b't') {
1138                 Ok(Dnt.into())
1139             } else {
1140                 validate(b, len)
1141             }
1142         }
1143         4 => {
1144             to_lower!(b, data, 4);
1145 
1146             if eq!(b == b'd' b'a' b't' b'e') {
1147                 Ok(Date.into())
1148             } else if eq!(b == b'e' b't' b'a' b'g') {
1149                 Ok(Etag.into())
1150             } else if eq!(b == b'f' b'r' b'o' b'm') {
1151                 Ok(From.into())
1152             } else if eq!(b == b'h' b'o' b's' b't') {
1153                 Ok(Host.into())
1154             } else if eq!(b == b'l' b'i' b'n' b'k') {
1155                 Ok(Link.into())
1156             } else if eq!(b == b'v' b'a' b'r' b'y') {
1157                 Ok(Vary.into())
1158             } else {
1159                 validate(b, len)
1160             }
1161         }
1162         5 => {
1163             to_lower!(b, data, 5);
1164 
1165             if eq!(b == b'a' b'l' b'l' b'o' b'w') {
1166                 Ok(Allow.into())
1167             } else if eq!(b == b'r' b'a' b'n' b'g' b'e') {
1168                 Ok(Range.into())
1169             } else {
1170                 validate(b, len)
1171             }
1172         }
1173         6 => {
1174             to_lower!(b, data, 6);
1175 
1176             if eq!(b == b'a' b'c' b'c' b'e' b'p' b't') {
1177                 return Ok(Accept.into());
1178             } else if eq!(b == b'c' b'o' b'o' b'k' b'i' b'e') {
1179                 return Ok(Cookie.into());
1180             } else if eq!(b == b'e' b'x' b'p' b'e' b'c' b't') {
1181                 return Ok(Expect.into());
1182             } else if eq!(b == b'o' b'r' b'i' b'g' b'i' b'n') {
1183                 return Ok(Origin.into());
1184             } else if eq!(b == b'p' b'r' b'a' b'g' b'm' b'a') {
1185                 return Ok(Pragma.into());
1186             } else if b[0] == b's' {
1187                 if eq!(b[1] == b'e' b'r' b'v' b'e' b'r') {
1188                     return Ok(Server.into());
1189                 }
1190             }
1191 
1192             validate(b, len)
1193         }
1194         7 => {
1195             to_lower!(b, data, 7);
1196 
1197             if eq!(b == b'a' b'l' b't' b'-' b's' b'v' b'c') {
1198                 Ok(AltSvc.into())
1199             } else if eq!(b == b'e' b'x' b'p' b'i' b'r' b'e' b's') {
1200                 Ok(Expires.into())
1201             } else if eq!(b == b'r' b'e' b'f' b'e' b'r' b'e' b'r') {
1202                 Ok(Referer.into())
1203             } else if eq!(b == b'r' b'e' b'f' b'r' b'e' b's' b'h') {
1204                 Ok(Refresh.into())
1205             } else if eq!(b == b't' b'r' b'a' b'i' b'l' b'e' b'r') {
1206                 Ok(Trailer.into())
1207             } else if eq!(b == b'u' b'p' b'g' b'r' b'a' b'd' b'e') {
1208                 Ok(Upgrade.into())
1209             } else if eq!(b == b'w' b'a' b'r' b'n' b'i' b'n' b'g') {
1210                 Ok(Warning.into())
1211             } else {
1212                 validate(b, len)
1213             }
1214         }
1215         8 => {
1216             to_lower!(b, data, 8);
1217 
1218             if eq!(b == b'i' b'f' b'-') {
1219                 if eq!(b[3] == b'm' b'a' b't' b'c' b'h') {
1220                     return Ok(IfMatch.into());
1221                 } else if eq!(b[3] == b'r' b'a' b'n' b'g' b'e') {
1222                     return Ok(IfRange.into());
1223                 }
1224             } else if eq!(b == b'l' b'o' b'c' b'a' b't' b'i' b'o' b'n') {
1225                 return Ok(Location.into());
1226             }
1227 
1228             validate(b, len)
1229         }
1230         9 => {
1231             to_lower!(b, data, 9);
1232 
1233             if eq!(b == b'f' b'o' b'r' b'w' b'a' b'r' b'd' b'e' b'd') {
1234                 Ok(Forwarded.into())
1235             } else {
1236                 validate(b, len)
1237             }
1238         }
1239         10 => {
1240             to_lower!(b, data, 10);
1241 
1242             if eq!(b == b'c' b'o' b'n' b'n' b'e' b'c' b't' b'i' b'o' b'n') {
1243                 Ok(Connection.into())
1244             } else if eq!(b == b's' b'e' b't' b'-' b'c' b'o' b'o' b'k' b'i' b'e') {
1245                 Ok(SetCookie.into())
1246             } else if eq!(b == b'u' b's' b'e' b'r' b'-' b'a' b'g' b'e' b'n' b't') {
1247                 Ok(UserAgent.into())
1248             } else {
1249                 validate(b, len)
1250             }
1251         }
1252         11 => {
1253             to_lower!(b, data, 11);
1254 
1255             if eq!(b == b'r' b'e' b't' b'r' b'y' b'-' b'a' b'f' b't' b'e' b'r') {
1256                 Ok(RetryAfter.into())
1257             } else {
1258                 validate(b, len)
1259             }
1260         }
1261         12 => {
1262             to_lower!(b, data, 12);
1263 
1264             if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b't' b'y' b'p' b'e') {
1265                 Ok(ContentType.into())
1266             } else if eq!(b == b'm' b'a' b'x' b'-' b'f' b'o' b'r' b'w' b'a' b'r' b'd' b's') {
1267                 Ok(MaxForwards.into())
1268             } else {
1269                 validate(b, len)
1270             }
1271         }
1272         13 => {
1273             to_lower!(b, data, 13);
1274 
1275             if b[0] == b'a' {
1276                 if eq!(b[1] == b'c' b'c' b'e' b'p' b't' b'-' b'r' b'a' b'n' b'g' b'e' b's') {
1277                     return Ok(AcceptRanges.into());
1278                 } else if eq!(b[1] == b'u' b't' b'h' b'o' b'r' b'i' b'z' b'a' b't' b'i' b'o' b'n') {
1279                     return Ok(Authorization.into());
1280                 }
1281             } else if b[0] == b'c' {
1282                 if eq!(b[1] == b'a' b'c' b'h' b'e' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l') {
1283                     return Ok(CacheControl.into());
1284                 } else if eq!(b[1] == b'o' b'n' b't' b'e' b'n' b't' b'-' b'r' b'a' b'n' b'g' b'e' )
1285                 {
1286                     return Ok(ContentRange.into());
1287                 }
1288             } else if eq!(b == b'i' b'f' b'-' b'n' b'o' b'n' b'e' b'-' b'm' b'a' b't' b'c' b'h') {
1289                 return Ok(IfNoneMatch.into());
1290             } else if eq!(b == b'l' b'a' b's' b't' b'-' b'm' b'o' b'd' b'i' b'f' b'i' b'e' b'd') {
1291                 return Ok(LastModified.into());
1292             }
1293 
1294             validate(b, len)
1295         }
1296         14 => {
1297             to_lower!(b, data, 14);
1298 
1299             if eq!(b == b'a' b'c' b'c' b'e' b'p' b't' b'-' b'c' b'h' b'a' b'r' b's' b'e' b't') {
1300                 Ok(AcceptCharset.into())
1301             } else if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b'l' b'e' b'n' b'g' b't' b'h')
1302             {
1303                 Ok(ContentLength.into())
1304             } else {
1305                 validate(b, len)
1306             }
1307         }
1308         15 => {
1309             to_lower!(b, data, 15);
1310 
1311             if eq!(b == b'a' b'c' b'c' b'e' b'p' b't' b'-') { // accept-
1312                 if eq!(b[7] == b'e' b'n' b'c' b'o' b'd' b'i' b'n' b'g') {
1313                     return Ok(AcceptEncoding.into())
1314                 } else if eq!(b[7] == b'l' b'a' b'n' b'g' b'u' b'a' b'g' b'e') {
1315                     return Ok(AcceptLanguage.into())
1316                 }
1317             } else if eq!(b == b'p' b'u' b'b' b'l' b'i' b'c' b'-' b'k' b'e' b'y' b'-' b'p' b'i' b'n' b's') {
1318                 return Ok(PublicKeyPins.into())
1319             } else if eq!(b == b'x' b'-' b'f' b'r' b'a' b'm' b'e' b'-' b'o' b'p' b't' b'i' b'o' b'n' b's') {
1320                 return Ok(XFrameOptions.into())
1321             }
1322             else if eq!(b == b'r' b'e' b'f' b'e' b'r' b'r' b'e' b'r' b'-' b'p' b'o' b'l' b'i' b'c' b'y') {
1323                 return Ok(ReferrerPolicy.into())
1324             }
1325 
1326             validate(b, len)
1327         }
1328         16 => {
1329             to_lower!(b, data, 16);
1330 
1331             if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-') {
1332                 if eq!(b[8] == b'l' b'a' b'n' b'g' b'u' b'a' b'g' b'e') {
1333                     return Ok(ContentLanguage.into())
1334                 } else if eq!(b[8] == b'l' b'o' b'c' b'a' b't' b'i' b'o' b'n') {
1335                     return Ok(ContentLocation.into())
1336                 } else if eq!(b[8] == b'e' b'n' b'c' b'o' b'd' b'i' b'n' b'g') {
1337                     return Ok(ContentEncoding.into())
1338                 }
1339             } else if eq!(b == b'w' b'w' b'w' b'-' b'a' b'u' b't' b'h' b'e' b'n' b't' b'i' b'c' b'a' b't' b'e') {
1340                 return Ok(WwwAuthenticate.into())
1341             } else if eq!(b == b'x' b'-' b'x' b's' b's' b'-' b'p' b'r' b'o' b't' b'e' b'c' b't' b'i' b'o' b'n') {
1342                 return Ok(XXssProtection.into())
1343             }
1344 
1345             validate(b, len)
1346         }
1347         17 => {
1348             to_lower!(b, data, 17);
1349 
1350             if eq!(b == b't' b'r' b'a' b'n' b's' b'f' b'e' b'r' b'-' b'e' b'n' b'c' b'o' b'd' b'i' b'n' b'g') {
1351                 Ok(TransferEncoding.into())
1352             } else if eq!(b == b'i' b'f' b'-' b'm' b'o' b'd' b'i' b'f' b'i' b'e' b'd' b'-' b's' b'i' b'n' b'c' b'e') {
1353                 Ok(IfModifiedSince.into())
1354             } else if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'k' b'e' b'y') {
1355                 Ok(SecWebSocketKey.into())
1356             } else {
1357                 validate(b, len)
1358             }
1359         }
1360         18 => {
1361             to_lower!(b, data, 18);
1362 
1363             if eq!(b == b'p' b'r' b'o' b'x' b'y' b'-' b'a' b'u' b't' b'h' b'e' b'n' b't' b'i' b'c' b'a' b't' b'e') {
1364                 Ok(ProxyAuthenticate.into())
1365             } else {
1366                 validate(b, len)
1367             }
1368         }
1369         19 => {
1370             to_lower!(b, data, 19);
1371 
1372             if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b'd' b'i' b's' b'p' b'o' b's' b'i' b't' b'i' b'o' b'n') {
1373                 Ok(ContentDisposition.into())
1374             } else if eq!(b == b'i' b'f' b'-' b'u' b'n' b'm' b'o' b'd' b'i' b'f' b'i' b'e' b'd' b'-' b's' b'i' b'n' b'c' b'e') {
1375                 Ok(IfUnmodifiedSince.into())
1376             } else if eq!(b == b'p' b'r' b'o' b'x' b'y' b'-' b'a' b'u' b't' b'h' b'o' b'r' b'i' b'z' b'a' b't' b'i' b'o' b'n') {
1377                 Ok(ProxyAuthorization.into())
1378             } else {
1379                 validate(b, len)
1380             }
1381         }
1382         20 => {
1383             to_lower!(b, data, 20);
1384 
1385             if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'a' b'c' b'c' b'e' b'p' b't') {
1386                 Ok(SecWebSocketAccept.into())
1387             } else {
1388                 validate(b, len)
1389             }
1390         }
1391         21 => {
1392             to_lower!(b, data, 21);
1393 
1394             if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'v' b'e' b'r' b's' b'i' b'o' b'n') {
1395                 Ok(SecWebSocketVersion.into())
1396             } else {
1397                 validate(b, len)
1398             }
1399         }
1400         22 => {
1401             to_lower!(b, data, 22);
1402 
1403             if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'm' b'a' b'x' b'-' b'a' b'g' b'e') {
1404                 Ok(AccessControlMaxAge.into())
1405             } else if eq!(b == b'x' b'-' b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b't' b'y' b'p' b'e' b'-' b'o' b'p' b't' b'i' b'o' b'n' b's') {
1406                 Ok(XContentTypeOptions.into())
1407             } else if eq!(b == b'x' b'-' b'd' b'n' b's' b'-' b'p' b'r' b'e' b'f' b'e' b't' b'c' b'h' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l') {
1408                 Ok(XDnsPrefetchControl.into())
1409             } else if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'p' b'r' b'o' b't' b'o' b'c' b'o' b'l') {
1410                 Ok(SecWebSocketProtocol.into())
1411             } else {
1412                 validate(b, len)
1413             }
1414         }
1415         23 => {
1416             to_lower!(b, data, 23);
1417 
1418             if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b's' b'e' b'c' b'u' b'r' b'i' b't' b'y' b'-' b'p' b'o' b'l' b'i' b'c' b'y') {
1419                 Ok(ContentSecurityPolicy.into())
1420             } else {
1421                 validate(b, len)
1422             }
1423         }
1424         24 => {
1425             to_lower!(b, data, 24);
1426 
1427             if eq!(b == b's' b'e' b'c' b'-' b'w' b'e' b'b' b's' b'o' b'c' b'k' b'e' b't' b'-' b'e' b'x' b't' b'e' b'n' b's' b'i' b'o' b'n' b's') {
1428                 Ok(SecWebSocketExtensions.into())
1429             } else {
1430                 validate(b, len)
1431             }
1432         }
1433         25 => {
1434             to_lower!(b, data, 25);
1435 
1436             if eq!(b == b's' b't' b'r' b'i' b'c' b't' b'-' b't' b'r' b'a' b'n' b's' b'p' b'o' b'r' b't' b'-' b's' b'e' b'c' b'u' b'r' b'i' b't' b'y') {
1437                 Ok(StrictTransportSecurity.into())
1438             } else if eq!(b == b'u' b'p' b'g' b'r' b'a' b'd' b'e' b'-' b'i' b'n' b's' b'e' b'c' b'u' b'r' b'e' b'-' b'r' b'e' b'q' b'u' b'e' b's' b't' b's') {
1439                 Ok(UpgradeInsecureRequests.into())
1440             } else {
1441                 validate(b, len)
1442             }
1443         }
1444         27 => {
1445             to_lower!(b, data, 27);
1446 
1447             if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'a' b'l' b'l' b'o' b'w' b'-' b'o' b'r' b'i' b'g' b'i' b'n') {
1448                 Ok(AccessControlAllowOrigin.into())
1449             } else if eq!(b == b'p' b'u' b'b' b'l' b'i' b'c' b'-' b'k' b'e' b'y' b'-' b'p' b'i' b'n' b's' b'-' b'r' b'e' b'p' b'o' b'r' b't' b'-' b'o' b'n' b'l' b'y') {
1450                 Ok(PublicKeyPinsReportOnly.into())
1451             } else {
1452                 validate(b, len)
1453             }
1454         }
1455         28 => {
1456             to_lower!(b, data, 28);
1457 
1458             if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'a' b'l' b'l' b'o' b'w' b'-') {
1459                 if eq!(b[21] == b'h' b'e' b'a' b'd' b'e' b'r' b's') {
1460                     return Ok(AccessControlAllowHeaders.into())
1461                 } else if eq!(b[21] == b'm' b'e' b't' b'h' b'o' b'd' b's') {
1462                     return Ok(AccessControlAllowMethods.into())
1463                 }
1464             }
1465 
1466             validate(b, len)
1467         }
1468         29 => {
1469             to_lower!(b, data, 29);
1470 
1471             if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-') {
1472                 if eq!(b[15] == b'e' b'x' b'p' b'o' b's' b'e' b'-' b'h' b'e' b'a' b'd' b'e' b'r' b's') {
1473                     return Ok(AccessControlExposeHeaders.into())
1474                 } else if eq!(b[15] == b'r' b'e' b'q' b'u' b'e' b's' b't' b'-' b'm' b'e' b't' b'h' b'o' b'd') {
1475                     return Ok(AccessControlRequestMethod.into())
1476                 }
1477             }
1478 
1479             validate(b, len)
1480         }
1481         30 => {
1482             to_lower!(b, data, 30);
1483 
1484             if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'r' b'e' b'q' b'u' b'e' b's' b't' b'-' b'h' b'e' b'a' b'd' b'e' b'r' b's') {
1485                 Ok(AccessControlRequestHeaders.into())
1486             } else {
1487                 validate(b, len)
1488             }
1489         }
1490         32 => {
1491             to_lower!(b, data, 32);
1492 
1493             if eq!(b == b'a' b'c' b'c' b'e' b's' b's' b'-' b'c' b'o' b'n' b't' b'r' b'o' b'l' b'-' b'a' b'l' b'l' b'o' b'w' b'-' b'c' b'r' b'e' b'd' b'e' b'n' b't' b'i' b'a' b'l' b's') {
1494                 Ok(AccessControlAllowCredentials.into())
1495             } else {
1496                 validate(b, len)
1497             }
1498         }
1499         35 => {
1500             to_lower!(b, data, 35);
1501 
1502             if eq!(b == b'c' b'o' b'n' b't' b'e' b'n' b't' b'-' b's' b'e' b'c' b'u' b'r' b'i' b't' b'y' b'-' b'p' b'o' b'l' b'i' b'c' b'y' b'-' b'r' b'e' b'p' b'o' b'r' b't' b'-' b'o' b'n' b'l' b'y') {
1503                 Ok(ContentSecurityPolicyReportOnly.into())
1504             } else {
1505                 validate(b, len)
1506             }
1507         }
1508         len if len < 64 => {
1509             for i in 0..len {
1510                 b[i] = table[data[i] as usize];
1511             }
1512             validate(b, len)
1513         }
1514         len if len <= super::MAX_HEADER_NAME_LEN => {
1515             Ok(HdrName::custom(data, false))
1516         }
1517         _ => Err(InvalidHeaderName::new()),
1518     }
1519 }
1520 
1521 #[cfg(all(debug_assertions, target_arch = "wasm32"))]
1522 /// This version works best in debug mode in wasm
parse_hdr<'a>( data: &'a [u8], b: &'a mut [u8; 64], table: &[u8; 256], ) -> Result<HdrName<'a>, InvalidHeaderName>1523 fn parse_hdr<'a>(
1524     data: &'a [u8],
1525     b: &'a mut [u8; 64],
1526     table: &[u8; 256],
1527 ) -> Result<HdrName<'a>, InvalidHeaderName> {
1528     use self::StandardHeader::*;
1529 
1530     let len = data.len();
1531 
1532     let validate = |buf: &'a [u8], len: usize| {
1533         let buf = &buf[..len];
1534         if buf.iter().any(|&b| b == 0) {
1535             Err(InvalidHeaderName::new())
1536         } else {
1537             Ok(HdrName::custom(buf, true))
1538         }
1539     };
1540 
1541     assert!(
1542         len < super::MAX_HEADER_NAME_LEN,
1543         "header name too long -- max length is {}",
1544         super::MAX_HEADER_NAME_LEN
1545     );
1546 
1547     match len {
1548         0 => Err(InvalidHeaderName::new()),
1549         len if len > 64 => Ok(HdrName::custom(data, false)),
1550         len => {
1551             // Read from data into the buffer - transforming using `table` as we go
1552             data.iter().zip(b.iter_mut()).for_each(|(index, out)| *out = table[*index as usize]);
1553             match &b[0..len] {
1554                 b"te" => Ok(Te.into()),
1555                 b"age" => Ok(Age.into()),
1556                 b"via" => Ok(Via.into()),
1557                 b"dnt" => Ok(Dnt.into()),
1558                 b"date" => Ok(Date.into()),
1559                 b"etag" => Ok(Etag.into()),
1560                 b"from" => Ok(From.into()),
1561                 b"host" => Ok(Host.into()),
1562                 b"link" => Ok(Link.into()),
1563                 b"vary" => Ok(Vary.into()),
1564                 b"allow" => Ok(Allow.into()),
1565                 b"range" => Ok(Range.into()),
1566                 b"accept" => Ok(Accept.into()),
1567                 b"cookie" => Ok(Cookie.into()),
1568                 b"expect" => Ok(Expect.into()),
1569                 b"origin" => Ok(Origin.into()),
1570                 b"pragma" => Ok(Pragma.into()),
1571                 b"server" => Ok(Server.into()),
1572                 b"alt-svc" => Ok(AltSvc.into()),
1573                 b"expires" => Ok(Expires.into()),
1574                 b"referer" => Ok(Referer.into()),
1575                 b"refresh" => Ok(Refresh.into()),
1576                 b"trailer" => Ok(Trailer.into()),
1577                 b"upgrade" => Ok(Upgrade.into()),
1578                 b"warning" => Ok(Warning.into()),
1579                 b"if-match" => Ok(IfMatch.into()),
1580                 b"if-range" => Ok(IfRange.into()),
1581                 b"location" => Ok(Location.into()),
1582                 b"forwarded" => Ok(Forwarded.into()),
1583                 b"connection" => Ok(Connection.into()),
1584                 b"set-cookie" => Ok(SetCookie.into()),
1585                 b"user-agent" => Ok(UserAgent.into()),
1586                 b"retry-after" => Ok(RetryAfter.into()),
1587                 b"content-type" => Ok(ContentType.into()),
1588                 b"max-forwards" => Ok(MaxForwards.into()),
1589                 b"accept-ranges" => Ok(AcceptRanges.into()),
1590                 b"authorization" => Ok(Authorization.into()),
1591                 b"cache-control" => Ok(CacheControl.into()),
1592                 b"content-range" => Ok(ContentRange.into()),
1593                 b"if-none-match" => Ok(IfNoneMatch.into()),
1594                 b"last-modified" => Ok(LastModified.into()),
1595                 b"accept-charset" => Ok(AcceptCharset.into()),
1596                 b"content-length" => Ok(ContentLength.into()),
1597                 b"accept-encoding" => Ok(AcceptEncoding.into()),
1598                 b"accept-language" => Ok(AcceptLanguage.into()),
1599                 b"public-key-pins" => Ok(PublicKeyPins.into()),
1600                 b"x-frame-options" => Ok(XFrameOptions.into()),
1601                 b"referrer-policy" => Ok(ReferrerPolicy.into()),
1602                 b"content-language" => Ok(ContentLanguage.into()),
1603                 b"content-location" => Ok(ContentLocation.into()),
1604                 b"content-encoding" => Ok(ContentEncoding.into()),
1605                 b"www-authenticate" => Ok(WwwAuthenticate.into()),
1606                 b"x-xss-protection" => Ok(XXssProtection.into()),
1607                 b"transfer-encoding" => Ok(TransferEncoding.into()),
1608                 b"if-modified-since" => Ok(IfModifiedSince.into()),
1609                 b"sec-websocket-key" => Ok(SecWebSocketKey.into()),
1610                 b"proxy-authenticate" => Ok(ProxyAuthenticate.into()),
1611                 b"content-disposition" => Ok(ContentDisposition.into()),
1612                 b"if-unmodified-since" => Ok(IfUnmodifiedSince.into()),
1613                 b"proxy-authorization" => Ok(ProxyAuthorization.into()),
1614                 b"sec-websocket-accept" => Ok(SecWebSocketAccept.into()),
1615                 b"sec-websocket-version" => Ok(SecWebSocketVersion.into()),
1616                 b"access-control-max-age" => Ok(AccessControlMaxAge.into()),
1617                 b"x-content-type-options" => Ok(XContentTypeOptions.into()),
1618                 b"x-dns-prefetch-control" => Ok(XDnsPrefetchControl.into()),
1619                 b"sec-websocket-protocol" => Ok(SecWebSocketProtocol.into()),
1620                 b"content-security-policy" => Ok(ContentSecurityPolicy.into()),
1621                 b"sec-websocket-extensions" => Ok(SecWebSocketExtensions.into()),
1622                 b"strict-transport-security" => Ok(StrictTransportSecurity.into()),
1623                 b"upgrade-insecure-requests" => Ok(UpgradeInsecureRequests.into()),
1624                 b"access-control-allow-origin" => Ok(AccessControlAllowOrigin.into()),
1625                 b"public-key-pins-report-only" => Ok(PublicKeyPinsReportOnly.into()),
1626                 b"access-control-allow-headers" => Ok(AccessControlAllowHeaders.into()),
1627                 b"access-control-allow-methods" => Ok(AccessControlAllowMethods.into()),
1628                 b"access-control-expose-headers" => Ok(AccessControlExposeHeaders.into()),
1629                 b"access-control-request-method" => Ok(AccessControlRequestMethod.into()),
1630                 b"access-control-request-headers" => Ok(AccessControlRequestHeaders.into()),
1631                 b"access-control-allow-credentials" => Ok(AccessControlAllowCredentials.into()),
1632                 b"content-security-policy-report-only" => {
1633                     Ok(ContentSecurityPolicyReportOnly.into())
1634                 }
1635                 other => validate(other, len),
1636             }
1637         }
1638     }
1639 }
1640 
1641 
1642 
1643 impl<'a> From<StandardHeader> for HdrName<'a> {
from(hdr: StandardHeader) -> HdrName<'a>1644     fn from(hdr: StandardHeader) -> HdrName<'a> {
1645         HdrName { inner: Repr::Standard(hdr) }
1646     }
1647 }
1648 
1649 impl HeaderName {
1650     /// Converts a slice of bytes to an HTTP header name.
1651     ///
1652     /// This function normalizes the input.
1653     #[allow(deprecated)]
from_bytes(src: &[u8]) -> Result<HeaderName, InvalidHeaderName>1654     pub fn from_bytes(src: &[u8]) -> Result<HeaderName, InvalidHeaderName> {
1655         #[allow(deprecated)]
1656         let mut buf = unsafe { mem::uninitialized() };
1657         match parse_hdr(src, &mut buf, &HEADER_CHARS)?.inner {
1658             Repr::Standard(std) => Ok(std.into()),
1659             Repr::Custom(MaybeLower { buf, lower: true }) => {
1660                 let buf = Bytes::copy_from_slice(buf);
1661                 let val = unsafe { ByteStr::from_utf8_unchecked(buf) };
1662                 Ok(Custom(val).into())
1663             }
1664             Repr::Custom(MaybeLower { buf, lower: false }) => {
1665                 use bytes::{BufMut};
1666                 let mut dst = BytesMut::with_capacity(buf.len());
1667 
1668                 for b in buf.iter() {
1669                     let b = HEADER_CHARS[*b as usize];
1670 
1671                     if b == 0 {
1672                         return Err(InvalidHeaderName::new());
1673                     }
1674 
1675                     dst.put_u8(b);
1676                 }
1677 
1678                 let val = unsafe { ByteStr::from_utf8_unchecked(dst.freeze()) };
1679 
1680                 Ok(Custom(val).into())
1681             }
1682         }
1683     }
1684 
1685     /// Converts a slice of bytes to an HTTP header name.
1686     ///
1687     /// This function expects the input to only contain lowercase characters.
1688     /// This is useful when decoding HTTP/2.0 or HTTP/3.0 headers. Both
1689     /// require that all headers be represented in lower case.
1690     ///
1691     /// # Examples
1692     ///
1693     /// ```
1694     /// # use http::header::*;
1695     ///
1696     /// // Parsing a lower case header
1697     /// let hdr = HeaderName::from_lowercase(b"content-length").unwrap();
1698     /// assert_eq!(CONTENT_LENGTH, hdr);
1699     ///
1700     /// // Parsing a header that contains uppercase characters
1701     /// assert!(HeaderName::from_lowercase(b"Content-Length").is_err());
1702     /// ```
1703     #[allow(deprecated)]
from_lowercase(src: &[u8]) -> Result<HeaderName, InvalidHeaderName>1704     pub fn from_lowercase(src: &[u8]) -> Result<HeaderName, InvalidHeaderName> {
1705         #[allow(deprecated)]
1706         let mut buf = unsafe { mem::uninitialized() };
1707         match parse_hdr(src, &mut buf, &HEADER_CHARS_H2)?.inner {
1708             Repr::Standard(std) => Ok(std.into()),
1709             Repr::Custom(MaybeLower { buf, lower: true }) => {
1710                 let buf = Bytes::copy_from_slice(buf);
1711                 let val = unsafe { ByteStr::from_utf8_unchecked(buf) };
1712                 Ok(Custom(val).into())
1713             }
1714             Repr::Custom(MaybeLower { buf, lower: false }) => {
1715                 for &b in buf.iter() {
1716                     if b != HEADER_CHARS[b as usize] {
1717                         return Err(InvalidHeaderName::new());
1718                     }
1719                 }
1720 
1721                 let buf = Bytes::copy_from_slice(buf);
1722                 let val = unsafe { ByteStr::from_utf8_unchecked(buf) };
1723                 Ok(Custom(val).into())
1724             }
1725         }
1726     }
1727 
1728     /// Converts a static string to a HTTP header name.
1729     ///
1730     /// This function panics when the static string is a invalid header.
1731     ///
1732     /// This function requires the static string to only contain lowercase
1733     /// characters, numerals and symbols, as per the HTTP/2.0 specification
1734     /// and header names internal representation within this library.
1735     ///
1736     ///
1737     /// # Examples
1738     ///
1739     /// ```
1740     /// # use http::header::*;
1741     /// // Parsing a standard header
1742     /// let hdr = HeaderName::from_static("content-length");
1743     /// assert_eq!(CONTENT_LENGTH, hdr);
1744     ///
1745     /// // Parsing a custom header
1746     /// let CUSTOM_HEADER: &'static str = "custom-header";
1747     ///
1748     /// let a = HeaderName::from_lowercase(b"custom-header").unwrap();
1749     /// let b = HeaderName::from_static(CUSTOM_HEADER);
1750     /// assert_eq!(a, b);
1751     /// ```
1752     ///
1753     /// ```should_panic
1754     /// # use http::header::*;
1755     /// #
1756     /// // Parsing a header that contains invalid symbols(s):
1757     /// HeaderName::from_static("content{}{}length"); // This line panics!
1758     ///
1759     /// // Parsing a header that contains invalid uppercase characters.
1760     /// let a = HeaderName::from_static("foobar");
1761     /// let b = HeaderName::from_static("FOOBAR"); // This line panics!
1762     /// ```
1763     #[allow(deprecated)]
from_static(src: &'static str) -> HeaderName1764     pub fn from_static(src: &'static str) -> HeaderName {
1765         let bytes = src.as_bytes();
1766         #[allow(deprecated)]
1767         let mut buf = unsafe { mem::uninitialized() };
1768         match parse_hdr(bytes, &mut buf, &HEADER_CHARS_H2) {
1769             Ok(hdr_name) => match hdr_name.inner {
1770                 Repr::Standard(std) => std.into(),
1771                 Repr::Custom(MaybeLower { buf: _, lower: true }) => {
1772                     let val = ByteStr::from_static(src);
1773                     Custom(val).into()
1774                 },
1775                 Repr::Custom(MaybeLower { buf: _, lower: false }) => {
1776                     // With lower false, the string is left unchecked by
1777                     // parse_hdr and must be validated manually.
1778                     for &b in bytes.iter() {
1779                         if HEADER_CHARS_H2[b as usize] == 0 {
1780                             panic!("invalid header name")
1781                         }
1782                     }
1783 
1784                     let val = ByteStr::from_static(src);
1785                     Custom(val).into()
1786                 }
1787             },
1788 
1789             Err(_) => panic!("invalid header name")
1790         }
1791     }
1792 
1793     /// Returns a `str` representation of the header.
1794     ///
1795     /// The returned string will always be lower case.
1796     #[inline]
as_str(&self) -> &str1797     pub fn as_str(&self) -> &str {
1798         match self.inner {
1799             Repr::Standard(v) => v.as_str(),
1800             Repr::Custom(ref v) => &*v.0,
1801         }
1802     }
1803 
into_bytes(self) -> Bytes1804     pub(super) fn into_bytes(self) -> Bytes {
1805         self.inner.into()
1806     }
1807 }
1808 
1809 impl FromStr for HeaderName {
1810     type Err = InvalidHeaderName;
1811 
from_str(s: &str) -> Result<HeaderName, InvalidHeaderName>1812     fn from_str(s: &str) -> Result<HeaderName, InvalidHeaderName> {
1813         HeaderName::from_bytes(s.as_bytes()).map_err(|_| InvalidHeaderName { _priv: () })
1814     }
1815 }
1816 
1817 impl AsRef<str> for HeaderName {
as_ref(&self) -> &str1818     fn as_ref(&self) -> &str {
1819         self.as_str()
1820     }
1821 }
1822 
1823 impl AsRef<[u8]> for HeaderName {
as_ref(&self) -> &[u8]1824     fn as_ref(&self) -> &[u8] {
1825         self.as_str().as_bytes()
1826     }
1827 }
1828 
1829 impl Borrow<str> for HeaderName {
borrow(&self) -> &str1830     fn borrow(&self) -> &str {
1831         self.as_str()
1832     }
1833 }
1834 
1835 impl fmt::Debug for HeaderName {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1836     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1837         fmt::Debug::fmt(self.as_str(), fmt)
1838     }
1839 }
1840 
1841 impl fmt::Display for HeaderName {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1842     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1843         fmt::Display::fmt(self.as_str(), fmt)
1844     }
1845 }
1846 
1847 impl InvalidHeaderName {
new() -> InvalidHeaderName1848     fn new() -> InvalidHeaderName {
1849         InvalidHeaderName { _priv: () }
1850     }
1851 }
1852 
1853 impl<'a> From<&'a HeaderName> for HeaderName {
from(src: &'a HeaderName) -> HeaderName1854     fn from(src: &'a HeaderName) -> HeaderName {
1855         src.clone()
1856     }
1857 }
1858 
1859 #[doc(hidden)]
1860 impl<T> From<Repr<T>> for Bytes
1861 where
1862     T: Into<Bytes>,
1863 {
from(repr: Repr<T>) -> Bytes1864     fn from(repr: Repr<T>) -> Bytes {
1865         match repr {
1866             Repr::Standard(header) => Bytes::from_static(header.as_str().as_bytes()),
1867             Repr::Custom(header) => header.into(),
1868         }
1869     }
1870 }
1871 
1872 impl From<Custom> for Bytes {
1873     #[inline]
from(Custom(inner): Custom) -> Bytes1874     fn from(Custom(inner): Custom) -> Bytes {
1875         Bytes::from(inner)
1876     }
1877 }
1878 
1879 impl<'a> TryFrom<&'a str> for HeaderName {
1880     type Error = InvalidHeaderName;
1881     #[inline]
try_from(s: &'a str) -> Result<Self, Self::Error>1882     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
1883         Self::from_bytes(s.as_bytes())
1884     }
1885 }
1886 
1887 impl<'a> TryFrom<&'a String> for HeaderName {
1888     type Error = InvalidHeaderName;
1889     #[inline]
try_from(s: &'a String) -> Result<Self, Self::Error>1890     fn try_from(s: &'a String) -> Result<Self, Self::Error> {
1891         Self::from_bytes(s.as_bytes())
1892     }
1893 }
1894 
1895 impl<'a> TryFrom<&'a [u8]> for HeaderName {
1896     type Error = InvalidHeaderName;
1897     #[inline]
try_from(s: &'a [u8]) -> Result<Self, Self::Error>1898     fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> {
1899         Self::from_bytes(s)
1900     }
1901 }
1902 
1903 #[doc(hidden)]
1904 impl From<StandardHeader> for HeaderName {
from(src: StandardHeader) -> HeaderName1905     fn from(src: StandardHeader) -> HeaderName {
1906         HeaderName {
1907             inner: Repr::Standard(src),
1908         }
1909     }
1910 }
1911 
1912 #[doc(hidden)]
1913 impl From<Custom> for HeaderName {
from(src: Custom) -> HeaderName1914     fn from(src: Custom) -> HeaderName {
1915         HeaderName {
1916             inner: Repr::Custom(src),
1917         }
1918     }
1919 }
1920 
1921 impl<'a> PartialEq<&'a HeaderName> for HeaderName {
1922     #[inline]
eq(&self, other: &&'a HeaderName) -> bool1923     fn eq(&self, other: &&'a HeaderName) -> bool {
1924         *self == **other
1925     }
1926 }
1927 
1928 impl<'a> PartialEq<HeaderName> for &'a HeaderName {
1929     #[inline]
eq(&self, other: &HeaderName) -> bool1930     fn eq(&self, other: &HeaderName) -> bool {
1931         *other == *self
1932     }
1933 }
1934 
1935 impl PartialEq<str> for HeaderName {
1936     /// Performs a case-insensitive comparison of the string against the header
1937     /// name
1938     ///
1939     /// # Examples
1940     ///
1941     /// ```
1942     /// use http::header::CONTENT_LENGTH;
1943     ///
1944     /// assert_eq!(CONTENT_LENGTH, "content-length");
1945     /// assert_eq!(CONTENT_LENGTH, "Content-Length");
1946     /// assert_ne!(CONTENT_LENGTH, "content length");
1947     /// ```
1948     #[inline]
eq(&self, other: &str) -> bool1949     fn eq(&self, other: &str) -> bool {
1950         eq_ignore_ascii_case(self.as_ref(), other.as_bytes())
1951     }
1952 }
1953 
1954 impl PartialEq<HeaderName> for str {
1955     /// Performs a case-insensitive comparison of the string against the header
1956     /// name
1957     ///
1958     /// # Examples
1959     ///
1960     /// ```
1961     /// use http::header::CONTENT_LENGTH;
1962     ///
1963     /// assert_eq!(CONTENT_LENGTH, "content-length");
1964     /// assert_eq!(CONTENT_LENGTH, "Content-Length");
1965     /// assert_ne!(CONTENT_LENGTH, "content length");
1966     /// ```
1967     #[inline]
eq(&self, other: &HeaderName) -> bool1968     fn eq(&self, other: &HeaderName) -> bool {
1969         *other == *self
1970     }
1971 }
1972 
1973 impl<'a> PartialEq<&'a str> for HeaderName {
1974     /// Performs a case-insensitive comparison of the string against the header
1975     /// name
1976     #[inline]
eq(&self, other: &&'a str) -> bool1977     fn eq(&self, other: &&'a str) -> bool {
1978         *self == **other
1979     }
1980 }
1981 
1982 impl<'a> PartialEq<HeaderName> for &'a str {
1983     /// Performs a case-insensitive comparison of the string against the header
1984     /// name
1985     #[inline]
eq(&self, other: &HeaderName) -> bool1986     fn eq(&self, other: &HeaderName) -> bool {
1987         *other == *self
1988     }
1989 }
1990 
1991 impl fmt::Debug for InvalidHeaderName {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1992     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1993         f.debug_struct("InvalidHeaderName")
1994             // skip _priv noise
1995             .finish()
1996     }
1997 }
1998 
1999 impl fmt::Display for InvalidHeaderName {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2000     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2001         f.write_str("invalid HTTP header name")
2002     }
2003 }
2004 
2005 impl Error for InvalidHeaderName {}
2006 
2007 // ===== HdrName =====
2008 
2009 impl<'a> HdrName<'a> {
custom(buf: &'a [u8], lower: bool) -> HdrName<'a>2010     fn custom(buf: &'a [u8], lower: bool) -> HdrName<'a> {
2011         HdrName {
2012             inner: Repr::Custom(MaybeLower {
2013                 buf: buf,
2014                 lower: lower,
2015             }),
2016         }
2017     }
2018 
2019     #[allow(deprecated)]
from_bytes<F, U>(hdr: &[u8], f: F) -> Result<U, InvalidHeaderName> where F: FnOnce(HdrName<'_>) -> U,2020     pub fn from_bytes<F, U>(hdr: &[u8], f: F) -> Result<U, InvalidHeaderName>
2021         where F: FnOnce(HdrName<'_>) -> U,
2022     {
2023         #[allow(deprecated)]
2024         let mut buf = unsafe { mem::uninitialized() };
2025         let hdr = parse_hdr(hdr, &mut buf, &HEADER_CHARS)?;
2026         Ok(f(hdr))
2027     }
2028 
2029     #[allow(deprecated)]
from_static<F, U>(hdr: &'static str, f: F) -> U where F: FnOnce(HdrName<'_>) -> U,2030     pub fn from_static<F, U>(hdr: &'static str, f: F) -> U
2031     where
2032         F: FnOnce(HdrName<'_>) -> U,
2033     {
2034         #[allow(deprecated)]
2035         let mut buf = unsafe { mem::uninitialized() };
2036         let hdr =
2037             parse_hdr(hdr.as_bytes(), &mut buf, &HEADER_CHARS).expect("static str is invalid name");
2038         f(hdr)
2039     }
2040 }
2041 
2042 #[doc(hidden)]
2043 impl<'a> From<HdrName<'a>> for HeaderName {
from(src: HdrName<'a>) -> HeaderName2044     fn from(src: HdrName<'a>) -> HeaderName {
2045         match src.inner {
2046             Repr::Standard(s) => HeaderName {
2047                 inner: Repr::Standard(s),
2048             },
2049             Repr::Custom(maybe_lower) => {
2050                 if maybe_lower.lower {
2051                     let buf = Bytes::copy_from_slice(&maybe_lower.buf[..]);
2052                     let byte_str = unsafe { ByteStr::from_utf8_unchecked(buf) };
2053 
2054                     HeaderName {
2055                         inner: Repr::Custom(Custom(byte_str)),
2056                     }
2057                 } else {
2058                     use bytes::BufMut;
2059                     let mut dst = BytesMut::with_capacity(maybe_lower.buf.len());
2060 
2061                     for b in maybe_lower.buf.iter() {
2062                         dst.put_u8(HEADER_CHARS[*b as usize]);
2063                     }
2064 
2065                     let buf = unsafe { ByteStr::from_utf8_unchecked(dst.freeze()) };
2066 
2067                     HeaderName {
2068                         inner: Repr::Custom(Custom(buf)),
2069                     }
2070                 }
2071             }
2072         }
2073     }
2074 }
2075 
2076 #[doc(hidden)]
2077 impl<'a> PartialEq<HdrName<'a>> for HeaderName {
2078     #[inline]
eq(&self, other: &HdrName<'a>) -> bool2079     fn eq(&self, other: &HdrName<'a>) -> bool {
2080         match self.inner {
2081             Repr::Standard(a) => match other.inner {
2082                 Repr::Standard(b) => a == b,
2083                 _ => false,
2084             },
2085             Repr::Custom(Custom(ref a)) => match other.inner {
2086                 Repr::Custom(ref b) => {
2087                     if b.lower {
2088                         a.as_bytes() == b.buf
2089                     } else {
2090                         eq_ignore_ascii_case(a.as_bytes(), b.buf)
2091                     }
2092                 }
2093                 _ => false,
2094             },
2095         }
2096     }
2097 }
2098 
2099 // ===== Custom =====
2100 
2101 impl Hash for Custom {
2102     #[inline]
hash<H: Hasher>(&self, hasher: &mut H)2103     fn hash<H: Hasher>(&self, hasher: &mut H) {
2104         hasher.write(self.0.as_bytes())
2105     }
2106 }
2107 
2108 // ===== MaybeLower =====
2109 
2110 impl<'a> Hash for MaybeLower<'a> {
2111     #[inline]
hash<H: Hasher>(&self, hasher: &mut H)2112     fn hash<H: Hasher>(&self, hasher: &mut H) {
2113         if self.lower {
2114             hasher.write(self.buf);
2115         } else {
2116             for &b in self.buf {
2117                 hasher.write(&[HEADER_CHARS[b as usize]]);
2118             }
2119         }
2120     }
2121 }
2122 
2123 // Assumes that the left hand side is already lower case
2124 #[inline]
eq_ignore_ascii_case(lower: &[u8], s: &[u8]) -> bool2125 fn eq_ignore_ascii_case(lower: &[u8], s: &[u8]) -> bool {
2126     if lower.len() != s.len() {
2127         return false;
2128     }
2129 
2130     lower.iter().zip(s).all(|(a, b)| {
2131         *a == HEADER_CHARS[*b as usize]
2132     })
2133 }
2134 
2135 #[cfg(test)]
2136 mod tests {
2137     use super::*;
2138     use self::StandardHeader::Vary;
2139 
2140     #[test]
test_bounds()2141     fn test_bounds() {
2142         fn check_bounds<T: Sync + Send>() {}
2143         check_bounds::<HeaderName>();
2144     }
2145 
2146     #[test]
test_parse_invalid_headers()2147     fn test_parse_invalid_headers() {
2148         for i in 0..128 {
2149             let hdr = vec![1u8; i];
2150             assert!(HeaderName::from_bytes(&hdr).is_err(), "{} invalid header chars did not fail", i);
2151         }
2152     }
2153 
2154     #[test]
test_invalid_name_lengths()2155     fn test_invalid_name_lengths() {
2156         assert!(
2157             HeaderName::from_bytes(&[]).is_err(),
2158             "zero-length header name is an error",
2159         );
2160         let mut long = vec![b'a'; super::super::MAX_HEADER_NAME_LEN];
2161         assert!(
2162             HeaderName::from_bytes(long.as_slice()).is_ok(),
2163             "max header name length is ok",
2164         );
2165         long.push(b'a');
2166         assert!(
2167             HeaderName::from_bytes(long.as_slice()).is_err(),
2168             "longer than max header name length is an error",
2169         );
2170     }
2171 
2172     #[test]
test_from_hdr_name()2173     fn test_from_hdr_name() {
2174         use self::StandardHeader::Vary;
2175 
2176         let name = HeaderName::from(HdrName {
2177             inner: Repr::Standard(Vary),
2178         });
2179 
2180         assert_eq!(name.inner, Repr::Standard(Vary));
2181 
2182         let name = HeaderName::from(HdrName {
2183             inner: Repr::Custom(MaybeLower {
2184                 buf: b"hello-world",
2185                 lower: true,
2186             }),
2187         });
2188 
2189         assert_eq!(name.inner, Repr::Custom(Custom(ByteStr::from_static("hello-world"))));
2190 
2191         let name = HeaderName::from(HdrName {
2192             inner: Repr::Custom(MaybeLower {
2193                 buf: b"Hello-World",
2194                 lower: false,
2195             }),
2196         });
2197 
2198         assert_eq!(name.inner, Repr::Custom(Custom(ByteStr::from_static("hello-world"))));
2199     }
2200 
2201     #[test]
test_eq_hdr_name()2202     fn test_eq_hdr_name() {
2203         use self::StandardHeader::Vary;
2204 
2205         let a = HeaderName { inner: Repr::Standard(Vary) };
2206         let b = HdrName { inner: Repr::Standard(Vary) };
2207 
2208         assert_eq!(a, b);
2209 
2210         let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static("vaary"))) };
2211         assert_ne!(a, b);
2212 
2213         let b = HdrName { inner: Repr::Custom(MaybeLower {
2214             buf: b"vaary",
2215             lower: true,
2216         })};
2217 
2218         assert_eq!(a, b);
2219 
2220         let b = HdrName { inner: Repr::Custom(MaybeLower {
2221             buf: b"vaary",
2222             lower: false,
2223         })};
2224 
2225         assert_eq!(a, b);
2226 
2227         let b = HdrName { inner: Repr::Custom(MaybeLower {
2228             buf: b"VAARY",
2229             lower: false,
2230         })};
2231 
2232         assert_eq!(a, b);
2233 
2234         let a = HeaderName { inner: Repr::Standard(Vary) };
2235         assert_ne!(a, b);
2236     }
2237 
2238     #[test]
test_from_static_std()2239     fn test_from_static_std() {
2240         let a = HeaderName { inner: Repr::Standard(Vary) };
2241 
2242         let b = HeaderName::from_static("vary");
2243         assert_eq!(a, b);
2244 
2245         let b = HeaderName::from_static("vaary");
2246         assert_ne!(a, b);
2247     }
2248 
2249     #[test]
2250     #[should_panic]
test_from_static_std_uppercase()2251     fn test_from_static_std_uppercase() {
2252         HeaderName::from_static("Vary");
2253     }
2254 
2255     #[test]
2256     #[should_panic]
test_from_static_std_symbol()2257     fn test_from_static_std_symbol() {
2258         HeaderName::from_static("vary{}");
2259     }
2260 
2261     // MaybeLower { lower: true }
2262     #[test]
test_from_static_custom_short()2263     fn test_from_static_custom_short() {
2264         let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static("customheader"))) };
2265         let b = HeaderName::from_static("customheader");
2266         assert_eq!(a, b);
2267     }
2268 
2269     #[test]
2270     #[should_panic]
test_from_static_custom_short_uppercase()2271     fn test_from_static_custom_short_uppercase() {
2272         HeaderName::from_static("custom header");
2273     }
2274 
2275     #[test]
2276     #[should_panic]
test_from_static_custom_short_symbol()2277     fn test_from_static_custom_short_symbol() {
2278         HeaderName::from_static("CustomHeader");
2279     }
2280 
2281     // MaybeLower { lower: false }
2282     #[test]
test_from_static_custom_long()2283     fn test_from_static_custom_long() {
2284         let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static(
2285             "longer-than-63--thisheaderislongerthansixtythreecharactersandthushandleddifferent"
2286         ))) };
2287         let b = HeaderName::from_static(
2288             "longer-than-63--thisheaderislongerthansixtythreecharactersandthushandleddifferent"
2289         );
2290         assert_eq!(a, b);
2291     }
2292 
2293     #[test]
2294     #[should_panic]
test_from_static_custom_long_uppercase()2295     fn test_from_static_custom_long_uppercase() {
2296         HeaderName::from_static(
2297             "Longer-Than-63--ThisHeaderIsLongerThanSixtyThreeCharactersAndThusHandledDifferent"
2298         );
2299     }
2300 
2301     #[test]
2302     #[should_panic]
test_from_static_custom_long_symbol()2303     fn test_from_static_custom_long_symbol() {
2304         HeaderName::from_static(
2305             "longer-than-63--thisheader{}{}{}{}islongerthansixtythreecharactersandthushandleddifferent"
2306         );
2307     }
2308 
2309     #[test]
test_from_static_custom_single_char()2310     fn test_from_static_custom_single_char() {
2311         let a = HeaderName { inner: Repr::Custom(Custom(ByteStr::from_static("a"))) };
2312         let b = HeaderName::from_static("a");
2313         assert_eq!(a, b);
2314     }
2315 
2316     #[test]
2317     #[should_panic]
test_from_static_empty()2318     fn test_from_static_empty() {
2319         HeaderName::from_static("");
2320     }
2321 
2322     #[test]
test_all_tokens()2323     fn test_all_tokens() {
2324         HeaderName::from_static("!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyz");
2325     }
2326 }
2327