1use crate::{JsonRpcAlg, JsonRpcApiAlg, JsonRpcFallibleAlg, JsonRpcMethodAlg, JsonRpcProgramAlg};
2use alux_ext::{ApplyAlg, HandlerContextAlg, OperationAlg};
3use core::marker::PhantomData;
4
5pub trait CompileJsonRpcProgram<Compiler> {
7 type Methods;
9
10 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods;
12}
13
14#[derive(Debug, Default)]
16pub struct Empty;
17
18#[derive(Debug)]
20pub struct Merge<Left, Right> {
21 left: Left,
22 right: Right,
23}
24
25#[derive(Debug)]
27pub struct Named<Program>(Program);
28
29#[derive(Debug, Default)]
31pub struct Positional;
32
33#[derive(Debug, Default)]
35pub struct NamedParams;
36
37#[derive(Debug, Default)]
39pub struct FalliblePositional;
40
41#[derive(Debug, Default)]
43pub struct FallibleNamed;
44
45#[derive(Debug)]
47pub struct Method<Handler, Params = Positional> {
48 name: &'static str,
49 handler: Handler,
50 marker: PhantomData<fn(Params)>,
51}
52
53#[derive(Debug)]
55pub struct Operation<Handler, Params = Positional> {
56 handler: Handler,
57 marker: PhantomData<fn(Params)>,
58}
59
60#[derive(Debug)]
62pub struct JsonRpcProgram<Program>(Program);
63
64#[derive(Debug, Default)]
66pub struct JsonRpcProgramBuilder;
67
68impl JsonRpcProgramBuilder {
69 pub fn methods(&self) -> JsonRpcProgram<Empty> {
71 JsonRpcProgram(Empty)
72 }
73
74 pub fn op<Handler>(&self, handler: Handler) -> Operation<Handler> {
76 Operation { handler, marker: PhantomData }
77 }
78
79 pub fn program<Program>(&self, program: Program) -> JsonRpcProgram<Named<Program>> {
81 JsonRpcProgram(Named(program))
82 }
83}
84
85impl<Program> JsonRpcProgram<Program> {
86 pub fn merge<Other>(self, other: JsonRpcProgram<Other>) -> JsonRpcProgram<Merge<Program, Other>> {
88 JsonRpcProgram(Merge { left: self.0, right: other.0 })
89 }
90
91 pub fn method<Handler, Params>(
93 self,
94 name: &'static str,
95 operation: Operation<Handler, Params>,
96 ) -> JsonRpcProgram<Merge<Program, Method<Handler, Params>>> {
97 self.merge(JsonRpcProgram(Method { name, handler: operation.handler, marker: PhantomData }))
98 }
99
100 pub fn into_program(self) -> Program {
102 self.0
103 }
104}
105
106impl<Handler, Params> Operation<Handler, Params> {
107 pub fn declare(self, name: &'static str) -> Method<Handler, Params> {
113 Method { name, handler: self.handler, marker: PhantomData }
114 }
115
116 fn retyped<Mode>(self) -> Operation<Handler, Mode> {
118 Operation { handler: self.handler, marker: PhantomData }
119 }
120}
121
122impl<Handler> Operation<Handler, Positional> {
123 #[must_use]
128 pub fn positional(self) -> Self {
129 self
130 }
131
132 pub fn named(self) -> Operation<Handler, NamedParams> {
135 self.retyped()
136 }
137
138 pub fn fallible(self) -> Operation<Handler, FalliblePositional> {
140 self.retyped()
141 }
142}
143
144impl<Handler> Operation<Handler, NamedParams> {
145 pub fn fallible(self) -> Operation<Handler, FallibleNamed> {
147 self.retyped()
148 }
149}
150
151impl<Handler> Operation<Handler, FalliblePositional> {
152 pub fn named(self) -> Operation<Handler, FallibleNamed> {
154 self.retyped()
155 }
156}
157
158impl<Compiler> CompileJsonRpcProgram<Compiler> for Empty
159where
160 Compiler: JsonRpcAlg,
161{
162 type Methods = Compiler::Methods;
163
164 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods {
165 compiler.jsonrpc_empty()
166 }
167}
168
169impl<Compiler, Left, Right, Methods> CompileJsonRpcProgram<Compiler> for Merge<Left, Right>
170where
171 Compiler: JsonRpcAlg<Methods = Methods>,
172 Left: CompileJsonRpcProgram<Compiler, Methods = Methods>,
173 Right: CompileJsonRpcProgram<Compiler, Methods = Methods>,
174{
175 type Methods = Methods;
176
177 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods {
178 compiler
179 .jsonrpc_merge(self.left.compile_jsonrpc_program(compiler), self.right.compile_jsonrpc_program(compiler))
180 }
181}
182
183impl<Compiler, Program> CompileJsonRpcProgram<Compiler> for Named<Program>
184where
185 Program: JsonRpcProgramAlg<Compiler>,
186{
187 type Methods = Program::Methods;
188
189 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods {
190 self.0.compile_jsonrpc(compiler)
191 }
192}
193
194impl<Compiler, Handler, Handle> CompileJsonRpcProgram<Compiler> for Method<Handler, Positional>
197where
198 Compiler: JsonRpcApiAlg
199 + HandlerContextAlg<Handler::Context, Handle = Handle>
200 + JsonRpcMethodAlg<Handle, Handler::Args, Handler::Output>,
201 Handler: OperationAlg + ApplyAlg<Handle, Handler::Args> + Send + Sync + 'static,
202{
203 type Methods = Compiler::Methods;
204
205 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods {
206 compiler.finish_jsonrpc_positional_method(self.name, Handler::ARG_NAMES, self.handler)
207 }
208}
209
210impl<Compiler, Handler, Handle> CompileJsonRpcProgram<Compiler> for Method<Handler, NamedParams>
211where
212 Compiler: JsonRpcApiAlg
213 + HandlerContextAlg<Handler::Context, Handle = Handle>
214 + JsonRpcMethodAlg<Handle, Handler::Args, Handler::Output>,
215 Handler: OperationAlg + ApplyAlg<Handle, Handler::Args> + Send + Sync + 'static,
216{
217 type Methods = Compiler::Methods;
218
219 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods {
220 compiler.finish_jsonrpc_named_method(self.name, Handler::ARG_NAMES, self.handler)
221 }
222}
223
224impl<Compiler, Handler, Handle> CompileJsonRpcProgram<Compiler> for Method<Handler, FalliblePositional>
225where
226 Compiler: JsonRpcApiAlg
227 + HandlerContextAlg<Handler::Context, Handle = Handle>
228 + JsonRpcFallibleAlg<Handle, Handler::Args, Handler::Output>,
229 Handler: OperationAlg + ApplyAlg<Handle, Handler::Args> + Send + Sync + 'static,
230{
231 type Methods = Compiler::Methods;
232
233 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods {
234 compiler.finish_jsonrpc_positional_fallible(self.name, Handler::ARG_NAMES, self.handler)
235 }
236}
237
238impl<Compiler, Handler, Handle> CompileJsonRpcProgram<Compiler> for Method<Handler, FallibleNamed>
239where
240 Compiler: JsonRpcApiAlg
241 + HandlerContextAlg<Handler::Context, Handle = Handle>
242 + JsonRpcFallibleAlg<Handle, Handler::Args, Handler::Output>,
243 Handler: OperationAlg + ApplyAlg<Handle, Handler::Args> + Send + Sync + 'static,
244{
245 type Methods = Compiler::Methods;
246
247 fn compile_jsonrpc_program(self, compiler: &Compiler) -> Self::Methods {
248 compiler.finish_jsonrpc_named_fallible(self.name, Handler::ARG_NAMES, self.handler)
249 }
250}