1use crate::TsHttpClient;
4use alux_http::{
5 BytesOutAlg, EmptyOutAlg, FileOutAlg, HeaderOutAlg, HeadersOutAlg, HtmlOutAlg, JsonOutAlg, OutputAlg,
6 RedirectOutAlg, ResultOutAlg, StatusOutAlg, StreamOutAlg, TextOutAlg,
7};
8use alux_shape::{ShapeAlg, ShapeOf};
9use alux_shape_typescript::{TsShape, TsType};
10use core::marker::PhantomData;
11
12pub trait TsOutputAlg<From> {
17 fn answer(shapes: &TsShape) -> TsType;
19}
20
21pub struct TsJsonOutput;
23
24impl<From> OutputAlg<From> for TsJsonOutput {
25 type Output = From;
26
27 fn output(from: From) -> From {
28 from
29 }
30}
31
32impl<From> TsOutputAlg<From> for TsJsonOutput
33where
34 From: ShapeOf<TsShape, Shape = TsType>,
35{
36 fn answer(shapes: &TsShape) -> TsType {
37 From::shape_of(shapes)
38 }
39}
40
41macro_rules! ts_outputs {
42 ($($output:ident => $answer:ident, $meaning:literal),+ $(,)?) => {
43 $(
44 #[doc = concat!("Answers a caller with what ", $meaning, " states.")]
45 pub struct $output;
46
47 impl<From> OutputAlg<From> for $output {
48 type Output = From;
49
50 fn output(from: From) -> From {
51 from
52 }
53 }
54
55 impl<From> TsOutputAlg<From> for $output {
56 fn answer(shapes: &TsShape) -> TsType {
57 shapes.$answer()
58 }
59 }
60 )+
61 };
62}
63
64ts_outputs! {
65 TsTextOutput => text, "plain text",
66 TsHtmlOutput => text, "HTML",
67 TsRedirectOutput => unit, "a redirect",
68 TsEmptyOutput => unit, "an answer with no body",
69}
70
71macro_rules! ts_byte_outputs {
72 ($($output:ident => $meaning:literal),+ $(,)?) => {
73 $(
74 #[doc = concat!("Answers a caller with the bytes ", $meaning, " states.")]
75 pub struct $output;
76
77 impl<From> OutputAlg<From> for $output {
78 type Output = From;
79
80 fn output(from: From) -> From {
81 from
82 }
83 }
84
85 impl<From> TsOutputAlg<From> for $output {
86 fn answer(shapes: &TsShape) -> TsType {
87 shapes.bytes(None)
88 }
89 }
90 )+
91 };
92}
93
94ts_byte_outputs! {
95 TsBytesOutput => "a raw-byte answer",
96 TsFileOutput => "a streamed file",
97 TsStreamOutput => "a streamed answer",
98}
99
100pub struct TsHeaderOutput<Inner, Name>(PhantomData<fn(Inner, Name)>);
102
103impl<Inner, Name, From> OutputAlg<From> for TsHeaderOutput<Inner, Name> {
104 type Output = From;
105
106 fn output(from: From) -> From {
107 from
108 }
109}
110
111impl<Inner, Name, Value, Rest> TsOutputAlg<(Value, Rest)> for TsHeaderOutput<Inner, Name>
112where
113 Inner: TsOutputAlg<Rest>,
114{
115 fn answer(shapes: &TsShape) -> TsType {
116 Inner::answer(shapes)
117 }
118}
119
120impl HeaderOutAlg for TsHttpClient {
121 type Header<Inner, Name> = TsHeaderOutput<Inner, Name>;
122}
123
124pub struct TsHeadersOutput<Inner, Headers>(PhantomData<fn(Inner, Headers)>);
127
128impl<Inner, Headers, From> OutputAlg<From> for TsHeadersOutput<Inner, Headers> {
129 type Output = From;
130
131 fn output(from: From) -> From {
132 from
133 }
134}
135
136impl<Inner, Headers, Rest> TsOutputAlg<(Headers, Rest)> for TsHeadersOutput<Inner, Headers>
137where
138 Inner: TsOutputAlg<Rest>,
139{
140 fn answer(shapes: &TsShape) -> TsType {
141 Inner::answer(shapes)
142 }
143}
144
145impl HeadersOutAlg for TsHttpClient {
146 type Headers<Inner, Headers> = TsHeadersOutput<Inner, Headers>;
147}
148
149pub struct TsStatusOutput<Inner, const CODE: u16>(PhantomData<Inner>);
151
152impl<Inner, From, const CODE: u16> OutputAlg<From> for TsStatusOutput<Inner, CODE> {
153 type Output = From;
154
155 fn output(from: From) -> From {
156 from
157 }
158}
159
160impl<Inner, From, const CODE: u16> TsOutputAlg<From> for TsStatusOutput<Inner, CODE>
161where
162 Inner: TsOutputAlg<From>,
163{
164 fn answer(shapes: &TsShape) -> TsType {
165 Inner::answer(shapes)
166 }
167}
168
169pub struct TsResultOutput<Inner, Error>(PhantomData<fn(Inner, Error)>);
171
172impl<Inner, Error, From> OutputAlg<From> for TsResultOutput<Inner, Error> {
173 type Output = From;
174
175 fn output(from: From) -> From {
176 from
177 }
178}
179
180impl<Inner, Error, Value> TsOutputAlg<Result<Value, Error>> for TsResultOutput<Inner, Error>
181where
182 Inner: TsOutputAlg<Value>,
183{
184 fn answer(shapes: &TsShape) -> TsType {
185 Inner::answer(shapes)
186 }
187}
188
189macro_rules! ts_kinds {
190 ($($alg:ident => $selected:ident, $output:ty),+ $(,)?) => {
191 $(
192 impl $alg for TsHttpClient {
193 type $selected<From> = $output;
194 }
195 )+
196 };
197}
198
199ts_kinds! {
200 JsonOutAlg => Json, TsJsonOutput,
201 FileOutAlg => File, TsFileOutput,
202 TextOutAlg => Text, TsTextOutput,
203 HtmlOutAlg => Html, TsHtmlOutput,
204 BytesOutAlg => Bytes, TsBytesOutput,
205 EmptyOutAlg => Empty, TsEmptyOutput,
206 RedirectOutAlg => Redirect, TsRedirectOutput,
207 StreamOutAlg => Stream, TsStreamOutput,
208}
209
210impl StatusOutAlg for TsHttpClient {
211 type Status<Inner, const CODE: u16> = TsStatusOutput<Inner, CODE>;
212}
213
214impl ResultOutAlg for TsHttpClient {
215 type Result<Inner, Error> = TsResultOutput<Inner, Error>;
216}