1use sark_http::{payload::response::dispatch, request::Id};
2
3use crate::{
4 body::{
5 self,
6 admit::{Retention, Stream},
7 },
8 request,
9 request::frame::proof,
10};
11
12mod error;
13mod input;
14mod never;
15mod reject;
16
17pub use error::Error;
18pub use input::Input;
19pub use never::Never;
20pub use reject::Reject;
21pub mod field;
22pub mod guard;
23pub mod raw;
24pub mod table;
25
26use field::{header, query};
27
28pub trait TaskBuild<'d>: body::Build<'d, Output = Built<'d, Self::Task>> {
30 type Task;
31
32 fn reject(error: Self::StepError) -> Reject;
33}
34
35pub trait Push<'d>: TaskBuild<'d> + body::Push<'d> {
37 fn reject_push(error: Self::Error) -> Reject;
38}
39
40pub struct Built<'d, T> {
42 id: Id<'d>,
43 request: T,
44}
45
46impl<'d, T> Built<'d, T> {
47 #[must_use]
48 pub const fn new(id: Id<'d>, request: T) -> Self {
49 Self { id, request }
50 }
51
52 #[must_use]
53 pub fn into_parts(self) -> (Id<'d>, T) {
54 (self.id, self.request)
55 }
56}
57
58pub trait Schema: Sized {
60 type Header: header::Policy<Self> + header::Fields<Self>;
61 type Query: query::Fields<Self>;
62 type RawHeaders: Copy + Default;
63 type Error;
64 type RawParams: RawParams;
65 type Body: body::Project;
66 type Frame: proof::Proof;
67
68 const FULL: bool = false;
69 const AUTHORITY: bool = false;
72 const BODY_RETENTION: Retention = <Self::Body as body::Project>::RETENTION;
73}
74
75pub trait Fields: Schema<Error = Error<Self::Identity>> {
76 type Identity: Copy;
77}
78
79pub trait Project: Schema {
81 type Params<'req>;
82 type Headers<'req>;
83 type Error<'req>;
84 type View<'req, 'd>
85 where
86 'd: 'req;
87 type ParsedBody<'req, 'd>
88 where
89 'd: 'req;
90
91 fn reject<'req>(error: <Self as Project>::Error<'req>) -> Reject;
92
93 fn from_params<'req, 'body>(
94 request: &request::raw::Parsed<request::Head<&'req [u8], Self::Frame>, Self>,
95 ) -> Result<Self::Params<'req>, <Self as Project>::Error<'body>>;
96
97 fn parse_body<'req, 'd>(
98 body: <Self::Body as body::Project>::View<'req, 'd>,
99 ) -> Result<Self::ParsedBody<'req, 'd>, <Self as Project>::Error<'req>>
100 where
101 'd: 'req;
102
103 fn from_parts<'req, 'd>(
104 params: Self::Params<'req>,
105 headers: Self::Headers<'req>,
106 body: Self::ParsedBody<'req, 'd>,
107 request: &request::View<'req, 'd, Self::Frame>,
108 ) -> Self::View<'req, 'd>
109 where
110 'd: 'req;
111
112 fn from_headers<'req, 'body>(
113 request: &request::raw::Parsed<request::Head<&'req [u8], Self::Frame>, Self>,
114 ) -> Result<Self::Headers<'req>, <Self as Project>::Error<'body>>;
115}
116
117pub trait Mode: sealed::Mode {
119 const STREAM: Stream;
120}
121
122#[derive(Debug)]
124pub struct Streaming;
125
126#[derive(Debug)]
128pub struct Buffered;
129
130impl Mode for Streaming {
131 const STREAM: Stream = Stream::Streaming;
132}
133
134impl Mode for Buffered {
135 const STREAM: Stream = Stream::Buffered;
136}
137
138mod sealed {
139 pub trait Mode {}
140
141 impl Mode for super::Streaming {}
142 impl Mode for super::Buffered {}
143}
144
145pub trait Own: Schema {
147 type Mode: Mode;
148
149 type Task<'d>;
151 type Error<'d>;
152 type TaskBuilder<'d>: TaskBuild<'d, Task = Self::Task<'d>>;
153
154 fn empty_task<'d>(_: Id<'d>) -> Option<Built<'d, Self::Task<'d>>> {
157 None
158 }
159
160 fn reject<'d>(error: <Self as Own>::Error<'d>) -> Reject;
161
162 fn start_task<'d>(
163 request: request::raw::Parsed<request::Retained<'d, Self::Frame>, Self>,
164 ) -> Result<Self::TaskBuilder<'d>, <Self as Own>::Error<'d>>;
165
166 fn start_stream<'d>(
167 request: request::raw::Parsed<request::Parts<'d, Self::Frame>, Self>,
168 ) -> Result<Self::TaskBuilder<'d>, <Self as Own>::Error<'d>>;
169}
170
171pub trait RawParams: Copy {
172 type Captures;
173
174 const PATH_NAMES: &'static [&'static [u8]];
176}
177
178pub trait Params: RawParams {
180 fn from_match(captures: Self::Captures) -> Self;
181}
182
183impl RawParams for () {
184 type Captures = ();
185 const PATH_NAMES: &'static [&'static [u8]] = &[];
186}
187
188pub trait Spec {
189 type Kind;
190
191 type Request: Project;
192 type Stream<'d>;
193 const MAX_BODY: usize = 1024 * 1024;
194}
195
196pub trait Task<'d, S>: Spec {
198 type Output: dispatch::IntoOutput<'d, 'd>;
199}