Skip to main content

sark_core/http/response/
shape.rs

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}