use std::marker::PhantomData;
use crate::endpoint::{QueryParameter, WebRequest, WebResponse};
use std::borrow::Cow;
use std::collections::HashMap;
use url::Url;
#[derive(Clone, Debug, Default)]
pub struct Request {
pub query: HashMap<String, String>,
pub urlbody: HashMap<String, String>,
pub auth: Option<String>,
}
#[derive(Clone, Debug, Default)]
pub struct Response {
pub status: Status,
pub location: Option<Url>,
pub www_authenticate: Option<String>,
pub body: Option<Body>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Status {
Ok,
Redirect,
BadRequest,
Unauthorized,
}
#[derive(Clone, Debug)]
pub enum Body {
Text(String),
Json(String),
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum NoError {}
pub struct MapErr<W, F, T>(W, F, PhantomData<T>);
impl Body {
pub fn as_str(&self) -> &str {
match self {
Body::Text(ref body) => body,
Body::Json(ref body) => body,
}
}
}
impl<W, F, T> MapErr<W, F, T> {
pub fn request(request: W, f: F) -> Self
where
W: WebRequest,
F: FnMut(W::Error) -> T,
{
MapErr(request, f, PhantomData)
}
pub fn response(response: W, f: F) -> Self
where
W: WebResponse,
F: FnMut(W::Error) -> T,
{
MapErr(response, f, PhantomData)
}
pub fn into_inner(self) -> W {
self.0
}
}
impl WebRequest for Request {
type Error = NoError;
type Response = Response;
fn query(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
Ok(Cow::Borrowed(&self.query))
}
fn urlbody(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
Ok(Cow::Borrowed(&self.urlbody))
}
fn authheader(&mut self) -> Result<Option<Cow<str>>, Self::Error> {
Ok(self.auth.as_ref().map(|string| Cow::Borrowed(string.as_str())))
}
}
impl WebResponse for Response {
type Error = NoError;
fn ok(&mut self) -> Result<(), Self::Error> {
self.status = Status::Ok;
self.location = None;
self.www_authenticate = None;
Ok(())
}
fn redirect(&mut self, url: Url) -> Result<(), Self::Error> {
self.status = Status::Redirect;
self.location = Some(url);
self.www_authenticate = None;
Ok(())
}
fn client_error(&mut self) -> Result<(), Self::Error> {
self.status = Status::BadRequest;
self.location = None;
self.www_authenticate = None;
Ok(())
}
fn unauthorized(&mut self, header_value: &str) -> Result<(), Self::Error> {
self.status = Status::Unauthorized;
self.location = None;
self.www_authenticate = Some(header_value.to_owned());
Ok(())
}
fn body_text(&mut self, text: &str) -> Result<(), Self::Error> {
self.body = Some(Body::Text(text.to_owned()));
Ok(())
}
fn body_json(&mut self, data: &str) -> Result<(), Self::Error> {
self.body = Some(Body::Json(data.to_owned()));
Ok(())
}
}
impl NoError {
pub fn into<T>(self) -> T {
match self {}
}
}
impl Default for Status {
fn default() -> Self {
Status::Ok
}
}
impl<W: WebRequest, F, T> WebRequest for MapErr<W, F, T>
where
F: FnMut(W::Error) -> T,
{
type Error = T;
type Response = MapErr<W::Response, F, T>;
fn query(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
self.0.query().map_err(&mut self.1)
}
fn urlbody(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
self.0.urlbody().map_err(&mut self.1)
}
fn authheader(&mut self) -> Result<Option<Cow<str>>, Self::Error> {
self.0.authheader().map_err(&mut self.1)
}
}
impl<W: WebResponse, F, T> WebResponse for MapErr<W, F, T>
where
F: FnMut(W::Error) -> T,
{
type Error = T;
fn ok(&mut self) -> Result<(), Self::Error> {
self.0.ok().map_err(&mut self.1)
}
fn redirect(&mut self, url: Url) -> Result<(), Self::Error> {
self.0.redirect(url).map_err(&mut self.1)
}
fn client_error(&mut self) -> Result<(), Self::Error> {
self.0.client_error().map_err(&mut self.1)
}
fn unauthorized(&mut self, header_value: &str) -> Result<(), Self::Error> {
self.0.unauthorized(header_value).map_err(&mut self.1)
}
fn body_text(&mut self, text: &str) -> Result<(), Self::Error> {
self.0.body_text(text).map_err(&mut self.1)
}
fn body_json(&mut self, data: &str) -> Result<(), Self::Error> {
self.0.body_json(data).map_err(&mut self.1)
}
}