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, AttributeMap, AttributeMapLoad};
16use crate::channel::{Channel, ChannelLoad, ChannelMap, ChannelMapLoad};
17use crate::step::{ErasedValue, TypedValue};
18use crate::value_mapper;
19use crate::{Context, HandlerResult, SdkResult, StepMovement, Value};
20
21pub struct Rpc<Input, Output> {
50 name: &'static str,
51 marker: PhantomData<fn(Input) -> Output>,
52}
53
54impl<Input, Output> Rpc<Input, Output> {
55 pub const fn new(name: &'static str) -> Self {
57 Self {
58 name,
59 marker: PhantomData,
60 }
61 }
62
63 pub fn timeout(self, timeout: Duration) -> RpcDefinition<Input, Output> {
65 RpcDefinition::from(self).timeout(timeout)
66 }
67
68 pub fn lock(self, lock: AttributeLock) -> RpcDefinition<Input, Output> {
70 RpcDefinition::from(self).lock(lock)
71 }
72
73 pub fn is_transactional(self) -> RpcDefinition<Input, Output> {
75 RpcDefinition::from(self).is_transactional()
76 }
77
78 pub fn load_attribute_map<T>(
80 self,
81 attribute_map: &AttributeMap<T>,
82 ) -> RpcDefinition<Input, Output> {
83 RpcDefinition::from(self).load_attribute_map(attribute_map)
84 }
85
86 pub fn load_attribute_map_instance(
88 self,
89 load: AttributeMapLoad,
90 ) -> RpcDefinition<Input, Output> {
91 RpcDefinition::from(self).load_attribute_map_instance(load)
92 }
93
94 pub fn load_channel<T>(self, channel: &Channel<T>) -> RpcDefinition<Input, Output> {
96 RpcDefinition::from(self).load_channel(channel)
97 }
98
99 pub fn load_channel_map<T>(self, channel_map: &ChannelMap<T>) -> RpcDefinition<Input, Output> {
101 RpcDefinition::from(self).load_channel_map(channel_map)
102 }
103
104 pub fn load_channel_map_instance(self, load: ChannelMapLoad) -> RpcDefinition<Input, Output> {
106 RpcDefinition::from(self).load_channel_map_instance(load)
107 }
108
109 pub(crate) fn name(&self) -> &'static str {
110 self.name
111 }
112}
113
114impl<Input, Output> Clone for Rpc<Input, Output> {
115 fn clone(&self) -> Self {
116 *self
117 }
118}
119
120impl<Input, Output> Copy for Rpc<Input, Output> {}
121
122pub struct RpcDefinition<Input, Output> {
127 rpc: Rpc<Input, Output>,
128 timeout: Option<Duration>,
129 locks: Vec<AttributeLock>,
130 is_transactional: bool,
131 load_attribute_maps: Vec<AttributeMapLoad>,
132 load_channels: Vec<ChannelLoad>,
133 load_channel_maps: Vec<ChannelMapLoad>,
134}
135
136impl<Input, Output> RpcDefinition<Input, Output> {
137 pub fn timeout(mut self, timeout: Duration) -> Self {
139 self.timeout = Some(timeout);
140 self
141 }
142
143 pub fn lock(mut self, lock: AttributeLock) -> Self {
145 self.locks.push(lock);
146 self
147 }
148
149 pub fn is_transactional(mut self) -> Self {
151 self.is_transactional = true;
152 self
153 }
154
155 pub fn load_attribute_map<T>(mut self, attribute_map: &AttributeMap<T>) -> Self {
157 self.load_attribute_maps.push(AttributeMapLoad {
158 name: attribute_map.name().to_owned(),
159 instance: None,
160 });
161 self
162 }
163
164 pub fn load_attribute_map_instance(mut self, load: AttributeMapLoad) -> Self {
166 self.load_attribute_maps.push(load);
167 self
168 }
169
170 pub fn load_channel<T>(mut self, channel: &Channel<T>) -> Self {
172 self.load_channels.push(ChannelLoad {
173 name: channel.name().to_owned(),
174 });
175 self
176 }
177
178 pub fn load_channel_map<T>(mut self, channel_map: &ChannelMap<T>) -> Self {
180 self.load_channel_maps.push(ChannelMapLoad {
181 name: channel_map.name().to_owned(),
182 instance: None,
183 });
184 self
185 }
186
187 pub fn load_channel_map_instance(mut self, load: ChannelMapLoad) -> Self {
189 self.load_channel_maps.push(load);
190 self
191 }
192}
193
194impl<Input, Output> From<Rpc<Input, Output>> for RpcDefinition<Input, Output> {
195 fn from(rpc: Rpc<Input, Output>) -> Self {
196 Self {
197 rpc,
198 timeout: None,
199 locks: Vec::new(),
200 is_transactional: false,
201 load_attribute_maps: Vec::new(),
202 load_channels: Vec::new(),
203 load_channel_maps: Vec::new(),
204 }
205 }
206}
207
208pub struct RpcList<FlowType> {
213 definitions: Vec<Box<dyn RpcBinder<FlowType>>>,
214}
215
216impl<FlowType> RpcList<FlowType>
217where
218 FlowType: Send + Sync + 'static,
219{
220 pub fn new() -> Self {
222 Self {
223 definitions: Vec::new(),
224 }
225 }
226
227 pub fn function<Input, Output>(
231 mut self,
232 definition: impl Into<RpcDefinition<Input, Output>>,
233 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
234 ) -> Self
235 where
236 Input: Value,
237 Output: Value,
238 {
239 self.definitions.push(Box::new(FunctionBinder {
240 definition: definition.into(),
241 handler,
242 }));
243 self
244 }
245
246 pub fn function_without_input<Output>(
248 mut self,
249 definition: impl Into<RpcDefinition<(), Output>>,
250 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
251 ) -> Self
252 where
253 Output: Value,
254 {
255 self.definitions.push(Box::new(FunctionWithoutInputBinder {
256 definition: definition.into(),
257 handler,
258 }));
259 self
260 }
261
262 pub fn procedure<Input>(
264 mut self,
265 definition: impl Into<RpcDefinition<Input, ()>>,
266 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
267 ) -> Self
268 where
269 Input: Value,
270 {
271 self.definitions.push(Box::new(ProcedureBinder {
272 definition: definition.into(),
273 handler,
274 }));
275 self
276 }
277
278 pub fn procedure_without_input(
280 mut self,
281 definition: impl Into<RpcDefinition<(), ()>>,
282 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
283 ) -> Self {
284 self.definitions.push(Box::new(ProcedureWithoutInputBinder {
285 definition: definition.into(),
286 handler,
287 }));
288 self
289 }
290
291 pub(crate) fn bind(self, flow: Arc<FlowType>) -> Vec<RegisteredRpc> {
292 self.definitions
293 .into_iter()
294 .map(|definition| definition.bind(Arc::clone(&flow)))
295 .collect()
296 }
297}
298
299impl<FlowType> Default for RpcList<FlowType>
300where
301 FlowType: Send + Sync + 'static,
302{
303 fn default() -> Self {
304 Self::new()
305 }
306}
307
308pub struct RpcResult<Output> {
312 output: Output,
313 next_steps: Vec<StepMovement>,
314 cancel_step_types: Vec<&'static str>,
315}
316
317impl<Output: Value> RpcResult<Output> {
318 pub fn new(output: Output) -> Self {
320 Self {
321 output,
322 next_steps: Vec::new(),
323 cancel_step_types: Vec::new(),
324 }
325 }
326
327 pub fn then(mut self, movement: StepMovement) -> Self {
329 self.next_steps.push(movement);
330 self
331 }
332
333 pub fn cancel_step<SelectedStep>(mut self, step: &SelectedStep) -> Self
338 where
339 SelectedStep: crate::Step,
340 {
341 let step_type = step.step_type();
342 if !self.cancel_step_types.contains(&step_type) {
343 self.cancel_step_types.push(step_type);
344 }
345 self
346 }
347
348 pub fn output(&self) -> &Output {
350 &self.output
351 }
352
353 pub fn next_steps(&self) -> &[StepMovement] {
355 &self.next_steps
356 }
357}
358
359pub(crate) struct ErasedRpcResult {
360 pub(crate) output: Box<dyn ErasedValue>,
361 pub(crate) next_steps: Vec<StepMovement>,
362 pub(crate) cancel_step_types: Vec<&'static str>,
363}
364
365#[derive(Clone)]
366pub(crate) struct RegisteredRpc {
367 pub(crate) name: &'static str,
368 pub(crate) timeout: Option<Duration>,
369 pub(crate) locks: Vec<AttributeLock>,
370 pub(crate) is_transactional: bool,
371 pub(crate) load_attribute_maps: Vec<AttributeMapLoad>,
372 pub(crate) load_channels: Vec<ChannelLoad>,
373 pub(crate) load_channel_maps: Vec<ChannelMapLoad>,
374 pub(crate) handler: Arc<dyn ErasedRpc>,
375}
376
377pub(crate) trait ErasedRpc: Send + Sync {
378 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult>;
379}
380
381trait RpcBinder<FlowType>: Send + Sync {
382 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc;
383}
384
385struct FunctionBinder<FlowType, Input, Output> {
386 definition: RpcDefinition<Input, Output>,
387 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
388}
389
390impl<FlowType, Input, Output> RpcBinder<FlowType> for FunctionBinder<FlowType, Input, Output>
391where
392 FlowType: Send + Sync + 'static,
393 Input: Value,
394 Output: Value,
395{
396 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
397 registered_rpc(
398 self.definition,
399 Arc::new(BoundFunction {
400 flow,
401 handler: self.handler,
402 }),
403 )
404 }
405}
406
407struct BoundFunction<FlowType, Input, Output> {
408 flow: Arc<FlowType>,
409 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<RpcResult<Output>>,
410}
411
412impl<FlowType, Input, Output> ErasedRpc for BoundFunction<FlowType, Input, Output>
413where
414 FlowType: Send + Sync + 'static,
415 Input: Value,
416 Output: Value,
417{
418 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
419 let result = (self.handler)(&self.flow, context, value_mapper::decode_handler(input)?)?;
420 Ok(ErasedRpcResult {
421 output: Box::new(TypedValue(result.output)),
422 next_steps: result.next_steps,
423 cancel_step_types: result.cancel_step_types,
424 })
425 }
426}
427
428struct FunctionWithoutInputBinder<FlowType, Output> {
429 definition: RpcDefinition<(), Output>,
430 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
431}
432
433impl<FlowType, Output> RpcBinder<FlowType> for FunctionWithoutInputBinder<FlowType, Output>
434where
435 FlowType: Send + Sync + 'static,
436 Output: Value,
437{
438 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
439 registered_rpc(
440 self.definition,
441 Arc::new(BoundFunctionWithoutInput {
442 flow,
443 handler: self.handler,
444 }),
445 )
446 }
447}
448
449struct BoundFunctionWithoutInput<FlowType, Output> {
450 flow: Arc<FlowType>,
451 handler: fn(&FlowType, &mut Context) -> HandlerResult<RpcResult<Output>>,
452}
453
454impl<FlowType, Output> ErasedRpc for BoundFunctionWithoutInput<FlowType, Output>
455where
456 FlowType: Send + Sync + 'static,
457 Output: Value,
458{
459 fn invoke(&self, context: &mut Context, _input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
460 let result = (self.handler)(&self.flow, context)?;
461 Ok(ErasedRpcResult {
462 output: Box::new(TypedValue(result.output)),
463 next_steps: result.next_steps,
464 cancel_step_types: result.cancel_step_types,
465 })
466 }
467}
468
469struct ProcedureBinder<FlowType, Input> {
470 definition: RpcDefinition<Input, ()>,
471 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
472}
473
474impl<FlowType, Input> RpcBinder<FlowType> for ProcedureBinder<FlowType, Input>
475where
476 FlowType: Send + Sync + 'static,
477 Input: Value,
478{
479 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
480 registered_rpc(
481 self.definition,
482 Arc::new(BoundProcedure {
483 flow,
484 handler: self.handler,
485 }),
486 )
487 }
488}
489
490struct BoundProcedure<FlowType, Input> {
491 flow: Arc<FlowType>,
492 handler: fn(&FlowType, &mut Context, Input) -> HandlerResult<()>,
493}
494
495impl<FlowType, Input> ErasedRpc for BoundProcedure<FlowType, Input>
496where
497 FlowType: Send + Sync + 'static,
498 Input: Value,
499{
500 fn invoke(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
501 (self.handler)(&self.flow, context, value_mapper::decode_handler(input)?)?;
502 Ok(empty_rpc_result())
503 }
504}
505
506struct ProcedureWithoutInputBinder<FlowType> {
507 definition: RpcDefinition<(), ()>,
508 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
509}
510
511impl<FlowType> RpcBinder<FlowType> for ProcedureWithoutInputBinder<FlowType>
512where
513 FlowType: Send + Sync + 'static,
514{
515 fn bind(self: Box<Self>, flow: Arc<FlowType>) -> RegisteredRpc {
516 registered_rpc(
517 self.definition,
518 Arc::new(BoundProcedureWithoutInput {
519 flow,
520 handler: self.handler,
521 }),
522 )
523 }
524}
525
526struct BoundProcedureWithoutInput<FlowType> {
527 flow: Arc<FlowType>,
528 handler: fn(&FlowType, &mut Context) -> HandlerResult<()>,
529}
530
531impl<FlowType> ErasedRpc for BoundProcedureWithoutInput<FlowType>
532where
533 FlowType: Send + Sync + 'static,
534{
535 fn invoke(&self, context: &mut Context, _input: &ProtoValue) -> HandlerResult<ErasedRpcResult> {
536 (self.handler)(&self.flow, context)?;
537 Ok(empty_rpc_result())
538 }
539}
540
541fn registered_rpc<Input, Output>(
542 definition: RpcDefinition<Input, Output>,
543 handler: Arc<dyn ErasedRpc>,
544) -> RegisteredRpc {
545 RegisteredRpc {
546 name: definition.rpc.name,
547 timeout: definition.timeout,
548 locks: definition.locks,
549 is_transactional: definition.is_transactional,
550 load_attribute_maps: definition.load_attribute_maps,
551 load_channels: definition.load_channels,
552 load_channel_maps: definition.load_channel_maps,
553 handler,
554 }
555}
556
557fn empty_rpc_result() -> ErasedRpcResult {
558 ErasedRpcResult {
559 output: Box::new(TypedValue(())),
560 next_steps: Vec::new(),
561 cancel_step_types: Vec::new(),
562 }
563}
564
565pub(crate) fn encode_rpc_output(output: &dyn ErasedValue) -> SdkResult<ProtoValue> {
566 output.encode()
567}