1use crate::TsHttpClient;
4use alux_http::{
5 BytesOutAlg, EmptyOutAlg, FileOutAlg, HeaderOutAlg, HtmlOutAlg, JsonOutAlg, OutputAlg, RedirectOutAlg,
6 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 TsStatusOutput<Inner, const CODE: u16>(PhantomData<Inner>);
126
127impl<Inner, From, const CODE: u16> OutputAlg<From> for TsStatusOutput<Inner, CODE> {
128 type Output = From;
129
130 fn output(from: From) -> From {
131 from
132 }
133}
134
135impl<Inner, From, const CODE: u16> TsOutputAlg<From> for TsStatusOutput<Inner, CODE>
136where
137 Inner: TsOutputAlg<From>,
138{
139 fn answer(shapes: &TsShape) -> TsType {
140 Inner::answer(shapes)
141 }
142}
143
144pub struct TsResultOutput<Inner, Error>(PhantomData<fn(Inner, Error)>);
146
147impl<Inner, Error, From> OutputAlg<From> for TsResultOutput<Inner, Error> {
148 type Output = From;
149
150 fn output(from: From) -> From {
151 from
152 }
153}
154
155impl<Inner, Error, Value> TsOutputAlg<Result<Value, Error>> for TsResultOutput<Inner, Error>
156where
157 Inner: TsOutputAlg<Value>,
158{
159 fn answer(shapes: &TsShape) -> TsType {
160 Inner::answer(shapes)
161 }
162}
163
164macro_rules! ts_kinds {
165 ($($alg:ident => $selected:ident, $output:ty),+ $(,)?) => {
166 $(
167 impl $alg for TsHttpClient {
168 type $selected<From> = $output;
169 }
170 )+
171 };
172}
173
174ts_kinds! {
175 JsonOutAlg => Json, TsJsonOutput,
176 FileOutAlg => File, TsFileOutput,
177 TextOutAlg => Text, TsTextOutput,
178 HtmlOutAlg => Html, TsHtmlOutput,
179 BytesOutAlg => Bytes, TsBytesOutput,
180 EmptyOutAlg => Empty, TsEmptyOutput,
181 RedirectOutAlg => Redirect, TsRedirectOutput,
182 StreamOutAlg => Stream, TsStreamOutput,
183}
184
185impl StatusOutAlg for TsHttpClient {
186 type Status<Inner, const CODE: u16> = TsStatusOutput<Inner, CODE>;
187}
188
189impl ResultOutAlg for TsHttpClient {
190 type Result<Inner, Error> = TsResultOutput<Inner, Error>;
191}