1use o3::buffer::resident::bound;
2
3use crate::{
4 payload,
5 payload::{
6 fixed::Body,
7 response::{
8 self, bounded, exact,
9 headers::{self, set},
10 status::Code,
11 },
12 },
13};
14
15pub mod chunk;
16
17pub enum Sync {}
18pub enum Polled {}
19pub enum Never {}
20
21pub trait Dispatch {
22 type Output<'d, E: Sink<'d>, S>;
23
24 fn fold<'d, E: Sink<'d>, S, T>(
25 output: Self::Output<'d, E, S>,
26 sync: impl FnOnce(E::Output) -> T,
27 stream: impl FnOnce(E::Stream<S>) -> T,
28 ) -> T;
29}
30
31impl Dispatch for Sync {
32 type Output<'d, E: Sink<'d>, S> = E::Output;
33
34 fn fold<'d, E: Sink<'d>, S, T>(
35 output: Self::Output<'d, E, S>,
36 sync: impl FnOnce(E::Output) -> T,
37 _: impl FnOnce(E::Stream<S>) -> T,
38 ) -> T {
39 sync(output)
40 }
41}
42
43impl Dispatch for Polled {
44 type Output<'d, E: Sink<'d>, S> = E::Stream<S>;
45
46 fn fold<'d, E: Sink<'d>, S, T>(
47 output: Self::Output<'d, E, S>,
48 _: impl FnOnce(E::Output) -> T,
49 stream: impl FnOnce(E::Stream<S>) -> T,
50 ) -> T {
51 stream(output)
52 }
53}
54
55pub enum Either<L, R> {
57 Left(L),
58 Right(R),
59}
60
61pub trait Accept<'d>: Sized {
63 type Output;
64 type Error;
65
66 fn fixed<H, B>(self, status: Code, headers: H, body: B) -> Result<Self::Output, Self::Error>
67 where
68 H: headers::Source,
69 B: response::Body<'d>;
70
71 fn statics<'body, H>(
72 self,
73 status: Code,
74 headers: H,
75 body: Body<'body>,
76 ) -> Result<Self::Output, Self::Error>
77 where
78 H: headers::Source,
79 'body: 'd,
80 {
81 self.fixed(status, headers, body)
82 }
83
84 fn exact<H, B>(self, status: Code, headers: H, body: B) -> Result<Self::Output, Self::Error>
85 where
86 H: headers::Source,
87 B: exact::TryBody;
88
89 fn bounded<H, B>(self, status: Code, headers: H, body: B) -> Result<Self::Output, Self::Error>
90 where
91 H: headers::Source,
92 B: bounded::Body;
93}
94
95pub trait Sink<'d>: Accept<'d> {
97 type Stream<S>;
98
99 fn stream<H, S>(
100 self,
101 status: Code,
102 headers: H,
103 stream: S,
104 ) -> Result<Self::Stream<S>, Self::Error>
105 where
106 H: headers::Source;
107}
108
109pub trait Emit<'req, 'd>: Sized {
110 type Kind: Dispatch;
111 type Stream;
112 type Bound: bound::Bound + 'd;
113
114 const BODY: payload::Kind;
115
116 fn emit<S>(
117 self,
118 sink: S,
119 ) -> Result<<Self::Kind as Dispatch>::Output<'d, S, Self::Stream>, S::Error>
120 where
121 S: Sink<'d>;
122}
123
124pub trait IntoOutput<'req, 'd>: Sized {
125 type Output: Emit<'req, 'd>;
126
127 fn into_output(self) -> Self::Output;
128}
129
130#[doc(hidden)]
131pub trait Complete<'req, 'd>: Sized {
132 type Bound: bound::Bound + 'd;
133
134 const BODY: payload::Kind;
135
136 fn complete<S>(self, sink: S) -> Result<S::Output, S::Error>
137 where
138 S: Accept<'d>;
139}
140
141impl<'req, 'd, T: Complete<'req, 'd>> Emit<'req, 'd> for T {
142 type Kind = Sync;
143 type Stream = Never;
144 type Bound = T::Bound;
145
146 const BODY: payload::Kind = T::BODY;
147
148 fn emit<S: Sink<'d>>(self, sink: S) -> Result<S::Output, S::Error> {
149 self.complete(sink)
150 }
151}
152
153pub trait Immediate<'req, 'd>: Sized {
156 type Bound: bound::Bound + 'd;
157
158 fn emit<S>(self, sink: S) -> Result<S::Output, S::Error>
159 where
160 S: Accept<'d>;
161}
162
163impl<'req, 'd, T> Immediate<'req, 'd> for T
164where
165 T: IntoOutput<'req, 'd>,
166 T::Output: Complete<'req, 'd>,
167{
168 type Bound = <T::Output as Complete<'req, 'd>>::Bound;
169
170 fn emit<S>(self, sink: S) -> Result<S::Output, S::Error>
171 where
172 S: Accept<'d>,
173 {
174 self.into_output().complete(sink)
175 }
176}
177
178impl<'req, 'd, L, R> IntoOutput<'req, 'd> for Either<L, R>
179where
180 L: Immediate<'req, 'd>,
181 R: Immediate<'req, 'd>,
182{
183 type Output = Self;
184
185 fn into_output(self) -> Self::Output {
186 self
187 }
188}
189
190impl<'req, 'd, T, E> IntoOutput<'req, 'd> for Result<T, E>
191where
192 T: Immediate<'req, 'd>,
193 E: Immediate<'req, 'd>,
194{
195 type Output = Either<T, E>;
196
197 fn into_output(self) -> Self::Output {
198 match self {
199 Ok(output) => Either::Left(output),
200 Err(error) => Either::Right(error),
201 }
202 }
203}
204
205impl<'req, 'd, L, R> Complete<'req, 'd> for Either<L, R>
206where
207 L: Immediate<'req, 'd>,
208 R: Immediate<'req, 'd>,
209{
210 type Bound = bound::Max<L::Bound, R::Bound>;
211
212 const BODY: payload::Kind = payload::Kind::Inline;
213
214 fn complete<S>(self, sink: S) -> Result<S::Output, S::Error>
215 where
216 S: Accept<'d>,
217 {
218 match self {
219 Self::Left(output) => output.emit(sink),
220 Self::Right(output) => output.emit(sink),
221 }
222 }
223}
224
225pub struct Stream<'req, S, const N: usize = 0> {
226 status: Code,
227 headers: set::Set<'req, N>,
228 stream: S,
229}
230
231impl<S, const N: usize> Stream<'_, S, N> {
232 pub fn with_status(mut self, status: Code) -> Self {
233 self.status = status;
234 self
235 }
236}
237
238impl<'req, S> Stream<'req, S, 0> {
239 pub fn new(stream: S) -> Self {
240 Self {
241 status: Code::OK,
242 headers: set::Set::new(),
243 stream,
244 }
245 }
246
247 pub fn headers<const N: usize>(self, headers: set::Set<'req, N>) -> Stream<'req, S, N> {
248 Stream {
249 status: self.status,
250 headers,
251 stream: self.stream,
252 }
253 }
254}
255
256impl<'req, 'd, 'head: 'req, S, const N: usize> IntoOutput<'req, 'd> for Stream<'head, S, N> {
257 type Output = Self;
258
259 fn into_output(self) -> Self::Output {
260 self
261 }
262}
263
264impl<'req, 'd, 'head: 'req, S, const N: usize> Emit<'req, 'd> for Stream<'head, S, N> {
265 type Kind = Polled;
266 type Stream = S;
267 type Bound = bound::Unbounded;
268
269 const BODY: payload::Kind = payload::Kind::Stream;
270
271 fn emit<E>(self, sink: E) -> Result<E::Stream<S>, E::Error>
272 where
273 E: Sink<'d>,
274 {
275 let Self {
276 status,
277 headers,
278 stream,
279 } = self;
280 sink.stream(status, headers, stream)
281 }
282}