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;
#[derive(Clone, Hash)]
pub struct HeaderValue {
    inner: Bytes,
    is_sensitive: bool,
}
pub struct InvalidHeaderValue {
    _priv: (),
}
#[derive(Debug)]
pub struct InvalidHeaderValueBytes(InvalidHeaderValue);
#[derive(Debug)]
pub struct ToStrError {
    _priv: (),
}
impl HeaderValue {
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[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,
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn from_str(src: &str) -> Result<HeaderValue, InvalidHeaderValue> {
        HeaderValue::try_from(src)
    }
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn from_name(name: HeaderName) -> HeaderValue {
        name.into()
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn from_bytes(src: &[u8]) -> Result<HeaderValue, InvalidHeaderValue> {
        HeaderValue::try_from(src)
    }
    
    
    
    
    
    
    
    
    #[inline]
    pub fn from_shared(src: Bytes) -> Result<HeaderValue, InvalidHeaderValueBytes> {
        HeaderValue::try_from(src).map_err(InvalidHeaderValueBytes)
    }
    
    
    
    
    #[inline]
    pub unsafe fn from_shared_unchecked(src: Bytes) -> HeaderValue {
        if cfg!(debug_assertions) {
            match HeaderValue::from_shared(src) {
                Ok(val) => val,
                Err(_err) => {
                    
                    
                    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,
        })
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    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)) }
    }
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn len(&self) -> usize {
        self.as_ref().len()
    }
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn as_bytes(&self) -> &[u8] {
        self.as_ref()
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn set_sensitive(&mut self, val: bool) {
        self.is_sensitive = val;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[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 {
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    if num as u64 > 999_999_999_999_999_999 {
                        BytesMut::with_capacity($max_len)
                    } else {
                        
                        BytesMut::new()
                    }
                } else {
                    
                    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! {
    
    
    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> {
        
        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::Debug for InvalidHeaderValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("InvalidHeaderValue")
            
            .finish()
    }
}
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"
    }
}
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));
}