use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use bytes::Bytes;
#[cfg(not(target_arch = "wasm32"))]
use crate::transport::RespStream;
use crate::transport::{ClientError, UpstreamClient};
#[cfg(not(target_arch = "wasm32"))]
pub type CustomSend = Box<
dyn FnOnce(
Arc<dyn UpstreamClient>,
)
-> Pin<Box<dyn Future<Output = Result<http::Response<Bytes>, ClientError>> + Send>>
+ Send,
>;
#[cfg(target_arch = "wasm32")]
pub type CustomSend = Box<
dyn FnOnce(
Arc<dyn UpstreamClient>,
) -> Pin<Box<dyn Future<Output = Result<http::Response<Bytes>, ClientError>>>>,
>;
#[cfg(not(target_arch = "wasm32"))]
pub type CustomStreamSend = Box<
dyn FnOnce(
Arc<dyn UpstreamClient>,
) -> Pin<
Box<
dyn Future<
Output = Result<
(http::StatusCode, http::HeaderMap, RespStream),
ClientError,
>,
> + Send,
>,
> + Send,
>;
#[allow(clippy::large_enum_variant)]
pub enum PreparedRequest {
Direct(http::Request<Bytes>),
Custom(CustomSend),
#[cfg(not(target_arch = "wasm32"))]
CustomStream(CustomStreamSend),
}
impl PreparedRequest {
pub fn new(request: http::Request<Bytes>) -> Self {
Self::Direct(request)
}
pub fn custom(send: CustomSend) -> Self {
Self::Custom(send)
}
#[cfg(not(target_arch = "wasm32"))]
pub fn custom_stream(send: CustomStreamSend) -> Self {
Self::CustomStream(send)
}
pub async fn send_buffered(
self,
client: Arc<dyn UpstreamClient>,
) -> Result<http::Response<Bytes>, ClientError> {
match self {
Self::Direct(request) => client.send(request).await,
Self::Custom(send) => send(client).await,
#[cfg(not(target_arch = "wasm32"))]
Self::CustomStream(_) => Err(ClientError::Config(
"streaming custom exchange cannot run in a buffered request path".into(),
)),
}
}
pub fn into_http(self) -> Result<http::Request<Bytes>, ClientError> {
match self {
Self::Direct(request) => Ok(request),
Self::Custom(_) => Err(ClientError::Config(
"custom exchange requires execution through an upstream client".into(),
)),
#[cfg(not(target_arch = "wasm32"))]
Self::CustomStream(_) => Err(ClientError::Config(
"streaming custom exchange requires the streaming pipeline executor".into(),
)),
}
}
}
impl std::fmt::Debug for PreparedRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Direct(r) => f.debug_tuple("Direct").field(r).finish(),
Self::Custom(_) => f.write_str("Custom(<closure>)"),
#[cfg(not(target_arch = "wasm32"))]
Self::CustomStream(_) => f.write_str("CustomStream(<closure>)"),
}
}
}