mirror of
https://github.com/openharmony/third_party_rust_http.git
synced 2026-07-19 22:53:59 -04:00
806 lines
21 KiB
Rust
806 lines
21 KiB
Rust
use bytes::{Bytes, BytesMut};
|
|
|
|
use std::{cmp, fmt, mem, str};
|
|
use std::error::Error;
|
|
use std::str::FromStr;
|
|
|
|
use ::convert::HttpTryFrom;
|
|
use ::error::Never;
|
|
use header::name::HeaderName;
|
|
|
|
/// Represents an HTTP header field value.
|
|
///
|
|
/// In practice, HTTP header field values are usually valid ASCII. However, the
|
|
/// HTTP spec allows for a header value to contain opaque bytes as well. In this
|
|
/// case, the header field value is not able to be represented as a string.
|
|
///
|
|
/// To handle this, the `HeaderValue` is useable as a type and can be compared
|
|
/// with strings and implements `Debug`. A `to_str` fn is provided that returns
|
|
/// an `Err` if the header value contains non visible ascii characters.
|
|
#[derive(Clone, Hash)]
|
|
pub struct HeaderValue {
|
|
inner: Bytes,
|
|
is_sensitive: bool,
|
|
}
|
|
|
|
/// A possible error when converting a `HeaderValue` from a string or byte
|
|
/// slice.
|
|
#[derive(Debug)]
|
|
pub struct InvalidHeaderValue {
|
|
_priv: (),
|
|
}
|
|
|
|
/// A possible error when converting a `HeaderValue` from a string or byte
|
|
/// slice.
|
|
#[derive(Debug)]
|
|
pub struct InvalidHeaderValueBytes(InvalidHeaderValue);
|
|
|
|
/// A possible error when converting a `HeaderValue` to a string representation.
|
|
///
|
|
/// Header field values may contain opaque bytes, in which case it is not
|
|
/// possible to represent the value as a string.
|
|
#[derive(Debug)]
|
|
pub struct ToStrError {
|
|
_priv: (),
|
|
}
|
|
|
|
impl HeaderValue {
|
|
/// Convert a static string to a `HeaderValue`.
|
|
///
|
|
/// This function will not perform any copying, however the string is
|
|
/// checked to ensure that no invalid characters are present. Only visible
|
|
/// ASCII characters (32-127) are permitted.
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// This function panics if the argument contains invalid header value
|
|
/// characters.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_static("hello");
|
|
/// assert_eq!(val, "hello");
|
|
/// ```
|
|
#[inline]
|
|
pub fn from_static(src: &'static str) -> HeaderValue {
|
|
let bytes = src.as_bytes();
|
|
for &b in bytes {
|
|
if !is_visible_ascii(b) {
|
|
panic!("invalid header value");
|
|
}
|
|
}
|
|
|
|
HeaderValue {
|
|
inner: Bytes::from_static(bytes),
|
|
is_sensitive: false,
|
|
}
|
|
}
|
|
|
|
/// Attempt to convert a string to a `HeaderValue`.
|
|
///
|
|
/// If the argument contains invalid header value characters, an error is
|
|
/// returned. Only visible ASCII characters (32-127) are permitted. Use
|
|
/// `from_bytes` to create a `HeaderValue` that includes opaque octets
|
|
/// (128-255).
|
|
///
|
|
/// This function is intended to be replaced in the future by a `TryFrom`
|
|
/// implementation once the trait is stabilized in std.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_str("hello").unwrap();
|
|
/// assert_eq!(val, "hello");
|
|
/// ```
|
|
///
|
|
/// An invalid value
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_str("\n");
|
|
/// assert!(val.is_err());
|
|
/// ```
|
|
#[inline]
|
|
pub fn from_str(src: &str) -> Result<HeaderValue, InvalidHeaderValue> {
|
|
HeaderValue::try_from(src)
|
|
}
|
|
|
|
/// Converts a HeaderName into a HeaderValue
|
|
///
|
|
/// Since every valid HeaderName is a valid HeaderValue this is done infallibly.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::{HeaderValue, HeaderName};
|
|
/// # use http::header::ACCEPT;
|
|
/// let val = HeaderValue::from_name(ACCEPT);
|
|
/// assert_eq!(val, HeaderValue::from_bytes(b"accept").unwrap());
|
|
/// ```
|
|
#[inline]
|
|
pub fn from_name(name: HeaderName) -> HeaderValue {
|
|
name.into()
|
|
}
|
|
|
|
/// Attempt to convert a byte slice to a `HeaderValue`.
|
|
///
|
|
/// If the argument contains invalid header value bytes, an error is
|
|
/// returned. Only byte values between 32 and 255 (inclusive) are permitted,
|
|
/// excluding byte 127 (DEL).
|
|
///
|
|
/// This function is intended to be replaced in the future by a `TryFrom`
|
|
/// implementation once the trait is stabilized in std.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_bytes(b"hello\xfa").unwrap();
|
|
/// assert_eq!(val, &b"hello\xfa"[..]);
|
|
/// ```
|
|
///
|
|
/// An invalid value
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_bytes(b"\n");
|
|
/// assert!(val.is_err());
|
|
/// ```
|
|
#[inline]
|
|
pub fn from_bytes(src: &[u8]) -> Result<HeaderValue, InvalidHeaderValue> {
|
|
HeaderValue::try_from(src)
|
|
}
|
|
|
|
/// Attempt to convert a `Bytes` buffer to a `HeaderValue`.
|
|
///
|
|
/// If the argument contains invalid header value bytes, an error is
|
|
/// returned. Only byte values between 32 and 255 (inclusive) are permitted,
|
|
/// excluding byte 127 (DEL).
|
|
///
|
|
/// This function is intended to be replaced in the future by a `TryFrom`
|
|
/// implementation once the trait is stabilized in std.
|
|
#[inline]
|
|
pub fn from_shared(src: Bytes) -> Result<HeaderValue, InvalidHeaderValueBytes> {
|
|
HeaderValue::try_from(src).map_err(InvalidHeaderValueBytes)
|
|
}
|
|
|
|
/// Convert a `Bytes` directly into a `HeaderValue` without validating.
|
|
///
|
|
/// This function does NOT validate that illegal bytes are not contained
|
|
/// within the buffer.
|
|
#[inline]
|
|
pub unsafe fn from_shared_unchecked(src: Bytes) -> HeaderValue {
|
|
if cfg!(debug_assertions) {
|
|
match HeaderValue::from_shared(src) {
|
|
Ok(val) => val,
|
|
Err(_err) => {
|
|
//TODO: if the Bytes were part of the InvalidHeaderValueBytes,
|
|
//this message could include the invalid bytes.
|
|
panic!("HeaderValue::from_shared_unchecked() with invalid bytes");
|
|
},
|
|
}
|
|
} else {
|
|
HeaderValue {
|
|
inner: src,
|
|
is_sensitive: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn try_from<T: AsRef<[u8]> + Into<Bytes>>(src: T) -> Result<HeaderValue, InvalidHeaderValue> {
|
|
for &b in src.as_ref() {
|
|
if !is_valid(b) {
|
|
return Err(InvalidHeaderValue {
|
|
_priv: (),
|
|
});
|
|
}
|
|
}
|
|
Ok(HeaderValue {
|
|
inner: src.into(),
|
|
is_sensitive: false,
|
|
})
|
|
}
|
|
|
|
/// Yields a `&str` slice if the `HeaderValue` only contains visible ASCII
|
|
/// chars.
|
|
///
|
|
/// This function will perform a scan of the header value, checking all the
|
|
/// characters.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_static("hello");
|
|
/// assert_eq!(val.to_str().unwrap(), "hello");
|
|
/// ```
|
|
pub fn to_str(&self) -> Result<&str, ToStrError> {
|
|
let bytes = self.as_ref();
|
|
|
|
for &b in bytes {
|
|
if !is_visible_ascii(b) {
|
|
return Err(ToStrError { _priv: () });
|
|
}
|
|
}
|
|
|
|
unsafe { Ok(str::from_utf8_unchecked(bytes)) }
|
|
}
|
|
|
|
/// Returns the length of `self`.
|
|
///
|
|
/// This length is in bytes.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_static("hello");
|
|
/// assert_eq!(val.len(), 5);
|
|
/// ```
|
|
#[inline]
|
|
pub fn len(&self) -> usize {
|
|
self.as_ref().len()
|
|
}
|
|
|
|
/// Returns true if the `HeaderValue` has a length of zero bytes.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_static("");
|
|
/// assert!(val.is_empty());
|
|
///
|
|
/// let val = HeaderValue::from_static("hello");
|
|
/// assert!(!val.is_empty());
|
|
/// ```
|
|
#[inline]
|
|
pub fn is_empty(&self) -> bool {
|
|
self.len() == 0
|
|
}
|
|
|
|
/// Converts a `HeaderValue` to a byte slice.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let val = HeaderValue::from_static("hello");
|
|
/// assert_eq!(val.as_bytes(), b"hello");
|
|
/// ```
|
|
#[inline]
|
|
pub fn as_bytes(&self) -> &[u8] {
|
|
self.as_ref()
|
|
}
|
|
|
|
/// Mark that the header value represents sensitive information.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let mut val = HeaderValue::from_static("my secret");
|
|
///
|
|
/// val.set_sensitive(true);
|
|
/// assert!(val.is_sensitive());
|
|
///
|
|
/// val.set_sensitive(false);
|
|
/// assert!(!val.is_sensitive());
|
|
/// ```
|
|
#[inline]
|
|
pub fn set_sensitive(&mut self, val: bool) {
|
|
self.is_sensitive = val;
|
|
}
|
|
|
|
/// Returns `true` if the value represents sensitive data.
|
|
///
|
|
/// Sensitive data could represent passwords or other data that should not
|
|
/// be stored on disk or in memory. This setting can be used by components
|
|
/// like caches to avoid storing the value. HPACK encoders must set the
|
|
/// header field to never index when `is_sensitive` returns true.
|
|
///
|
|
/// Note that sensitivity is not factored into equality or ordering.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// # use http::header::HeaderValue;
|
|
/// let mut val = HeaderValue::from_static("my secret");
|
|
///
|
|
/// val.set_sensitive(true);
|
|
/// assert!(val.is_sensitive());
|
|
///
|
|
/// val.set_sensitive(false);
|
|
/// assert!(!val.is_sensitive());
|
|
/// ```
|
|
#[inline]
|
|
pub fn is_sensitive(&self) -> bool {
|
|
self.is_sensitive
|
|
}
|
|
}
|
|
|
|
impl AsRef<[u8]> for HeaderValue {
|
|
#[inline]
|
|
fn as_ref(&self) -> &[u8] {
|
|
self.inner.as_ref()
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for HeaderValue {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
if self.is_sensitive {
|
|
f.write_str("Sensitive")
|
|
} else {
|
|
f.write_str("\"")?;
|
|
let mut from = 0;
|
|
let bytes = self.as_bytes();
|
|
for (i, &b) in bytes.iter().enumerate() {
|
|
if !is_visible_ascii(b) || b == b'"' {
|
|
if from != i {
|
|
f.write_str(unsafe {
|
|
str::from_utf8_unchecked(&bytes[from..i])
|
|
})?;
|
|
}
|
|
if b == b'"' {
|
|
f.write_str("\\\"")?;
|
|
} else {
|
|
write!(f, "\\x{:x}", b)?;
|
|
}
|
|
from = i + 1;
|
|
}
|
|
}
|
|
|
|
f.write_str(unsafe {
|
|
str::from_utf8_unchecked(&bytes[from..])
|
|
})?;
|
|
f.write_str("\"")
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<HeaderName> for HeaderValue {
|
|
#[inline]
|
|
fn from(h: HeaderName) -> HeaderValue {
|
|
HeaderValue {
|
|
inner: h.into(),
|
|
is_sensitive: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
macro_rules! from_integers {
|
|
($($name:ident: $t:ident => $max_len:expr),*) => {$(
|
|
impl From<$t> for HeaderValue {
|
|
fn from(num: $t) -> HeaderValue {
|
|
let mut buf = if mem::size_of::<BytesMut>() - 1 < $max_len {
|
|
// On 32bit platforms, BytesMut max inline size
|
|
// is 15 bytes, but the $max_len could be bigger.
|
|
//
|
|
// The likelihood of the number *actually* being
|
|
// that big is very small, so only allocate
|
|
// if the number needs that space.
|
|
//
|
|
// The largest decimal number in 15 digits:
|
|
// It wold be 10.pow(15) - 1, but this is a constant
|
|
// version.
|
|
if num as u64 > 999_999_999_999_999_999 {
|
|
BytesMut::with_capacity($max_len)
|
|
} else {
|
|
// fits inline...
|
|
BytesMut::new()
|
|
}
|
|
} else {
|
|
// full value fits inline, so don't allocate!
|
|
BytesMut::new()
|
|
};
|
|
let _ = ::itoa::fmt(&mut buf, num);
|
|
HeaderValue {
|
|
inner: buf.freeze(),
|
|
is_sensitive: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HttpTryFrom<$t> for HeaderValue {
|
|
type Error = Never;
|
|
|
|
#[inline]
|
|
fn try_from(num: $t) -> Result<Self, Self::Error> {
|
|
Ok(num.into())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn $name() {
|
|
let n: $t = 55;
|
|
let val = HeaderValue::from(n);
|
|
assert_eq!(val, &n.to_string());
|
|
|
|
let n = ::std::$t::MAX;
|
|
let val = HeaderValue::from(n);
|
|
assert_eq!(val, &n.to_string());
|
|
}
|
|
)*};
|
|
}
|
|
|
|
from_integers! {
|
|
// integer type => maximum decimal length
|
|
|
|
// u8 purposely left off... HeaderValue::from(b'3') could be confusing
|
|
from_u16: u16 => 5,
|
|
from_i16: i16 => 6,
|
|
from_u32: u32 => 10,
|
|
from_i32: i32 => 11,
|
|
from_u64: u64 => 20,
|
|
from_i64: i64 => 20
|
|
}
|
|
|
|
#[cfg(target_pointer_width = "16")]
|
|
from_integers! {
|
|
from_usize: usize => 5,
|
|
from_isize: isize => 6
|
|
}
|
|
|
|
#[cfg(target_pointer_width = "32")]
|
|
from_integers! {
|
|
from_usize: usize => 10,
|
|
from_isize: isize => 11
|
|
}
|
|
|
|
#[cfg(target_pointer_width = "64")]
|
|
from_integers! {
|
|
from_usize: usize => 20,
|
|
from_isize: isize => 20
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod from_header_name_tests {
|
|
use super::*;
|
|
use header::map::HeaderMap;
|
|
use header::name;
|
|
|
|
#[test]
|
|
fn it_can_insert_header_name_as_header_value() {
|
|
let mut map = HeaderMap::new();
|
|
map.insert(name::UPGRADE, name::SEC_WEBSOCKET_PROTOCOL.into());
|
|
map.insert(name::ACCEPT, name::HeaderName::from_bytes(b"hello-world").unwrap().into());
|
|
|
|
assert_eq!(
|
|
map.get(name::UPGRADE).unwrap(),
|
|
HeaderValue::from_bytes(b"sec-websocket-protocol").unwrap()
|
|
);
|
|
|
|
assert_eq!(
|
|
map.get(name::ACCEPT).unwrap(),
|
|
HeaderValue::from_bytes(b"hello-world").unwrap()
|
|
);
|
|
}
|
|
}
|
|
|
|
impl FromStr for HeaderValue {
|
|
type Err = InvalidHeaderValue;
|
|
|
|
#[inline]
|
|
fn from_str(s: &str) -> Result<HeaderValue, Self::Err> {
|
|
HeaderValue::from_str(s)
|
|
}
|
|
}
|
|
|
|
impl From<HeaderValue> for Bytes {
|
|
#[inline]
|
|
fn from(value: HeaderValue) -> Bytes {
|
|
value.inner
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a HeaderValue> for HeaderValue {
|
|
#[inline]
|
|
fn from(t: &'a HeaderValue) -> Self {
|
|
t.clone()
|
|
}
|
|
}
|
|
|
|
impl<'a> HttpTryFrom<&'a HeaderValue> for HeaderValue {
|
|
type Error = ::error::Never;
|
|
|
|
#[inline]
|
|
fn try_from(t: &'a HeaderValue) -> Result<Self, Self::Error> {
|
|
Ok(t.clone())
|
|
}
|
|
}
|
|
|
|
impl<'a> HttpTryFrom<&'a str> for HeaderValue {
|
|
type Error = InvalidHeaderValue;
|
|
|
|
#[inline]
|
|
fn try_from(t: &'a str) -> Result<Self, Self::Error> {
|
|
t.parse()
|
|
}
|
|
}
|
|
|
|
impl<'a> HttpTryFrom<&'a String> for HeaderValue {
|
|
type Error = InvalidHeaderValue;
|
|
#[inline]
|
|
fn try_from(s: &'a String) -> Result<Self, Self::Error> {
|
|
Self::from_bytes(s.as_bytes())
|
|
}
|
|
}
|
|
|
|
impl<'a> HttpTryFrom<&'a [u8]> for HeaderValue {
|
|
type Error = InvalidHeaderValue;
|
|
|
|
#[inline]
|
|
fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
|
|
HeaderValue::from_bytes(t)
|
|
}
|
|
}
|
|
|
|
impl HttpTryFrom<String> for HeaderValue {
|
|
type Error = InvalidHeaderValueBytes;
|
|
|
|
#[inline]
|
|
fn try_from(t: String) -> Result<Self, Self::Error> {
|
|
HeaderValue::from_shared(t.into())
|
|
}
|
|
}
|
|
|
|
impl HttpTryFrom<Bytes> for HeaderValue {
|
|
type Error = InvalidHeaderValueBytes;
|
|
|
|
#[inline]
|
|
fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
|
|
HeaderValue::from_shared(bytes)
|
|
}
|
|
}
|
|
|
|
impl HttpTryFrom<HeaderName> for HeaderValue {
|
|
type Error = InvalidHeaderValue;
|
|
|
|
#[inline]
|
|
fn try_from(name: HeaderName) -> Result<Self, Self::Error> {
|
|
// Infallable as header names have the same validations
|
|
Ok(name.into())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod try_from_header_name_tests {
|
|
use super::*;
|
|
use header::name;
|
|
|
|
#[test]
|
|
fn it_converts_using_try_from() {
|
|
assert_eq!(
|
|
HeaderValue::try_from(name::UPGRADE).unwrap(),
|
|
HeaderValue::from_bytes(b"upgrade").unwrap()
|
|
);
|
|
}
|
|
}
|
|
|
|
fn is_visible_ascii(b: u8) -> bool {
|
|
b >= 32 && b < 127 || b == b'\t'
|
|
}
|
|
|
|
#[inline]
|
|
fn is_valid(b: u8) -> bool {
|
|
b >= 32 && b != 127 || b == b'\t'
|
|
}
|
|
|
|
impl fmt::Display for InvalidHeaderValue {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
self.description().fmt(f)
|
|
}
|
|
}
|
|
|
|
impl Error for InvalidHeaderValue {
|
|
fn description(&self) -> &str {
|
|
"failed to parse header value"
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for InvalidHeaderValueBytes {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
self.0.fmt(f)
|
|
}
|
|
}
|
|
|
|
impl Error for InvalidHeaderValueBytes {
|
|
fn description(&self) -> &str {
|
|
self.0.description()
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for ToStrError {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
self.description().fmt(f)
|
|
}
|
|
}
|
|
|
|
impl Error for ToStrError {
|
|
fn description(&self) -> &str {
|
|
"failed to convert header to a str"
|
|
}
|
|
}
|
|
|
|
// ===== PartialEq / PartialOrd =====
|
|
|
|
impl PartialEq for HeaderValue {
|
|
#[inline]
|
|
fn eq(&self, other: &HeaderValue) -> bool {
|
|
self.inner == other.inner
|
|
}
|
|
}
|
|
|
|
impl Eq for HeaderValue {}
|
|
|
|
impl PartialOrd for HeaderValue {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
|
|
self.inner.partial_cmp(&other.inner)
|
|
}
|
|
}
|
|
|
|
impl Ord for HeaderValue {
|
|
#[inline]
|
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
self.inner.cmp(&other.inner)
|
|
}
|
|
}
|
|
|
|
impl PartialEq<str> for HeaderValue {
|
|
#[inline]
|
|
fn eq(&self, other: &str) -> bool {
|
|
self.inner == other.as_bytes()
|
|
}
|
|
}
|
|
|
|
impl PartialEq<[u8]> for HeaderValue {
|
|
#[inline]
|
|
fn eq(&self, other: &[u8]) -> bool {
|
|
self.inner == other
|
|
}
|
|
}
|
|
|
|
impl PartialOrd<str> for HeaderValue {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
|
|
(*self.inner).partial_cmp(other.as_bytes())
|
|
}
|
|
}
|
|
|
|
impl PartialOrd<[u8]> for HeaderValue {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
|
|
(*self.inner).partial_cmp(other)
|
|
}
|
|
}
|
|
|
|
impl PartialEq<HeaderValue> for str {
|
|
#[inline]
|
|
fn eq(&self, other: &HeaderValue) -> bool {
|
|
*other == *self
|
|
}
|
|
}
|
|
|
|
impl PartialEq<HeaderValue> for [u8] {
|
|
#[inline]
|
|
fn eq(&self, other: &HeaderValue) -> bool {
|
|
*other == *self
|
|
}
|
|
}
|
|
|
|
impl PartialOrd<HeaderValue> for str {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
|
|
self.as_bytes().partial_cmp(other.as_bytes())
|
|
}
|
|
}
|
|
|
|
impl PartialOrd<HeaderValue> for [u8] {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
|
|
self.partial_cmp(other.as_bytes())
|
|
}
|
|
}
|
|
|
|
impl PartialEq<String> for HeaderValue {
|
|
#[inline]
|
|
fn eq(&self, other: &String) -> bool {
|
|
*self == &other[..]
|
|
}
|
|
}
|
|
|
|
impl PartialOrd<String> for HeaderValue {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
|
|
self.inner.partial_cmp(other.as_bytes())
|
|
}
|
|
}
|
|
|
|
impl PartialEq<HeaderValue> for String {
|
|
#[inline]
|
|
fn eq(&self, other: &HeaderValue) -> bool {
|
|
*other == *self
|
|
}
|
|
}
|
|
|
|
impl PartialOrd<HeaderValue> for String {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
|
|
self.as_bytes().partial_cmp(other.as_bytes())
|
|
}
|
|
}
|
|
|
|
impl<'a> PartialEq<HeaderValue> for &'a HeaderValue {
|
|
#[inline]
|
|
fn eq(&self, other: &HeaderValue) -> bool {
|
|
**self == *other
|
|
}
|
|
}
|
|
|
|
impl<'a> PartialOrd<HeaderValue> for &'a HeaderValue {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
|
|
(**self).partial_cmp(other)
|
|
}
|
|
}
|
|
|
|
impl<'a, T: ?Sized> PartialEq<&'a T> for HeaderValue
|
|
where HeaderValue: PartialEq<T>
|
|
{
|
|
#[inline]
|
|
fn eq(&self, other: &&'a T) -> bool {
|
|
*self == **other
|
|
}
|
|
}
|
|
|
|
impl<'a, T: ?Sized> PartialOrd<&'a T> for HeaderValue
|
|
where HeaderValue: PartialOrd<T>
|
|
{
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
|
|
self.partial_cmp(*other)
|
|
}
|
|
}
|
|
|
|
impl<'a> PartialEq<HeaderValue> for &'a str {
|
|
#[inline]
|
|
fn eq(&self, other: &HeaderValue) -> bool {
|
|
*other == *self
|
|
}
|
|
}
|
|
|
|
impl<'a> PartialOrd<HeaderValue> for &'a str {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &HeaderValue) -> Option<cmp::Ordering> {
|
|
self.as_bytes().partial_cmp(other.as_bytes())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_try_from() {
|
|
HeaderValue::try_from(vec![127]).unwrap_err();
|
|
}
|
|
|
|
#[test]
|
|
fn test_debug() {
|
|
let cases = &[
|
|
("hello", "\"hello\""),
|
|
("hello \"world\"", "\"hello \\\"world\\\"\""),
|
|
("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""),
|
|
];
|
|
|
|
for &(value, expected) in cases {
|
|
let val = HeaderValue::from_bytes(value.as_bytes()).unwrap();
|
|
let actual = format!("{:?}", val);
|
|
assert_eq!(expected, actual);
|
|
}
|
|
|
|
let mut sensitive = HeaderValue::from_static("password");
|
|
sensitive.set_sensitive(true);
|
|
assert_eq!("Sensitive", format!("{:?}", sensitive));
|
|
}
|