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 cancel_step_types: Vec<&'static str>,
226}
227
228impl<Output: Value> RpcResult<Output> {
229 pub fn new(output: Output) -> Self {
231 Self {
232 output,
233 next_steps: Vec::new(),
234 cancel_step_types: Vec::new(),
235 }
236 }
237
238 pub fn then(mut self, movement: StepMovement) -> Self {
240 self.next_steps.push(movement);
241 self
242 }
243
244 pub fn cancel_step<SelectedStep>(mut self, step: &SelectedStep) -> Self
249 where
250 SelectedStep: crate::Step,
251 {
252 let step_type = step.step_type();
253 if !self.cancel_step_types.contains(&step_type) {
254 self.cancel_step_types.push(step_type);
255 }
256 self
257 }
258
259 pub fn output(&self) -> &Output {
261 &self.output
262 }
263
264 pub fn next_steps(&self) -> &[StepMovement] {
266 &self.next_steps
267 }
268}
269
270pub(crate) struct ErasedRpcResult {
271 pub(crate) output: Box<dyn ErasedValue>,
272 pub(crate) next_steps: Vec<StepMovement>,
273 pub(crate) cancel_step_types: Vec<&'static str>,
274}
275
276#[derive(Clone)]
277pub(crate) struct RegisteredRpc {
278 pub(crate) name: &'static str,
279 pub(crate) timeout: Option<Duration>,
280 pub(crate) locks: Vec<AttributeLock>,
281 pub(crate) handler: Arc<dyn ErasedRpc>,
282}
283
284pub(crate) trait ErasedRpc: Send + Sync {
285 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult>;
286}
287
288trait RpcBinder<FlowType>: Send + Sync {
289 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc;
290}
291
292struct FunctionBinder<FlowType, Input, Output> {
293 definition: RpcDefinition<Input, Output>,
294 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
295}
296
297impl<FlowType, Input, Output> RpcBinder<FlowType> for FunctionBinder<FlowType, Input, Output>
298where
299 FlowType: Send + Sync + 'static,
300 Input: Value,
301 Output: Value,
302{
303 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
304 registered_rpc(
305 self.definition,
306 Arc::new(BoundFunction {
307 flow,
308 handler: self.handler,
309 }),
310 )
311 }
312}
313
314struct BoundFunction<FlowType, Input, Output> {
315 flow: Arc<FlowType>,
316 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
317}
318
319impl<FlowType, Input, Output> ErasedRpc for BoundFunction<FlowType, Input, Output>
320where
321 FlowType: Send + Sync + 'static,
322 Input: Value,
323 Output: Value,
324{
325 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
326 let result = (self.handler)(&self.flow, context, value_mapper::decode_handler(input)?)?;
327 Ok(ErasedRpcResult {
328 output: Box::new(TypedValue(result.output)),
329 next_steps: result.next_steps,
330 cancel_step_types: result.cancel_step_types,
331 })
332 }
333}
334
335struct FunctionWithoutInputBinder<FlowType, Output> {
336 definition: RpcDefinition<(), Output>,
337 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
338}
339
340impl<FlowType, Output> RpcBinder<FlowType> for FunctionWithoutInputBinder<FlowType, Output>
341where
342 FlowType: Send + Sync + 'static,
343 Output: Value,
344{
345 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
346 registered_rpc(
347 self.definition,
348 Arc::new(BoundFunctionWithoutInput {
349 flow,
350 handler: self.handler,
351 }),
352 )
353 }
354}
355
356struct BoundFunctionWithoutInput<FlowType, Output> {
357 flow: Arc<FlowType>,
358 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
359}
360
361impl<FlowType, Output> ErasedRpc for BoundFunctionWithoutInput<FlowType, Output>
362where
363 FlowType: Send + Sync + 'static,
364 Output: Value,
365{
366 fn invoke(&self, context: &mut Context, _input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
367 let result = (self.handler)(&self.flow, context)?;
368 Ok(ErasedRpcResult {
369 output: Box::new(TypedValue(result.output)),
370 next_steps: result.next_steps,
371 cancel_step_types: result.cancel_step_types,
372 })
373 }
374}
375
376struct ProcedureBinder<FlowType, Input> {
377 definition: RpcDefinition<Input, ()>,
378 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
379}
380
381impl<FlowType, Input> RpcBinder<FlowType> for ProcedureBinder<FlowType, Input>
382where
383 FlowType: Send + Sync + 'static,
384 Input: Value,
385{
386 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
387 registered_rpc(
388 self.definition,
389 Arc::new(BoundProcedure {
390 flow,
391 handler: self.handler,
392 }),
393 )
394 }
395}
396
397struct BoundProcedure<FlowType, Input> {
398 flow: Arc<FlowType>,
399 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
400}
401
402impl<FlowType, Input> ErasedRpc for BoundProcedure<FlowType, Input>
403where
404 FlowType: Send + Sync + 'static,
405 Input: Value,
406{
407 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
408 (self.handler)(&self.flow, context, value_mapper::decode_handler(input)?)?;
409 Ok(empty_rpc_result())
410 }
411}
412
413struct ProcedureWithoutInputBinder<FlowType> {
414 definition: RpcDefinition<(), ()>,
415 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
416}
417
418impl<FlowType> RpcBinder<FlowType> for ProcedureWithoutInputBinder<FlowType>
419where
420 FlowType: Send + Sync + 'static,
421{
422 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
423 registered_rpc(
424 self.definition,
425 Arc::new(BoundProcedureWithoutInput {
426 flow,
427 handler: self.handler,
428 }),
429 )
430 }
431}
432
433struct BoundProcedureWithoutInput<FlowType> {
434 flow: Arc<FlowType>,
435 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
436}
437
438impl<FlowType> ErasedRpc for BoundProcedureWithoutInput<FlowType>
439where
440 FlowType: Send + Sync + 'static,
441{
442 fn invoke(&self, context: &mut Context, _input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
443 (self.handler)(&self.flow, context)?;
444 Ok(empty_rpc_result())
445 }
446}
447
448fn registered_rpc<Input, Output>(
449 definition: RpcDefinition<Input, Output>,
450 handler: Arc<dyn ErasedRpc>,
451) -> RegisteredRpc {
452 RegisteredRpc {
453 name: definition.rpc.name,
454 timeout: definition.timeout,
455 locks: definition.locks,
456 handler,
457 }
458}
459
460fn empty_rpc_result() -> ErasedRpcResult {
461 ErasedRpcResult {
462 output: Box::new(TypedValue(())),
463 next_steps: Vec::new(),
464 cancel_step_types: Vec::new(),
465 }
466}
467
468pub(crate) fn encode_rpc_output(output: &dyn ErasedValue) -> SdkResult<ProtoValue> {
469 output.encode()
470}