use std::convert::TryFrom;
use bytes::Bytes;
use conjure_error::Error;
use conjure_object::{Plain, ToPlain};
use futures_core::Stream;
use http::{header::CONTENT_TYPE, HeaderValue, Response, StatusCode};
use serde::de::{DeserializeOwned, IgnoredAny};
use crate::client::{
AsyncDeserializeResponse, AsyncRequestBody, AsyncSerializeRequest, AsyncWriteBody,
BoxAsyncWriteBody, BoxLocalAsyncWriteBody, ConjureRuntime, DeserializeResponse, EncodeHeader,
EncodeParam, LocalAsyncDeserializeResponse, LocalAsyncRequestBody, LocalAsyncSerializeRequest,
LocalAsyncWriteBody, RequestBody, SerializeRequest, StdResponseDeserializer, WriteBody,
};
use crate::private::APPLICATION_OCTET_STREAM;
pub enum BinaryRequestSerializer {}
impl<'a, T, R> SerializeRequest<'a, T, R> for BinaryRequestSerializer
where
T: WriteBody<R> + 'a,
{
fn content_type(_: &ConjureRuntime, _: &T) -> HeaderValue {
APPLICATION_OCTET_STREAM
}
fn serialize(_: &ConjureRuntime, value: T) -> Result<RequestBody<'a, R>, Error> {
Ok(RequestBody::Streaming(Box::new(value)))
}
}
impl<'a, T, R> AsyncSerializeRequest<'a, T, R> for BinaryRequestSerializer
where
T: AsyncWriteBody<R> + Send + 'a,
{
fn content_type(_: &ConjureRuntime, _: &T) -> HeaderValue {
APPLICATION_OCTET_STREAM
}
fn serialize(_: &ConjureRuntime, value: T) -> Result<AsyncRequestBody<'a, R>, Error> {
Ok(AsyncRequestBody::Streaming(BoxAsyncWriteBody::new(value)))
}
}
impl<'a, T, R> LocalAsyncSerializeRequest<'a, T, R> for BinaryRequestSerializer
where
T: LocalAsyncWriteBody<R> + 'a,
{
fn content_type(_: &ConjureRuntime, _: &T) -> HeaderValue {
APPLICATION_OCTET_STREAM
}
fn serialize(_: &ConjureRuntime, value: T) -> Result<LocalAsyncRequestBody<'a, R>, Error> {
Ok(LocalAsyncRequestBody::Streaming(
BoxLocalAsyncWriteBody::new(value),
))
}
}
pub enum CollectionResponseDeserializer {}
impl<T, R> DeserializeResponse<T, R> for CollectionResponseDeserializer
where
T: DeserializeOwned + Default,
R: Iterator<Item = Result<Bytes, Error>>,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<StdResponseDeserializer as DeserializeResponse<T, R>>::accept(runtime)
}
fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<T, Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(T::default());
}
<StdResponseDeserializer as DeserializeResponse<T, R>>::deserialize(runtime, response)
}
}
impl<T, R> AsyncDeserializeResponse<T, R> for CollectionResponseDeserializer
where
T: DeserializeOwned + Default,
R: Stream<Item = Result<Bytes, Error>> + Send,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<StdResponseDeserializer as AsyncDeserializeResponse<T, R>>::accept(runtime)
}
async fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<T, Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(T::default());
}
<StdResponseDeserializer as AsyncDeserializeResponse<T, R>>::deserialize(runtime, response)
.await
}
}
impl<T, R> LocalAsyncDeserializeResponse<T, R> for CollectionResponseDeserializer
where
T: DeserializeOwned + Default,
R: Stream<Item = Result<Bytes, Error>>,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<StdResponseDeserializer as LocalAsyncDeserializeResponse<T, R>>::accept(runtime)
}
async fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<T, Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(T::default());
}
<StdResponseDeserializer as LocalAsyncDeserializeResponse<T, R>>::deserialize(
runtime, response,
)
.await
}
}
pub enum BinaryResponseDeserializer {}
impl<R> DeserializeResponse<R, R> for BinaryResponseDeserializer {
fn accept(_: &ConjureRuntime) -> Option<HeaderValue> {
Some(APPLICATION_OCTET_STREAM)
}
fn deserialize(_: &ConjureRuntime, response: Response<R>) -> Result<R, Error> {
if response.headers().get(CONTENT_TYPE) != Some(&APPLICATION_OCTET_STREAM) {
return Err(Error::internal_safe("invalid response Content-Type"));
}
Ok(response.into_body())
}
}
impl<R> AsyncDeserializeResponse<R, R> for BinaryResponseDeserializer
where
R: Send,
{
fn accept(_: &ConjureRuntime) -> Option<HeaderValue> {
Some(APPLICATION_OCTET_STREAM)
}
async fn deserialize(_: &ConjureRuntime, response: Response<R>) -> Result<R, Error> {
if response.headers().get(CONTENT_TYPE) != Some(&APPLICATION_OCTET_STREAM) {
return Err(Error::internal_safe("invalid response Content-Type"));
}
Ok(response.into_body())
}
}
impl<R> LocalAsyncDeserializeResponse<R, R> for BinaryResponseDeserializer {
fn accept(_: &ConjureRuntime) -> Option<HeaderValue> {
Some(APPLICATION_OCTET_STREAM)
}
async fn deserialize(_: &ConjureRuntime, response: Response<R>) -> Result<R, Error> {
if response.headers().get(CONTENT_TYPE) != Some(&APPLICATION_OCTET_STREAM) {
return Err(Error::internal_safe("invalid response Content-Type"));
}
Ok(response.into_body())
}
}
pub enum OptionalBinaryResponseDeserializer {}
impl<R> DeserializeResponse<Option<R>, R> for OptionalBinaryResponseDeserializer {
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<BinaryResponseDeserializer as DeserializeResponse<R, R>>::accept(runtime)
}
fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<Option<R>, Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(None);
}
<BinaryResponseDeserializer as DeserializeResponse<R, R>>::deserialize(runtime, response)
.map(Some)
}
}
impl<R> AsyncDeserializeResponse<Option<R>, R> for OptionalBinaryResponseDeserializer
where
R: Send,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<BinaryResponseDeserializer as AsyncDeserializeResponse<R, R>>::accept(runtime)
}
async fn deserialize(
runtime: &ConjureRuntime,
response: Response<R>,
) -> Result<Option<R>, Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(None);
}
<BinaryResponseDeserializer as AsyncDeserializeResponse<R, R>>::deserialize(
runtime, response,
)
.await
.map(Some)
}
}
impl<R> LocalAsyncDeserializeResponse<Option<R>, R> for OptionalBinaryResponseDeserializer {
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<BinaryResponseDeserializer as LocalAsyncDeserializeResponse<R, R>>::accept(runtime)
}
async fn deserialize(
runtime: &ConjureRuntime,
response: Response<R>,
) -> Result<Option<R>, Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(None);
}
<BinaryResponseDeserializer as LocalAsyncDeserializeResponse<R, R>>::deserialize(
runtime, response,
)
.await
.map(Some)
}
}
pub enum EmptyResponseDeserializer {}
impl<R> DeserializeResponse<(), R> for EmptyResponseDeserializer
where
R: Iterator<Item = Result<Bytes, Error>>,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<StdResponseDeserializer as DeserializeResponse<(), R>>::accept(runtime)
}
fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<(), Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(());
}
<StdResponseDeserializer as DeserializeResponse<IgnoredAny, R>>::deserialize(
runtime, response,
)?;
Ok(())
}
}
impl<R> AsyncDeserializeResponse<(), R> for EmptyResponseDeserializer
where
R: Stream<Item = Result<Bytes, Error>> + Send,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<StdResponseDeserializer as AsyncDeserializeResponse<(), R>>::accept(runtime)
}
async fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<(), Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(());
}
<StdResponseDeserializer as AsyncDeserializeResponse<IgnoredAny, R>>::deserialize(
runtime, response,
)
.await?;
Ok(())
}
}
impl<R> LocalAsyncDeserializeResponse<(), R> for EmptyResponseDeserializer
where
R: Stream<Item = Result<Bytes, Error>>,
{
fn accept(runtime: &ConjureRuntime) -> Option<HeaderValue> {
<StdResponseDeserializer as LocalAsyncDeserializeResponse<(), R>>::accept(runtime)
}
async fn deserialize(runtime: &ConjureRuntime, response: Response<R>) -> Result<(), Error> {
if response.status() == StatusCode::NO_CONTENT {
return Ok(());
}
<StdResponseDeserializer as LocalAsyncDeserializeResponse<IgnoredAny, R>>::deserialize(
runtime, response,
)
.await?;
Ok(())
}
}
pub enum PlainEncoder {}
impl<T> EncodeParam<T> for PlainEncoder
where
T: Plain,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<String>, Error> {
Ok(vec![value.to_plain()])
}
}
impl<T> EncodeHeader<T> for PlainEncoder
where
T: Plain,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<HeaderValue>, Error> {
HeaderValue::try_from(value.to_plain())
.map_err(Error::internal_safe)
.map(|v| vec![v])
}
}
pub enum PlainSeqEncoder {}
impl<T, U> EncodeParam<T> for PlainSeqEncoder
where
T: IntoIterator<Item = U>,
U: Plain,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<String>, Error> {
Ok(value.into_iter().map(|v| v.to_plain()).collect())
}
}
impl<T, U> EncodeHeader<T> for PlainSeqEncoder
where
T: IntoIterator<Item = U>,
U: Plain,
{
fn encode(_: &ConjureRuntime, value: T) -> Result<Vec<HeaderValue>, Error> {
value
.into_iter()
.map(|v| HeaderValue::try_from(v.to_plain()).map_err(Error::internal_safe))
.collect()
}
}