1use std::marker::PhantomData;
10use std::sync::Arc;
11use std::time::Duration;
12
13use dex_protocol::dex::Value as ProtoValue;
14
15use crate::attribute::AttributeLock;
16use crate::step::{ErasedValue, TypedValue};
17use crate::value_mapper;
18use crate::{Context, HandlerResult, SdkResult, StepMovement, Value};
19
20pub struct Rpc<Input, Output> {
49 name: &'static str,
50 marker: PhantomData<fn(Input) -> Output>,
51}
52
53impl<Input, Output> Rpc<Input, Output> {
54 pub const fn new(name: &'static str) -> Self {
56 Self {
57 name,
58 marker: PhantomData,
59 }
60 }
61
62 pub fn timeout(self, timeout: Duration) -> RpcDefinition<Input, Output> {
64 RpcDefinition::from(self).timeout(timeout)
65 }
66
67 pub fn lock(self, lock: AttributeLock) -> RpcDefinition<Input, Output> {
69 RpcDefinition::from(self).lock(lock)
70 }
71
72 pub(crate) fn name(&self) -> &'static str {
73 self.name
74 }
75}
76
77impl<Input, Output> Clone for Rpc<Input, Output> {
78 fn clone(&self) -> Self {
79 *self
80 }
81}
82
83impl<Input, Output> Copy for Rpc<Input, Output> {}
84
85pub struct RpcDefinition<Input, Output> {
90 rpc: Rpc<Input, Output>,
91 timeout: Option<Duration>,
92 locks: Vec<AttributeLock>,
93}
94
95impl<Input, Output> RpcDefinition<Input, Output> {
96 pub fn timeout(mut self, timeout: Duration) -> Self {
98 self.timeout = Some(timeout);
99 self
100 }
101
102 pub fn lock(mut self, lock: AttributeLock) -> Self {
104 self.locks.push(lock);
105 self
106 }
107}
108
109impl<Input, Output> From<Rpc<Input, Output>> for RpcDefinition<Input, Output> {
110 fn from(rpc: Rpc<Input, Output>) -> Self {
111 Self {
112 rpc,
113 timeout: None,
114 locks: Vec::new(),
115 }
116 }
117}
118
119pub struct RpcList<FlowType> {
124 definitions: Vec<Box<dyn RpcBinder<FlowType>>>,
125}
126
127impl<FlowType> RpcList<FlowType>
128where
129 FlowType: Send + Sync + 'static,
130{
131 pub fn new() -> Self {
133 Self {
134 definitions: Vec::new(),
135 }
136 }
137
138 pub fn function<Input, Output>(
142 mut self,
143 definition: impl Into<RpcDefinition<Input, Output>>,
144 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
145 ) -> Self
146 where
147 Input: Value,
148 Output: Value,
149 {
150 self.definitions.push(Box::new(FunctionBinder {
151 definition: definition.into(),
152 handler,
153 }));
154 self
155 }
156
157 pub fn function_without_input<Output>(
159 mut self,
160 definition: impl Into<RpcDefinition<(), Output>>,
161 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
162 ) -> Self
163 where
164 Output: Value,
165 {
166 self.definitions.push(Box::new(FunctionWithoutInputBinder {
167 definition: definition.into(),
168 handler,
169 }));
170 self
171 }
172
173 pub fn procedure<Input>(
175 mut self,
176 definition: impl Into<RpcDefinition<Input, ()>>,
177 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
178 ) -> Self
179 where
180 Input: Value,
181 {
182 self.definitions.push(Box::new(ProcedureBinder {
183 definition: definition.into(),
184 handler,
185 }));
186 self
187 }
188
189 pub fn procedure_without_input(
191 mut self,
192 definition: impl Into<RpcDefinition<(), ()>>,
193 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
194 ) -> Self {
195 self.definitions.push(Box::new(ProcedureWithoutInputBinder {
196 definition: definition.into(),
197 handler,
198 }));
199 self
200 }
201
202 pub(crate) fn bind(self, flow: Arc<FlowType>) -> Vec<RegisteredRpc> {
203 self.definitions
204 .into_iter()
205 .map(|definition| definition.bind(Arc::clone(&flow)))
206 .collect()
207 }
208}
209
210impl<FlowType> Default for RpcList<FlowType>
211where
212 FlowType: Send + Sync + 'static,
213{
214 fn default() -> Self {
215 Self::new()
216 }
217}
218
219pub struct RpcResult<Output> {
223 output: Output,
224 next_steps: Vec<StepMovement>,
225}
226
227impl<Output: Value> RpcResult<Output> {
228 pub fn new(output: Output) -> Self {
230 Self {
231 output,
232 next_steps: Vec::new(),
233 }
234 }
235
236 pub fn then(mut self, movement: StepMovement) -> Self {
238 self.next_steps.push(movement);
239 self
240 }
241
242 pub fn output(&self) -> &Output {
244 &self.output
245 }
246
247 pub fn next_steps(&self) -> &[StepMovement] {
249 &self.next_steps
250 }
251}
252
253pub(crate) struct ErasedRpcResult {
254 pub(crate) output: Box<dyn ErasedValue>,
255 pub(crate) next_steps: Vec<StepMovement>,
256}
257
258#[derive(Clone)]
259pub(crate) struct RegisteredRpc {
260 pub(crate) name: &'static str,
261 pub(crate) timeout: Option<Duration>,
262 pub(crate) locks: Vec<AttributeLock>,
263 pub(crate) handler: Arc<dyn ErasedRpc>,
264}
265
266pub(crate) trait ErasedRpc: Send + Sync {
267 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult>;
268}
269
270trait RpcBinder<FlowType>: Send + Sync {
271 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc;
272}
273
274struct FunctionBinder<FlowType, Input, Output> {
275 definition: RpcDefinition<Input, Output>,
276 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
277}
278
279impl<FlowType, Input, Output> RpcBinder<FlowType> for FunctionBinder<FlowType, Input, Output>
280where
281 FlowType: Send + Sync + 'static,
282 Input: Value,
283 Output: Value,
284{
285 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
286 registered_rpc(
287 self.definition,
288 Arc::new(BoundFunction {
289 flow,
290 handler: self.handler,
291 }),
292 )
293 }
294}
295
296struct BoundFunction<FlowType, Input, Output> {
297 flow: Arc<FlowType>,
298 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
299}
300
301impl<FlowType, Input, Output> ErasedRpc for BoundFunction<FlowType, Input, Output>
302where
303 FlowType: Send + Sync + 'static,
304 Input: Value,
305 Output: Value,
306{
307 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
308 let result = (self.handler)(&self.flow, context, value_mapper::decode_handler(input)?)?;
309 Ok(ErasedRpcResult {
310 output: Box::new(TypedValue(result.output)),
311 next_steps: result.next_steps,
312 })
313 }
314}
315
316struct FunctionWithoutInputBinder<FlowType, Output> {
317 definition: RpcDefinition<(), Output>,
318 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
319}
320
321impl<FlowType, Output> RpcBinder<FlowType> for FunctionWithoutInputBinder<FlowType, Output>
322where
323 FlowType: Send + Sync + 'static,
324 Output: Value,
325{
326 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
327 registered_rpc(
328 self.definition,
329 Arc::new(BoundFunctionWithoutInput {
330 flow,
331 handler: self.handler,
332 }),
333 )
334 }
335}
336
337struct BoundFunctionWithoutInput<FlowType, Output> {
338 flow: Arc<FlowType>,
339 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
340}
341
342impl<FlowType, Output> ErasedRpc for BoundFunctionWithoutInput<FlowType, Output>
343where
344 FlowType: Send + Sync + 'static,
345 Output: Value,
346{
347 fn invoke(&self, context: &mut Context, _input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
348 let result = (self.handler)(&self.flow, context)?;
349 Ok(ErasedRpcResult {
350 output: Box::new(TypedValue(result.output)),
351 next_steps: result.next_steps,
352 })
353 }
354}
355
356struct ProcedureBinder<FlowType, Input> {
357 definition: RpcDefinition<Input, ()>,
358 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
359}
360
361impl<FlowType, Input> RpcBinder<FlowType> for ProcedureBinder<FlowType, Input>
362where
363 FlowType: Send + Sync + 'static,
364 Input: Value,
365{
366 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
367 registered_rpc(
368 self.definition,
369 Arc::new(BoundProcedure {
370 flow,
371 handler: self.handler,
372 }),
373 )
374 }
375}
376
377struct BoundProcedure<FlowType, Input> {
378 flow: Arc<FlowType>,
379 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
380}
381
382impl<FlowType, Input> ErasedRpc for BoundProcedure<FlowType, Input>
383where
384 FlowType: Send + Sync + 'static,
385 Input: Value,
386{
387 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
388 (self.handler)(&self.flow, context, value_mapper::decode_handler(input)?)?;
389 Ok(empty_rpc_result())
390 }
391}
392
393struct ProcedureWithoutInputBinder<FlowType> {
394 definition: RpcDefinition<(), ()>,
395 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
396}
397
398impl<FlowType> RpcBinder<FlowType> for ProcedureWithoutInputBinder<FlowType>
399where
400 FlowType: Send + Sync + 'static,
401{
402 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
403 registered_rpc(
404 self.definition,
405 Arc::new(BoundProcedureWithoutInput {
406 flow,
407 handler: self.handler,
408 }),
409 )
410 }
411}
412
413struct BoundProcedureWithoutInput<FlowType> {
414 flow: Arc<FlowType>,
415 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
416}
417
418impl<FlowType> ErasedRpc for BoundProcedureWithoutInput<FlowType>
419where
420 FlowType: Send + Sync + 'static,
421{
422 fn invoke(&self, context: &mut Context, _input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
423 (self.handler)(&self.flow, context)?;
424 Ok(empty_rpc_result())
425 }
426}
427
428fn registered_rpc<Input, Output>(
429 definition: RpcDefinition<Input, Output>,
430 handler: Arc<dyn ErasedRpc>,
431) -> RegisteredRpc {
432 RegisteredRpc {
433 name: definition.rpc.name,
434 timeout: definition.timeout,
435 locks: definition.locks,
436 handler,
437 }
438}
439
440fn empty_rpc_result() -> ErasedRpcResult {
441 ErasedRpcResult {
442 output: Box::new(TypedValue(())),
443 next_steps: Vec::new(),
444 }
445}
446
447pub(crate) fn encode_rpc_output(output: &dyn ErasedValue) -> SdkResult<ProtoValue> {
448 output.encode()
449}