1use crate::WithAlg;
4use core::marker::PhantomData;
5
6pub trait OutputAlg<From> {
11 type Output;
13
14 fn output(from: From) -> Self::Output;
16}
17
18pub trait OutputKindAlg<Interpreter: ?Sized, From> {
20 type Transform;
27}
28
29macro_rules! output_kinds {
30 ($($declaration:ident => $kind:ident, $alg:ident, $selected:ident, $meaning:literal),+ $(,)?) => {
31 $(
32 #[doc = concat!("Selects the converter used for ", $meaning, " API outputs.")]
33 pub trait $alg {
34 #[doc = concat!("The ", $meaning, " converter selected for `From`.")]
35 type $selected<From>;
36 }
37
38 #[doc = concat!("Selects ", $meaning, " output semantics.")]
39 #[derive(Debug, Default)]
40 pub struct $kind;
41
42 impl<Interpreter, From> OutputKindAlg<Interpreter, From> for $kind
43 where
44 Interpreter: $alg + ?Sized,
45 {
46 type Transform = Interpreter::$selected<From>;
47 }
48 )+
49 };
50}
51
52with_output_kinds!(output_kinds);
53
54pub trait StatusOutAlg {
56 type Status<Inner, const CODE: u16>;
58}
59
60#[derive(Debug, Default)]
65pub struct StatusOut<Kind, const CODE: u16>(PhantomData<Kind>);
66
67impl<Interpreter, From, Kind, const CODE: u16> OutputKindAlg<Interpreter, From> for StatusOut<Kind, CODE>
68where
69 Interpreter: StatusOutAlg + ?Sized,
70 Kind: OutputKindAlg<Interpreter, From>,
71{
72 type Transform = Interpreter::Status<Kind::Transform, CODE>;
73}
74
75pub trait HeaderOutAlg {
77 type Header<Inner, Name>;
79}
80
81#[derive(Debug, Default)]
87pub struct HeaderOut<Kind, Name>(PhantomData<fn(Kind, Name)>);
88
89impl<Interpreter, Value, Rest, Kind, Name> OutputKindAlg<Interpreter, (Value, Rest)> for HeaderOut<Kind, Name>
90where
91 Interpreter: HeaderOutAlg + ?Sized,
92 Kind: OutputKindAlg<Interpreter, Rest>,
93{
94 type Transform = Interpreter::Header<Kind::Transform, Name>;
95}
96
97pub trait HeadersOutAlg {
99 type Headers<Inner, Headers>;
101}
102
103#[derive(Debug, Default)]
110pub struct HeadersOut<Kind, Headers>(PhantomData<fn(Kind, Headers)>);
111
112impl<Interpreter, Headers, Rest, Kind> OutputKindAlg<Interpreter, (Headers, Rest)> for HeadersOut<Kind, Headers>
113where
114 Interpreter: HeadersOutAlg + ?Sized,
115 Kind: OutputKindAlg<Interpreter, Rest>,
116{
117 type Transform = Interpreter::Headers<Kind::Transform, Headers>;
118}
119
120pub trait ResultOutAlg {
122 type Result<Inner, Error>;
124}
125
126#[derive(Debug, Default)]
131pub struct ResultOut<Kind>(PhantomData<Kind>);
132
133impl<Interpreter, Kind, Value, Error> OutputKindAlg<Interpreter, Result<Value, Error>> for ResultOut<Kind>
134where
135 Interpreter: ResultOutAlg + ?Sized,
136 Kind: OutputKindAlg<Interpreter, Value>,
137{
138 type Transform = Interpreter::Result<Kind::Transform, Error>;
139}
140
141#[derive(Debug, Default)]
156pub struct Pending<Wrappers>(PhantomData<Wrappers>);
157
158pub trait WrapAlg {
160 type Wrap<Inner>;
162}
163
164impl<const CODE: u16> WrapAlg for StatusOut<(), CODE> {
165 type Wrap<Inner> = StatusOut<Inner, CODE>;
166}
167
168impl<Name> WrapAlg for HeaderOut<(), Name> {
169 type Wrap<Inner> = HeaderOut<Inner, Name>;
170}
171
172impl<Headers> WrapAlg for HeadersOut<(), Headers> {
173 type Wrap<Inner> = HeadersOut<Inner, Headers>;
174}
175
176impl WrapAlg for ResultOut<()> {
177 type Wrap<Inner> = ResultOut<Inner>;
178}
179
180#[diagnostic::on_unimplemented(
182 message = "`{Self}` already states its output kind",
183 note = "wrappers such as `.status()`, `.out_header()`, `.out_headers()`, and `.result()` come before the kind, which closes the declaration"
184)]
185pub trait OpenAlg {
186 type With<Wrapper>;
188}
189
190impl OpenAlg for () {
191 type With<Wrapper> = Pending<(Wrapper,)>;
192}
193
194impl<Wrappers> OpenAlg for Pending<Wrappers>
195where
196 Wrappers: WithAlg,
197{
198 type With<Wrapper> = Pending<Wrappers::With<Wrapper>>;
199}
200
201#[diagnostic::on_unimplemented(
203 message = "`{Self}` already states its output kind",
204 note = "a declaration states one kind, last, after the wrappers around it"
205)]
206pub trait CloseAlg<Kind> {
207 type Closed;
209}
210
211impl<Kind> CloseAlg<Kind> for () {
212 type Closed = Kind;
213}
214
215impl<Kind, Wrappers> CloseAlg<Kind> for Pending<Wrappers>
216where
217 Wrappers: FoldAlg<Kind>,
218{
219 type Closed = Wrappers::Folded;
220}
221
222pub trait FoldAlg<Kind> {
224 type Folded;
226}
227
228macro_rules! fold_wrappers {
229 () => {
230 impl<Kind> FoldAlg<Kind> for () {
231 type Folded = Kind;
232 }
233 };
234 ($first:ident $(, $rest:ident)*) => {
235 impl<Kind, $first $(, $rest)*> FoldAlg<Kind> for ($first, $($rest,)*)
236 where
237 $first: WrapAlg,
238 ($($rest,)*): FoldAlg<Kind>,
239 {
240 type Folded = $first::Wrap<<($($rest,)*) as FoldAlg<Kind>>::Folded>;
241 }
242
243 fold_wrappers!($($rest),*);
244 };
245}
246
247fold_wrappers!(W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16);