1use std::any::TypeId;
10use std::marker::PhantomData;
11
12use dex_protocol::dex::Value as ProtoValue;
13
14use crate::channel::ChannelGuard;
15use crate::step_options::ErasedStepOptions;
16use crate::value_mapper;
17use crate::{Context, HandlerResult, SdkResult, StepOptions, Value, Wait, short_type_name};
18
19pub trait Step: Send + Sync + 'static {
45 type Input: Value;
47
48 fn execute(&self, context: &mut Context, input: Self::Input) -> HandlerResult<StepDecision>;
54
55 fn wait_for(&self, _context: &mut Context, _input: Self::Input) -> HandlerResult<Wait> {
60 Ok(Wait::skip_immediately())
61 }
62
63 fn step_type(&self) -> &'static str {
67 short_type_name::<Self>()
68 }
69
70 fn options(&self) -> StepOptions<Self::Input> {
74 StepOptions::new()
75 }
76}
77
78pub struct StepList<'a, StartInput> {
83 definitions: Vec<StepDefinition<'a>>,
84 marker: PhantomData<fn(StartInput)>,
85}
86
87impl<'a, StartInput: Value> StepList<'a, StartInput> {
88 pub fn empty() -> Self {
90 Self {
91 definitions: Vec::new(),
92 marker: PhantomData,
93 }
94 }
95
96 pub fn start<StartStep>(step: &'a StartStep) -> Self
98 where
99 StartStep: Step<Input = StartInput>,
100 {
101 Self {
102 definitions: vec![StepDefinition::new(step, true)],
103 marker: PhantomData,
104 }
105 }
106
107 pub fn and<OtherStep>(mut self, step: &'a OtherStep) -> Self
109 where
110 OtherStep: Step,
111 {
112 self.definitions.push(StepDefinition::new(step, false));
113 self
114 }
115
116 pub(crate) fn into_definitions(self) -> Vec<RegisteredStep> {
117 self.definitions
118 .into_iter()
119 .map(|definition| RegisteredStep {
120 name: definition.name,
121 starting: definition.starting,
122 input_type: definition.input_type,
123 })
124 .collect()
125 }
126
127 pub(crate) fn find(&self, name: &str) -> Option<&dyn ErasedStep> {
128 self.definitions
129 .iter()
130 .find(|definition| definition.name == name)
131 .map(|definition| definition.handler)
132 }
133}
134
135impl<StartInput: Value> Default for StepList<'_, StartInput> {
136 fn default() -> Self {
137 Self::empty()
138 }
139}
140
141pub struct StepMovement {
146 pub(crate) target_step_type: &'static str,
147 input: Box<dyn ErasedValue>,
148 pub(crate) options_override: Option<ErasedStepOptions>,
149}
150
151impl StepMovement {
152 pub fn to<TargetStep>(step: &TargetStep, input: TargetStep::Input) -> Self
154 where
155 TargetStep: Step,
156 {
157 Self {
158 target_step_type: step.step_type(),
159 input: Box::new(TypedValue(input)),
160 options_override: None,
161 }
162 }
163
164 pub fn to_with_options<TargetStep>(
166 step: &TargetStep,
167 input: TargetStep::Input,
168 options: StepOptions<TargetStep::Input>,
169 ) -> Self
170 where
171 TargetStep: Step,
172 {
173 Self {
174 target_step_type: step.step_type(),
175 input: Box::new(TypedValue(input)),
176 options_override: Some(options.into()),
177 }
178 }
179
180 pub(crate) fn encode_input(&self) -> SdkResult<ProtoValue> {
181 self.input.encode()
182 }
183}
184
185pub struct StepDecision {
190 pub(crate) kind: StepDecisionKind,
191 pub(crate) cancel_step_types: Vec<&'static str>,
192 pub(crate) cancel_sibling_step_types: Vec<&'static str>,
193}
194
195pub(crate) enum StepDecisionKind {
196 Next(Vec<StepMovement>),
197 GracefulComplete(Box<dyn ErasedValue>),
198 ForceComplete(Box<dyn ErasedValue>),
199 ForceCompleteIfChannelsEmpty {
200 output: Box<dyn ErasedValue>,
201 fallback: Box<StepMovement>,
202 channels: Vec<ChannelGuard>,
203 },
204 ForceFail(String),
205 DeadEnd,
206}
207
208impl StepDecision {
209 pub fn go_to<TargetStep>(step: &TargetStep, input: TargetStep::Input) -> Self
211 where
212 TargetStep: Step,
213 {
214 Self::go_to_many([StepMovement::to(step, input)])
215 }
216
217 pub fn go_to_many(movements: impl IntoIterator<Item = StepMovement>) -> Self {
219 Self {
220 kind: StepDecisionKind::Next(movements.into_iter().collect()),
221 cancel_step_types: Vec::new(),
222 cancel_sibling_step_types: Vec::new(),
223 }
224 }
225
226 pub fn graceful_complete<Output: Value>(output: Output) -> Self {
228 Self {
229 kind: StepDecisionKind::GracefulComplete(Box::new(TypedValue(output))),
230 cancel_step_types: Vec::new(),
231 cancel_sibling_step_types: Vec::new(),
232 }
233 }
234
235 pub fn force_complete<Output: Value>(output: Output) -> Self {
237 Self {
238 kind: StepDecisionKind::ForceComplete(Box::new(TypedValue(output))),
239 cancel_step_types: Vec::new(),
240 cancel_sibling_step_types: Vec::new(),
241 }
242 }
243
244 pub fn force_complete_if_channels_empty<Output: Value>(
246 output: Output,
247 fallback: StepMovement,
248 channels: impl IntoIterator<Item = ChannelGuard>,
249 ) -> Self {
250 Self {
251 kind: StepDecisionKind::ForceCompleteIfChannelsEmpty {
252 output: Box::new(TypedValue(output)),
253 fallback: Box::new(fallback),
254 channels: channels.into_iter().collect(),
255 },
256 cancel_step_types: Vec::new(),
257 cancel_sibling_step_types: Vec::new(),
258 }
259 }
260
261 pub fn force_fail(reason: impl Into<String>) -> Self {
263 Self {
264 kind: StepDecisionKind::ForceFail(reason.into()),
265 cancel_step_types: Vec::new(),
266 cancel_sibling_step_types: Vec::new(),
267 }
268 }
269
270 pub fn dead_end() -> Self {
274 Self {
275 kind: StepDecisionKind::DeadEnd,
276 cancel_step_types: Vec::new(),
277 cancel_sibling_step_types: Vec::new(),
278 }
279 }
280
281 pub fn cancel_step<SelectedStep>(mut self, step: &SelectedStep) -> Self
287 where
288 SelectedStep: Step,
289 {
290 let step_type = step.step_type();
291 if !self.cancel_step_types.contains(&step_type) {
292 self.cancel_step_types.push(step_type);
293 }
294 self.cancel_sibling_step_types
295 .retain(|selected| *selected != step_type);
296 self
297 }
298
299 pub fn cancel_sibling_step<SelectedStep>(mut self, step: &SelectedStep) -> Self
305 where
306 SelectedStep: Step,
307 {
308 let step_type = step.step_type();
309 if !self.cancel_step_types.contains(&step_type)
310 && !self.cancel_sibling_step_types.contains(&step_type)
311 {
312 self.cancel_sibling_step_types.push(step_type);
313 }
314 self
315 }
316}
317
318#[derive(Clone)]
319pub(crate) struct RegisteredStep {
320 pub(crate) name: &'static str,
321 pub(crate) starting: bool,
322 pub(crate) input_type: TypeId,
323}
324
325struct StepDefinition<'a> {
326 name: &'static str,
327 starting: bool,
328 handler: &'a dyn ErasedStep,
329 input_type: TypeId,
330}
331
332impl<'a> StepDefinition<'a> {
333 fn new<SomeStep>(step: &'a SomeStep, starting: bool) -> Self
334 where
335 SomeStep: Step,
336 {
337 let name = step.step_type();
338 Self {
339 name,
340 starting,
341 handler: step,
342 input_type: TypeId::of::<SomeStep::Input>(),
343 }
344 }
345}
346
347pub(crate) trait ErasedStep: Send + Sync {
348 fn wait_for(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<Wait>;
349 fn execute(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<StepDecision>;
350 fn options(&self) -> ErasedStepOptions;
351}
352
353impl<SomeStep> ErasedStep for SomeStep
354where
355 SomeStep: Step,
356{
357 fn wait_for(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<Wait> {
358 Step::wait_for(self, context, value_mapper::decode_handler(input)?)
359 }
360
361 fn execute(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<StepDecision> {
362 Step::execute(self, context, value_mapper::decode_handler(input)?)
363 }
364
365 fn options(&self) -> ErasedStepOptions {
366 Step::options(self).into()
367 }
368}
369
370pub(crate) trait ErasedValue: Send + Sync {
371 fn encode(&self) -> SdkResult<ProtoValue>;
372}
373
374pub(crate) struct TypedValue<T>(pub(crate) T);
375
376impl<T: Value> ErasedValue for TypedValue<T> {
377 fn encode(&self) -> SdkResult<ProtoValue> {
378 value_mapper::encode(&self.0)
379 }
380}