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