Skip to main content

sark_core/http/response/
shape.rs

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}