use bytes::Bytes;
use http::HeaderValue;
use crate::{BoxError, Request, body::Body};
pub mod form;
pub mod json;
pub mod multipart;
#[cfg(feature = "ndjson")]
pub mod ndjson;
pub mod octet;
#[cfg(feature = "sse")]
pub mod sse;
pub mod text;
#[cfg(feature = "xml")]
pub mod xml;
pub fn encode_body<E, T>(encoder: &E, data: T, request: Request) -> Result<Request, E::Error>
where
E: BodyEncoder<T>,
{
let (mut parts, _) = request.into_parts();
let body = encoder.encode(data)?;
parts.headers.insert(
http::header::CONTENT_TYPE,
BodyContentType::content_type(encoder),
);
Ok(Request::from_parts(parts, body))
}
pub trait BodyContentType {
fn content_type(&self) -> HeaderValue;
}
pub trait BodyEncoder<T>: BodyContentType {
type Error: std::error::Error + Send + Sync + 'static;
fn encode(&self, data: T) -> Result<Body, Self::Error>;
}
pub async fn decode_body<D, B, O>(decoder: &D, body: B) -> Result<O, D::Error>
where
D: BodyDecoder<O>,
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
B::Error: Into<BoxError>,
{
decoder.decode(body).await
}
pub trait BodyDecoder<O> {
type Error: std::error::Error + Send + Sync + 'static;
fn decode<B>(&self, body: B) -> impl Future<Output = Result<O, Self::Error>> + Send
where
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
B::Error: Into<BoxError>;
}