1use dope_fiber::{Context, Fiber};
2use http::StatusCode;
3use o3::buffer::Shared;
4
5use super::{
6 Chunked, EncodedBody, EncodedResponseInner, FixedResponseInner, MonoResponseInner, ServeInner,
7 StaticResponseInner, Stream,
8};
9
10pub struct NeverStream(std::marker::PhantomData<()>);
11
12impl<'d> Fiber<'d> for NeverStream {
13 type Output = Option<Shared>;
14 fn poll(
15 self: std::pin::Pin<&mut Self>,
16 _cx: std::pin::Pin<&mut Context<'_, 'd>>,
17 ) -> std::task::Poll<Self::Output> {
18 unreachable!("NeverStream polled — non-Stream Shape")
19 }
20}
21
22pub trait Shape<'req>: Sized {
23 type StreamInner: 'static;
24
25 fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
26 let _ = (out, date);
27 unreachable!("Shape::write_into_slice called on non-Fixed shape")
28 }
29
30 fn preserialize(&self) -> (Vec<u8>, usize) {
31 unreachable!("Shape::preserialize called on non-Fixed shape")
32 }
33
34 fn write_head_only(&self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, &'static [u8])> {
35 let _ = (out, date);
36 unreachable!("Shape::write_head_only called on non-Static-body shape")
37 }
38
39 fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
40 let _ = (out, date);
41 None
42 }
43
44 fn preserialize_static(&self) -> Option<(Vec<u8>, usize, &'static [u8])> {
45 None
46 }
47
48 fn write_head_stream(
49 self,
50 out: &mut [u8],
51 date: &[u8; 29],
52 ) -> Option<(usize, Self::StreamInner)> {
53 let _ = (out, date);
54 unreachable!("Shape::write_head_stream called on non-Stream-body shape")
55 }
56
57 fn body_for_gzip(&self) -> Option<&[u8]> {
58 None
59 }
60
61 fn write_gzip_head(self, out: &mut [u8], date: &[u8; 29], body_len: usize) -> Option<usize> {
62 let _ = (out, date, body_len);
63 unreachable!("Shape::write_gzip_head called on shape without body_for_gzip")
64 }
65
66 fn status(&self) -> StatusCode {
67 unreachable!("Shape::status called on shape without a status line")
68 }
69
70 fn body_bytes(&self) -> &[u8] {
71 &[]
72 }
73
74 fn headers_wire(&self) -> Shared {
75 Shared::new()
76 }
77}
78
79impl<'req, const N: usize> Shape<'req> for FixedResponseInner<'req, N> {
80 type StreamInner = NeverStream;
81
82 fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
83 FixedResponseInner::write_into_slice(self, out, date)
84 }
85
86 fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
87 FixedResponseInner::write_head_split(self, out, date)
88 }
89
90 fn preserialize(&self) -> (Vec<u8>, usize) {
91 FixedResponseInner::preserialize(self)
92 }
93
94 fn body_for_gzip(&self) -> Option<&[u8]> {
95 if self.has_content_encoding() {
96 None
97 } else {
98 Some(self.body_ref())
99 }
100 }
101
102 fn write_gzip_head(self, out: &mut [u8], date: &[u8; 29], body_len: usize) -> Option<usize> {
103 FixedResponseInner::write_gzip_head(self, out, date, body_len)
104 }
105
106 fn status(&self) -> StatusCode {
107 FixedResponseInner::status(self)
108 }
109
110 fn body_bytes(&self) -> &[u8] {
111 self.body_ref()
112 }
113
114 fn headers_wire(&self) -> Shared {
115 self.wire_headers()
116 }
117}
118
119impl<'req, B, const N: usize> Shape<'req> for EncodedResponseInner<'req, B, N>
120where
121 B: EncodedBody,
122{
123 type StreamInner = NeverStream;
124
125 fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
126 EncodedResponseInner::write_into_slice(self, out, date)
127 }
128
129 fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
130 EncodedResponseInner::write_head_split(self, out, date)
131 }
132
133 fn preserialize(&self) -> (Vec<u8>, usize) {
134 EncodedResponseInner::preserialize(self)
135 }
136
137 fn status(&self) -> StatusCode {
138 EncodedResponseInner::status(self)
139 }
140
141 fn headers_wire(&self) -> Shared {
142 EncodedResponseInner::wire_headers(self)
143 }
144}
145
146impl<'req, const N: usize> Shape<'req> for MonoResponseInner<'req, N> {
147 type StreamInner = NeverStream;
148
149 fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
150 MonoResponseInner::write_into_slice(self, out, date)
151 }
152
153 fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
154 MonoResponseInner::write_head_split(self, out, date)
155 }
156}
157
158impl<'req, const N: usize> Shape<'req> for StaticResponseInner<'req, N> {
159 type StreamInner = NeverStream;
160
161 fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
162 StaticResponseInner::write_into_slice(self, out, date)
163 }
164
165 fn write_head_only(&self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, &'static [u8])> {
166 StaticResponseInner::write_head_only(self, out, date)
167 }
168
169 fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
170 StaticResponseInner::write_head_split(self, out, date)
171 }
172
173 fn preserialize_static(&self) -> Option<(Vec<u8>, usize, &'static [u8])> {
174 Some(StaticResponseInner::preserialize_static(self))
175 }
176
177 fn status(&self) -> StatusCode {
178 StaticResponseInner::status(self)
179 }
180
181 fn body_bytes(&self) -> &[u8] {
182 self.body_ref()
183 }
184
185 fn headers_wire(&self) -> Shared {
186 StaticResponseInner::wire_headers(self)
187 }
188}
189
190impl<'req> Shape<'req> for Chunked {
191 type StreamInner = NeverStream;
192
193 fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
194 Self::write_into_slice(self, out, date)
195 }
196
197 fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
198 Chunked::write_head_split(self, out, date)
199 }
200}
201
202impl<'req, S> Shape<'req> for Stream<S>
203where
204 S: 'static,
205{
206 type StreamInner = S;
207
208 fn write_head_stream(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, S)> {
209 Stream::<S>::write_head_stream(self, out, date)
210 }
211}
212
213impl<'req, const N: usize> Shape<'req> for ServeInner<'req, N> {
214 type StreamInner = NeverStream;
215
216 fn write_into_slice(&self, out: &mut [u8], date: &[u8; 29]) -> Option<usize> {
217 match self {
218 Self::Fixed(f) => f.write_into_slice(out, date),
219 Self::Mono(m) => m.write_into_slice(out, date),
220 Self::Chunked(c) => c.write_into_slice(out, date),
221 }
222 }
223
224 fn preserialize(&self) -> (Vec<u8>, usize) {
225 match self {
226 Self::Fixed(f) => f.preserialize(),
227 Self::Mono(_) | Self::Chunked(_) => {
228 unreachable!("Shape::preserialize: STATIC_RESPONSE route returned non-Fixed")
229 }
230 }
231 }
232
233 fn write_head_split(self, out: &mut [u8], date: &[u8; 29]) -> Option<(usize, Shared)> {
234 match self {
235 Self::Mono(m) => MonoResponseInner::write_head_split(m, out, date),
236 Self::Chunked(c) => Chunked::write_head_split(c, out, date),
237 Self::Fixed(f) => FixedResponseInner::write_head_split(f, out, date),
238 }
239 }
240
241 fn body_for_gzip(&self) -> Option<&[u8]> {
242 match self {
243 Self::Fixed(f) if !f.has_content_encoding() => Some(f.body_ref()),
244 _ => None,
245 }
246 }
247
248 fn write_gzip_head(self, out: &mut [u8], date: &[u8; 29], body_len: usize) -> Option<usize> {
249 match self {
250 Self::Fixed(f) => FixedResponseInner::write_gzip_head(f, out, date, body_len),
251 _ => unreachable!("write_gzip_head on non-Fixed ServeInner"),
252 }
253 }
254
255 fn status(&self) -> StatusCode {
256 match self {
257 Self::Fixed(f) => f.status(),
258 Self::Mono(m) => m.status(),
259 Self::Chunked(_) => StatusCode::OK,
260 }
261 }
262
263 fn body_bytes(&self) -> &[u8] {
264 match self {
265 Self::Fixed(f) => f.body_ref(),
266 Self::Mono(_) | Self::Chunked(_) => &[],
267 }
268 }
269
270 fn headers_wire(&self) -> Shared {
271 match self {
272 Self::Fixed(f) => f.wire_headers(),
273 Self::Mono(_) | Self::Chunked(_) => Shared::new(),
274 }
275 }
276}