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