use conjure_error::Error;
use http::{HeaderMap, Method};
use serde::{Deserializer, Serialize};
use std::error;
use std::io::Write;
use crate::{PathParams, QueryParams};
pub trait Client {
type BinaryWriter;
type BinaryBody;
#[allow(clippy::too_many_arguments)]
fn request<'a, T, U>(
&self,
method: Method,
path: &'static str,
path_params: PathParams,
query_params: QueryParams,
headers: HeaderMap,
body: T,
response_visitor: U,
) -> Result<U::Output, Error>
where
T: RequestBody<'a, Self::BinaryWriter>,
U: VisitResponse<Self::BinaryBody>;
}
pub trait RequestBody<'a, W> {
fn accept<V>(self, visitor: V) -> V::Output
where
V: VisitRequestBody<'a, W>;
}
pub trait VisitRequestBody<'a, W> {
type Output;
fn visit_empty(self) -> Self::Output;
fn visit_serializable<T>(self, body: T) -> Self::Output
where
T: Serialize + 'a;
fn visit_binary<T>(self, body: T) -> Self::Output
where
T: WriteBody<W> + 'a;
}
pub trait VisitResponse<T>: Sized {
type Output;
fn accept(&self) -> Accept;
fn visit_empty(self) -> Result<Self::Output, Error> {
Err(Error::internal_safe("unexpected empty response"))
}
fn visit_serializable<'de, D>(self, deserializer: D) -> Result<Self::Output, Error>
where
D: Deserializer<'de>,
D::Error: Into<Box<error::Error + Sync + Send>>,
{
let _ = deserializer;
Err(Error::internal_safe("unexpected serializable response"))
}
fn visit_binary(self, body: T) -> Result<Self::Output, Error> {
let _ = body;
Err(Error::internal_safe("unexpected binary response"))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Accept {
Empty,
Serializable,
Binary,
}
pub trait WriteBody<W> {
fn write_body(&mut self, w: &mut W) -> Result<(), Error>;
fn reset(&mut self) -> bool;
}
impl<W> WriteBody<W> for &[u8]
where
W: Write,
{
fn write_body(&mut self, w: &mut W) -> Result<(), Error> {
w.write_all(self).map_err(Error::internal_safe)
}
fn reset(&mut self) -> bool {
true
}
}