1use std::convert::Infallible;
2
3pub type Stream<'d, R, A> =
4 <<<R as route::Task<'d, A>>::Output as dispatch::IntoOutput<'d, 'd>>::Output as dispatch::Emit<
5 'd,
6 'd,
7 >>::Stream;
8
9pub type Emitted<'d, S, B> = Result<
10 (
11 <S as decode::Encode<'d, 'd>>::Prepared,
12 Option<B>,
13 life::Outcome,
14 ),
15 (
16 <S as decode::Encode<'d, 'd>>::Error,
17 <S as decode::Cancel>::Target,
18 ),
19>;
20
21pub type Prepared<'d, S> = Result<
22 (<S as decode::Encode<'d, 'd>>::Prepared, State),
23 (
24 <S as decode::Encode<'d, 'd>>::Error,
25 <S as decode::Cancel>::Target,
26 ),
27>;
28
29pub type Complete<'d, S> = Result<
30 (<S as decode::Encode<'d, 'd>>::Prepared, life::Outcome),
31 (
32 <S as decode::Encode<'d, 'd>>::Error,
33 <S as decode::Cancel>::Target,
34 ),
35>;
36
37use sark_http::{
38 payload::response::{Response, dispatch, dispatch::chunk::Chunk},
39 request::Id,
40};
41
42use crate::{
43 decode, life,
44 route::{self, Reject},
45};
46
47pub enum Outcome<T> {
48 Response(T),
49 Rejected(Reject),
50}
51
52pub enum Event<'d, E> {
53 Head,
56 Chunk(Chunk<'d>),
57 Failed(E),
58 End,
60}
61
62pub enum State {
63 Complete(life::Outcome),
64 Streaming,
65}
66
67pub enum Access<T> {
68 Absent,
70 Active,
72 Ready(T),
73}
74
75pub struct Output<'d, R: route::Task<'d, A>, A> {
77 id: Id<'d>,
78 outcome: Outcome<R::Output>,
79}
80
81impl<'d, R: route::Task<'d, A>, A> Output<'d, R, A> {
82 pub const fn response(id: Id<'d>, response: R::Output) -> Self {
83 Self {
84 id,
85 outcome: Outcome::Response(response),
86 }
87 }
88
89 pub const fn rejected(id: Id<'d>, reject: Reject) -> Self {
90 Self {
91 id,
92 outcome: Outcome::Rejected(reject),
93 }
94 }
95
96 pub fn into_parts(self) -> (Id<'d>, Outcome<R::Output>) {
97 (self.id, self.outcome)
98 }
99
100 pub fn emit<S>(self, make: impl FnOnce(Id<'d>) -> S) -> Emitted<'d, S, Stream<'d, R, A>>
101 where
102 S: decode::Streaming<'d, 'd>,
103 {
104 let sink = make(self.id);
105 match self.outcome {
106 Outcome::Response(response) => {
107 let emitted =
108 dispatch::Emit::emit(dispatch::IntoOutput::into_output(response), sink)?;
109 let (prepared, stream) =
110 <<<R::Output as dispatch::IntoOutput<'d, 'd>>::Output as dispatch::Emit<
111 'd,
112 'd,
113 >>::Kind as dispatch::Dispatch>::fold::<S, Stream<'d, R, A>, _>(
114 emitted,
115 |prepared| (prepared, None),
116 S::split_stream,
117 );
118 Ok((prepared, stream, life::Outcome::Completed))
119 }
120 Outcome::Rejected(reject) => {
121 let prepared = dispatch::Immediate::emit(Response::new(reject.status()), sink)?;
122 Ok((prepared, None, life::Outcome::Rejected))
123 }
124 }
125 }
126}
127pub trait Completion<'d>: Sized {
129 fn emit<E: decode::Encode<'d, 'd>>(self, make: impl FnOnce(Id<'d>) -> E) -> Complete<'d, E>;
130}
131
132impl<'d, R, A> Completion<'d> for Output<'d, R, A>
133where
134 R: route::Task<'d, A>,
135 <R::Output as dispatch::IntoOutput<'d, 'd>>::Output: dispatch::Complete<'d, 'd>,
136{
137 fn emit<E: decode::Encode<'d, 'd>>(self, make: impl FnOnce(Id<'d>) -> E) -> Complete<'d, E> {
138 let sink = make(self.id);
139 let (prepared, outcome) = match self.outcome {
140 Outcome::Response(response) => (
141 dispatch::Immediate::emit(response, sink)?,
142 life::Outcome::Completed,
143 ),
144 Outcome::Rejected(reject) => (
145 dispatch::Immediate::emit(Response::new(reject.status()), sink)?,
146 life::Outcome::Rejected,
147 ),
148 };
149 Ok((prepared, outcome))
150 }
151}
152
153impl<'d> Completion<'d> for Infallible {
154 fn emit<E: decode::Encode<'d, 'd>>(self, _: impl FnOnce(Id<'d>) -> E) -> Complete<'d, E> {
155 match self {}
156 }
157}