1 use bytes::{Bytes, BytesMut};
2 
3 use std::convert::TryFrom;
4 use std::error::Error;
5 use std::fmt::Write;
6 use std::str::FromStr;
7 use std::{cmp, fmt, mem, str};
8 
9 use crate::header::name::HeaderName;
10 
11 /// Represents an HTTP header field value.
12 ///
13 /// In practice, HTTP header field values are usually valid ASCII. However, the
14 /// HTTP spec allows for a header value to contain opaque bytes as well. In this
15 /// case, the header field value is not able to be represented as a string.
16 ///
17 /// To handle this, the `HeaderValue` is useable as a type and can be compared
18 /// with strings and implements `Debug`. A `to_str` fn is provided that returns
19 /// an `Err` if the header value contains non visible ascii characters.
20 #[derive(Clone, Hash)]
21 pub struct HeaderValue {
22     inner: Bytes,
23     is_sensitive: bool,
24 }
25 
26 /// A possible error when converting a `HeaderValue` from a string or byte
27 /// slice.
28 pub struct InvalidHeaderValue {
29     _priv: (),
30 }
31 
32 /// A possible error when converting a `HeaderValue` to a string representation.
33 ///
34 /// Header field values may contain opaque bytes, in which case it is not
35 /// possible to represent the value as a string.
36 #[derive(Debug)]
37 pub struct ToStrError {
38     _priv: (),
39 }
40 
41 impl HeaderValue {
42     /// Convert a static string to a `HeaderValue`.
43     ///
44     /// This function will not perform any copying, however the string is
45     /// checked to ensure that no invalid characters are present. Only visible
46     /// ASCII characters (32-127) are permitted.
47     ///
48     /// # Panics
49     ///
50     /// This function panics if the argument contains invalid header value
51     /// characters.
52     ///
53     /// Until [Allow panicking in constants](https://github.com/rust-lang/rfcs/pull/2345)
54     /// makes its way into stable, the panic message at compile-time is
55     /// going to look cryptic, but should at least point at your header value:
56     ///
57     /// ```text
58     /// error: any use of this value will cause an error
59     ///   --> http/src/header/value.rs:67:17
60     ///    |
61     /// 67 |                 ([] as [u8; 0])[0]; // Invalid header value
62     ///    |                 ^^^^^^^^^^^^^^^^^^
63     ///    |                 |
64     ///    |                 index out of bounds: the length is 0 but the index is 0
65     ///    |                 inside `HeaderValue::from_static` at http/src/header/value.rs:67:17
66     ///    |                 inside `INVALID_HEADER` at src/main.rs:73:33
67     ///    |
68     ///   ::: src/main.rs:73:1
69     ///    |
70     /// 73 | const INVALID_HEADER: HeaderValue = HeaderValue::from_static("жsome value");
71     ///    | ----------------------------------------------------------------------------
72     /// ```
73     ///
74     /// # Examples
75     ///
76     /// ```
77     /// # use http::header::HeaderValue;
78     /// let val = HeaderValue::from_static("hello");
79     /// assert_eq!(val, "hello");
80     /// ```
81     #[inline]
82     #[allow(unconditional_panic)] // required for the panic circumvention
from_static(src: &'static str) -> HeaderValue83     pub const fn from_static(src: &'static str) -> HeaderValue {
84         let bytes = src.as_bytes();
85         let mut i = 0;
86         while i < bytes.len() {
87             if !is_visible_ascii(bytes[i]) {
88                 ([] as [u8; 0])[0]; // Invalid header value
89             }
90             i += 1;
91         }
92 
93         HeaderValue {
94             inner: Bytes::from_static(bytes),
95             is_sensitive: false,
96         }
97     }
98 
99     /// Attempt to convert a string to a `HeaderValue`.
100     ///
101     /// If the argument contains invalid header value characters, an error is
102     /// returned. Only visible ASCII characters (32-127) are permitted. Use
103     /// `from_bytes` to create a `HeaderValue` that includes opaque octets
104     /// (128-255).
105     ///
106     /// This function is intended to be replaced in the future by a `TryFrom`
107     /// implementation once the trait is stabilized in std.
108     ///
109     /// # Examples
110     ///
111     /// ```
112     /// # use http::header::HeaderValue;
113     /// let val = HeaderValue::from_str("hello").unwrap();
114     /// assert_eq!(val, "hello");
115     /// ```
116     ///
117     /// An invalid value
118     ///
119     /// ```
120     /// # use http::header::HeaderValue;
121     /// let val = HeaderValue::from_str("\n");
122     /// assert!(val.is_err());
123     /// ```
124     #[inline]
from_str(src: &str) -> Result<HeaderValue, InvalidHeaderValue>125     pub fn from_str(src: &str) -> Result<HeaderValue, InvalidHeaderValue> {
126         HeaderValue::try_from_generic(src, |s| Bytes::copy_from_slice(s.as_bytes()))
127     }
128 
129     /// Converts a HeaderName into a HeaderValue
130     ///
131     /// Since every valid HeaderName is a valid HeaderValue this is done infallibly.
132     ///
133     /// # Examples
134     ///
135     /// ```
136     /// # use http::header::{HeaderValue, HeaderName};
137     /// # use http::header::ACCEPT;
138     /// let val = HeaderValue::from_name(ACCEPT);
139     /// assert_eq!(val, HeaderValue::from_bytes(b"accept").unwrap());
140     /// ```
141     #[inline]
from_name(name: HeaderName) -> HeaderValue142     pub fn from_name(name: HeaderName) -> HeaderValue {
143         name.into()
144     }
145 
146     /// Attempt to convert a byte slice to a `HeaderValue`.
147     ///
148     /// If the argument contains invalid header value bytes, an error is
149     /// returned. Only byte values between 32 and 255 (inclusive) are permitted,
150     /// excluding byte 127 (DEL).
151     ///
152     /// This function is intended to be replaced in the future by a `TryFrom`
153     /// implementation once the trait is stabilized in std.
154     ///
155     /// # Examples
156     ///
157     /// ```
158     /// # use http::header::HeaderValue;
159     /// let val = HeaderValue::from_bytes(b"hello\xfa").unwrap();
160     /// assert_eq!(val, &b"hello\xfa"[..]);
161     /// ```
162     ///
163     /// An invalid value
164     ///
165     /// ```
166     /// # use http::header::HeaderValue;
167     /// let val = HeaderValue::from_bytes(b"\n");
168     /// assert!(val.is_err());
169     /// ```
170     #[inline]
from_bytes(src: &[u8]) -> Result<HeaderValue, InvalidHeaderValue>171     pub fn from_bytes(src: &[u8]) -> Result<HeaderValue, InvalidHeaderValue> {
172         HeaderValue::try_from_generic(src, Bytes::copy_from_slice)
173     }
174 
175     /// Attempt to convert a `Bytes` buffer to a `HeaderValue`.
176     ///
177     /// This will try to prevent a copy if the type passed is the type used
178     /// internally, and will copy the data if it is not.
from_maybe_shared<T>(src: T) -> Result<HeaderValue, InvalidHeaderValue> where T: AsRef<[u8]> + 'static,179     pub fn from_maybe_shared<T>(src: T) -> Result<HeaderValue, InvalidHeaderValue>
180     where
181         T: AsRef<[u8]> + 'static,
182     {
183         if_downcast_into!(T, Bytes, src, {
184             return HeaderValue::from_shared(src);
185         });
186 
187         HeaderValue::from_bytes(src.as_ref())
188     }
189 
190     /// Convert a `Bytes` directly into a `HeaderValue` without validating.
191     ///
192     /// This function does NOT validate that illegal bytes are not contained
193     /// within the buffer.
from_maybe_shared_unchecked<T>(src: T) -> HeaderValue where T: AsRef<[u8]> + 'static,194     pub unsafe fn from_maybe_shared_unchecked<T>(src: T) -> HeaderValue
195     where
196         T: AsRef<[u8]> + 'static,
197     {
198         if cfg!(debug_assertions) {
199             match HeaderValue::from_maybe_shared(src) {
200                 Ok(val) => val,
201                 Err(_err) => {
202                     panic!("HeaderValue::from_maybe_shared_unchecked() with invalid bytes");
203                 }
204             }
205         } else {
206 
207             if_downcast_into!(T, Bytes, src, {
208                 return HeaderValue {
209                     inner: src,
210                     is_sensitive: false,
211                 };
212             });
213 
214             let src = Bytes::copy_from_slice(src.as_ref());
215             HeaderValue {
216                 inner: src,
217                 is_sensitive: false,
218             }
219         }
220     }
221 
from_shared(src: Bytes) -> Result<HeaderValue, InvalidHeaderValue>222     fn from_shared(src: Bytes) -> Result<HeaderValue, InvalidHeaderValue> {
223         HeaderValue::try_from_generic(src, std::convert::identity)
224     }
225 
try_from_generic<T: AsRef<[u8]>, F: FnOnce(T) -> Bytes>(src: T, into: F) -> Result<HeaderValue, InvalidHeaderValue>226     fn try_from_generic<T: AsRef<[u8]>, F: FnOnce(T) -> Bytes>(src: T, into: F) -> Result<HeaderValue, InvalidHeaderValue> {
227         for &b in src.as_ref() {
228             if !is_valid(b) {
229                 return Err(InvalidHeaderValue { _priv: () });
230             }
231         }
232         Ok(HeaderValue {
233             inner: into(src),
234             is_sensitive: false,
235         })
236     }
237 
238     /// Yields a `&str` slice if the `HeaderValue` only contains visible ASCII
239     /// chars.
240     ///
241     /// This function will perform a scan of the header value, checking all the
242     /// characters.
243     ///
244     /// # Examples
245     ///
246     /// ```
247     /// # use http::header::HeaderValue;
248     /// let val = HeaderValue::from_static("hello");
249     /// assert_eq!(val.to_str().unwrap(), "hello");
250     /// ```
to_str(&self) -> Result<&str, ToStrError>251     pub fn to_str(&self) -> Result<&str, ToStrError> {
252         let bytes = self.as_ref();
253 
254         for &b in bytes {
255             if !is_visible_ascii(b) {
256                 return Err(ToStrError { _priv: () });
257             }
258         }
259 
260         unsafe { Ok(str::from_utf8_unchecked(bytes)) }
261     }
262 
263     /// Returns the length of `self`.
264     ///
265     /// This length is in bytes.
266     ///
267     /// # Examples
268     ///
269     /// ```
270     /// # use http::header::HeaderValue;
271     /// let val = HeaderValue::from_static("hello");
272     /// assert_eq!(val.len(), 5);
273     /// ```
274     #[inline]
len(&self) -> usize275     pub fn len(&self) -> usize {
276         self.as_ref().len()
277     }
278 
279     /// Returns true if the `HeaderValue` has a length of zero bytes.
280     ///
281     /// # Examples
282     ///
283     /// ```
284     /// # use http::header::HeaderValue;
285     /// let val = HeaderValue::from_static("");
286     /// assert!(val.is_empty());
287     ///
288     /// let val = HeaderValue::from_static("hello");
289     /// assert!(!val.is_empty());
290     /// ```
291     #[inline]
is_empty(&self) -> bool292     pub fn is_empty(&self) -> bool {
293         self.len() == 0
294     }
295 
296     /// Converts a `HeaderValue` to a byte slice.
297     ///
298     /// # Examples
299     ///
300     /// ```
301     /// # use http::header::HeaderValue;
302     /// let val = HeaderValue::from_static("hello");
303     /// assert_eq!(val.as_bytes(), b"hello");
304     /// ```
305     #[inline]
as_bytes(&self) -> &[u8]306     pub fn as_bytes(&self) -> &[u8] {
307         self.as_ref()
308     }
309 
310     /// Mark that the header value represents sensitive information.
311     ///
312     /// # Examples
313     ///
314     /// ```
315     /// # use http::header::HeaderValue;
316     /// let mut val = HeaderValue::from_static("my secret");
317     ///
318     /// val.set_sensitive(true);
319     /// assert!(val.is_sensitive());
320     ///
321     /// val.set_sensitive(false);
322     /// assert!(!val.is_sensitive());
323     /// ```
324     #[inline]
set_sensitive(&mut self, val: bool)325     pub fn set_sensitive(&mut self, val: bool) {
326         self.is_sensitive = val;
327     }
328 
329     /// Returns `true` if the value represents sensitive data.
330     ///
331     /// Sensitive data could represent passwords or other data that should not
332     /// be stored on disk or in memory. By marking header values as sensitive,
333     /// components using this crate can be instructed to treat them with special
334     /// care for security reasons. For example, caches can avoid storing
335     /// sensitive values, and HPACK encoders used by HTTP/2.0 implementations
336     /// can choose not to compress them.
337     ///
338     /// Additionally, sensitive values will be masked by the `Debug`
339     /// implementation of `HeaderValue`.
340     ///
341     /// Note that sensitivity is not factored into equality or ordering.
342     ///
343     /// # Examples
344     ///
345     /// ```
346     /// # use http::header::HeaderValue;
347     /// let mut val = HeaderValue::from_static("my secret");
348     ///
349     /// val.set_sensitive(true);
350     /// assert!(val.is_sensitive());
351     ///
352     /// val.set_sensitive(false);
353     /// assert!(!val.is_sensitive());
354     /// ```
355     #[inline]
is_sensitive(&self) -> bool356     pub fn is_sensitive(&self) -> bool {
357         self.is_sensitive
358     }
359 }
360 
361 impl AsRef<[u8]> for HeaderValue {
362     #[inline]
as_ref(&self) -> &[u8]363     fn as_ref(&self) -> &[u8] {
364         self.inner.as_ref()
365     }
366 }
367 
368 impl fmt::Debug for HeaderValue {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result369     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370         if self.is_sensitive {
371             f.write_str("Sensitive")
372         } else {
373             f.write_str("\"")?;
374             let mut from = 0;
375             let bytes = self.as_bytes();
376             for (i, &b) in bytes.iter().enumerate() {
377                 if !is_visible_ascii(b) || b == b'"' {
378                     if from != i {
379                         f.write_str(unsafe { str::from_utf8_unchecked(&bytes[from..i]) })?;
380                     }
381                     if b == b'"' {
382                         f.write_str("\\\"")?;
383                     } else {
384                         write!(f, "\\x{:x}", b)?;
385                     }
386                     from = i + 1;
387                 }
388             }
389 
390             f.write_str(unsafe { str::from_utf8_unchecked(&bytes[from..]) })?;
391             f.write_str("\"")
392         }
393     }
394 }
395 
396 impl From<HeaderName> for HeaderValue {
397     #[inline]
from(h: HeaderName) -> HeaderValue398     fn from(h: HeaderName) -> HeaderValue {
399         HeaderValue {
400             inner: h.into_bytes(),
401             is_sensitive: false,
402         }
403     }
404 }
405 
406 macro_rules! from_integers {
407     ($($name:ident: $t:ident => $max_len:expr),*) => {$(
408         impl From<$t> for HeaderValue {
409             fn from(num: $t) -> HeaderValue {
410                 let mut buf = if mem::size_of::<BytesMut>() - 1 < $max_len {
411                     // On 32bit platforms, BytesMut max inline size
412                     // is 15 bytes, but the $max_len could be bigger.
413                     //
414                     // The likelihood of the number *actually* being
415                     // that big is very small, so only allocate
416                     // if the number needs that space.
417                     //
418                     // The largest decimal number in 15 digits:
419                     // It wold be 10.pow(15) - 1, but this is a constant
420                     // version.
421                     if num as u64 > 999_999_999_999_999_999 {
422                         BytesMut::with_capacity($max_len)
423                     } else {
424                         // fits inline...
425                         BytesMut::new()
426                     }
427                 } else {
428                     // full value fits inline, so don't allocate!
429                     BytesMut::new()
430                 };
431                 let _ = buf.write_str(::itoa::Buffer::new().format(num));
432                 HeaderValue {
433                     inner: buf.freeze(),
434                     is_sensitive: false,
435                 }
436             }
437         }
438 
439         #[test]
440         fn $name() {
441             let n: $t = 55;
442             let val = HeaderValue::from(n);
443             assert_eq!(val, &n.to_string());
444 
445             let n = ::std::$t::MAX;
446             let val = HeaderValue::from(n);
447             assert_eq!(val, &n.to_string());
448         }
449     )*};
450 }
451 
452 from_integers! {
453     // integer type => maximum decimal length
454 
455     // u8 purposely left off... HeaderValue::from(b'3') could be confusing
456     from_u16: u16 => 5,
457     from_i16: i16 => 6,
458     from_u32: u32 => 10,
459     from_i32: i32 => 11,
460     from_u64: u64 => 20,
461     from_i64: i64 => 20
462 }
463 
464 #[cfg(target_pointer_width = "16")]
465 from_integers! {
466     from_usize: usize => 5,
467     from_isize: isize => 6
468 }
469 
470 #[cfg(target_pointer_width = "32")]
471 from_integers! {
472     from_usize: usize => 10,
473     from_isize: isize => 11
474 }
475 
476 #[cfg(target_pointer_width = "64")]
477 from_integers! {
478     from_usize: usize => 20,
479     from_isize: isize => 20
480 }
481 
482 #[cfg(test)]
483 mod from_header_name_tests {
484     use super::*;
485     use crate::header::map::HeaderMap;
486     use crate::header::name;
487 
488     #[test]
it_can_insert_header_name_as_header_value()489     fn it_can_insert_header_name_as_header_value() {
490         let mut map = HeaderMap::new();
491         map.insert(name::UPGRADE, name::SEC_WEBSOCKET_PROTOCOL.into());
492         map.insert(
493             name::ACCEPT,
494             name::HeaderName::from_bytes(b"hello-world").unwrap().into(),
495         );
496 
497         assert_eq!(
498             map.get(name::UPGRADE).unwrap(),
499             HeaderValue::from_bytes(b"sec-websocket-protocol").unwrap()
500         );
501 
502         assert_eq!(
503             map.get(name::ACCEPT).unwrap(),
504             HeaderValue::from_bytes(b"hello-world").unwrap()
505         );
506     }
507 }
508 
509 impl FromStr for HeaderValue {
510     type Err = InvalidHeaderValue;
511 
512     #[inline]
from_str(s: &str) -> Result<HeaderValue, Self::Err>513     fn from_str(s: &str) -> Result<HeaderValue, Self::Err> {
514         HeaderValue::from_str(s)
515     }
516 }
517 
518 impl<'a> From<&'a HeaderValue> for HeaderValue {
519     #[inline]
from(t: &'a HeaderValue) -> Self520     fn from(t: &'a HeaderValue) -> Self {
521         t.clone()
522     }
523 }
524 
525 impl<'a> TryFrom<&'a str> for HeaderValue {
526     type Error = InvalidHeaderValue;
527 
528     #[inline]
try_from(t: &'a str) -> Result<Self, Self::Error>529     fn try_from(t: &'a str) -> Result<Self, Self::Error> {
530         t.parse()
531     }
532 }
533 
534 impl<'a> TryFrom<&'a String> for HeaderValue {
535     type Error = InvalidHeaderValue;
536     #[inline]
try_from(s: &'a String) -> Result<Self, Self::Error>537     fn try_from(s: &'a String) -> Result<Self, Self::Error> {
538         Self::from_bytes(s.as_bytes())
539     }
540 }
541 
542 impl<'a> TryFrom<&'a [u8]> for HeaderValue {
543     type Error = InvalidHeaderValue;
544 
545     #[inline]
try_from(t: &'a [u8]) -> Result<Self, Self::Error>546     fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
547         HeaderValue::from_bytes(t)
548     }
549 }
550 
551 impl TryFrom<String> for HeaderValue {
552     type Error = InvalidHeaderValue;
553 
554     #[inline]
try_from(t: String) -> Result<Self, Self::Error>555     fn try_from(t: String) -> Result<Self, Self::Error> {
556         HeaderValue::from_shared(t.into())
557     }
558 }
559 
560 impl TryFrom<Vec<u8>> for HeaderValue {
561     type Error = InvalidHeaderValue;
562 
563     #[inline]
try_from(vec: Vec<u8>) -> Result<Self, Self::Error>564     fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
565         HeaderValue::from_shared(vec.into())
566     }
567 }
568 
569 #[cfg(test)]
570 mod try_from_header_name_tests {
571     use super::*;
572     use crate::header::name;
573 
574     #[test]
it_converts_using_try_from()575     fn it_converts_using_try_from() {
576         assert_eq!(
577             HeaderValue::try_from(name::UPGRADE).unwrap(),
578             HeaderValue::from_bytes(b"upgrade").unwrap()
579         );
580     }
581 }
582 
is_visible_ascii(b: u8) -> bool583 const fn is_visible_ascii(b: u8) -> bool {
584     b >= 32 && b < 127 || b == b'\t'
585 }
586 
587 #[inline]
is_valid(b: u8) -> bool588 fn is_valid(b: u8) -> bool {
589     b >= 32 && b != 127 || b == b'\t'
590 }
591 
592 impl fmt::Debug for InvalidHeaderValue {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result593     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
594         f.debug_struct("InvalidHeaderValue")
595             // skip _priv noise
596             .finish()
597     }
598 }
599 
600 impl fmt::Display for InvalidHeaderValue {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result601     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
602         f.write_str("failed to parse header value")
603     }
604 }
605 
606 impl Error for InvalidHeaderValue {}
607 
608 impl fmt::Display for ToStrError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result609     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
610         f.write_str("failed to convert header to a str")
611     }
612 }
613 
614 impl Error for ToStrError {}
615 
616 // ===== PartialEq / PartialOrd =====
617 
618 impl PartialEq for HeaderValue {
619     #[inline]
eq(&self, other: &HeaderValue) -> bool620     fn eq(&self, other: &HeaderValue) -> bool {
621         self.inner == other.inner
622     }
623 }
624 
625 impl Eq for HeaderValue {}
626 
627 impl PartialOrd for HeaderValue {
628     #[inline]
partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering>629     fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
630         self.inner.partial_cmp(&other.inner)
631     }
632 }
633 
634 impl Ord for HeaderValue {
635     #[inline]
cmp(&self, other: &Self) -> cmp::Ordering636     fn cmp(&self, other: &Self) -> cmp::Ordering {
637         self.inner.cmp(&other.inner)
638     }
639 }
640 
641 impl PartialEq<str> for HeaderValue {
642     #[inline]
eq(&self, other: &str) -> bool643     fn eq(&self, other: &str) -> bool {
644         self.inner == other.as_bytes()
645     }
646 }
647 
648 impl PartialEq<[u8]> for HeaderValue {
649     #[inline]
eq(&self, other: &[u8]) -> bool650     fn eq(&self, other: &[u8]) -> bool {
651         self.inner == other
652     }
653 }
654 
655 impl PartialOrd<str> for HeaderValue {
656     #[inline]
partial_cmp(&self, other: &str) -> Option<cmp::Ordering>657     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
658         (*self.inner).partial_cmp(other.as_bytes())
659     }
660 }
661 
662 impl PartialOrd<[u8]> for HeaderValue {
663     #[inline]
partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering>664     fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
665         (*self.inner).partial_cmp(other)
666     }
667 }
668 
669 impl PartialEq<HeaderValue> for str {
670     #[inline]
eq(&self, other: &HeaderValue) -> bool671     fn eq(&self, other: &HeaderValue) -> bool {
672         *other == *self
673     }
674 }
675 
676 impl PartialEq<HeaderValue> for [u8] {
677     #[inline]
eq(&self, other: &HeaderValue) -> bool678     fn eq(&self, other: &HeaderValue) -> bool {
679         *other == *self
680     }
681 }
682 
683 impl PartialOrd<HeaderValue> for str {
684     #[inline]
partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering>685     fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
686         self.as_bytes().partial_cmp(other.as_bytes())
687     }
688 }
689 
690 impl PartialOrd<HeaderValue> for [u8] {
691     #[inline]
partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering>692     fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
693         self.partial_cmp(other.as_bytes())
694     }
695 }
696 
697 impl PartialEq<String> for HeaderValue {
698     #[inline]
eq(&self, other: &String) -> bool699     fn eq(&self, other: &String) -> bool {
700         *self == &other[..]
701     }
702 }
703 
704 impl PartialOrd<String> for HeaderValue {
705     #[inline]
partial_cmp(&self, other: &String) -> Option<cmp::Ordering>706     fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
707         self.inner.partial_cmp(other.as_bytes())
708     }
709 }
710 
711 impl PartialEq<HeaderValue> for String {
712     #[inline]
eq(&self, other: &HeaderValue) -> bool713     fn eq(&self, other: &HeaderValue) -> bool {
714         *other == *self
715     }
716 }
717 
718 impl PartialOrd<HeaderValue> for String {
719     #[inline]
partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering>720     fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
721         self.as_bytes().partial_cmp(other.as_bytes())
722     }
723 }
724 
725 impl<'a> PartialEq<HeaderValue> for &'a HeaderValue {
726     #[inline]
eq(&self, other: &HeaderValue) -> bool727     fn eq(&self, other: &HeaderValue) -> bool {
728         **self == *other
729     }
730 }
731 
732 impl<'a> PartialOrd<HeaderValue> for &'a HeaderValue {
733     #[inline]
partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering>734     fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
735         (**self).partial_cmp(other)
736     }
737 }
738 
739 impl<'a, T: ?Sized> PartialEq<&'a T> for HeaderValue
740 where
741     HeaderValue: PartialEq<T>,
742 {
743     #[inline]
eq(&self, other: &&'a T) -> bool744     fn eq(&self, other: &&'a T) -> bool {
745         *self == **other
746     }
747 }
748 
749 impl<'a, T: ?Sized> PartialOrd<&'a T> for HeaderValue
750 where
751     HeaderValue: PartialOrd<T>,
752 {
753     #[inline]
partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering>754     fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
755         self.partial_cmp(*other)
756     }
757 }
758 
759 impl<'a> PartialEq<HeaderValue> for &'a str {
760     #[inline]
eq(&self, other: &HeaderValue) -> bool761     fn eq(&self, other: &HeaderValue) -> bool {
762         *other == *self
763     }
764 }
765 
766 impl<'a> PartialOrd<HeaderValue> for &'a str {
767     #[inline]
partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering>768     fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
769         self.as_bytes().partial_cmp(other.as_bytes())
770     }
771 }
772 
773 #[test]
test_try_from()774 fn test_try_from() {
775     HeaderValue::try_from(vec![127]).unwrap_err();
776 }
777 
778 #[test]
test_debug()779 fn test_debug() {
780     let cases = &[
781         ("hello", "\"hello\""),
782         ("hello \"world\"", "\"hello \\\"world\\\"\""),
783         ("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""),
784     ];
785 
786     for &(value, expected) in cases {
787         let val = HeaderValue::from_bytes(value.as_bytes()).unwrap();
788         let actual = format!("{:?}", val);
789         assert_eq!(expected, actual);
790     }
791 
792     let mut sensitive = HeaderValue::from_static("password");
793     sensitive.set_sensitive(true);
794     assert_eq!("Sensitive", format!("{:?}", sensitive));
795 }
796