xitca_http/h1/proto/
buf_write.rs1use core::convert::Infallible;
2
3use std::io::Write;
4
5use crate::{
6 bytes::{Buf, BufMut, BufMutWriter, Bytes, BytesMut, EitherBuf, buf::Chain},
7 util::buffered::{BufWrite, ListWriteBuf, WriteBuf},
8};
9
10pub trait H1BufWrite: BufWrite {
12 #[inline]
15 fn write_buf_head<F, T, E>(&mut self, func: F) -> Result<T, E>
16 where
17 F: FnOnce(&mut BytesMut) -> Result<T, E>,
18 {
19 self.write_buf(func)
20 }
21
22 fn write_buf_static(&mut self, bytes: &'static [u8]) {
24 let _ = self.write_buf(|buf| {
25 buf.put_slice(bytes);
26 Ok::<_, Infallible>(())
27 });
28 }
29
30 fn write_buf_bytes(&mut self, bytes: Bytes) {
32 let _ = self.write_buf(|buf| {
33 buf.put_slice(bytes.as_ref());
34 Ok::<_, Infallible>(())
35 });
36 }
37
38 fn write_buf_bytes_chunked(&mut self, bytes: Bytes) {
40 let _ = self.write_buf(|buf| {
41 write!(BufMutWriter(buf), "{:X}\r\n", bytes.len()).unwrap();
42 buf.reserve(bytes.len() + 2);
43 buf.put_slice(bytes.as_ref());
44 buf.put_slice(b"\r\n");
45 Ok::<_, Infallible>(())
46 });
47 }
48}
49
50impl H1BufWrite for BytesMut {}
51
52impl<const BUF_LIMIT: usize> H1BufWrite for WriteBuf<BUF_LIMIT> {}
53
54type Eof = Chain<Chain<Bytes, Bytes>, &'static [u8]>;
56
57type EncodedBuf<B, B2> = EitherBuf<B, EitherBuf<B2, &'static [u8]>>;
58
59impl<const BUF_LIMIT: usize> H1BufWrite for ListWriteBuf<EncodedBuf<Bytes, Eof>, BUF_LIMIT> {
60 fn write_buf_head<F, T, E>(&mut self, func: F) -> Result<T, E>
61 where
62 F: FnOnce(&mut BytesMut) -> Result<T, E>,
63 {
64 self.write_buf(func).inspect(|_| {
67 let bytes = self.split_buf().freeze();
68 self.buffer(EitherBuf::Left(bytes));
69 })
70 }
71
72 #[inline]
73 fn write_buf_static(&mut self, bytes: &'static [u8]) {
74 self.buffer(EitherBuf::Right(EitherBuf::Right(bytes)));
75 }
76
77 #[inline]
78 fn write_buf_bytes(&mut self, bytes: Bytes) {
79 self.buffer(EitherBuf::Left(bytes));
80 }
81
82 #[inline]
83 fn write_buf_bytes_chunked(&mut self, bytes: Bytes) {
84 let chunk = Bytes::from(format!("{:X}\r\n", bytes.len()))
85 .chain(bytes)
86 .chain(b"\r\n" as &'static [u8]);
87 self.buffer(EitherBuf::Right(EitherBuf::Left(chunk)));
88 }
89}
90
91impl<L, R> H1BufWrite for EitherBuf<L, R>
92where
93 L: H1BufWrite,
94 R: H1BufWrite,
95{
96 #[inline]
97 fn write_buf_head<F, T, E>(&mut self, func: F) -> Result<T, E>
98 where
99 F: FnOnce(&mut BytesMut) -> Result<T, E>,
100 {
101 match *self {
102 Self::Left(ref mut l) => l.write_buf_head(func),
103 Self::Right(ref mut r) => r.write_buf_head(func),
104 }
105 }
106
107 #[inline]
108 fn write_buf_static(&mut self, bytes: &'static [u8]) {
109 match *self {
110 Self::Left(ref mut l) => l.write_buf_static(bytes),
111 Self::Right(ref mut r) => r.write_buf_static(bytes),
112 }
113 }
114
115 #[inline]
116 fn write_buf_bytes(&mut self, bytes: Bytes) {
117 match *self {
118 Self::Left(ref mut l) => l.write_buf_bytes(bytes),
119 Self::Right(ref mut r) => r.write_buf_bytes(bytes),
120 }
121 }
122
123 #[inline]
124 fn write_buf_bytes_chunked(&mut self, bytes: Bytes) {
125 match *self {
126 Self::Left(ref mut l) => l.write_buf_bytes_chunked(bytes),
127 Self::Right(ref mut r) => r.write_buf_bytes_chunked(bytes),
128 }
129 }
130}