min_http11_core 0.2.2

Minimum HTTP/1.1 version, request line and headers
Documentation
use crate::error::{Error, Result};
use std::convert::{TryFrom, TryInto};
use std::fmt::{Display, Formatter};

const HTTP11: &[u8] = b"HTTP/1.1";

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Version {
    Http11,
    Unsupported(&'static [u8]),
}

impl Version {
    pub fn as_slice(&self) -> &'static [u8] {
        self.into()
    }
    pub fn from_static(value: &'static [u8]) -> Self {
        value.try_into().unwrap_or(Version::Unsupported(value))
    }
}

impl Display for Version {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.as_slice().escape_ascii())
    }
}

impl<'a, const N: usize> TryFrom<&'a [u8; N]> for Version {
    type Error = Error;

    fn try_from(value: &'a [u8; N]) -> Result<Self> {
        value.as_slice().try_into()
    }
}

impl<'a> TryFrom<&'a [u8]> for Version {
    type Error = Error;

    fn try_from(value: &'a [u8]) -> Result<Self> {
        match value {
            HTTP11 => Ok(Version::Http11),
            other => Err(Error::UnsupportedVersion(other.escape_ascii().to_string())),
        }
    }
}

impl From<&Version> for &'static [u8] {
    fn from(value: &Version) -> Self {
        match value {
            Version::Http11 => HTTP11,
            Version::Unsupported(value) => value,
        }
    }
}

impl AsRef<[u8]> for Version {
    fn as_ref(&self) -> &'static [u8] {
        self.into()
    }
}

impl TryFrom<&str> for Version {
    type Error = Error;

    fn try_from(value: &str) -> Result<Self> {
        value.as_bytes().try_into()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn from_bytes() {
        assert_eq!(HTTP11.try_into(), Ok(Version::Http11));
        let unknown: Result<Version> = b"HTTP/1.0".try_into();
        assert!(unknown.is_err());
    }

    #[test]
    fn from_str() {
        assert_eq!("HTTP/1.1".try_into(), Ok(Version::Http11));
        let unknown: Result<Version> = "UNKNOWN".try_into();
        assert!(unknown.is_err());
    }

    #[test]
    fn as_ref() {
        assert_eq!(Version::Http11.as_ref(), HTTP11);
        assert_eq!(Version::from_static(b"HTTP/2").as_ref(), b"HTTP/2")
    }
}