safe_http 0.1.0-beta.4

Simple and safe HTTP types.
Documentation
mod invalid;
mod validate;

pub use invalid::InvalidHeaderValue;

use self::validate::validate;
use shared_bytes::{SharedBytes, SharedStr};
use std::{fmt, sync::Arc};

#[derive(Debug, Clone, PartialEq, Hash)]
pub struct HeaderValue(SharedBytes);

impl HeaderValue {
    #[track_caller]
    #[inline]
    pub const fn from_static(b: &'static [u8]) -> Self {
        match validate(b) {
            Ok(()) => Self(SharedBytes::from_static(b)),
            Err(_e) => panic!("invalid static Fragment"),
        }
    }

    #[inline]
    pub fn as_shared_bytes(&self) -> &SharedBytes {
        &self.0
    }

    #[inline]
    pub fn into_shared_bytes(self) -> SharedBytes {
        self.0
    }

    #[inline]
    pub fn as_slice(&self) -> &[u8] {
        self.0.as_slice()
    }
}

impl AsRef<[u8]> for HeaderValue {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        self.as_slice()
    }
}

impl Eq for HeaderValue {}

impl PartialEq<str> for HeaderValue {
    fn eq(&self, other: &str) -> bool {
        self.as_slice() == other.as_bytes()
    }
}

impl PartialEq<String> for HeaderValue {
    fn eq(&self, other: &String) -> bool {
        self.as_slice() == other.as_bytes()
    }
}

impl PartialEq<[u8]> for HeaderValue {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_slice() == other
    }
}

impl PartialEq<Vec<u8>> for HeaderValue {
    fn eq(&self, other: &Vec<u8>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<T> PartialEq<&'_ T> for HeaderValue
where
    Self: PartialEq<T>,
    T: ?Sized,
{
    fn eq(&self, other: &&T) -> bool {
        self.eq(*other)
    }
}

impl From<HeaderValue> for SharedBytes {
    fn from(x: HeaderValue) -> Self {
        x.into_shared_bytes()
    }
}

impl From<HeaderValue> for Vec<u8> {
    fn from(x: HeaderValue) -> Self {
        x.into_shared_bytes().into_vec()
    }
}

impl TryFrom<&'static str> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: &'static str) -> Result<Self, Self::Error> {
        validate(value.as_bytes())?;
        Ok(Self(value.into()))
    }
}

impl TryFrom<String> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: String) -> Result<Self, Self::Error> {
        validate(value.as_bytes())?;
        Ok(Self(value.into()))
    }
}

impl TryFrom<Arc<String>> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: Arc<String>) -> Result<Self, Self::Error> {
        validate(value.as_bytes())?;
        Ok(Self(value.into()))
    }
}

impl TryFrom<SharedStr> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: SharedStr) -> Result<Self, Self::Error> {
        validate(value.as_bytes())?;
        Ok(Self(value.into()))
    }
}

impl TryFrom<&'static [u8]> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> {
        validate(value)?;
        Ok(Self(value.into()))
    }
}

impl TryFrom<Vec<u8>> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
        validate(value.as_slice())?;
        Ok(Self(value.into()))
    }
}

impl TryFrom<Arc<Vec<u8>>> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: Arc<Vec<u8>>) -> Result<Self, Self::Error> {
        validate(value.as_slice())?;
        Ok(Self(value.into()))
    }
}

impl TryFrom<SharedBytes> for HeaderValue {
    type Error = InvalidHeaderValue;

    fn try_from(value: SharedBytes) -> Result<Self, Self::Error> {
        validate(value.as_slice())?;
        Ok(Self(value))
    }
}

impl fmt::Display for HeaderValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for &byte in self.as_slice() {
            char::from(byte).fmt(f)?;
        }
        Ok(())
    }
}