use super::*;
use h2::{server::SendResponse, SendStream, StreamId};
#[derive(Debug)]
pub struct Response {
pub status: http::StatusCode,
pub headers: http::HeaderMap,
#[doc(hidden)]
pub sender: SendResponse<Bytes>,
}
impl Response {
#[inline]
pub fn stream_id(&self) -> StreamId {
self.sender.stream_id()
}
fn create_response(mut self, end: bool) -> Result<SendStream<Bytes>> {
let mut response = http::Response::new(());
*response.status_mut() = self.status;
*response.headers_mut() = self.headers;
self.sender.send_response(response, end)
}
#[inline]
pub fn send_headers(self) -> Result<()> {
self.create_response(true)?;
Ok(())
}
#[inline]
pub fn send_stream(self) -> Result<Responder> {
let inner = self.create_response(false)?;
Ok(Responder { inner })
}
#[inline]
pub async fn write(self, bytes: impl Into<Bytes>) -> Result<()> {
self.send_stream()?.end_write(bytes).await
}
#[inline]
pub fn write_unbound(self, bytes: impl Into<Bytes>) -> Result<()> {
self.send_stream()?.end_write_unbound(bytes)
}
}
pub struct Responder {
#[doc(hidden)]
pub inner: SendStream<Bytes>,
}
impl Responder {
#[doc(hidden)]
pub async fn write_bytes(&mut self, mut bytes: Bytes, end: bool) -> Result<()> {
loop {
let len = bytes.len();
self.inner.reserve_capacity(len);
match poll_fn(|cx| self.inner.poll_capacity(cx)).await {
None => return Err(h2::Error::from(h2::Reason::CANCEL)),
Some(nbytes) => {
let nbytes = nbytes?;
if len <= nbytes {
return self.inner.send_data(bytes, end);
}
self.inner.send_data(bytes.split_to(nbytes), false)?;
}
};
}
}
pub async fn write(&mut self, bytes: impl Into<Bytes>) -> Result<()> {
let bytes = bytes.into();
if bytes.is_empty() {
return Ok(());
}
self.write_bytes(bytes, false).await
}
pub async fn end_write(mut self, bytes: impl Into<Bytes>) -> Result<()> {
let bytes = bytes.into();
if bytes.is_empty() {
return self.end();
}
self.write_bytes(bytes, true).await
}
pub fn write_unbound(&mut self, bytes: impl Into<Bytes>) -> Result<()> {
self.inner.send_data(bytes.into(), false)
}
pub fn end_write_unbound(mut self, bytes: impl Into<Bytes>) -> Result<()> {
self.inner.send_data(bytes.into(), true)
}
#[inline]
pub fn end(mut self) -> Result<()> {
self.inner.send_data(Bytes::new(), true)
}
}