use core::convert::Infallible;
use std::io::Write;
use crate::{
bytes::{buf::Chain, Buf, BufMut, BufMutWriter, Bytes, BytesMut, EitherBuf},
util::buffered::{BufWrite, ListWriteBuf, WriteBuf},
};
pub trait H1BufWrite: BufWrite {
#[inline]
fn write_buf_head<F, T, E>(&mut self, func: F) -> Result<T, E>
where
F: FnOnce(&mut BytesMut) -> Result<T, E>,
{
self.write_buf(func)
}
fn write_buf_static(&mut self, bytes: &'static [u8]) {
let _ = self.write_buf(|buf| {
buf.put_slice(bytes);
Ok::<_, Infallible>(())
});
}
fn write_buf_bytes(&mut self, bytes: Bytes) {
let _ = self.write_buf(|buf| {
buf.put_slice(bytes.as_ref());
Ok::<_, Infallible>(())
});
}
fn write_buf_bytes_chunked(&mut self, bytes: Bytes) {
let _ = self.write_buf(|buf| {
write!(BufMutWriter(buf), "{:X}\r\n", bytes.len()).unwrap();
buf.reserve(bytes.len() + 2);
buf.put_slice(bytes.as_ref());
buf.put_slice(b"\r\n");
Ok::<_, Infallible>(())
});
}
}
impl H1BufWrite for BytesMut {}
impl<const BUF_LIMIT: usize> H1BufWrite for WriteBuf<BUF_LIMIT> {}
type Eof = Chain<Chain<Bytes, Bytes>, &'static [u8]>;
type EncodedBuf<B, B2> = EitherBuf<B, EitherBuf<B2, &'static [u8]>>;
impl<const BUF_LIMIT: usize> H1BufWrite for ListWriteBuf<EncodedBuf<Bytes, Eof>, BUF_LIMIT> {
fn write_buf_head<F, T, E>(&mut self, func: F) -> Result<T, E>
where
F: FnOnce(&mut BytesMut) -> Result<T, E>,
{
self.write_buf(func).map(|t| {
let bytes = self.split_buf().freeze();
self.buffer(EitherBuf::Left(bytes));
t
})
}
#[inline]
fn write_buf_static(&mut self, bytes: &'static [u8]) {
self.buffer(EitherBuf::Right(EitherBuf::Right(bytes)));
}
#[inline]
fn write_buf_bytes(&mut self, bytes: Bytes) {
self.buffer(EitherBuf::Left(bytes));
}
#[inline]
fn write_buf_bytes_chunked(&mut self, bytes: Bytes) {
let chunk = Bytes::from(format!("{:X}\r\n", bytes.len()))
.chain(bytes)
.chain(b"\r\n" as &'static [u8]);
self.buffer(EitherBuf::Right(EitherBuf::Left(chunk)));
}
}
impl<L, R> H1BufWrite for EitherBuf<L, R>
where
L: H1BufWrite,
R: H1BufWrite,
{
#[inline]
fn write_buf_head<F, T, E>(&mut self, func: F) -> Result<T, E>
where
F: FnOnce(&mut BytesMut) -> Result<T, E>,
{
match *self {
Self::Left(ref mut l) => l.write_buf_head(func),
Self::Right(ref mut r) => r.write_buf_head(func),
}
}
#[inline]
fn write_buf_static(&mut self, bytes: &'static [u8]) {
match *self {
Self::Left(ref mut l) => l.write_buf_static(bytes),
Self::Right(ref mut r) => r.write_buf_static(bytes),
}
}
#[inline]
fn write_buf_bytes(&mut self, bytes: Bytes) {
match *self {
Self::Left(ref mut l) => l.write_buf_bytes(bytes),
Self::Right(ref mut r) => r.write_buf_bytes(bytes),
}
}
#[inline]
fn write_buf_bytes_chunked(&mut self, bytes: Bytes) {
match *self {
Self::Left(ref mut l) => l.write_buf_bytes_chunked(bytes),
Self::Right(ref mut r) => r.write_buf_bytes_chunked(bytes),
}
}
}