Coverage Report

Created: 2025-10-13 06:32

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