1use std::marker::PhantomData;
10
11use dex_protocol::dex::Value as ProtoValue;
12
13use crate::channel::ChannelGuard;
14use crate::step_options::ErasedStepOptions;
15use crate::value_mapper;
16use crate::{Context, HandlerResult, SdkResult, StepOptions, Value, Wait, short_type_name};
17
18pub trait Step: Send + Sync + 'static {
44 type Input: Value;
46
47 fn execute(&self, context: &mut Context, input: Self::Input) -> HandlerResult<StepDecision>;
53
54 fn wait_for(&self, _context: &mut Context, _input: Self::Input) -> HandlerResult<Wait> {
59 Ok(Wait::skip_immediately())
60 }
61
62 fn step_type(&self) -> &'static str {
66 short_type_name::<Self>()
67 }
68
69 fn options(&self) -> StepOptions<Self::Input> {
73 StepOptions::new()
74 }
75}
76
77pub struct StepList<'a, StartInput> {
82 definitions: Vec<StepDefinition<'a>>,
83 marker: PhantomData<fn(StartInput)>,
84}
85
86impl<'a, StartInput: Value> StepList<'a, StartInput> {
87 pub fn empty() -> Self {
89 Self {
90 definitions: Vec::new(),
91 marker: PhantomData,
92 }
93 }
94
95 pub fn start<StartStep>(step: &'a StartStep) -> Self
97 where
98 StartStep: Step<Input = StartInput>,
99 {
100 Self {
101 definitions: vec![StepDefinition::new(step, true)],
102 marker: PhantomData,
103 }
104 }
105
106 pub fn and<OtherStep>(mut self, step: &'a OtherStep) -> Self
108 where
109 OtherStep: Step,
110 {
111 self.definitions.push(StepDefinition::new(step, false));
112 self
113 }
114
115 pub(crate) fn into_definitions(self) -> Vec<RegisteredStep> {
116 self.definitions
117 .into_iter()
118 .map(|definition| RegisteredStep {
119 name: definition.name,
120 starting: definition.starting,
121 })
122 .collect()
123 }
124
125 pub(crate) fn find(&self, name: &str) -> Option<&dyn ErasedStep> {
126 self.definitions
127 .iter()
128 .find(|definition| definition.name == name)
129 .map(|definition| definition.handler)
130 }
131}
132
133impl<StartInput: Value> Default for StepList<'_, StartInput> {
134 fn default() -> Self {
135 Self::empty()
136 }
137}
138
139pub struct StepMovement {
144 pub(crate) target_step_type: &'static str,
145 input: Box<dyn ErasedValue>,
146 pub(crate) options_override: Option<ErasedStepOptions>,
147}
148
149impl StepMovement {
150 pub fn to<TargetStep>(step: &TargetStep, input: TargetStep::Input) -> Self
152 where
153 TargetStep: Step,
154 {
155 Self {
156 target_step_type: step.step_type(),
157 input: Box::new(TypedValue(input)),
158 options_override: None,
159 }
160 }
161
162 pub fn to_with_options<TargetStep>(
164 step: &TargetStep,
165 input: TargetStep::Input,
166 options: StepOptions<TargetStep::Input>,
167 ) -> Self
168 where
169 TargetStep: Step,
170 {
171 Self {
172 target_step_type: step.step_type(),
173 input: Box::new(TypedValue(input)),
174 options_override: Some(options.into()),
175 }
176 }
177
178 pub(crate) fn encode_input(&self) -> SdkResult<ProtoValue> {
179 self.input.encode()
180 }
181}
182
183pub struct StepDecision {
188 pub(crate) kind: StepDecisionKind,
189}
190
191pub(crate) enum StepDecisionKind {
192 Next(Vec<StepMovement>),
193 GracefulComplete(Box<dyn ErasedValue>),
194 ForceComplete(Box<dyn ErasedValue>),
195 ForceCompleteIfChannelsEmpty {
196 output: Box<dyn ErasedValue>,
197 fallback: Box<StepMovement>,
198 channels: Vec<ChannelGuard>,
199 },
200 ForceFail(String),
201 DeadEnd,
202}
203
204impl StepDecision {
205 pub fn go_to<TargetStep>(step: &TargetStep, input: TargetStep::Input) -> Self
207 where
208 TargetStep: Step,
209 {
210 Self::go_to_many([StepMovement::to(step, input)])
211 }
212
213 pub fn go_to_many(movements: impl IntoIterator<Item = StepMovement>) -> Self {
215 Self {
216 kind: StepDecisionKind::Next(movements.into_iter().collect()),
217 }
218 }
219
220 pub fn graceful_complete<Output: Value>(output: Output) -> Self {
222 Self {
223 kind: StepDecisionKind::GracefulComplete(Box::new(TypedValue(output))),
224 }
225 }
226
227 pub fn force_complete<Output: Value>(output: Output) -> Self {
229 Self {
230 kind: StepDecisionKind::ForceComplete(Box::new(TypedValue(output))),
231 }
232 }
233
234 pub fn force_complete_if_channels_empty<Output: Value>(
236 output: Output,
237 fallback: StepMovement,
238 channels: impl IntoIterator<Item = ChannelGuard>,
239 ) -> Self {
240 Self {
241 kind: StepDecisionKind::ForceCompleteIfChannelsEmpty {
242 output: Box::new(TypedValue(output)),
243 fallback: Box::new(fallback),
244 channels: channels.into_iter().collect(),
245 },
246 }
247 }
248
249 pub fn force_fail(reason: impl Into<String>) -> Self {
251 Self {
252 kind: StepDecisionKind::ForceFail(reason.into()),
253 }
254 }
255
256 pub fn dead_end() -> Self {
260 Self {
261 kind: StepDecisionKind::DeadEnd,
262 }
263 }
264}
265
266#[derive(Clone)]
267pub(crate) struct RegisteredStep {
268 pub(crate) name: &'static str,
269 pub(crate) starting: bool,
270}
271
272struct StepDefinition<'a> {
273 name: &'static str,
274 starting: bool,
275 handler: &'a dyn ErasedStep,
276}
277
278impl<'a> StepDefinition<'a> {
279 fn new<SomeStep>(step: &'a SomeStep, starting: bool) -> Self
280 where
281 SomeStep: Step,
282 {
283 let name = step.step_type();
284 Self {
285 name,
286 starting,
287 handler: step,
288 }
289 }
290}
291
292pub(crate) trait ErasedStep: Send + Sync {
293 fn wait_for(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<Wait>;
294 fn execute(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<StepDecision>;
295 fn options(&self) -> ErasedStepOptions;
296}
297
298impl<SomeStep> ErasedStep for SomeStep
299where
300 SomeStep: Step,
301{
302 fn wait_for(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<Wait> {
303 Step::wait_for(self, context, value_mapper::decode_handler(input)?)
304 }
305
306 fn execute(&self, context: &mut Context, input: &ProtoValue) -> HandlerResult<StepDecision> {
307 Step::execute(self, context, value_mapper::decode_handler(input)?)
308 }
309
310 fn options(&self) -> ErasedStepOptions {
311 Step::options(self).into()
312 }
313}
314
315pub(crate) trait ErasedValue: Send + Sync {
316 fn encode(&self) -> SdkResult<ProtoValue>;
317}
318
319pub(crate) struct TypedValue<T>(pub(crate) T);
320
321impl<T: Value> ErasedValue for TypedValue<T> {
322 fn encode(&self) -> SdkResult<ProtoValue> {
323 value_mapper::encode(&self.0)
324 }
325}