athene 2.0.4

A simple and lightweight rust web framework based on hyper
Documentation
use crate::error::Error;
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
use std::fmt::{self, Display, Formatter};

#[derive(Clone, Debug, PartialEq)]
pub enum DispositionType {
    /// Inline implies default processing
    Inline,
    /// Attachment implies that the recipient should prompt the user to save the response locally,
    /// rather than process it normally (as per its media type).
    Attachment,
}

pub(crate) struct ContentDisposition {
    typ: DispositionType,
    encoded_filename: Option<String>,
}

impl ContentDisposition {
    /// Construct by disposition type and optional filename.
    #[inline]
    pub(crate) fn new(typ: DispositionType, filename: Option<&str>) -> Self {
        const HTTP_VALUE: &AsciiSet = &CONTROLS
            .add(b' ')
            .add(b'"')
            .add(b'%')
            .add(b'\'')
            .add(b'(')
            .add(b')')
            .add(b'*')
            .add(b',')
            .add(b'/')
            .add(b':')
            .add(b';')
            .add(b'<')
            .add(b'-')
            .add(b'>')
            .add(b'?')
            .add(b'[')
            .add(b'\\')
            .add(b']')
            .add(b'{')
            .add(b'}');
        Self {
            typ,
            encoded_filename: filename
                .map(|name| utf8_percent_encode(name, HTTP_VALUE).to_string()),
        }
    }
}

impl TryFrom<ContentDisposition> for hyper::http::HeaderValue {
    type Error = Error;
    #[inline]
    fn try_from(value: ContentDisposition) -> Result<Self, Self::Error> {
        value
            .to_string()
            .try_into()
            .map_err(|err| Error::Other(format!("Not a valid header value {}", err)))
    }
}

impl Display for ContentDisposition {
    #[inline]
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match &self.encoded_filename {
            None => f.write_fmt(format_args!("{}", self.typ)),
            Some(name) => f.write_fmt(format_args!(
                "{}; filename={}; filename*=UTF-8''{}",
                self.typ, name, name
            )),
        }
    }
}

impl Display for DispositionType {
    #[inline]
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            DispositionType::Inline => f.write_str("inline"),
            DispositionType::Attachment => f.write_str("attachment"),
        }
    }
}