use std::future::Future;
use std::marker::PhantomData;
use prost::Message;
use serde::de::DeserializeOwned;
use reqwest::Response;
use crate::{CondSend, CondSync, Result};
pub trait ResponseHandler {
type Output;
const ACCEPT_HEADER: &'static str;
fn handle_response(
self,
response: Response,
) -> impl Future<Output = Result<Self::Output>> + CondSend + CondSync;
}
pub struct JsonResponseHandler<T>(PhantomData<fn() -> T>);
impl<T> Default for JsonResponseHandler<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> JsonResponseHandler<T> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl<T: DeserializeOwned> ResponseHandler for JsonResponseHandler<T> {
type Output = T;
const ACCEPT_HEADER: &'static str = "application/json";
async fn handle_response(self, response: Response) -> Result<Self::Output> {
Ok(response.json().await?)
}
}
pub struct ProtoResponseHandler<T>(PhantomData<fn() -> T>);
impl<T> Default for ProtoResponseHandler<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> ProtoResponseHandler<T> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl<T: Message + Default + CondSend + CondSync> ResponseHandler for ProtoResponseHandler<T> {
type Output = T;
const ACCEPT_HEADER: &'static str = "application/protobuf";
async fn handle_response(self, response: Response) -> Result<Self::Output> {
let bytes = response.bytes().await?;
Ok(T::decode(bytes)?)
}
}
#[derive(Default)]
pub struct RawResponseHandler;
impl ResponseHandler for RawResponseHandler {
type Output = Response;
const ACCEPT_HEADER: &'static str = "*/*";
async fn handle_response(self, response: Response) -> Result<Self::Output> {
Ok(response)
}
}
#[derive(Default)]
pub struct NoResponseHandler;
impl ResponseHandler for NoResponseHandler {
type Output = ();
const ACCEPT_HEADER: &'static str = "*/*";
async fn handle_response(self, _response: Response) -> Result<Self::Output> {
Ok(())
}
}