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