#[repr(u8)]
#[derive(Debug, PartialEq, Eq)]
pub enum Header {
Input(header::Input) = 1,
Success(header::Success) = 2,
Redirect(header::Redirect) = 3,
FailTemp(header::FailTemp) = 4,
FailPerm(header::FailPerm) = 5,
CertRequired(header::CertRequired) = 6,
}
pub mod raw {
pub use super::Meta;
pub type Status = [u8; 2];
pub struct Header {
pub meta: Meta,
pub status: Status,
}
}
pub mod header {
use url::Url;
use crate::response::Mime;
use super::Meta;
#[derive(Debug, PartialEq, Eq)]
pub struct Input {
pub prompt: String,
pub sensitive: Option<bool>,
}
impl From<(u8, Meta)> for Input {
fn from((code, meta): (u8, Meta)) -> Self {
let prompt = super::Meta::try_from(meta).unwrap().0;
let sensitive = match code {
0 => Some(false),
1 => Some(true),
_ => None,
};
Self { prompt, sensitive }
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Success {
pub mime: Mime,
}
impl From<(u8, Meta)> for Success {
fn from((_, meta): (u8, Meta)) -> Self {
let mime = Mime::try_from(Meta::try_from(meta).unwrap()).expect("failed to read mime");
Self { mime }
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Redirect {
pub url: Url,
pub temporary: Option<bool>,
}
impl From<(u8, Meta)> for Redirect {
fn from((code, meta): (u8, Meta)) -> Self {
let temporary = match code {
0 => Some(true),
1 => Some(false),
_ => None,
};
Self {
url: meta.0.parse().expect("not a valid url"),
temporary,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct FailTemp {
pub message: String,
pub typ: Option<sub::FailTemp>,
}
impl From<(u8, Meta)> for FailTemp {
fn from((code, meta): (u8, Meta)) -> Self {
let typ = sub::FailTemp::try_from(code).ok();
Self {
message: meta.0,
typ,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct FailPerm {
pub message: String,
pub typ: Option<sub::FailPerm>,
}
impl From<(u8, Meta)> for FailPerm {
fn from((code, meta): (u8, Meta)) -> Self {
let typ = sub::FailPerm::try_from(code).ok();
Self {
message: meta.0,
typ,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct CertRequired {
pub message: String,
pub typ: Option<sub::CertRequired>,
}
impl From<(u8, Meta)> for CertRequired {
fn from(value: (u8, Meta)) -> Self {
let (code, meta) = value;
let typ = sub::CertRequired::try_from(code).ok();
Self {
message: meta.0,
typ,
}
}
}
mod sub {
use num_enum::TryFromPrimitive;
#[derive(Debug, PartialEq, Eq, TryFromPrimitive)]
#[repr(u8)]
pub enum FailTemp {
TemporaryFailure = 0,
ServerUnavailable = 1,
CgiError = 2,
ProxyError = 3,
SlowDown = 4,
}
#[derive(Debug, PartialEq, Eq, TryFromPrimitive)]
#[repr(u8)]
pub enum FailPerm {
PermanentFailure = 0,
NotFound = 1,
Gone = 2,
ProxyRequestRefused = 3,
BadRequest = 9,
}
#[derive(Debug, PartialEq, Eq, TryFromPrimitive)]
#[repr(u8)]
pub enum CertRequired {
ClientCertificateRequired = 0,
CertificateNotAuthorised = 1,
CertificateNotValid = 2,
}
}
}
impl TryFrom<raw::Header> for Header {
type Error = String;
fn try_from(value: raw::Header) -> Result<Self, Self::Error> {
let raw::Header { status, meta } = value;
let [status, sub] = status;
match match status {
1 => Some(Header::Input((sub, meta).into())),
2 => Some(Header::Success((sub, meta).into())),
3 => Some(Header::Redirect((sub, meta).into())),
4 => Some(Header::FailTemp((sub, meta).into())),
5 => Some(Header::FailPerm((sub, meta).into())),
6 => Some(Header::CertRequired((sub, meta).into())),
_ => None,
} {
Some(s) => Ok(s),
None => Err(format!("bad status code: [{:?},{:?}]", status, sub)),
}
}
}
pub use mime::Mime;
#[derive(Debug, PartialEq, Eq)]
pub struct Meta(pub String);
impl From<Meta> for Mime {
fn from(value: Meta) -> Self {
value.0.parse().unwrap()
}
}