pub(crate) mod handle;
use crate::{
convert::{Borrowable, ToHeaderName, ToHeaderValue},
experimental::StreamingBodyExt,
handle::StreamingBodyHandle,
http::Body,
};
use http::header::HeaderMap;
use std::io::{BufWriter, Write};
#[must_use = "streaming bodies must be `.finish()`ed"]
pub struct StreamingBody {
writer: BufWriter<StreamingBodyHandle>,
}
impl StreamingBody {
pub fn finish(self) -> std::io::Result<()> {
self.writer
.into_inner()?
.finish()
.map_err(std::io::Error::other)
}
pub fn abandon(self) -> std::io::Result<()> {
self.writer
.into_inner()?
.abandon()
.map_err(std::io::Error::other)
}
fn handle(&mut self) -> &mut StreamingBodyHandle {
self.writer.get_mut()
}
pub(crate) fn into_handle(self) -> std::io::Result<StreamingBodyHandle> {
Ok(self.writer.into_inner()?)
}
#[doc = include_str!("../../../docs/snippets/body-append-constant-time.md")]
pub fn append(&mut self, other: Body) {
self.writer.flush().expect("fastly_http_body::write failed");
self.handle().append(other.into_handle())
}
}
impl From<StreamingBodyHandle> for StreamingBody {
fn from(handle: StreamingBodyHandle) -> Self {
Self {
writer: BufWriter::new(handle),
}
}
}
impl Write for StreamingBody {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.writer.write(buf)
}
fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
self.writer.write_vectored(bufs)
}
fn flush(&mut self) -> std::io::Result<()> {
self.writer.flush()
}
}
impl StreamingBodyExt for StreamingBody {
fn append_trailer(&mut self, name: impl ToHeaderName, value: impl ToHeaderValue) {
self.handle().append_trailer(
name.into_borrowable().as_ref(),
value.into_borrowable().as_ref(),
);
}
fn finish_with_trailers(mut self, trailers: &HeaderMap) -> Result<(), std::io::Error> {
self.writer.get_mut().set_trailers(trailers);
self.writer
.into_inner()?
.finish()
.map_err(std::io::Error::other)
}
}