use std::{ collections::*, convert::{TryFrom, TryInto}, iter::FromIterator, }; use serde::{Deserialize, Serialize}; pub enum Error { Unsupported, InvalidHeaderName, } impl From for Error { fn from (x: hyper::header::InvalidHeaderName) -> Self { Self::InvalidHeaderName } } #[derive (Deserialize, Serialize)] pub enum Method { // Only GET is supported for now Get, } impl TryFrom for Method { type Error = Error; fn try_from (x: hyper::Method) -> Result { match x { hyper::Method::GET => Ok (Self::Get), _ => Err (Error::Unsupported), } } } impl From for hyper::Method { fn from (x: Method) -> Self { match x { Method::Get => Self::GET, } } } #[derive (Deserialize, Serialize)] pub struct RequestParts { pub method: Method, // Technically URIs are subtle and complex but I don't care pub uri: String, // Technically Hyper has headers in a multi-map // but I don't feel like doing that right now. // Headers are _kinda_ ASCII but they can also be binary. // HTTP is nutty. pub headers: HashMap >, } impl TryFrom for RequestParts { type Error = Error; fn try_from (x: http::request::Parts) -> Result { let method = x.method.try_into ()?; let uri = x.uri.to_string (); let headers = HashMap::from_iter ( x.headers.into_iter () .filter_map (|(k, v)| k.map (|k| (k, v))) .map (|(k, v)| (String::from (k.as_str ()), v.as_bytes ().to_vec ())) ); Ok (Self { method, uri, headers, }) } } impl TryFrom for http::request::Builder { type Error = Error; fn try_from (x: RequestParts) -> Result { let method = Method::from (x.method); let mut result = Self::new () .method (method) .uri (x.uri) ; for (k, v) in x.headers.into_iter () { result = result.header (http::header::HeaderName::try_from (&k)?, v); } Ok (result) } } #[derive (Deserialize, Serialize)] pub enum StatusCode { Ok, NotFound, } impl TryFrom for StatusCode { type Error = Error; fn try_from (x: hyper::StatusCode) -> Result { match x { hyper::StatusCode::OK => Ok (Self::Ok), hyper::StatusCode::NOT_FOUND => Ok (Self::NotFound), _ => Err (Error::Unsupported), } } } impl From for hyper::StatusCode { fn from (x: StatusCode) -> Self { match x { StatusCode::Ok => Self::OK, StatusCode::NotFound => Self::NOT_FOUND, } } } #[derive (Deserialize, Serialize)] pub struct Response { pub status_code: String, // Technically Hyper has headers in a multi-map // but I don't feel like doing that right now. pub headers: HashMap , }