use bytes::Bytes;
use conjure_error::Error;
use futures_core::Stream;
use http::{HeaderValue, Request, Response};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::convert::TryFrom;
use std::fmt::Display;
use std::future::Future;
use std::io::Write;
use std::marker::PhantomData;
use std::pin::Pin;
use std::sync::Arc;
pub use crate::client::encoding::*;
#[doc(inline)]
pub use crate::client::runtime::ConjureRuntime;
use crate::private;
pub mod conjure;
mod encoding;
pub mod runtime;
pub trait Service<C> {
fn new(client: C, runtime: &Arc<ConjureRuntime>) -> Self;
}
pub trait AsyncService<C> {
fn new(client: C, runtime: &Arc<ConjureRuntime>) -> Self;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Endpoint {
service: &'static str,
version: Option<&'static str>,
name: &'static str,
path: &'static str,
}
impl Endpoint {
#[inline]
pub fn new(
service: &'static str,
version: Option<&'static str>,
name: &'static str,
path: &'static str,
) -> Self {
Endpoint {
service,
version,
name,
path,
}
}
#[inline]
pub fn service(&self) -> &'static str {
self.service
}
#[inline]
pub fn version(&self) -> Option<&'static str> {
self.version
}
#[inline]
pub fn name(&self) -> &'static str {
self.name
}
#[inline]
pub fn path(&self) -> &'static str {
self.path
}
}
pub enum RequestBody<'a, W> {
Empty,
Fixed(Bytes),
Streaming(Box<dyn WriteBody<W> + 'a>),
}
pub enum AsyncRequestBody<'a, W> {
Empty,
Fixed(Bytes),
Streaming(BoxAsyncWriteBody<'a, W>),
}
pub enum LocalAsyncRequestBody<'a, W> {
Empty,
Fixed(Bytes),
Streaming(BoxLocalAsyncWriteBody<'a, W>),
}
pub trait Client {
type BodyWriter;
type ResponseBody: Iterator<Item = Result<Bytes, Error>>;
fn send(
&self,
req: Request<RequestBody<'_, Self::BodyWriter>>,
) -> Result<Response<Self::ResponseBody>, Error>;
}
pub trait AsyncClient {
type BodyWriter;
type ResponseBody: Stream<Item = Result<Bytes, Error>>;
fn send(
&self,
req: Request<AsyncRequestBody<'_, Self::BodyWriter>>,
) -> impl Future<Output = Result<Response<Self::ResponseBody>, Error>> + Send;
}
pub trait LocalAsyncClient {
type BodyWriter;
type ResponseBody: Stream<Item = Result<Bytes, Error>>;
fn send(
&self,
req: Request<LocalAsyncRequestBody<'_, Self::BodyWriter>>,
) -> impl Future<Output = Result<Response<Self::ResponseBody>, Error>>;
}
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
}
}
pub trait AsyncWriteBody<W> {
fn write_body(
self: Pin<&mut Self>,
w: Pin<&mut W>,
) -> impl Future<Output = Result<(), Error>> + Send;
fn reset(self: Pin<&mut Self>) -> impl Future<Output = bool> + Send;
}
trait AsyncWriteBodyEraser<W> {
fn write_body<'a>(
self: Pin<&'a mut Self>,
w: Pin<&'a mut W>,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>;
fn reset<'a>(self: Pin<&'a mut Self>) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>>
where
W: 'a;
}
impl<T, W> AsyncWriteBodyEraser<W> for T
where
T: AsyncWriteBody<W> + ?Sized,
{
fn write_body<'a>(
self: Pin<&'a mut Self>,
w: Pin<&'a mut W>,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>> {
Box::pin(self.write_body(w))
}
fn reset<'a>(self: Pin<&'a mut Self>) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>>
where
W: 'a,
{
Box::pin(self.reset())
}
}
pub struct BoxAsyncWriteBody<'a, W> {
inner: Pin<Box<dyn AsyncWriteBodyEraser<W> + Send + 'a>>,
}
impl<'a, W> BoxAsyncWriteBody<'a, W> {
pub fn new<T>(v: T) -> Self
where
T: AsyncWriteBody<W> + Send + 'a,
{
BoxAsyncWriteBody { inner: Box::pin(v) }
}
}
impl<W> AsyncWriteBody<W> for BoxAsyncWriteBody<'_, W>
where
W: Send,
{
async fn write_body(mut self: Pin<&mut Self>, w: Pin<&mut W>) -> Result<(), Error> {
self.inner.as_mut().write_body(w).await
}
async fn reset(mut self: Pin<&mut Self>) -> bool {
self.inner.as_mut().reset().await
}
}
pub trait LocalAsyncWriteBody<W> {
fn write_body(self: Pin<&mut Self>, w: Pin<&mut W>) -> impl Future<Output = Result<(), Error>>;
fn reset(self: Pin<&mut Self>) -> impl Future<Output = bool>;
}
trait LocalAsyncWriteBodyEraser<W> {
fn write_body<'a>(
self: Pin<&'a mut Self>,
w: Pin<&'a mut W>,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'a>>;
fn reset<'a>(self: Pin<&'a mut Self>) -> Pin<Box<dyn Future<Output = bool> + 'a>>
where
W: 'a;
}
impl<T, W> LocalAsyncWriteBodyEraser<W> for T
where
T: LocalAsyncWriteBody<W> + ?Sized,
{
fn write_body<'a>(
self: Pin<&'a mut Self>,
w: Pin<&'a mut W>,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'a>> {
Box::pin(self.write_body(w))
}
fn reset<'a>(self: Pin<&'a mut Self>) -> Pin<Box<dyn Future<Output = bool> + 'a>>
where
W: 'a,
{
Box::pin(self.reset())
}
}
pub struct BoxLocalAsyncWriteBody<'a, W> {
inner: Pin<Box<dyn LocalAsyncWriteBodyEraser<W> + 'a>>,
}
impl<'a, W> BoxLocalAsyncWriteBody<'a, W> {
pub fn new<T>(v: T) -> Self
where
T: LocalAsyncWriteBody<W> + 'a,
{
BoxLocalAsyncWriteBody { inner: Box::pin(v) }
}
}
impl<W> LocalAsyncWriteBody<W> for BoxLocalAsyncWriteBody<'_, W> {
async fn write_body(mut self: Pin<&mut Self>, w: Pin<&mut W>) -> Result<(), Error> {
self.inner.as_mut().write_body(w).await
}
async fn reset(mut self: Pin<&mut Self>) -> bool {
self.inner.as_mut().reset().await
}
}
pub trait SerializeRequest<'a, T, W> {
fn content_type(runtime: &ConjureRuntime, value: &T) -> HeaderValue;
fn content_length(runtime: &ConjureRuntime, value: &T) -> Option<u64> {
let _runtime = runtime;
let _value = value;
None
}
fn serialize(runtime: &ConjureRuntime, value: T) -> Result<RequestBody<'a, W>, Error>;
}
pub trait AsyncSerializeRequest<'a, T, W> {
fn content_type(runtime: &ConjureRuntime, value: &T) -> HeaderValue;
fn content_length(runtime: &ConjureRuntime, value: &T) -> Option<u64> {
let _runtime = runtime;
let _value = value;
None
}
fn serialize(runtime: &ConjureRuntime, value: T) -> Result<AsyncRequestBody<'a, W>, Error>;
}
pub trait LocalAsyncSerializeRequest<'a, T, W> {
fn content_type(runtime: &ConjureRuntime, value: &T) -> HeaderValue;
fn content_length(runtime: &ConjureRuntime, value: &T) -> Option<u64> {
let _runtime = runtime;
let _value = value;
None
}
fn serialize(runtime: &ConjureRuntime, value: T)
-> Result<LocalAsyncRequestBody<'a, W>, Error>;
}
pub enum StdRequestSerializer {}
impl StdRequestSerializer {
fn serialize_inner<B>(
runtime: &ConjureRuntime,
value: &dyn erased_serde::Serialize,
make_body: impl FnOnce(Bytes) -> B,
) -> Result<B, Error> {
let mut body = vec![];
value
.erased_serialize(
&mut *runtime
.request_body_encoding()
.serializer(&mut body)
.serializer(),
)
.map_err(Error::internal)?;
Ok(make_body(body.into()))
}
}
impl<'a, T, W> SerializeRequest<'a, T, W> for StdRequestSerializer
where
T: Serialize,
{
fn content_type(runtime: &ConjureRuntime, _: &T) -> HeaderValue {
runtime.request_body_encoding().content_type()
}
fn serialize(runtime: &ConjureRuntime, value: T) -> Result<RequestBody<'a, W>, Error> {
Self::serialize_inner(runtime, &value, RequestBody::Fixed)
}
}
impl<'a, T, W> AsyncSerializeRequest<'a, T, W> for StdRequestSerializer
where
T: Serialize,
{
fn content_type(runtime: &ConjureRuntime, _: &T) -> HeaderValue {
runtime.request_body_encoding().content_type()
}
fn serialize(runtime: &ConjureRuntime, value: T) -> Result<AsyncRequestBody<'a, W>, Error> {
Self::serialize_inner(runtime, &value, AsyncRequestBody::Fixed)
}
}
impl<'a, T, W> LocalAsyncSerializeRequest<'a, T, W> for StdRequestSerializer
where
T: Serialize,
{
fn content_type(runtime: &ConjureRuntime, _: &T) -> HeaderValue {
runtime.request_body_encoding().content_type()
}
fn serialize(
runtime: &ConjureRuntime,
value: T,
) -> Result<LocalAsyncRequestBody<'a, W>, Error> {
Self::serialize_inner(runtime, &value, LocalAsyncRequestBody::Fixed)
}
}
pub trait DeserializeResponse<T, R> {
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue>;
fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<T, Error>;
}
pub trait AsyncDeserializeResponse<T, R> {
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue>;
fn deserialize(
runtime: &ConjureRuntime,
response: Response<R>,
) -> impl Future<Output = Result<T, Error>> + Send;
}
pub trait LocalAsyncDeserializeResponse<T, R> {
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue>;
fn deserialize(
runtime: &ConjureRuntime,
response: Response<R>,
) -> impl Future<Output = Result<T, Error>>;
}
pub enum UnitResponseDeserializer {}
impl<R> DeserializeResponse<(), R> for UnitResponseDeserializer {
fn accept(_: &ConjureRuntime) -> Option<HeaderValue> {
None
}
fn deserialize(_: &ConjureRuntime, _: Response<R>) -> Result<(), Error> {
Ok(())
}
}
impl<R> AsyncDeserializeResponse<(), R> for UnitResponseDeserializer
where
R: Send,
{
fn accept(_: &ConjureRuntime) -> Option<HeaderValue> {
None
}
async fn deserialize(_: &ConjureRuntime, _: Response<R>) -> Result<(), Error> {
Ok(())
}
}
impl<R> LocalAsyncDeserializeResponse<(), R> for UnitResponseDeserializer {
fn accept(_: &ConjureRuntime) -> Option<HeaderValue> {
None
}
async fn deserialize(_: &ConjureRuntime, _: Response<R>) -> Result<(), Error> {
Ok(())
}
}
pub enum StdResponseDeserializer {}
impl<T, R> DeserializeResponse<T, R> for StdResponseDeserializer
where
T: DeserializeOwned,
R: Iterator<Item = Result<Bytes, Error>>,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
Some(runtime.accept())
}
fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<T, Error> {
let encoding = runtime.response_body_encoding(response.headers())?;
let buf = private::read_body(response.into_body(), None)?;
let v =
T::deserialize(encoding.deserializer(&buf).deserializer()).map_err(Error::internal)?;
Ok(v)
}
}
impl<T, R> AsyncDeserializeResponse<T, R> for StdResponseDeserializer
where
T: DeserializeOwned,
R: Stream<Item = Result<Bytes, Error>> + Send,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
Some(runtime.accept())
}
async fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<T, Error> {
let encoding = runtime.response_body_encoding(response.headers())?;
let buf = private::async_read_body(response.into_body(), None).await?;
let v =
T::deserialize(encoding.deserializer(&buf).deserializer()).map_err(Error::internal)?;
Ok(v)
}
}
impl<T, R> LocalAsyncDeserializeResponse<T, R> for StdResponseDeserializer
where
T: DeserializeOwned,
R: Stream<Item = Result<Bytes, Error>>,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
Some(runtime.accept())
}
async fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<T, Error> {
let encoding = runtime.response_body_encoding(response.headers())?;
let buf = private::async_read_body(response.into_body(), None).await?;
let v =
T::deserialize(encoding.deserializer(&buf).deserializer()).map_err(Error::internal)?;
Ok(v)
}
}
pub trait EncodeHeader<T> {
fn encode(runtime: &ConjureRuntime, value: T) -> Result<Vec<HeaderValue>, Error>;
}
pub trait EncodeParam<T> {
fn encode(runtime: &ConjureRuntime, value: T) -> Result<Vec<String>, Error>;
}
pub enum DisplayEncoder {}
impl<T> EncodeHeader<T> for DisplayEncoder
where
T: Display,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<HeaderValue>, Error> {
HeaderValue::try_from(value.to_string())
.map_err(Error::internal_safe)
.map(|v| vec![v])
}
}
impl<T> EncodeParam<T> for DisplayEncoder
where
T: Display,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<String>, Error> {
Ok(vec![value.to_string()])
}
}
pub enum DisplaySeqEncoder {}
impl<T, U> EncodeHeader<T> for DisplaySeqEncoder
where
T: IntoIterator<Item = U>,
U: Display,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<HeaderValue>, Error> {
value
.into_iter()
.map(|v| HeaderValue::try_from(v.to_string()).map_err(Error::internal_safe))
.collect()
}
}
impl<T, U> EncodeParam<T> for DisplaySeqEncoder
where
T: IntoIterator<Item = U>,
U: Display,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<String>, Error> {
Ok(value.into_iter().map(|v| v.to_string()).collect())
}
}
pub struct AsRefEncoder<D, U> {
_p: PhantomData<(D, U)>,
}
impl<T, D, U> EncodeHeader<T> for AsRefEncoder<D, U>
where
T: AsRef<U>,
for<'a> D: EncodeHeader<&'a U>,
{
fn encode(runtime: &ConjureRuntime, value: T) -> Result<Vec<HeaderValue>, Error> {
D::encode(runtime, value.as_ref())
}
}
impl<T, D, U> EncodeParam<T> for AsRefEncoder<D, U>
where
T: AsRef<U>,
for<'a> D: EncodeParam<&'a U>,
{
fn encode(runtime: &ConjureRuntime, value: T) -> Result<Vec<String>, Error> {
D::encode(runtime, value.as_ref())
}
}