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