use std::convert::Infallible;
use std::time::Duration;
use bytes::Bytes;
use http_body_util::{BodyExt, Empty, Full};
use hyper::body::Incoming;
use crate::{BoxError, ReqBody, ResponseBody};
pub(crate) const MAX_REQUEST_BODY_BUFFER: usize = 16 << 20;
pub(crate) const MAX_INFLIGHT_BODY_BUFFERS: usize = 64;
pub(crate) const INBOUND_BODY_READ_TIMEOUT: Duration = Duration::from_secs(30);
pub(crate) fn full(bytes: Vec<u8>) -> ResponseBody {
Full::new(Bytes::from(bytes))
.map_err(|e: Infallible| -> BoxError { match e {} })
.boxed()
}
pub(crate) fn stream(body: Incoming) -> ResponseBody {
body.map_err(|e| -> BoxError { Box::new(e) }).boxed()
}
pub(crate) fn box_incoming(body: Incoming) -> ReqBody {
body.map_err(|e| -> BoxError { Box::new(e) }).boxed()
}
pub(crate) fn empty_req() -> ReqBody {
Empty::<Bytes>::new()
.map_err(|e: Infallible| -> BoxError { match e {} })
.boxed()
}
pub(crate) enum BufferOutcome {
Buffered(Vec<u8>),
TooLarge,
ReadError,
}
pub(crate) async fn buffer_request_body(mut body: ReqBody, max: usize) -> BufferOutcome {
use hyper::body::Body;
let hint = usize::try_from(body.size_hint().lower()).unwrap_or(usize::MAX);
let mut buf = Vec::with_capacity(hint.min(max));
while let Some(frame) = body.frame().await {
let Ok(frame) = frame else {
return BufferOutcome::ReadError;
};
if let Ok(data) = frame.into_data() {
if buf.len() + data.len() > max {
return BufferOutcome::TooLarge;
}
buf.extend_from_slice(&data);
}
}
BufferOutcome::Buffered(buf)
}
pub(crate) fn req_full(bytes: Bytes) -> ReqBody {
Full::new(bytes)
.map_err(|e: Infallible| -> BoxError { match e {} })
.boxed()
}