use bytes::Bytes;
use http::HeaderValue;
use http_body_util::{BodyExt, Full};
use crate::{
BoxError,
body::{
Body,
codec::{BodyContentType, BodyDecoder, BodyEncoder},
},
};
#[derive(Clone, Debug)]
pub struct OctetEncoder {
pub content_type: HeaderValue,
}
impl Default for OctetEncoder {
fn default() -> Self {
Self {
content_type: HeaderValue::from_static("application/octet-stream"),
}
}
}
impl OctetEncoder {
pub fn with_content_type(content_type: HeaderValue) -> Self {
Self { content_type }
}
}
impl BodyContentType for OctetEncoder {
fn content_type(&self) -> HeaderValue {
self.content_type.clone()
}
}
impl BodyEncoder<Bytes> for OctetEncoder {
type Error = std::convert::Infallible;
fn encode(&self, data: Bytes) -> Result<Body, Self::Error> {
Ok(Body::new(Full::new(data)))
}
}
impl BodyEncoder<&Bytes> for OctetEncoder {
type Error = std::convert::Infallible;
fn encode(&self, data: &Bytes) -> Result<Body, Self::Error> {
<Self as BodyEncoder<Bytes>>::encode(self, data.clone())
}
}
impl BodyEncoder<Vec<u8>> for OctetEncoder {
type Error = std::convert::Infallible;
fn encode(&self, data: Vec<u8>) -> Result<Body, Self::Error> {
Ok(Body::new(Full::new(Bytes::from(data))))
}
}
#[derive(Clone, Debug, Default)]
pub struct OctetDecoder;
#[derive(Debug, thiserror::Error)]
pub enum OctetDecodeError {
#[error("body read error: {0}")]
Body(#[source] BoxError),
}
impl BodyDecoder<Bytes> for OctetDecoder {
type Error = OctetDecodeError;
async fn decode<B>(&self, body: B) -> Result<Bytes, Self::Error>
where
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
B::Error: Into<BoxError>,
{
let collected = body
.collect()
.await
.map_err(|e| OctetDecodeError::Body(e.into()))?;
Ok(collected.to_bytes())
}
}