Coverage Report

Created: 2025-12-31 06:49

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