StateMachineBuilder

Struct StateMachineBuilder 

Source
pub struct StateMachineBuilder<S, E, C>
where S: State, E: Event, C: Context,
{ pub(crate) id: Option<String>, pub(crate) transitions: Vec<Transition<S, E, C>>, pub(crate) fail_callback: Option<FailCallback<S, E, C>>, pub(crate) state_actions: HashMap<S, StateActions<S, E, C>>, pub(crate) state_timeouts: HashMap<S, Duration>, pub(crate) timeout_transitions: HashMap<S, (S, E)>, pub(crate) async_actions: HashMap<(S, E), Box<dyn AsyncAction<S, E, C>>>, }
Expand description

Builder for creating state machines with fluent API

Fields§

§id: Option<String>§transitions: Vec<Transition<S, E, C>>§fail_callback: Option<FailCallback<S, E, C>>§state_actions: HashMap<S, StateActions<S, E, C>>§state_timeouts: HashMap<S, Duration>§timeout_transitions: HashMap<S, (S, E)>§async_actions: HashMap<(S, E), Box<dyn AsyncAction<S, E, C>>>

Implementations§

Source§

impl<S, E, C> StateMachineBuilder<S, E, C>
where S: State, E: Event, C: Context,

Source

pub fn new() -> Self

Create a new state machine builder

Source

pub fn id(self, id: impl Into<String>) -> Self

Set the ID of the state machine

Examples found in repository?
examples/traffic_light_example.rs (line 68)
44pub fn build_traffic_light_system(
45) -> StateMachine<TrafficLightState, TrafficLightEvent, TrafficContext> {
46    let mut builder =
47        StateMachineBuilderFactory::create::<TrafficLightState, TrafficLightEvent, TrafficContext>(
48        );
49
50    // Configure the state machine based on available features
51    configure_basic_transitions(&mut builder);
52
53    #[cfg(feature = "extended")]
54    configure_entry_exit_actions(&mut builder);
55
56    #[cfg(feature = "guards")]
57    configure_priority_transitions(&mut builder);
58
59    #[cfg(feature = "timeout")]
60    configure_timeouts(&mut builder);
61
62    builder.set_fail_callback(Arc::new(|state, event, ctx| {
63        eprintln!(
64            "WARNING: Invalid transition from {:?} with {:?} at intersection {}",
65            state, event, ctx.intersection_id
66        );
67    }));
68    builder.id("TrafficLightController").build()
69}
More examples
Hide additional examples
examples/order_example.rs (line 66)
43fn basic_example() {
44    println!("=== Basic State Machine Example ===");
45
46    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
47
48    builder
49        .external_transition()
50        .from(OrderState::New)
51        .to(OrderState::PaymentPending)
52        .on(OrderEvent::Pay)
53        .perform(|_s, _e, ctx| {
54            println!("Order {} payment initiated", ctx.order_id);
55        });
56
57    builder
58        .external_transition()
59        .from(OrderState::PaymentPending)
60        .to(OrderState::PaymentReceived)
61        .on(OrderEvent::ConfirmPayment)
62        .perform(|_s, _e, ctx| {
63            println!("Payment confirmed for order {}", ctx.order_id);
64        });
65
66    let state_machine = builder.id("BasicOrderMachine").build();
67
68    let context = OrderContext {
69        order_id: "ORD-001".to_string(),
70        amount: 99.99,
71        customer_id: "CUST-123".to_string(),
72    };
73
74    let result = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
75    println!("Transition result: {:?}", result);
76}
77
78/// Example 2: With history tracking (requires 'history' feature)
79#[cfg(feature = "history")]
80fn history_example() {
81    println!("\n=== History Tracking Example ===");
82
83    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
84
85    builder
86        .external_transition()
87        .from(OrderState::New)
88        .to(OrderState::PaymentPending)
89        .on(OrderEvent::Pay)
90        .perform(|_s, _e, _c| {});
91
92    builder
93        .external_transition()
94        .from(OrderState::PaymentPending)
95        .to(OrderState::PaymentReceived)
96        .on(OrderEvent::ConfirmPayment)
97        .perform(|_s, _e, _c| {});
98
99    builder
100        .external_transition()
101        .from(OrderState::PaymentReceived)
102        .to(OrderState::Processing)
103        .on(OrderEvent::Process)
104        .perform(|_s, _e, _c| {});
105
106    let state_machine = builder.id("HistoryOrderMachine").build();
107
108    let context = OrderContext {
109        order_id: "ORD-002".to_string(),
110        amount: 149.99,
111        customer_id: "CUST-456".to_string(),
112    };
113
114    // Execute multiple transitions
115    let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
116    let _ = state_machine.fire_event(
117        OrderState::PaymentPending,
118        OrderEvent::ConfirmPayment,
119        context.clone(),
120    );
121    let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
122
123    // Check history
124    let history = state_machine.get_history();
125    println!("Transition history:");
126    for (i, record) in history.iter().enumerate() {
127        println!(
128            "  {}. {:?} -> {:?} via {:?} (success: {})",
129            i + 1,
130            record.from,
131            record.to,
132            record.event,
133            record.success
134        );
135    }
136}
137
138/// Example 3: With entry/exit actions (requires 'extended' feature)
139#[cfg(feature = "extended")]
140fn extended_example() {
141    println!("\n=== Extended State Machine Example ===");
142
143    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
144
145    builder
146        .with_entry_action(OrderState::Processing, |state, ctx| {
147            println!(
148                "ENTRY: Starting to process order {} in state {:?}",
149                ctx.order_id, state
150            );
151        })
152        .with_exit_action(OrderState::Processing, |state, ctx| {
153            println!(
154                "EXIT: Finished processing order {} from state {:?}",
155                ctx.order_id, state
156            );
157        })
158        .with_entry_action(OrderState::Shipped, |_state, ctx| {
159            println!("ENTRY: Order {} has been shipped!", ctx.order_id);
160        });
161
162    builder
163        .external_transition()
164        .from(OrderState::PaymentReceived)
165        .to(OrderState::Processing)
166        .on(OrderEvent::Process)
167        .perform(|_s, _e, _c| {});
168
169    builder
170        .external_transition()
171        .from(OrderState::Processing)
172        .to(OrderState::Shipped)
173        .on(OrderEvent::Ship)
174        .perform(|_s, _e, _c| {});
175
176    let state_machine = builder.id("ExtendedOrderMachine").build();
177
178    let context = OrderContext {
179        order_id: "ORD-003".to_string(),
180        amount: 299.99,
181        customer_id: "CUST-789".to_string(),
182    };
183
184    let _ = state_machine.fire_event(
185        OrderState::PaymentReceived,
186        OrderEvent::Process,
187        context.clone(),
188    );
189    let _ = state_machine.fire_event(OrderState::Processing, OrderEvent::Ship, context);
190}
191
192/// Example 4: With metrics (requires 'metrics' feature)
193#[cfg(feature = "metrics")]
194fn metrics_example() {
195    println!("\n=== Metrics Collection Example ===");
196
197    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
198
199    // Add multiple transitions
200    builder
201        .external_transition()
202        .from(OrderState::New)
203        .to(OrderState::PaymentPending)
204        .on(OrderEvent::Pay)
205        .perform(|_s, _e, _c| {});
206
207    builder
208        .external_transition()
209        .from(OrderState::PaymentPending)
210        .to(OrderState::PaymentReceived)
211        .on(OrderEvent::ConfirmPayment)
212        .when(|_s, _e, ctx| ctx.amount > 0.0)
213        .perform(|_s, _e, _c| {});
214
215    builder
216        .external_transitions()
217        .from_among(vec![
218            OrderState::New,
219            OrderState::PaymentPending,
220            OrderState::Processing,
221        ])
222        .to(OrderState::Cancelled)
223        .on(OrderEvent::Cancel)
224        .perform(|_s, _e, _c| {});
225
226    let state_machine = builder.id("MetricsOrderMachine").build();
227
228    // Simulate multiple orders
229    for i in 0..10 {
230        let context = OrderContext {
231            order_id: format!("ORD-{:03}", i),
232            amount: (i as f64) * 10.0,
233            customer_id: format!("CUST-{:03}", i),
234        };
235
236        let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
237
238        if i % 3 == 0 {
239            // Some orders get cancelled
240            let _ =
241                state_machine.fire_event(OrderState::PaymentPending, OrderEvent::Cancel, context);
242        } else {
243            // Others proceed normally
244            let _ = state_machine.fire_event(
245                OrderState::PaymentPending,
246                OrderEvent::ConfirmPayment,
247                context,
248            );
249        }
250    }
251
252    // Get and display metrics
253    let metrics = state_machine.get_metrics();
254    println!("State Machine Metrics:");
255    println!("  Total transitions: {}", metrics.total_transitions);
256    println!("  Successful: {}", metrics.successful_transitions);
257    println!("  Failed: {}", metrics.failed_transitions);
258    println!("  Success rate: {:.2}%", metrics.success_rate() * 100.0);
259
260    if let Some(avg_time) = metrics.average_transition_time() {
261        println!("  Average transition time: {:?}", avg_time);
262    }
263
264    println!("  State visit counts:");
265    for (state, count) in &metrics.state_visit_counts {
266        println!("    {}: {}", state, count);
267    }
268}
269
270/// Example 5: With guard priorities (requires 'guards' feature)
271#[cfg(feature = "guards")]
272fn guards_example() {
273    println!("\n=== Guard Priorities Example ===");
274
275    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
276
277    // Multiple transitions with different priorities
278    builder
279        .external_transition()
280        .from(OrderState::PaymentReceived)
281        .to(OrderState::Processing)
282        .on(OrderEvent::Process)
283        .when(|_s, _e, ctx| ctx.amount < 100.0)
284        .with_priority(10)
285        .perform(|_s, _e, ctx| {
286            println!(
287                "Processing small order {} (amount: {})",
288                ctx.order_id, ctx.amount
289            );
290        });
291
292    builder
293        .external_transition()
294        .from(OrderState::PaymentReceived)
295        .to(OrderState::Processing)
296        .on(OrderEvent::Process)
297        .when(|_s, _e, ctx| ctx.amount >= 100.0 && ctx.amount < 1000.0)
298        .with_priority(20)
299        .perform(|_s, _e, ctx| {
300            println!(
301                "Processing medium order {} (amount: {})",
302                ctx.order_id, ctx.amount
303            );
304        });
305
306    builder
307        .external_transition()
308        .from(OrderState::PaymentReceived)
309        .to(OrderState::Processing)
310        .on(OrderEvent::Process)
311        .when(|_s, _e, ctx| ctx.amount >= 1000.0)
312        .with_priority(30)
313        .perform(|_s, _e, ctx| {
314            println!(
315                "Processing large order {} (amount: {}) - Priority handling!",
316                ctx.order_id, ctx.amount
317            );
318        });
319
320    let state_machine = builder.id("GuardsOrderMachine").build();
321
322    // Test with different order amounts
323    let contexts = vec![
324        OrderContext {
325            order_id: "ORD-SMALL".to_string(),
326            amount: 50.0,
327            customer_id: "C1".to_string(),
328        },
329        OrderContext {
330            order_id: "ORD-MEDIUM".to_string(),
331            amount: 500.0,
332            customer_id: "C2".to_string(),
333        },
334        OrderContext {
335            order_id: "ORD-LARGE".to_string(),
336            amount: 5000.0,
337            customer_id: "C3".to_string(),
338        },
339    ];
340
341    for context in contexts {
342        let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
343    }
344}
345
346/// Example 6: With visualization (requires 'visualization' feature)
347#[cfg(feature = "visualization")]
348fn visualization_example() {
349    println!("\n=== Visualization Example ===");
350
351    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
352
353    // Build a complete order flow
354    builder
355        .external_transition()
356        .from(OrderState::New)
357        .to(OrderState::PaymentPending)
358        .on(OrderEvent::Pay)
359        .perform(|_s, _e, _c| {});
360
361    builder
362        .external_transition()
363        .from(OrderState::PaymentPending)
364        .to(OrderState::PaymentReceived)
365        .on(OrderEvent::ConfirmPayment)
366        .perform(|_s, _e, _c| {});
367
368    builder
369        .external_transition()
370        .from(OrderState::PaymentReceived)
371        .to(OrderState::Processing)
372        .on(OrderEvent::Process)
373        .perform(|_s, _e, _c| {});
374
375    builder
376        .external_transition()
377        .from(OrderState::Processing)
378        .to(OrderState::Shipped)
379        .on(OrderEvent::Ship)
380        .perform(|_s, _e, _c| {});
381
382    builder
383        .external_transition()
384        .from(OrderState::Shipped)
385        .to(OrderState::Delivered)
386        .on(OrderEvent::Deliver)
387        .perform(|_s, _e, _c| {});
388
389    builder
390        .external_transitions()
391        .from_among(vec![
392            OrderState::New,
393            OrderState::PaymentPending,
394            OrderState::Processing,
395        ])
396        .to(OrderState::Cancelled)
397        .on(OrderEvent::Cancel)
398        .perform(|_s, _e, _c| {});
399
400    builder
401        .external_transition()
402        .from(OrderState::Cancelled)
403        .to(OrderState::Refunded)
404        .on(OrderEvent::Refund)
405        .perform(|_s, _e, _c| {});
406
407    let state_machine = builder.id("VisualOrderMachine").build();
408
409    println!("DOT Format:");
410    println!("{}", state_machine.to_dot());
411
412    println!("\nPlantUML Format:");
413    println!("{}", state_machine.to_plantuml());
414}
415
416/// Example 7: With parallel regions (requires 'parallel' feature)
417#[cfg(feature = "parallel")]
418fn parallel_example() {
419    println!("\n=== Parallel Regions Example ===");
420
421    // Order processing region
422    let mut order_builder =
423        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
424    order_builder
425        .external_transition()
426        .from(OrderState::New)
427        .to(OrderState::Processing)
428        .on(OrderEvent::Process)
429        .perform(|_s, _e, ctx| {
430            println!("Order region: Processing order {}", ctx.order_id);
431        });
432
433    // Payment processing region (using same states/events for simplicity)
434    let mut payment_builder =
435        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
436    payment_builder
437        .external_transition()
438        .from(OrderState::PaymentPending)
439        .to(OrderState::PaymentReceived)
440        .on(OrderEvent::ConfirmPayment)
441        .perform(|_s, _e, ctx| {
442            println!(
443                "Payment region: Payment confirmed for order {}",
444                ctx.order_id
445            );
446        });
447
448    let mut parallel_machine = ParallelStateMachine::new();
449    parallel_machine.add_region(order_builder.id("OrderRegion").build());
450    parallel_machine.add_region(payment_builder.id("PaymentRegion").build());
451
452    let context = OrderContext {
453        order_id: "ORD-PARALLEL".to_string(),
454        amount: 199.99,
455        customer_id: "CUST-P1".to_string(),
456    };
457
458    // Fire events in parallel regions
459    println!("Firing Process event in parallel regions:");
460    let results = parallel_machine.fire_event(
461        vec![OrderState::New, OrderState::PaymentPending],
462        OrderEvent::Process,
463        context.clone(),
464    );
465
466    for (i, result) in results.iter().enumerate() {
467        println!("  Region {}: {:?}", i, result);
468    }
469
470    println!("Firing ConfirmPayment event in parallel regions:");
471    let results = parallel_machine.fire_event(
472        vec![OrderState::Processing, OrderState::PaymentPending],
473        OrderEvent::ConfirmPayment,
474        context,
475    );
476
477    for (i, result) in results.iter().enumerate() {
478        println!("  Region {}: {:?}", i, result);
479    }
480}
481
482/// Example 8: Complete example with multiple features
483#[cfg(all(feature = "history", feature = "metrics", feature = "extended"))]
484fn complete_example() {
485    println!("\n=== Complete Example with Multiple Features ===");
486
487    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
488
489    // Configure entry/exit actions
490    builder
491        .with_entry_action(OrderState::Processing, |_s, ctx| {
492            println!("[ENTRY] Starting to process order {}", ctx.order_id);
493        })
494        .with_exit_action(OrderState::Processing, |_s, ctx| {
495            println!("[EXIT] Finished processing order {}", ctx.order_id);
496        });
497
498    // Build transitions
499    builder
500        .external_transition()
501        .from(OrderState::New)
502        .to(OrderState::PaymentPending)
503        .on(OrderEvent::Pay)
504        .perform(|_s, _e, ctx| {
505            println!("Payment initiated for ${}", ctx.amount);
506        });
507
508    builder
509        .external_transition()
510        .from(OrderState::PaymentPending)
511        .to(OrderState::PaymentReceived)
512        .on(OrderEvent::ConfirmPayment)
513        .when(|_s, _e, ctx| ctx.amount > 0.0)
514        .perform(|_s, _e, ctx| {
515            println!("Payment confirmed: ${}", ctx.amount);
516        });
517
518    builder
519        .external_transition()
520        .from(OrderState::PaymentReceived)
521        .to(OrderState::Processing)
522        .on(OrderEvent::Process)
523        .perform(|_s, _e, _c| {});
524
525    builder
526        .external_transition()
527        .from(OrderState::Processing)
528        .to(OrderState::Shipped)
529        .on(OrderEvent::Ship)
530        .perform(|_s, _e, ctx| {
531            println!("Order {} shipped", ctx.order_id);
532        });
533
534    builder.set_fail_callback(Arc::new(|state, event, ctx| {
535        println!(
536            "FAILED: Cannot handle {:?} in state {:?} for order {}",
537            event, state, ctx.order_id
538        );
539    }));
540
541    let state_machine = builder.id("CompleteOrderMachine").build();
542
543    // Process an order through the complete flow
544    let context = OrderContext {
545        order_id: "ORD-COMPLETE".to_string(),
546        amount: 999.99,
547        customer_id: "CUST-VIP".to_string(),
548    };
549
550    println!("\nProcessing order through complete flow:");
551    let states = [
552        (OrderState::New, OrderEvent::Pay),
553        (OrderState::PaymentPending, OrderEvent::ConfirmPayment),
554        (OrderState::PaymentReceived, OrderEvent::Process),
555        (OrderState::Processing, OrderEvent::Ship),
556    ];
557
558    for (state, event) in &states {
559        let result = state_machine.fire_event(state.clone(), event.clone(), context.clone());
560        println!("  {:?} + {:?} = {:?}", state, event, result);
561    }
562
563    // Try an invalid transition
564    println!("\nTrying invalid transition:");
565    let _ = state_machine.fire_event(OrderState::Shipped, OrderEvent::Pay, context);
566
567    // Display collected data
568    println!("\nHistory:");
569    for record in state_machine.get_history() {
570        println!(
571            "  {:?} -> {:?} (success: {})",
572            record.from, record.to, record.success
573        );
574    }
575
576    println!("\nMetrics:");
577    let metrics = state_machine.get_metrics();
578    println!(
579        "  Total: {}, Success: {}, Failed: {}",
580        metrics.total_transitions, metrics.successful_transitions, metrics.failed_transitions
581    );
582}
Source

pub fn external_transition(&mut self) -> ExternalTransitionBuilder<'_, S, E, C>

Start building an external transition

Examples found in repository?
examples/order_example.rs (line 49)
43fn basic_example() {
44    println!("=== Basic State Machine Example ===");
45
46    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
47
48    builder
49        .external_transition()
50        .from(OrderState::New)
51        .to(OrderState::PaymentPending)
52        .on(OrderEvent::Pay)
53        .perform(|_s, _e, ctx| {
54            println!("Order {} payment initiated", ctx.order_id);
55        });
56
57    builder
58        .external_transition()
59        .from(OrderState::PaymentPending)
60        .to(OrderState::PaymentReceived)
61        .on(OrderEvent::ConfirmPayment)
62        .perform(|_s, _e, ctx| {
63            println!("Payment confirmed for order {}", ctx.order_id);
64        });
65
66    let state_machine = builder.id("BasicOrderMachine").build();
67
68    let context = OrderContext {
69        order_id: "ORD-001".to_string(),
70        amount: 99.99,
71        customer_id: "CUST-123".to_string(),
72    };
73
74    let result = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
75    println!("Transition result: {:?}", result);
76}
77
78/// Example 2: With history tracking (requires 'history' feature)
79#[cfg(feature = "history")]
80fn history_example() {
81    println!("\n=== History Tracking Example ===");
82
83    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
84
85    builder
86        .external_transition()
87        .from(OrderState::New)
88        .to(OrderState::PaymentPending)
89        .on(OrderEvent::Pay)
90        .perform(|_s, _e, _c| {});
91
92    builder
93        .external_transition()
94        .from(OrderState::PaymentPending)
95        .to(OrderState::PaymentReceived)
96        .on(OrderEvent::ConfirmPayment)
97        .perform(|_s, _e, _c| {});
98
99    builder
100        .external_transition()
101        .from(OrderState::PaymentReceived)
102        .to(OrderState::Processing)
103        .on(OrderEvent::Process)
104        .perform(|_s, _e, _c| {});
105
106    let state_machine = builder.id("HistoryOrderMachine").build();
107
108    let context = OrderContext {
109        order_id: "ORD-002".to_string(),
110        amount: 149.99,
111        customer_id: "CUST-456".to_string(),
112    };
113
114    // Execute multiple transitions
115    let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
116    let _ = state_machine.fire_event(
117        OrderState::PaymentPending,
118        OrderEvent::ConfirmPayment,
119        context.clone(),
120    );
121    let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
122
123    // Check history
124    let history = state_machine.get_history();
125    println!("Transition history:");
126    for (i, record) in history.iter().enumerate() {
127        println!(
128            "  {}. {:?} -> {:?} via {:?} (success: {})",
129            i + 1,
130            record.from,
131            record.to,
132            record.event,
133            record.success
134        );
135    }
136}
137
138/// Example 3: With entry/exit actions (requires 'extended' feature)
139#[cfg(feature = "extended")]
140fn extended_example() {
141    println!("\n=== Extended State Machine Example ===");
142
143    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
144
145    builder
146        .with_entry_action(OrderState::Processing, |state, ctx| {
147            println!(
148                "ENTRY: Starting to process order {} in state {:?}",
149                ctx.order_id, state
150            );
151        })
152        .with_exit_action(OrderState::Processing, |state, ctx| {
153            println!(
154                "EXIT: Finished processing order {} from state {:?}",
155                ctx.order_id, state
156            );
157        })
158        .with_entry_action(OrderState::Shipped, |_state, ctx| {
159            println!("ENTRY: Order {} has been shipped!", ctx.order_id);
160        });
161
162    builder
163        .external_transition()
164        .from(OrderState::PaymentReceived)
165        .to(OrderState::Processing)
166        .on(OrderEvent::Process)
167        .perform(|_s, _e, _c| {});
168
169    builder
170        .external_transition()
171        .from(OrderState::Processing)
172        .to(OrderState::Shipped)
173        .on(OrderEvent::Ship)
174        .perform(|_s, _e, _c| {});
175
176    let state_machine = builder.id("ExtendedOrderMachine").build();
177
178    let context = OrderContext {
179        order_id: "ORD-003".to_string(),
180        amount: 299.99,
181        customer_id: "CUST-789".to_string(),
182    };
183
184    let _ = state_machine.fire_event(
185        OrderState::PaymentReceived,
186        OrderEvent::Process,
187        context.clone(),
188    );
189    let _ = state_machine.fire_event(OrderState::Processing, OrderEvent::Ship, context);
190}
191
192/// Example 4: With metrics (requires 'metrics' feature)
193#[cfg(feature = "metrics")]
194fn metrics_example() {
195    println!("\n=== Metrics Collection Example ===");
196
197    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
198
199    // Add multiple transitions
200    builder
201        .external_transition()
202        .from(OrderState::New)
203        .to(OrderState::PaymentPending)
204        .on(OrderEvent::Pay)
205        .perform(|_s, _e, _c| {});
206
207    builder
208        .external_transition()
209        .from(OrderState::PaymentPending)
210        .to(OrderState::PaymentReceived)
211        .on(OrderEvent::ConfirmPayment)
212        .when(|_s, _e, ctx| ctx.amount > 0.0)
213        .perform(|_s, _e, _c| {});
214
215    builder
216        .external_transitions()
217        .from_among(vec![
218            OrderState::New,
219            OrderState::PaymentPending,
220            OrderState::Processing,
221        ])
222        .to(OrderState::Cancelled)
223        .on(OrderEvent::Cancel)
224        .perform(|_s, _e, _c| {});
225
226    let state_machine = builder.id("MetricsOrderMachine").build();
227
228    // Simulate multiple orders
229    for i in 0..10 {
230        let context = OrderContext {
231            order_id: format!("ORD-{:03}", i),
232            amount: (i as f64) * 10.0,
233            customer_id: format!("CUST-{:03}", i),
234        };
235
236        let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
237
238        if i % 3 == 0 {
239            // Some orders get cancelled
240            let _ =
241                state_machine.fire_event(OrderState::PaymentPending, OrderEvent::Cancel, context);
242        } else {
243            // Others proceed normally
244            let _ = state_machine.fire_event(
245                OrderState::PaymentPending,
246                OrderEvent::ConfirmPayment,
247                context,
248            );
249        }
250    }
251
252    // Get and display metrics
253    let metrics = state_machine.get_metrics();
254    println!("State Machine Metrics:");
255    println!("  Total transitions: {}", metrics.total_transitions);
256    println!("  Successful: {}", metrics.successful_transitions);
257    println!("  Failed: {}", metrics.failed_transitions);
258    println!("  Success rate: {:.2}%", metrics.success_rate() * 100.0);
259
260    if let Some(avg_time) = metrics.average_transition_time() {
261        println!("  Average transition time: {:?}", avg_time);
262    }
263
264    println!("  State visit counts:");
265    for (state, count) in &metrics.state_visit_counts {
266        println!("    {}: {}", state, count);
267    }
268}
269
270/// Example 5: With guard priorities (requires 'guards' feature)
271#[cfg(feature = "guards")]
272fn guards_example() {
273    println!("\n=== Guard Priorities Example ===");
274
275    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
276
277    // Multiple transitions with different priorities
278    builder
279        .external_transition()
280        .from(OrderState::PaymentReceived)
281        .to(OrderState::Processing)
282        .on(OrderEvent::Process)
283        .when(|_s, _e, ctx| ctx.amount < 100.0)
284        .with_priority(10)
285        .perform(|_s, _e, ctx| {
286            println!(
287                "Processing small order {} (amount: {})",
288                ctx.order_id, ctx.amount
289            );
290        });
291
292    builder
293        .external_transition()
294        .from(OrderState::PaymentReceived)
295        .to(OrderState::Processing)
296        .on(OrderEvent::Process)
297        .when(|_s, _e, ctx| ctx.amount >= 100.0 && ctx.amount < 1000.0)
298        .with_priority(20)
299        .perform(|_s, _e, ctx| {
300            println!(
301                "Processing medium order {} (amount: {})",
302                ctx.order_id, ctx.amount
303            );
304        });
305
306    builder
307        .external_transition()
308        .from(OrderState::PaymentReceived)
309        .to(OrderState::Processing)
310        .on(OrderEvent::Process)
311        .when(|_s, _e, ctx| ctx.amount >= 1000.0)
312        .with_priority(30)
313        .perform(|_s, _e, ctx| {
314            println!(
315                "Processing large order {} (amount: {}) - Priority handling!",
316                ctx.order_id, ctx.amount
317            );
318        });
319
320    let state_machine = builder.id("GuardsOrderMachine").build();
321
322    // Test with different order amounts
323    let contexts = vec![
324        OrderContext {
325            order_id: "ORD-SMALL".to_string(),
326            amount: 50.0,
327            customer_id: "C1".to_string(),
328        },
329        OrderContext {
330            order_id: "ORD-MEDIUM".to_string(),
331            amount: 500.0,
332            customer_id: "C2".to_string(),
333        },
334        OrderContext {
335            order_id: "ORD-LARGE".to_string(),
336            amount: 5000.0,
337            customer_id: "C3".to_string(),
338        },
339    ];
340
341    for context in contexts {
342        let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
343    }
344}
345
346/// Example 6: With visualization (requires 'visualization' feature)
347#[cfg(feature = "visualization")]
348fn visualization_example() {
349    println!("\n=== Visualization Example ===");
350
351    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
352
353    // Build a complete order flow
354    builder
355        .external_transition()
356        .from(OrderState::New)
357        .to(OrderState::PaymentPending)
358        .on(OrderEvent::Pay)
359        .perform(|_s, _e, _c| {});
360
361    builder
362        .external_transition()
363        .from(OrderState::PaymentPending)
364        .to(OrderState::PaymentReceived)
365        .on(OrderEvent::ConfirmPayment)
366        .perform(|_s, _e, _c| {});
367
368    builder
369        .external_transition()
370        .from(OrderState::PaymentReceived)
371        .to(OrderState::Processing)
372        .on(OrderEvent::Process)
373        .perform(|_s, _e, _c| {});
374
375    builder
376        .external_transition()
377        .from(OrderState::Processing)
378        .to(OrderState::Shipped)
379        .on(OrderEvent::Ship)
380        .perform(|_s, _e, _c| {});
381
382    builder
383        .external_transition()
384        .from(OrderState::Shipped)
385        .to(OrderState::Delivered)
386        .on(OrderEvent::Deliver)
387        .perform(|_s, _e, _c| {});
388
389    builder
390        .external_transitions()
391        .from_among(vec![
392            OrderState::New,
393            OrderState::PaymentPending,
394            OrderState::Processing,
395        ])
396        .to(OrderState::Cancelled)
397        .on(OrderEvent::Cancel)
398        .perform(|_s, _e, _c| {});
399
400    builder
401        .external_transition()
402        .from(OrderState::Cancelled)
403        .to(OrderState::Refunded)
404        .on(OrderEvent::Refund)
405        .perform(|_s, _e, _c| {});
406
407    let state_machine = builder.id("VisualOrderMachine").build();
408
409    println!("DOT Format:");
410    println!("{}", state_machine.to_dot());
411
412    println!("\nPlantUML Format:");
413    println!("{}", state_machine.to_plantuml());
414}
415
416/// Example 7: With parallel regions (requires 'parallel' feature)
417#[cfg(feature = "parallel")]
418fn parallel_example() {
419    println!("\n=== Parallel Regions Example ===");
420
421    // Order processing region
422    let mut order_builder =
423        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
424    order_builder
425        .external_transition()
426        .from(OrderState::New)
427        .to(OrderState::Processing)
428        .on(OrderEvent::Process)
429        .perform(|_s, _e, ctx| {
430            println!("Order region: Processing order {}", ctx.order_id);
431        });
432
433    // Payment processing region (using same states/events for simplicity)
434    let mut payment_builder =
435        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
436    payment_builder
437        .external_transition()
438        .from(OrderState::PaymentPending)
439        .to(OrderState::PaymentReceived)
440        .on(OrderEvent::ConfirmPayment)
441        .perform(|_s, _e, ctx| {
442            println!(
443                "Payment region: Payment confirmed for order {}",
444                ctx.order_id
445            );
446        });
447
448    let mut parallel_machine = ParallelStateMachine::new();
449    parallel_machine.add_region(order_builder.id("OrderRegion").build());
450    parallel_machine.add_region(payment_builder.id("PaymentRegion").build());
451
452    let context = OrderContext {
453        order_id: "ORD-PARALLEL".to_string(),
454        amount: 199.99,
455        customer_id: "CUST-P1".to_string(),
456    };
457
458    // Fire events in parallel regions
459    println!("Firing Process event in parallel regions:");
460    let results = parallel_machine.fire_event(
461        vec![OrderState::New, OrderState::PaymentPending],
462        OrderEvent::Process,
463        context.clone(),
464    );
465
466    for (i, result) in results.iter().enumerate() {
467        println!("  Region {}: {:?}", i, result);
468    }
469
470    println!("Firing ConfirmPayment event in parallel regions:");
471    let results = parallel_machine.fire_event(
472        vec![OrderState::Processing, OrderState::PaymentPending],
473        OrderEvent::ConfirmPayment,
474        context,
475    );
476
477    for (i, result) in results.iter().enumerate() {
478        println!("  Region {}: {:?}", i, result);
479    }
480}
481
482/// Example 8: Complete example with multiple features
483#[cfg(all(feature = "history", feature = "metrics", feature = "extended"))]
484fn complete_example() {
485    println!("\n=== Complete Example with Multiple Features ===");
486
487    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
488
489    // Configure entry/exit actions
490    builder
491        .with_entry_action(OrderState::Processing, |_s, ctx| {
492            println!("[ENTRY] Starting to process order {}", ctx.order_id);
493        })
494        .with_exit_action(OrderState::Processing, |_s, ctx| {
495            println!("[EXIT] Finished processing order {}", ctx.order_id);
496        });
497
498    // Build transitions
499    builder
500        .external_transition()
501        .from(OrderState::New)
502        .to(OrderState::PaymentPending)
503        .on(OrderEvent::Pay)
504        .perform(|_s, _e, ctx| {
505            println!("Payment initiated for ${}", ctx.amount);
506        });
507
508    builder
509        .external_transition()
510        .from(OrderState::PaymentPending)
511        .to(OrderState::PaymentReceived)
512        .on(OrderEvent::ConfirmPayment)
513        .when(|_s, _e, ctx| ctx.amount > 0.0)
514        .perform(|_s, _e, ctx| {
515            println!("Payment confirmed: ${}", ctx.amount);
516        });
517
518    builder
519        .external_transition()
520        .from(OrderState::PaymentReceived)
521        .to(OrderState::Processing)
522        .on(OrderEvent::Process)
523        .perform(|_s, _e, _c| {});
524
525    builder
526        .external_transition()
527        .from(OrderState::Processing)
528        .to(OrderState::Shipped)
529        .on(OrderEvent::Ship)
530        .perform(|_s, _e, ctx| {
531            println!("Order {} shipped", ctx.order_id);
532        });
533
534    builder.set_fail_callback(Arc::new(|state, event, ctx| {
535        println!(
536            "FAILED: Cannot handle {:?} in state {:?} for order {}",
537            event, state, ctx.order_id
538        );
539    }));
540
541    let state_machine = builder.id("CompleteOrderMachine").build();
542
543    // Process an order through the complete flow
544    let context = OrderContext {
545        order_id: "ORD-COMPLETE".to_string(),
546        amount: 999.99,
547        customer_id: "CUST-VIP".to_string(),
548    };
549
550    println!("\nProcessing order through complete flow:");
551    let states = [
552        (OrderState::New, OrderEvent::Pay),
553        (OrderState::PaymentPending, OrderEvent::ConfirmPayment),
554        (OrderState::PaymentReceived, OrderEvent::Process),
555        (OrderState::Processing, OrderEvent::Ship),
556    ];
557
558    for (state, event) in &states {
559        let result = state_machine.fire_event(state.clone(), event.clone(), context.clone());
560        println!("  {:?} + {:?} = {:?}", state, event, result);
561    }
562
563    // Try an invalid transition
564    println!("\nTrying invalid transition:");
565    let _ = state_machine.fire_event(OrderState::Shipped, OrderEvent::Pay, context);
566
567    // Display collected data
568    println!("\nHistory:");
569    for record in state_machine.get_history() {
570        println!(
571            "  {:?} -> {:?} (success: {})",
572            record.from, record.to, record.success
573        );
574    }
575
576    println!("\nMetrics:");
577    let metrics = state_machine.get_metrics();
578    println!(
579        "  Total: {}, Success: {}, Failed: {}",
580        metrics.total_transitions, metrics.successful_transitions, metrics.failed_transitions
581    );
582}
More examples
Hide additional examples
examples/traffic_light_example.rs (line 77)
72fn configure_basic_transitions<'a>(
73    builder: &'a mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
74) -> &'a mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext> {
75    // Normal traffic light cycle
76    builder
77        .external_transition()
78        .from(TrafficLightState::Green)
79        .to(TrafficLightState::Yellow)
80        .on(TrafficLightEvent::Timer)
81        .perform(|_s, _e, ctx| {
82            println!("[{}] Changing to YELLOW", ctx.intersection_id);
83        });
84
85    builder
86        .external_transition()
87        .from(TrafficLightState::Yellow)
88        .to(TrafficLightState::Red)
89        .on(TrafficLightEvent::Timer)
90        .perform(|_s, _e, ctx| {
91            println!("[{}] Changing to RED", ctx.intersection_id);
92        });
93
94    builder
95        .external_transition()
96        .from(TrafficLightState::Red)
97        .to(TrafficLightState::Green)
98        .on(TrafficLightEvent::Timer)
99        .when(|_s, _e, ctx| !ctx.emergency_active)
100        .perform(|_s, _e, ctx| {
101            println!("[{}] Changing to GREEN", ctx.intersection_id);
102        });
103
104    // Emergency vehicle handling
105    builder
106        .external_transitions()
107        .from_among(vec![
108            TrafficLightState::Green,
109            TrafficLightState::Yellow,
110            TrafficLightState::Red,
111        ])
112        .to(TrafficLightState::Emergency)
113        .on(TrafficLightEvent::EmergencyVehicleDetected)
114        .perform(|from, _e, ctx| {
115            println!(
116                "[{}] EMERGENCY MODE! Was in {:?}",
117                ctx.intersection_id, from
118            );
119        });
120
121    builder
122        .external_transition()
123        .from(TrafficLightState::Emergency)
124        .to(TrafficLightState::Red)
125        .on(TrafficLightEvent::EmergencyCleared)
126        .perform(|_s, _e, ctx| {
127            println!(
128                "[{}] Emergency cleared, returning to RED",
129                ctx.intersection_id
130            );
131        });
132
133    // Maintenance mode
134    builder
135        .external_transitions()
136        .from_among(vec![
137            TrafficLightState::Green,
138            TrafficLightState::Yellow,
139            TrafficLightState::Red,
140        ])
141        .to(TrafficLightState::FlashingYellow)
142        .on(TrafficLightEvent::MaintenanceMode)
143        .perform(|_s, _e, ctx| {
144            println!(
145                "[{}] Entering maintenance mode - FLASHING YELLOW",
146                ctx.intersection_id
147            );
148        });
149
150    builder
151        .external_transition()
152        .from(TrafficLightState::FlashingYellow)
153        .to(TrafficLightState::Red)
154        .on(TrafficLightEvent::NormalMode)
155        .perform(|_s, _e, ctx| {
156            println!("[{}] Exiting maintenance mode", ctx.intersection_id);
157        });
158
159    builder
160}
161
162/// Configure entry and exit actions for states
163#[cfg(feature = "extended")]
164fn configure_entry_exit_actions(
165    builder: &mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
166) {
167    // Entry actions
168    builder.with_entry_action(TrafficLightState::Green, |_state, ctx| {
169        println!(
170            "[{}] GREEN light ON - Vehicles may proceed",
171            ctx.intersection_id
172        );
173        // In a real system, this would control the actual light hardware
174    });
175
176    builder.with_entry_action(TrafficLightState::Yellow, |_state, ctx| {
177        println!(
178            "[{}] YELLOW light ON - Prepare to stop",
179            ctx.intersection_id
180        );
181    });
182
183    builder.with_entry_action(TrafficLightState::Red, |_state, ctx| {
184        println!(
185            "[{}] RED light ON - Vehicles must stop",
186            ctx.intersection_id
187        );
188        if ctx.pedestrian_waiting {
189            println!(
190                "[{}] Pedestrian crossing signal activated",
191                ctx.intersection_id
192            );
193        }
194    });
195
196    builder.with_entry_action(TrafficLightState::Emergency, |_state, ctx| {
197        println!(
198            "[{}] EMERGENCY MODE - All lights RED except emergency route",
199            ctx.intersection_id
200        );
201        // Would trigger emergency protocols in real system
202    });
203
204    // Exit actions
205    builder.with_exit_action(TrafficLightState::Green, |_state, ctx| {
206        println!("[{}] GREEN light OFF", ctx.intersection_id);
207    });
208
209    builder.with_exit_action(TrafficLightState::Emergency, |_state, ctx| {
210        println!("[{}] Exiting emergency mode", ctx.intersection_id);
211    });
212}
213
214/// Configure priority-based transitions for complex scenarios
215#[cfg(feature = "guards")]
216fn configure_priority_transitions(
217    builder: &mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
218) {
219    // High-priority pedestrian crossing during low traffic
220    builder
221        .external_transition()
222        .from(TrafficLightState::Green)
223        .to(TrafficLightState::Yellow)
224        .on(TrafficLightEvent::PedestrianRequest)
225        .when(|_s, _e, ctx| ctx.traffic_density < 0.3 && ctx.pedestrian_waiting)
226        .with_priority(100)
227        .perform(|_s, _e, ctx| {
228            println!(
229                "[{}] Pedestrian priority - changing to yellow",
230                ctx.intersection_id
231            );
232        });
233
234    // Normal pedestrian request
235    builder
236        .external_transition()
237        .from(TrafficLightState::Green)
238        .to(TrafficLightState::Yellow)
239        .on(TrafficLightEvent::PedestrianRequest)
240        .when(|_s, _e, ctx| {
241            ctx.pedestrian_waiting && ctx.time_in_state > std::time::Duration::from_secs(10)
242        })
243        .with_priority(50)
244        .perform(|_s, _e, ctx| {
245            println!("[{}] Pedestrian request accepted", ctx.intersection_id);
246        });
247
248    // Rush hour handling - extend green time
249    builder
250        .internal_transition()
251        .within(TrafficLightState::Green)
252        .on(TrafficLightEvent::Timer)
253        .when(|_s, _e, ctx| {
254            ctx.traffic_density > 0.8 && ctx.time_in_state < std::time::Duration::from_secs(90)
255        })
256        .with_priority(200)
257        .perform(|_s, _e, ctx| {
258            println!(
259                "[{}] High traffic - extending green phase",
260                ctx.intersection_id
261            );
262        });
263}
Source

pub fn internal_transition(&mut self) -> InternalTransitionBuilder<'_, S, E, C>

Start building an internal transition

Examples found in repository?
examples/traffic_light_example.rs (line 250)
216fn configure_priority_transitions(
217    builder: &mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
218) {
219    // High-priority pedestrian crossing during low traffic
220    builder
221        .external_transition()
222        .from(TrafficLightState::Green)
223        .to(TrafficLightState::Yellow)
224        .on(TrafficLightEvent::PedestrianRequest)
225        .when(|_s, _e, ctx| ctx.traffic_density < 0.3 && ctx.pedestrian_waiting)
226        .with_priority(100)
227        .perform(|_s, _e, ctx| {
228            println!(
229                "[{}] Pedestrian priority - changing to yellow",
230                ctx.intersection_id
231            );
232        });
233
234    // Normal pedestrian request
235    builder
236        .external_transition()
237        .from(TrafficLightState::Green)
238        .to(TrafficLightState::Yellow)
239        .on(TrafficLightEvent::PedestrianRequest)
240        .when(|_s, _e, ctx| {
241            ctx.pedestrian_waiting && ctx.time_in_state > std::time::Duration::from_secs(10)
242        })
243        .with_priority(50)
244        .perform(|_s, _e, ctx| {
245            println!("[{}] Pedestrian request accepted", ctx.intersection_id);
246        });
247
248    // Rush hour handling - extend green time
249    builder
250        .internal_transition()
251        .within(TrafficLightState::Green)
252        .on(TrafficLightEvent::Timer)
253        .when(|_s, _e, ctx| {
254            ctx.traffic_density > 0.8 && ctx.time_in_state < std::time::Duration::from_secs(90)
255        })
256        .with_priority(200)
257        .perform(|_s, _e, ctx| {
258            println!(
259                "[{}] High traffic - extending green phase",
260                ctx.intersection_id
261            );
262        });
263}
Source

pub fn external_transitions( &mut self, ) -> ExternalTransitionsBuilder<'_, S, E, C>

Start building external transitions from multiple states

Examples found in repository?
examples/order_example.rs (line 216)
194fn metrics_example() {
195    println!("\n=== Metrics Collection Example ===");
196
197    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
198
199    // Add multiple transitions
200    builder
201        .external_transition()
202        .from(OrderState::New)
203        .to(OrderState::PaymentPending)
204        .on(OrderEvent::Pay)
205        .perform(|_s, _e, _c| {});
206
207    builder
208        .external_transition()
209        .from(OrderState::PaymentPending)
210        .to(OrderState::PaymentReceived)
211        .on(OrderEvent::ConfirmPayment)
212        .when(|_s, _e, ctx| ctx.amount > 0.0)
213        .perform(|_s, _e, _c| {});
214
215    builder
216        .external_transitions()
217        .from_among(vec![
218            OrderState::New,
219            OrderState::PaymentPending,
220            OrderState::Processing,
221        ])
222        .to(OrderState::Cancelled)
223        .on(OrderEvent::Cancel)
224        .perform(|_s, _e, _c| {});
225
226    let state_machine = builder.id("MetricsOrderMachine").build();
227
228    // Simulate multiple orders
229    for i in 0..10 {
230        let context = OrderContext {
231            order_id: format!("ORD-{:03}", i),
232            amount: (i as f64) * 10.0,
233            customer_id: format!("CUST-{:03}", i),
234        };
235
236        let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
237
238        if i % 3 == 0 {
239            // Some orders get cancelled
240            let _ =
241                state_machine.fire_event(OrderState::PaymentPending, OrderEvent::Cancel, context);
242        } else {
243            // Others proceed normally
244            let _ = state_machine.fire_event(
245                OrderState::PaymentPending,
246                OrderEvent::ConfirmPayment,
247                context,
248            );
249        }
250    }
251
252    // Get and display metrics
253    let metrics = state_machine.get_metrics();
254    println!("State Machine Metrics:");
255    println!("  Total transitions: {}", metrics.total_transitions);
256    println!("  Successful: {}", metrics.successful_transitions);
257    println!("  Failed: {}", metrics.failed_transitions);
258    println!("  Success rate: {:.2}%", metrics.success_rate() * 100.0);
259
260    if let Some(avg_time) = metrics.average_transition_time() {
261        println!("  Average transition time: {:?}", avg_time);
262    }
263
264    println!("  State visit counts:");
265    for (state, count) in &metrics.state_visit_counts {
266        println!("    {}: {}", state, count);
267    }
268}
269
270/// Example 5: With guard priorities (requires 'guards' feature)
271#[cfg(feature = "guards")]
272fn guards_example() {
273    println!("\n=== Guard Priorities Example ===");
274
275    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
276
277    // Multiple transitions with different priorities
278    builder
279        .external_transition()
280        .from(OrderState::PaymentReceived)
281        .to(OrderState::Processing)
282        .on(OrderEvent::Process)
283        .when(|_s, _e, ctx| ctx.amount < 100.0)
284        .with_priority(10)
285        .perform(|_s, _e, ctx| {
286            println!(
287                "Processing small order {} (amount: {})",
288                ctx.order_id, ctx.amount
289            );
290        });
291
292    builder
293        .external_transition()
294        .from(OrderState::PaymentReceived)
295        .to(OrderState::Processing)
296        .on(OrderEvent::Process)
297        .when(|_s, _e, ctx| ctx.amount >= 100.0 && ctx.amount < 1000.0)
298        .with_priority(20)
299        .perform(|_s, _e, ctx| {
300            println!(
301                "Processing medium order {} (amount: {})",
302                ctx.order_id, ctx.amount
303            );
304        });
305
306    builder
307        .external_transition()
308        .from(OrderState::PaymentReceived)
309        .to(OrderState::Processing)
310        .on(OrderEvent::Process)
311        .when(|_s, _e, ctx| ctx.amount >= 1000.0)
312        .with_priority(30)
313        .perform(|_s, _e, ctx| {
314            println!(
315                "Processing large order {} (amount: {}) - Priority handling!",
316                ctx.order_id, ctx.amount
317            );
318        });
319
320    let state_machine = builder.id("GuardsOrderMachine").build();
321
322    // Test with different order amounts
323    let contexts = vec![
324        OrderContext {
325            order_id: "ORD-SMALL".to_string(),
326            amount: 50.0,
327            customer_id: "C1".to_string(),
328        },
329        OrderContext {
330            order_id: "ORD-MEDIUM".to_string(),
331            amount: 500.0,
332            customer_id: "C2".to_string(),
333        },
334        OrderContext {
335            order_id: "ORD-LARGE".to_string(),
336            amount: 5000.0,
337            customer_id: "C3".to_string(),
338        },
339    ];
340
341    for context in contexts {
342        let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
343    }
344}
345
346/// Example 6: With visualization (requires 'visualization' feature)
347#[cfg(feature = "visualization")]
348fn visualization_example() {
349    println!("\n=== Visualization Example ===");
350
351    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
352
353    // Build a complete order flow
354    builder
355        .external_transition()
356        .from(OrderState::New)
357        .to(OrderState::PaymentPending)
358        .on(OrderEvent::Pay)
359        .perform(|_s, _e, _c| {});
360
361    builder
362        .external_transition()
363        .from(OrderState::PaymentPending)
364        .to(OrderState::PaymentReceived)
365        .on(OrderEvent::ConfirmPayment)
366        .perform(|_s, _e, _c| {});
367
368    builder
369        .external_transition()
370        .from(OrderState::PaymentReceived)
371        .to(OrderState::Processing)
372        .on(OrderEvent::Process)
373        .perform(|_s, _e, _c| {});
374
375    builder
376        .external_transition()
377        .from(OrderState::Processing)
378        .to(OrderState::Shipped)
379        .on(OrderEvent::Ship)
380        .perform(|_s, _e, _c| {});
381
382    builder
383        .external_transition()
384        .from(OrderState::Shipped)
385        .to(OrderState::Delivered)
386        .on(OrderEvent::Deliver)
387        .perform(|_s, _e, _c| {});
388
389    builder
390        .external_transitions()
391        .from_among(vec![
392            OrderState::New,
393            OrderState::PaymentPending,
394            OrderState::Processing,
395        ])
396        .to(OrderState::Cancelled)
397        .on(OrderEvent::Cancel)
398        .perform(|_s, _e, _c| {});
399
400    builder
401        .external_transition()
402        .from(OrderState::Cancelled)
403        .to(OrderState::Refunded)
404        .on(OrderEvent::Refund)
405        .perform(|_s, _e, _c| {});
406
407    let state_machine = builder.id("VisualOrderMachine").build();
408
409    println!("DOT Format:");
410    println!("{}", state_machine.to_dot());
411
412    println!("\nPlantUML Format:");
413    println!("{}", state_machine.to_plantuml());
414}
More examples
Hide additional examples
examples/traffic_light_example.rs (line 106)
72fn configure_basic_transitions<'a>(
73    builder: &'a mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
74) -> &'a mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext> {
75    // Normal traffic light cycle
76    builder
77        .external_transition()
78        .from(TrafficLightState::Green)
79        .to(TrafficLightState::Yellow)
80        .on(TrafficLightEvent::Timer)
81        .perform(|_s, _e, ctx| {
82            println!("[{}] Changing to YELLOW", ctx.intersection_id);
83        });
84
85    builder
86        .external_transition()
87        .from(TrafficLightState::Yellow)
88        .to(TrafficLightState::Red)
89        .on(TrafficLightEvent::Timer)
90        .perform(|_s, _e, ctx| {
91            println!("[{}] Changing to RED", ctx.intersection_id);
92        });
93
94    builder
95        .external_transition()
96        .from(TrafficLightState::Red)
97        .to(TrafficLightState::Green)
98        .on(TrafficLightEvent::Timer)
99        .when(|_s, _e, ctx| !ctx.emergency_active)
100        .perform(|_s, _e, ctx| {
101            println!("[{}] Changing to GREEN", ctx.intersection_id);
102        });
103
104    // Emergency vehicle handling
105    builder
106        .external_transitions()
107        .from_among(vec![
108            TrafficLightState::Green,
109            TrafficLightState::Yellow,
110            TrafficLightState::Red,
111        ])
112        .to(TrafficLightState::Emergency)
113        .on(TrafficLightEvent::EmergencyVehicleDetected)
114        .perform(|from, _e, ctx| {
115            println!(
116                "[{}] EMERGENCY MODE! Was in {:?}",
117                ctx.intersection_id, from
118            );
119        });
120
121    builder
122        .external_transition()
123        .from(TrafficLightState::Emergency)
124        .to(TrafficLightState::Red)
125        .on(TrafficLightEvent::EmergencyCleared)
126        .perform(|_s, _e, ctx| {
127            println!(
128                "[{}] Emergency cleared, returning to RED",
129                ctx.intersection_id
130            );
131        });
132
133    // Maintenance mode
134    builder
135        .external_transitions()
136        .from_among(vec![
137            TrafficLightState::Green,
138            TrafficLightState::Yellow,
139            TrafficLightState::Red,
140        ])
141        .to(TrafficLightState::FlashingYellow)
142        .on(TrafficLightEvent::MaintenanceMode)
143        .perform(|_s, _e, ctx| {
144            println!(
145                "[{}] Entering maintenance mode - FLASHING YELLOW",
146                ctx.intersection_id
147            );
148        });
149
150    builder
151        .external_transition()
152        .from(TrafficLightState::FlashingYellow)
153        .to(TrafficLightState::Red)
154        .on(TrafficLightEvent::NormalMode)
155        .perform(|_s, _e, ctx| {
156            println!("[{}] Exiting maintenance mode", ctx.intersection_id);
157        });
158
159    builder
160}
Source

pub fn set_fail_callback( &mut self, callback: FailCallback<S, E, C>, ) -> &mut Self

Set fail callback

Examples found in repository?
examples/traffic_light_example.rs (lines 62-67)
44pub fn build_traffic_light_system(
45) -> StateMachine<TrafficLightState, TrafficLightEvent, TrafficContext> {
46    let mut builder =
47        StateMachineBuilderFactory::create::<TrafficLightState, TrafficLightEvent, TrafficContext>(
48        );
49
50    // Configure the state machine based on available features
51    configure_basic_transitions(&mut builder);
52
53    #[cfg(feature = "extended")]
54    configure_entry_exit_actions(&mut builder);
55
56    #[cfg(feature = "guards")]
57    configure_priority_transitions(&mut builder);
58
59    #[cfg(feature = "timeout")]
60    configure_timeouts(&mut builder);
61
62    builder.set_fail_callback(Arc::new(|state, event, ctx| {
63        eprintln!(
64            "WARNING: Invalid transition from {:?} with {:?} at intersection {}",
65            state, event, ctx.intersection_id
66        );
67    }));
68    builder.id("TrafficLightController").build()
69}
More examples
Hide additional examples
examples/order_example.rs (lines 534-539)
484fn complete_example() {
485    println!("\n=== Complete Example with Multiple Features ===");
486
487    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
488
489    // Configure entry/exit actions
490    builder
491        .with_entry_action(OrderState::Processing, |_s, ctx| {
492            println!("[ENTRY] Starting to process order {}", ctx.order_id);
493        })
494        .with_exit_action(OrderState::Processing, |_s, ctx| {
495            println!("[EXIT] Finished processing order {}", ctx.order_id);
496        });
497
498    // Build transitions
499    builder
500        .external_transition()
501        .from(OrderState::New)
502        .to(OrderState::PaymentPending)
503        .on(OrderEvent::Pay)
504        .perform(|_s, _e, ctx| {
505            println!("Payment initiated for ${}", ctx.amount);
506        });
507
508    builder
509        .external_transition()
510        .from(OrderState::PaymentPending)
511        .to(OrderState::PaymentReceived)
512        .on(OrderEvent::ConfirmPayment)
513        .when(|_s, _e, ctx| ctx.amount > 0.0)
514        .perform(|_s, _e, ctx| {
515            println!("Payment confirmed: ${}", ctx.amount);
516        });
517
518    builder
519        .external_transition()
520        .from(OrderState::PaymentReceived)
521        .to(OrderState::Processing)
522        .on(OrderEvent::Process)
523        .perform(|_s, _e, _c| {});
524
525    builder
526        .external_transition()
527        .from(OrderState::Processing)
528        .to(OrderState::Shipped)
529        .on(OrderEvent::Ship)
530        .perform(|_s, _e, ctx| {
531            println!("Order {} shipped", ctx.order_id);
532        });
533
534    builder.set_fail_callback(Arc::new(|state, event, ctx| {
535        println!(
536            "FAILED: Cannot handle {:?} in state {:?} for order {}",
537            event, state, ctx.order_id
538        );
539    }));
540
541    let state_machine = builder.id("CompleteOrderMachine").build();
542
543    // Process an order through the complete flow
544    let context = OrderContext {
545        order_id: "ORD-COMPLETE".to_string(),
546        amount: 999.99,
547        customer_id: "CUST-VIP".to_string(),
548    };
549
550    println!("\nProcessing order through complete flow:");
551    let states = [
552        (OrderState::New, OrderEvent::Pay),
553        (OrderState::PaymentPending, OrderEvent::ConfirmPayment),
554        (OrderState::PaymentReceived, OrderEvent::Process),
555        (OrderState::Processing, OrderEvent::Ship),
556    ];
557
558    for (state, event) in &states {
559        let result = state_machine.fire_event(state.clone(), event.clone(), context.clone());
560        println!("  {:?} + {:?} = {:?}", state, event, result);
561    }
562
563    // Try an invalid transition
564    println!("\nTrying invalid transition:");
565    let _ = state_machine.fire_event(OrderState::Shipped, OrderEvent::Pay, context);
566
567    // Display collected data
568    println!("\nHistory:");
569    for record in state_machine.get_history() {
570        println!(
571            "  {:?} -> {:?} (success: {})",
572            record.from, record.to, record.success
573        );
574    }
575
576    println!("\nMetrics:");
577    let metrics = state_machine.get_metrics();
578    println!(
579        "  Total: {}, Success: {}, Failed: {}",
580        metrics.total_transitions, metrics.successful_transitions, metrics.failed_transitions
581    );
582}
Source

pub fn with_entry_action<F>(&mut self, state: S, action: F) -> &mut Self
where F: Fn(&S, &C) + Send + Sync + 'static,

Add entry action for a state

Examples found in repository?
examples/traffic_light_example.rs (lines 168-174)
164fn configure_entry_exit_actions(
165    builder: &mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
166) {
167    // Entry actions
168    builder.with_entry_action(TrafficLightState::Green, |_state, ctx| {
169        println!(
170            "[{}] GREEN light ON - Vehicles may proceed",
171            ctx.intersection_id
172        );
173        // In a real system, this would control the actual light hardware
174    });
175
176    builder.with_entry_action(TrafficLightState::Yellow, |_state, ctx| {
177        println!(
178            "[{}] YELLOW light ON - Prepare to stop",
179            ctx.intersection_id
180        );
181    });
182
183    builder.with_entry_action(TrafficLightState::Red, |_state, ctx| {
184        println!(
185            "[{}] RED light ON - Vehicles must stop",
186            ctx.intersection_id
187        );
188        if ctx.pedestrian_waiting {
189            println!(
190                "[{}] Pedestrian crossing signal activated",
191                ctx.intersection_id
192            );
193        }
194    });
195
196    builder.with_entry_action(TrafficLightState::Emergency, |_state, ctx| {
197        println!(
198            "[{}] EMERGENCY MODE - All lights RED except emergency route",
199            ctx.intersection_id
200        );
201        // Would trigger emergency protocols in real system
202    });
203
204    // Exit actions
205    builder.with_exit_action(TrafficLightState::Green, |_state, ctx| {
206        println!("[{}] GREEN light OFF", ctx.intersection_id);
207    });
208
209    builder.with_exit_action(TrafficLightState::Emergency, |_state, ctx| {
210        println!("[{}] Exiting emergency mode", ctx.intersection_id);
211    });
212}
More examples
Hide additional examples
examples/order_example.rs (lines 146-151)
140fn extended_example() {
141    println!("\n=== Extended State Machine Example ===");
142
143    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
144
145    builder
146        .with_entry_action(OrderState::Processing, |state, ctx| {
147            println!(
148                "ENTRY: Starting to process order {} in state {:?}",
149                ctx.order_id, state
150            );
151        })
152        .with_exit_action(OrderState::Processing, |state, ctx| {
153            println!(
154                "EXIT: Finished processing order {} from state {:?}",
155                ctx.order_id, state
156            );
157        })
158        .with_entry_action(OrderState::Shipped, |_state, ctx| {
159            println!("ENTRY: Order {} has been shipped!", ctx.order_id);
160        });
161
162    builder
163        .external_transition()
164        .from(OrderState::PaymentReceived)
165        .to(OrderState::Processing)
166        .on(OrderEvent::Process)
167        .perform(|_s, _e, _c| {});
168
169    builder
170        .external_transition()
171        .from(OrderState::Processing)
172        .to(OrderState::Shipped)
173        .on(OrderEvent::Ship)
174        .perform(|_s, _e, _c| {});
175
176    let state_machine = builder.id("ExtendedOrderMachine").build();
177
178    let context = OrderContext {
179        order_id: "ORD-003".to_string(),
180        amount: 299.99,
181        customer_id: "CUST-789".to_string(),
182    };
183
184    let _ = state_machine.fire_event(
185        OrderState::PaymentReceived,
186        OrderEvent::Process,
187        context.clone(),
188    );
189    let _ = state_machine.fire_event(OrderState::Processing, OrderEvent::Ship, context);
190}
191
192/// Example 4: With metrics (requires 'metrics' feature)
193#[cfg(feature = "metrics")]
194fn metrics_example() {
195    println!("\n=== Metrics Collection Example ===");
196
197    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
198
199    // Add multiple transitions
200    builder
201        .external_transition()
202        .from(OrderState::New)
203        .to(OrderState::PaymentPending)
204        .on(OrderEvent::Pay)
205        .perform(|_s, _e, _c| {});
206
207    builder
208        .external_transition()
209        .from(OrderState::PaymentPending)
210        .to(OrderState::PaymentReceived)
211        .on(OrderEvent::ConfirmPayment)
212        .when(|_s, _e, ctx| ctx.amount > 0.0)
213        .perform(|_s, _e, _c| {});
214
215    builder
216        .external_transitions()
217        .from_among(vec![
218            OrderState::New,
219            OrderState::PaymentPending,
220            OrderState::Processing,
221        ])
222        .to(OrderState::Cancelled)
223        .on(OrderEvent::Cancel)
224        .perform(|_s, _e, _c| {});
225
226    let state_machine = builder.id("MetricsOrderMachine").build();
227
228    // Simulate multiple orders
229    for i in 0..10 {
230        let context = OrderContext {
231            order_id: format!("ORD-{:03}", i),
232            amount: (i as f64) * 10.0,
233            customer_id: format!("CUST-{:03}", i),
234        };
235
236        let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
237
238        if i % 3 == 0 {
239            // Some orders get cancelled
240            let _ =
241                state_machine.fire_event(OrderState::PaymentPending, OrderEvent::Cancel, context);
242        } else {
243            // Others proceed normally
244            let _ = state_machine.fire_event(
245                OrderState::PaymentPending,
246                OrderEvent::ConfirmPayment,
247                context,
248            );
249        }
250    }
251
252    // Get and display metrics
253    let metrics = state_machine.get_metrics();
254    println!("State Machine Metrics:");
255    println!("  Total transitions: {}", metrics.total_transitions);
256    println!("  Successful: {}", metrics.successful_transitions);
257    println!("  Failed: {}", metrics.failed_transitions);
258    println!("  Success rate: {:.2}%", metrics.success_rate() * 100.0);
259
260    if let Some(avg_time) = metrics.average_transition_time() {
261        println!("  Average transition time: {:?}", avg_time);
262    }
263
264    println!("  State visit counts:");
265    for (state, count) in &metrics.state_visit_counts {
266        println!("    {}: {}", state, count);
267    }
268}
269
270/// Example 5: With guard priorities (requires 'guards' feature)
271#[cfg(feature = "guards")]
272fn guards_example() {
273    println!("\n=== Guard Priorities Example ===");
274
275    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
276
277    // Multiple transitions with different priorities
278    builder
279        .external_transition()
280        .from(OrderState::PaymentReceived)
281        .to(OrderState::Processing)
282        .on(OrderEvent::Process)
283        .when(|_s, _e, ctx| ctx.amount < 100.0)
284        .with_priority(10)
285        .perform(|_s, _e, ctx| {
286            println!(
287                "Processing small order {} (amount: {})",
288                ctx.order_id, ctx.amount
289            );
290        });
291
292    builder
293        .external_transition()
294        .from(OrderState::PaymentReceived)
295        .to(OrderState::Processing)
296        .on(OrderEvent::Process)
297        .when(|_s, _e, ctx| ctx.amount >= 100.0 && ctx.amount < 1000.0)
298        .with_priority(20)
299        .perform(|_s, _e, ctx| {
300            println!(
301                "Processing medium order {} (amount: {})",
302                ctx.order_id, ctx.amount
303            );
304        });
305
306    builder
307        .external_transition()
308        .from(OrderState::PaymentReceived)
309        .to(OrderState::Processing)
310        .on(OrderEvent::Process)
311        .when(|_s, _e, ctx| ctx.amount >= 1000.0)
312        .with_priority(30)
313        .perform(|_s, _e, ctx| {
314            println!(
315                "Processing large order {} (amount: {}) - Priority handling!",
316                ctx.order_id, ctx.amount
317            );
318        });
319
320    let state_machine = builder.id("GuardsOrderMachine").build();
321
322    // Test with different order amounts
323    let contexts = vec![
324        OrderContext {
325            order_id: "ORD-SMALL".to_string(),
326            amount: 50.0,
327            customer_id: "C1".to_string(),
328        },
329        OrderContext {
330            order_id: "ORD-MEDIUM".to_string(),
331            amount: 500.0,
332            customer_id: "C2".to_string(),
333        },
334        OrderContext {
335            order_id: "ORD-LARGE".to_string(),
336            amount: 5000.0,
337            customer_id: "C3".to_string(),
338        },
339    ];
340
341    for context in contexts {
342        let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
343    }
344}
345
346/// Example 6: With visualization (requires 'visualization' feature)
347#[cfg(feature = "visualization")]
348fn visualization_example() {
349    println!("\n=== Visualization Example ===");
350
351    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
352
353    // Build a complete order flow
354    builder
355        .external_transition()
356        .from(OrderState::New)
357        .to(OrderState::PaymentPending)
358        .on(OrderEvent::Pay)
359        .perform(|_s, _e, _c| {});
360
361    builder
362        .external_transition()
363        .from(OrderState::PaymentPending)
364        .to(OrderState::PaymentReceived)
365        .on(OrderEvent::ConfirmPayment)
366        .perform(|_s, _e, _c| {});
367
368    builder
369        .external_transition()
370        .from(OrderState::PaymentReceived)
371        .to(OrderState::Processing)
372        .on(OrderEvent::Process)
373        .perform(|_s, _e, _c| {});
374
375    builder
376        .external_transition()
377        .from(OrderState::Processing)
378        .to(OrderState::Shipped)
379        .on(OrderEvent::Ship)
380        .perform(|_s, _e, _c| {});
381
382    builder
383        .external_transition()
384        .from(OrderState::Shipped)
385        .to(OrderState::Delivered)
386        .on(OrderEvent::Deliver)
387        .perform(|_s, _e, _c| {});
388
389    builder
390        .external_transitions()
391        .from_among(vec![
392            OrderState::New,
393            OrderState::PaymentPending,
394            OrderState::Processing,
395        ])
396        .to(OrderState::Cancelled)
397        .on(OrderEvent::Cancel)
398        .perform(|_s, _e, _c| {});
399
400    builder
401        .external_transition()
402        .from(OrderState::Cancelled)
403        .to(OrderState::Refunded)
404        .on(OrderEvent::Refund)
405        .perform(|_s, _e, _c| {});
406
407    let state_machine = builder.id("VisualOrderMachine").build();
408
409    println!("DOT Format:");
410    println!("{}", state_machine.to_dot());
411
412    println!("\nPlantUML Format:");
413    println!("{}", state_machine.to_plantuml());
414}
415
416/// Example 7: With parallel regions (requires 'parallel' feature)
417#[cfg(feature = "parallel")]
418fn parallel_example() {
419    println!("\n=== Parallel Regions Example ===");
420
421    // Order processing region
422    let mut order_builder =
423        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
424    order_builder
425        .external_transition()
426        .from(OrderState::New)
427        .to(OrderState::Processing)
428        .on(OrderEvent::Process)
429        .perform(|_s, _e, ctx| {
430            println!("Order region: Processing order {}", ctx.order_id);
431        });
432
433    // Payment processing region (using same states/events for simplicity)
434    let mut payment_builder =
435        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
436    payment_builder
437        .external_transition()
438        .from(OrderState::PaymentPending)
439        .to(OrderState::PaymentReceived)
440        .on(OrderEvent::ConfirmPayment)
441        .perform(|_s, _e, ctx| {
442            println!(
443                "Payment region: Payment confirmed for order {}",
444                ctx.order_id
445            );
446        });
447
448    let mut parallel_machine = ParallelStateMachine::new();
449    parallel_machine.add_region(order_builder.id("OrderRegion").build());
450    parallel_machine.add_region(payment_builder.id("PaymentRegion").build());
451
452    let context = OrderContext {
453        order_id: "ORD-PARALLEL".to_string(),
454        amount: 199.99,
455        customer_id: "CUST-P1".to_string(),
456    };
457
458    // Fire events in parallel regions
459    println!("Firing Process event in parallel regions:");
460    let results = parallel_machine.fire_event(
461        vec![OrderState::New, OrderState::PaymentPending],
462        OrderEvent::Process,
463        context.clone(),
464    );
465
466    for (i, result) in results.iter().enumerate() {
467        println!("  Region {}: {:?}", i, result);
468    }
469
470    println!("Firing ConfirmPayment event in parallel regions:");
471    let results = parallel_machine.fire_event(
472        vec![OrderState::Processing, OrderState::PaymentPending],
473        OrderEvent::ConfirmPayment,
474        context,
475    );
476
477    for (i, result) in results.iter().enumerate() {
478        println!("  Region {}: {:?}", i, result);
479    }
480}
481
482/// Example 8: Complete example with multiple features
483#[cfg(all(feature = "history", feature = "metrics", feature = "extended"))]
484fn complete_example() {
485    println!("\n=== Complete Example with Multiple Features ===");
486
487    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
488
489    // Configure entry/exit actions
490    builder
491        .with_entry_action(OrderState::Processing, |_s, ctx| {
492            println!("[ENTRY] Starting to process order {}", ctx.order_id);
493        })
494        .with_exit_action(OrderState::Processing, |_s, ctx| {
495            println!("[EXIT] Finished processing order {}", ctx.order_id);
496        });
497
498    // Build transitions
499    builder
500        .external_transition()
501        .from(OrderState::New)
502        .to(OrderState::PaymentPending)
503        .on(OrderEvent::Pay)
504        .perform(|_s, _e, ctx| {
505            println!("Payment initiated for ${}", ctx.amount);
506        });
507
508    builder
509        .external_transition()
510        .from(OrderState::PaymentPending)
511        .to(OrderState::PaymentReceived)
512        .on(OrderEvent::ConfirmPayment)
513        .when(|_s, _e, ctx| ctx.amount > 0.0)
514        .perform(|_s, _e, ctx| {
515            println!("Payment confirmed: ${}", ctx.amount);
516        });
517
518    builder
519        .external_transition()
520        .from(OrderState::PaymentReceived)
521        .to(OrderState::Processing)
522        .on(OrderEvent::Process)
523        .perform(|_s, _e, _c| {});
524
525    builder
526        .external_transition()
527        .from(OrderState::Processing)
528        .to(OrderState::Shipped)
529        .on(OrderEvent::Ship)
530        .perform(|_s, _e, ctx| {
531            println!("Order {} shipped", ctx.order_id);
532        });
533
534    builder.set_fail_callback(Arc::new(|state, event, ctx| {
535        println!(
536            "FAILED: Cannot handle {:?} in state {:?} for order {}",
537            event, state, ctx.order_id
538        );
539    }));
540
541    let state_machine = builder.id("CompleteOrderMachine").build();
542
543    // Process an order through the complete flow
544    let context = OrderContext {
545        order_id: "ORD-COMPLETE".to_string(),
546        amount: 999.99,
547        customer_id: "CUST-VIP".to_string(),
548    };
549
550    println!("\nProcessing order through complete flow:");
551    let states = [
552        (OrderState::New, OrderEvent::Pay),
553        (OrderState::PaymentPending, OrderEvent::ConfirmPayment),
554        (OrderState::PaymentReceived, OrderEvent::Process),
555        (OrderState::Processing, OrderEvent::Ship),
556    ];
557
558    for (state, event) in &states {
559        let result = state_machine.fire_event(state.clone(), event.clone(), context.clone());
560        println!("  {:?} + {:?} = {:?}", state, event, result);
561    }
562
563    // Try an invalid transition
564    println!("\nTrying invalid transition:");
565    let _ = state_machine.fire_event(OrderState::Shipped, OrderEvent::Pay, context);
566
567    // Display collected data
568    println!("\nHistory:");
569    for record in state_machine.get_history() {
570        println!(
571            "  {:?} -> {:?} (success: {})",
572            record.from, record.to, record.success
573        );
574    }
575
576    println!("\nMetrics:");
577    let metrics = state_machine.get_metrics();
578    println!(
579        "  Total: {}, Success: {}, Failed: {}",
580        metrics.total_transitions, metrics.successful_transitions, metrics.failed_transitions
581    );
582}
Source

pub fn with_exit_action<F>(&mut self, state: S, action: F) -> &mut Self
where F: Fn(&S, &C) + Send + Sync + 'static,

Add exit action for a state

Examples found in repository?
examples/traffic_light_example.rs (lines 205-207)
164fn configure_entry_exit_actions(
165    builder: &mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
166) {
167    // Entry actions
168    builder.with_entry_action(TrafficLightState::Green, |_state, ctx| {
169        println!(
170            "[{}] GREEN light ON - Vehicles may proceed",
171            ctx.intersection_id
172        );
173        // In a real system, this would control the actual light hardware
174    });
175
176    builder.with_entry_action(TrafficLightState::Yellow, |_state, ctx| {
177        println!(
178            "[{}] YELLOW light ON - Prepare to stop",
179            ctx.intersection_id
180        );
181    });
182
183    builder.with_entry_action(TrafficLightState::Red, |_state, ctx| {
184        println!(
185            "[{}] RED light ON - Vehicles must stop",
186            ctx.intersection_id
187        );
188        if ctx.pedestrian_waiting {
189            println!(
190                "[{}] Pedestrian crossing signal activated",
191                ctx.intersection_id
192            );
193        }
194    });
195
196    builder.with_entry_action(TrafficLightState::Emergency, |_state, ctx| {
197        println!(
198            "[{}] EMERGENCY MODE - All lights RED except emergency route",
199            ctx.intersection_id
200        );
201        // Would trigger emergency protocols in real system
202    });
203
204    // Exit actions
205    builder.with_exit_action(TrafficLightState::Green, |_state, ctx| {
206        println!("[{}] GREEN light OFF", ctx.intersection_id);
207    });
208
209    builder.with_exit_action(TrafficLightState::Emergency, |_state, ctx| {
210        println!("[{}] Exiting emergency mode", ctx.intersection_id);
211    });
212}
More examples
Hide additional examples
examples/order_example.rs (lines 152-157)
140fn extended_example() {
141    println!("\n=== Extended State Machine Example ===");
142
143    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
144
145    builder
146        .with_entry_action(OrderState::Processing, |state, ctx| {
147            println!(
148                "ENTRY: Starting to process order {} in state {:?}",
149                ctx.order_id, state
150            );
151        })
152        .with_exit_action(OrderState::Processing, |state, ctx| {
153            println!(
154                "EXIT: Finished processing order {} from state {:?}",
155                ctx.order_id, state
156            );
157        })
158        .with_entry_action(OrderState::Shipped, |_state, ctx| {
159            println!("ENTRY: Order {} has been shipped!", ctx.order_id);
160        });
161
162    builder
163        .external_transition()
164        .from(OrderState::PaymentReceived)
165        .to(OrderState::Processing)
166        .on(OrderEvent::Process)
167        .perform(|_s, _e, _c| {});
168
169    builder
170        .external_transition()
171        .from(OrderState::Processing)
172        .to(OrderState::Shipped)
173        .on(OrderEvent::Ship)
174        .perform(|_s, _e, _c| {});
175
176    let state_machine = builder.id("ExtendedOrderMachine").build();
177
178    let context = OrderContext {
179        order_id: "ORD-003".to_string(),
180        amount: 299.99,
181        customer_id: "CUST-789".to_string(),
182    };
183
184    let _ = state_machine.fire_event(
185        OrderState::PaymentReceived,
186        OrderEvent::Process,
187        context.clone(),
188    );
189    let _ = state_machine.fire_event(OrderState::Processing, OrderEvent::Ship, context);
190}
191
192/// Example 4: With metrics (requires 'metrics' feature)
193#[cfg(feature = "metrics")]
194fn metrics_example() {
195    println!("\n=== Metrics Collection Example ===");
196
197    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
198
199    // Add multiple transitions
200    builder
201        .external_transition()
202        .from(OrderState::New)
203        .to(OrderState::PaymentPending)
204        .on(OrderEvent::Pay)
205        .perform(|_s, _e, _c| {});
206
207    builder
208        .external_transition()
209        .from(OrderState::PaymentPending)
210        .to(OrderState::PaymentReceived)
211        .on(OrderEvent::ConfirmPayment)
212        .when(|_s, _e, ctx| ctx.amount > 0.0)
213        .perform(|_s, _e, _c| {});
214
215    builder
216        .external_transitions()
217        .from_among(vec![
218            OrderState::New,
219            OrderState::PaymentPending,
220            OrderState::Processing,
221        ])
222        .to(OrderState::Cancelled)
223        .on(OrderEvent::Cancel)
224        .perform(|_s, _e, _c| {});
225
226    let state_machine = builder.id("MetricsOrderMachine").build();
227
228    // Simulate multiple orders
229    for i in 0..10 {
230        let context = OrderContext {
231            order_id: format!("ORD-{:03}", i),
232            amount: (i as f64) * 10.0,
233            customer_id: format!("CUST-{:03}", i),
234        };
235
236        let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
237
238        if i % 3 == 0 {
239            // Some orders get cancelled
240            let _ =
241                state_machine.fire_event(OrderState::PaymentPending, OrderEvent::Cancel, context);
242        } else {
243            // Others proceed normally
244            let _ = state_machine.fire_event(
245                OrderState::PaymentPending,
246                OrderEvent::ConfirmPayment,
247                context,
248            );
249        }
250    }
251
252    // Get and display metrics
253    let metrics = state_machine.get_metrics();
254    println!("State Machine Metrics:");
255    println!("  Total transitions: {}", metrics.total_transitions);
256    println!("  Successful: {}", metrics.successful_transitions);
257    println!("  Failed: {}", metrics.failed_transitions);
258    println!("  Success rate: {:.2}%", metrics.success_rate() * 100.0);
259
260    if let Some(avg_time) = metrics.average_transition_time() {
261        println!("  Average transition time: {:?}", avg_time);
262    }
263
264    println!("  State visit counts:");
265    for (state, count) in &metrics.state_visit_counts {
266        println!("    {}: {}", state, count);
267    }
268}
269
270/// Example 5: With guard priorities (requires 'guards' feature)
271#[cfg(feature = "guards")]
272fn guards_example() {
273    println!("\n=== Guard Priorities Example ===");
274
275    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
276
277    // Multiple transitions with different priorities
278    builder
279        .external_transition()
280        .from(OrderState::PaymentReceived)
281        .to(OrderState::Processing)
282        .on(OrderEvent::Process)
283        .when(|_s, _e, ctx| ctx.amount < 100.0)
284        .with_priority(10)
285        .perform(|_s, _e, ctx| {
286            println!(
287                "Processing small order {} (amount: {})",
288                ctx.order_id, ctx.amount
289            );
290        });
291
292    builder
293        .external_transition()
294        .from(OrderState::PaymentReceived)
295        .to(OrderState::Processing)
296        .on(OrderEvent::Process)
297        .when(|_s, _e, ctx| ctx.amount >= 100.0 && ctx.amount < 1000.0)
298        .with_priority(20)
299        .perform(|_s, _e, ctx| {
300            println!(
301                "Processing medium order {} (amount: {})",
302                ctx.order_id, ctx.amount
303            );
304        });
305
306    builder
307        .external_transition()
308        .from(OrderState::PaymentReceived)
309        .to(OrderState::Processing)
310        .on(OrderEvent::Process)
311        .when(|_s, _e, ctx| ctx.amount >= 1000.0)
312        .with_priority(30)
313        .perform(|_s, _e, ctx| {
314            println!(
315                "Processing large order {} (amount: {}) - Priority handling!",
316                ctx.order_id, ctx.amount
317            );
318        });
319
320    let state_machine = builder.id("GuardsOrderMachine").build();
321
322    // Test with different order amounts
323    let contexts = vec![
324        OrderContext {
325            order_id: "ORD-SMALL".to_string(),
326            amount: 50.0,
327            customer_id: "C1".to_string(),
328        },
329        OrderContext {
330            order_id: "ORD-MEDIUM".to_string(),
331            amount: 500.0,
332            customer_id: "C2".to_string(),
333        },
334        OrderContext {
335            order_id: "ORD-LARGE".to_string(),
336            amount: 5000.0,
337            customer_id: "C3".to_string(),
338        },
339    ];
340
341    for context in contexts {
342        let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
343    }
344}
345
346/// Example 6: With visualization (requires 'visualization' feature)
347#[cfg(feature = "visualization")]
348fn visualization_example() {
349    println!("\n=== Visualization Example ===");
350
351    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
352
353    // Build a complete order flow
354    builder
355        .external_transition()
356        .from(OrderState::New)
357        .to(OrderState::PaymentPending)
358        .on(OrderEvent::Pay)
359        .perform(|_s, _e, _c| {});
360
361    builder
362        .external_transition()
363        .from(OrderState::PaymentPending)
364        .to(OrderState::PaymentReceived)
365        .on(OrderEvent::ConfirmPayment)
366        .perform(|_s, _e, _c| {});
367
368    builder
369        .external_transition()
370        .from(OrderState::PaymentReceived)
371        .to(OrderState::Processing)
372        .on(OrderEvent::Process)
373        .perform(|_s, _e, _c| {});
374
375    builder
376        .external_transition()
377        .from(OrderState::Processing)
378        .to(OrderState::Shipped)
379        .on(OrderEvent::Ship)
380        .perform(|_s, _e, _c| {});
381
382    builder
383        .external_transition()
384        .from(OrderState::Shipped)
385        .to(OrderState::Delivered)
386        .on(OrderEvent::Deliver)
387        .perform(|_s, _e, _c| {});
388
389    builder
390        .external_transitions()
391        .from_among(vec![
392            OrderState::New,
393            OrderState::PaymentPending,
394            OrderState::Processing,
395        ])
396        .to(OrderState::Cancelled)
397        .on(OrderEvent::Cancel)
398        .perform(|_s, _e, _c| {});
399
400    builder
401        .external_transition()
402        .from(OrderState::Cancelled)
403        .to(OrderState::Refunded)
404        .on(OrderEvent::Refund)
405        .perform(|_s, _e, _c| {});
406
407    let state_machine = builder.id("VisualOrderMachine").build();
408
409    println!("DOT Format:");
410    println!("{}", state_machine.to_dot());
411
412    println!("\nPlantUML Format:");
413    println!("{}", state_machine.to_plantuml());
414}
415
416/// Example 7: With parallel regions (requires 'parallel' feature)
417#[cfg(feature = "parallel")]
418fn parallel_example() {
419    println!("\n=== Parallel Regions Example ===");
420
421    // Order processing region
422    let mut order_builder =
423        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
424    order_builder
425        .external_transition()
426        .from(OrderState::New)
427        .to(OrderState::Processing)
428        .on(OrderEvent::Process)
429        .perform(|_s, _e, ctx| {
430            println!("Order region: Processing order {}", ctx.order_id);
431        });
432
433    // Payment processing region (using same states/events for simplicity)
434    let mut payment_builder =
435        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
436    payment_builder
437        .external_transition()
438        .from(OrderState::PaymentPending)
439        .to(OrderState::PaymentReceived)
440        .on(OrderEvent::ConfirmPayment)
441        .perform(|_s, _e, ctx| {
442            println!(
443                "Payment region: Payment confirmed for order {}",
444                ctx.order_id
445            );
446        });
447
448    let mut parallel_machine = ParallelStateMachine::new();
449    parallel_machine.add_region(order_builder.id("OrderRegion").build());
450    parallel_machine.add_region(payment_builder.id("PaymentRegion").build());
451
452    let context = OrderContext {
453        order_id: "ORD-PARALLEL".to_string(),
454        amount: 199.99,
455        customer_id: "CUST-P1".to_string(),
456    };
457
458    // Fire events in parallel regions
459    println!("Firing Process event in parallel regions:");
460    let results = parallel_machine.fire_event(
461        vec![OrderState::New, OrderState::PaymentPending],
462        OrderEvent::Process,
463        context.clone(),
464    );
465
466    for (i, result) in results.iter().enumerate() {
467        println!("  Region {}: {:?}", i, result);
468    }
469
470    println!("Firing ConfirmPayment event in parallel regions:");
471    let results = parallel_machine.fire_event(
472        vec![OrderState::Processing, OrderState::PaymentPending],
473        OrderEvent::ConfirmPayment,
474        context,
475    );
476
477    for (i, result) in results.iter().enumerate() {
478        println!("  Region {}: {:?}", i, result);
479    }
480}
481
482/// Example 8: Complete example with multiple features
483#[cfg(all(feature = "history", feature = "metrics", feature = "extended"))]
484fn complete_example() {
485    println!("\n=== Complete Example with Multiple Features ===");
486
487    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
488
489    // Configure entry/exit actions
490    builder
491        .with_entry_action(OrderState::Processing, |_s, ctx| {
492            println!("[ENTRY] Starting to process order {}", ctx.order_id);
493        })
494        .with_exit_action(OrderState::Processing, |_s, ctx| {
495            println!("[EXIT] Finished processing order {}", ctx.order_id);
496        });
497
498    // Build transitions
499    builder
500        .external_transition()
501        .from(OrderState::New)
502        .to(OrderState::PaymentPending)
503        .on(OrderEvent::Pay)
504        .perform(|_s, _e, ctx| {
505            println!("Payment initiated for ${}", ctx.amount);
506        });
507
508    builder
509        .external_transition()
510        .from(OrderState::PaymentPending)
511        .to(OrderState::PaymentReceived)
512        .on(OrderEvent::ConfirmPayment)
513        .when(|_s, _e, ctx| ctx.amount > 0.0)
514        .perform(|_s, _e, ctx| {
515            println!("Payment confirmed: ${}", ctx.amount);
516        });
517
518    builder
519        .external_transition()
520        .from(OrderState::PaymentReceived)
521        .to(OrderState::Processing)
522        .on(OrderEvent::Process)
523        .perform(|_s, _e, _c| {});
524
525    builder
526        .external_transition()
527        .from(OrderState::Processing)
528        .to(OrderState::Shipped)
529        .on(OrderEvent::Ship)
530        .perform(|_s, _e, ctx| {
531            println!("Order {} shipped", ctx.order_id);
532        });
533
534    builder.set_fail_callback(Arc::new(|state, event, ctx| {
535        println!(
536            "FAILED: Cannot handle {:?} in state {:?} for order {}",
537            event, state, ctx.order_id
538        );
539    }));
540
541    let state_machine = builder.id("CompleteOrderMachine").build();
542
543    // Process an order through the complete flow
544    let context = OrderContext {
545        order_id: "ORD-COMPLETE".to_string(),
546        amount: 999.99,
547        customer_id: "CUST-VIP".to_string(),
548    };
549
550    println!("\nProcessing order through complete flow:");
551    let states = [
552        (OrderState::New, OrderEvent::Pay),
553        (OrderState::PaymentPending, OrderEvent::ConfirmPayment),
554        (OrderState::PaymentReceived, OrderEvent::Process),
555        (OrderState::Processing, OrderEvent::Ship),
556    ];
557
558    for (state, event) in &states {
559        let result = state_machine.fire_event(state.clone(), event.clone(), context.clone());
560        println!("  {:?} + {:?} = {:?}", state, event, result);
561    }
562
563    // Try an invalid transition
564    println!("\nTrying invalid transition:");
565    let _ = state_machine.fire_event(OrderState::Shipped, OrderEvent::Pay, context);
566
567    // Display collected data
568    println!("\nHistory:");
569    for record in state_machine.get_history() {
570        println!(
571            "  {:?} -> {:?} (success: {})",
572            record.from, record.to, record.success
573        );
574    }
575
576    println!("\nMetrics:");
577    let metrics = state_machine.get_metrics();
578    println!(
579        "  Total: {}, Success: {}, Failed: {}",
580        metrics.total_transitions, metrics.successful_transitions, metrics.failed_transitions
581    );
582}
Source

pub fn with_state_timeout( &mut self, state: S, duration: Duration, target_state: S, timeout_event: E, ) -> &mut Self

Set timeout for a state

Examples found in repository?
examples/traffic_light_example.rs (lines 273-278)
267fn configure_timeouts(
268    builder: &mut StateMachineBuilder<TrafficLightState, TrafficLightEvent, TrafficContext>,
269) {
270    use std::time::Duration;
271
272    // Safety timeout - Yellow shouldn't last too long
273    builder.with_state_timeout(
274        TrafficLightState::Yellow,
275        Duration::from_secs(5),
276        TrafficLightState::Red,
277        TrafficLightEvent::Timer,
278    );
279
280    // Emergency timeout - Auto-clear if no manual clear
281    builder.with_state_timeout(
282        TrafficLightState::Emergency,
283        Duration::from_secs(300), // 5 minutes
284        TrafficLightState::Red,
285        TrafficLightEvent::EmergencyCleared,
286    );
287}
Source

pub fn build(self) -> StateMachine<S, E, C>

Build the state machine

Examples found in repository?
examples/traffic_light_example.rs (line 68)
44pub fn build_traffic_light_system(
45) -> StateMachine<TrafficLightState, TrafficLightEvent, TrafficContext> {
46    let mut builder =
47        StateMachineBuilderFactory::create::<TrafficLightState, TrafficLightEvent, TrafficContext>(
48        );
49
50    // Configure the state machine based on available features
51    configure_basic_transitions(&mut builder);
52
53    #[cfg(feature = "extended")]
54    configure_entry_exit_actions(&mut builder);
55
56    #[cfg(feature = "guards")]
57    configure_priority_transitions(&mut builder);
58
59    #[cfg(feature = "timeout")]
60    configure_timeouts(&mut builder);
61
62    builder.set_fail_callback(Arc::new(|state, event, ctx| {
63        eprintln!(
64            "WARNING: Invalid transition from {:?} with {:?} at intersection {}",
65            state, event, ctx.intersection_id
66        );
67    }));
68    builder.id("TrafficLightController").build()
69}
More examples
Hide additional examples
examples/order_example.rs (line 66)
43fn basic_example() {
44    println!("=== Basic State Machine Example ===");
45
46    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
47
48    builder
49        .external_transition()
50        .from(OrderState::New)
51        .to(OrderState::PaymentPending)
52        .on(OrderEvent::Pay)
53        .perform(|_s, _e, ctx| {
54            println!("Order {} payment initiated", ctx.order_id);
55        });
56
57    builder
58        .external_transition()
59        .from(OrderState::PaymentPending)
60        .to(OrderState::PaymentReceived)
61        .on(OrderEvent::ConfirmPayment)
62        .perform(|_s, _e, ctx| {
63            println!("Payment confirmed for order {}", ctx.order_id);
64        });
65
66    let state_machine = builder.id("BasicOrderMachine").build();
67
68    let context = OrderContext {
69        order_id: "ORD-001".to_string(),
70        amount: 99.99,
71        customer_id: "CUST-123".to_string(),
72    };
73
74    let result = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
75    println!("Transition result: {:?}", result);
76}
77
78/// Example 2: With history tracking (requires 'history' feature)
79#[cfg(feature = "history")]
80fn history_example() {
81    println!("\n=== History Tracking Example ===");
82
83    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
84
85    builder
86        .external_transition()
87        .from(OrderState::New)
88        .to(OrderState::PaymentPending)
89        .on(OrderEvent::Pay)
90        .perform(|_s, _e, _c| {});
91
92    builder
93        .external_transition()
94        .from(OrderState::PaymentPending)
95        .to(OrderState::PaymentReceived)
96        .on(OrderEvent::ConfirmPayment)
97        .perform(|_s, _e, _c| {});
98
99    builder
100        .external_transition()
101        .from(OrderState::PaymentReceived)
102        .to(OrderState::Processing)
103        .on(OrderEvent::Process)
104        .perform(|_s, _e, _c| {});
105
106    let state_machine = builder.id("HistoryOrderMachine").build();
107
108    let context = OrderContext {
109        order_id: "ORD-002".to_string(),
110        amount: 149.99,
111        customer_id: "CUST-456".to_string(),
112    };
113
114    // Execute multiple transitions
115    let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
116    let _ = state_machine.fire_event(
117        OrderState::PaymentPending,
118        OrderEvent::ConfirmPayment,
119        context.clone(),
120    );
121    let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
122
123    // Check history
124    let history = state_machine.get_history();
125    println!("Transition history:");
126    for (i, record) in history.iter().enumerate() {
127        println!(
128            "  {}. {:?} -> {:?} via {:?} (success: {})",
129            i + 1,
130            record.from,
131            record.to,
132            record.event,
133            record.success
134        );
135    }
136}
137
138/// Example 3: With entry/exit actions (requires 'extended' feature)
139#[cfg(feature = "extended")]
140fn extended_example() {
141    println!("\n=== Extended State Machine Example ===");
142
143    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
144
145    builder
146        .with_entry_action(OrderState::Processing, |state, ctx| {
147            println!(
148                "ENTRY: Starting to process order {} in state {:?}",
149                ctx.order_id, state
150            );
151        })
152        .with_exit_action(OrderState::Processing, |state, ctx| {
153            println!(
154                "EXIT: Finished processing order {} from state {:?}",
155                ctx.order_id, state
156            );
157        })
158        .with_entry_action(OrderState::Shipped, |_state, ctx| {
159            println!("ENTRY: Order {} has been shipped!", ctx.order_id);
160        });
161
162    builder
163        .external_transition()
164        .from(OrderState::PaymentReceived)
165        .to(OrderState::Processing)
166        .on(OrderEvent::Process)
167        .perform(|_s, _e, _c| {});
168
169    builder
170        .external_transition()
171        .from(OrderState::Processing)
172        .to(OrderState::Shipped)
173        .on(OrderEvent::Ship)
174        .perform(|_s, _e, _c| {});
175
176    let state_machine = builder.id("ExtendedOrderMachine").build();
177
178    let context = OrderContext {
179        order_id: "ORD-003".to_string(),
180        amount: 299.99,
181        customer_id: "CUST-789".to_string(),
182    };
183
184    let _ = state_machine.fire_event(
185        OrderState::PaymentReceived,
186        OrderEvent::Process,
187        context.clone(),
188    );
189    let _ = state_machine.fire_event(OrderState::Processing, OrderEvent::Ship, context);
190}
191
192/// Example 4: With metrics (requires 'metrics' feature)
193#[cfg(feature = "metrics")]
194fn metrics_example() {
195    println!("\n=== Metrics Collection Example ===");
196
197    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
198
199    // Add multiple transitions
200    builder
201        .external_transition()
202        .from(OrderState::New)
203        .to(OrderState::PaymentPending)
204        .on(OrderEvent::Pay)
205        .perform(|_s, _e, _c| {});
206
207    builder
208        .external_transition()
209        .from(OrderState::PaymentPending)
210        .to(OrderState::PaymentReceived)
211        .on(OrderEvent::ConfirmPayment)
212        .when(|_s, _e, ctx| ctx.amount > 0.0)
213        .perform(|_s, _e, _c| {});
214
215    builder
216        .external_transitions()
217        .from_among(vec![
218            OrderState::New,
219            OrderState::PaymentPending,
220            OrderState::Processing,
221        ])
222        .to(OrderState::Cancelled)
223        .on(OrderEvent::Cancel)
224        .perform(|_s, _e, _c| {});
225
226    let state_machine = builder.id("MetricsOrderMachine").build();
227
228    // Simulate multiple orders
229    for i in 0..10 {
230        let context = OrderContext {
231            order_id: format!("ORD-{:03}", i),
232            amount: (i as f64) * 10.0,
233            customer_id: format!("CUST-{:03}", i),
234        };
235
236        let _ = state_machine.fire_event(OrderState::New, OrderEvent::Pay, context.clone());
237
238        if i % 3 == 0 {
239            // Some orders get cancelled
240            let _ =
241                state_machine.fire_event(OrderState::PaymentPending, OrderEvent::Cancel, context);
242        } else {
243            // Others proceed normally
244            let _ = state_machine.fire_event(
245                OrderState::PaymentPending,
246                OrderEvent::ConfirmPayment,
247                context,
248            );
249        }
250    }
251
252    // Get and display metrics
253    let metrics = state_machine.get_metrics();
254    println!("State Machine Metrics:");
255    println!("  Total transitions: {}", metrics.total_transitions);
256    println!("  Successful: {}", metrics.successful_transitions);
257    println!("  Failed: {}", metrics.failed_transitions);
258    println!("  Success rate: {:.2}%", metrics.success_rate() * 100.0);
259
260    if let Some(avg_time) = metrics.average_transition_time() {
261        println!("  Average transition time: {:?}", avg_time);
262    }
263
264    println!("  State visit counts:");
265    for (state, count) in &metrics.state_visit_counts {
266        println!("    {}: {}", state, count);
267    }
268}
269
270/// Example 5: With guard priorities (requires 'guards' feature)
271#[cfg(feature = "guards")]
272fn guards_example() {
273    println!("\n=== Guard Priorities Example ===");
274
275    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
276
277    // Multiple transitions with different priorities
278    builder
279        .external_transition()
280        .from(OrderState::PaymentReceived)
281        .to(OrderState::Processing)
282        .on(OrderEvent::Process)
283        .when(|_s, _e, ctx| ctx.amount < 100.0)
284        .with_priority(10)
285        .perform(|_s, _e, ctx| {
286            println!(
287                "Processing small order {} (amount: {})",
288                ctx.order_id, ctx.amount
289            );
290        });
291
292    builder
293        .external_transition()
294        .from(OrderState::PaymentReceived)
295        .to(OrderState::Processing)
296        .on(OrderEvent::Process)
297        .when(|_s, _e, ctx| ctx.amount >= 100.0 && ctx.amount < 1000.0)
298        .with_priority(20)
299        .perform(|_s, _e, ctx| {
300            println!(
301                "Processing medium order {} (amount: {})",
302                ctx.order_id, ctx.amount
303            );
304        });
305
306    builder
307        .external_transition()
308        .from(OrderState::PaymentReceived)
309        .to(OrderState::Processing)
310        .on(OrderEvent::Process)
311        .when(|_s, _e, ctx| ctx.amount >= 1000.0)
312        .with_priority(30)
313        .perform(|_s, _e, ctx| {
314            println!(
315                "Processing large order {} (amount: {}) - Priority handling!",
316                ctx.order_id, ctx.amount
317            );
318        });
319
320    let state_machine = builder.id("GuardsOrderMachine").build();
321
322    // Test with different order amounts
323    let contexts = vec![
324        OrderContext {
325            order_id: "ORD-SMALL".to_string(),
326            amount: 50.0,
327            customer_id: "C1".to_string(),
328        },
329        OrderContext {
330            order_id: "ORD-MEDIUM".to_string(),
331            amount: 500.0,
332            customer_id: "C2".to_string(),
333        },
334        OrderContext {
335            order_id: "ORD-LARGE".to_string(),
336            amount: 5000.0,
337            customer_id: "C3".to_string(),
338        },
339    ];
340
341    for context in contexts {
342        let _ = state_machine.fire_event(OrderState::PaymentReceived, OrderEvent::Process, context);
343    }
344}
345
346/// Example 6: With visualization (requires 'visualization' feature)
347#[cfg(feature = "visualization")]
348fn visualization_example() {
349    println!("\n=== Visualization Example ===");
350
351    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
352
353    // Build a complete order flow
354    builder
355        .external_transition()
356        .from(OrderState::New)
357        .to(OrderState::PaymentPending)
358        .on(OrderEvent::Pay)
359        .perform(|_s, _e, _c| {});
360
361    builder
362        .external_transition()
363        .from(OrderState::PaymentPending)
364        .to(OrderState::PaymentReceived)
365        .on(OrderEvent::ConfirmPayment)
366        .perform(|_s, _e, _c| {});
367
368    builder
369        .external_transition()
370        .from(OrderState::PaymentReceived)
371        .to(OrderState::Processing)
372        .on(OrderEvent::Process)
373        .perform(|_s, _e, _c| {});
374
375    builder
376        .external_transition()
377        .from(OrderState::Processing)
378        .to(OrderState::Shipped)
379        .on(OrderEvent::Ship)
380        .perform(|_s, _e, _c| {});
381
382    builder
383        .external_transition()
384        .from(OrderState::Shipped)
385        .to(OrderState::Delivered)
386        .on(OrderEvent::Deliver)
387        .perform(|_s, _e, _c| {});
388
389    builder
390        .external_transitions()
391        .from_among(vec![
392            OrderState::New,
393            OrderState::PaymentPending,
394            OrderState::Processing,
395        ])
396        .to(OrderState::Cancelled)
397        .on(OrderEvent::Cancel)
398        .perform(|_s, _e, _c| {});
399
400    builder
401        .external_transition()
402        .from(OrderState::Cancelled)
403        .to(OrderState::Refunded)
404        .on(OrderEvent::Refund)
405        .perform(|_s, _e, _c| {});
406
407    let state_machine = builder.id("VisualOrderMachine").build();
408
409    println!("DOT Format:");
410    println!("{}", state_machine.to_dot());
411
412    println!("\nPlantUML Format:");
413    println!("{}", state_machine.to_plantuml());
414}
415
416/// Example 7: With parallel regions (requires 'parallel' feature)
417#[cfg(feature = "parallel")]
418fn parallel_example() {
419    println!("\n=== Parallel Regions Example ===");
420
421    // Order processing region
422    let mut order_builder =
423        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
424    order_builder
425        .external_transition()
426        .from(OrderState::New)
427        .to(OrderState::Processing)
428        .on(OrderEvent::Process)
429        .perform(|_s, _e, ctx| {
430            println!("Order region: Processing order {}", ctx.order_id);
431        });
432
433    // Payment processing region (using same states/events for simplicity)
434    let mut payment_builder =
435        StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
436    payment_builder
437        .external_transition()
438        .from(OrderState::PaymentPending)
439        .to(OrderState::PaymentReceived)
440        .on(OrderEvent::ConfirmPayment)
441        .perform(|_s, _e, ctx| {
442            println!(
443                "Payment region: Payment confirmed for order {}",
444                ctx.order_id
445            );
446        });
447
448    let mut parallel_machine = ParallelStateMachine::new();
449    parallel_machine.add_region(order_builder.id("OrderRegion").build());
450    parallel_machine.add_region(payment_builder.id("PaymentRegion").build());
451
452    let context = OrderContext {
453        order_id: "ORD-PARALLEL".to_string(),
454        amount: 199.99,
455        customer_id: "CUST-P1".to_string(),
456    };
457
458    // Fire events in parallel regions
459    println!("Firing Process event in parallel regions:");
460    let results = parallel_machine.fire_event(
461        vec![OrderState::New, OrderState::PaymentPending],
462        OrderEvent::Process,
463        context.clone(),
464    );
465
466    for (i, result) in results.iter().enumerate() {
467        println!("  Region {}: {:?}", i, result);
468    }
469
470    println!("Firing ConfirmPayment event in parallel regions:");
471    let results = parallel_machine.fire_event(
472        vec![OrderState::Processing, OrderState::PaymentPending],
473        OrderEvent::ConfirmPayment,
474        context,
475    );
476
477    for (i, result) in results.iter().enumerate() {
478        println!("  Region {}: {:?}", i, result);
479    }
480}
481
482/// Example 8: Complete example with multiple features
483#[cfg(all(feature = "history", feature = "metrics", feature = "extended"))]
484fn complete_example() {
485    println!("\n=== Complete Example with Multiple Features ===");
486
487    let mut builder = StateMachineBuilderFactory::create::<OrderState, OrderEvent, OrderContext>();
488
489    // Configure entry/exit actions
490    builder
491        .with_entry_action(OrderState::Processing, |_s, ctx| {
492            println!("[ENTRY] Starting to process order {}", ctx.order_id);
493        })
494        .with_exit_action(OrderState::Processing, |_s, ctx| {
495            println!("[EXIT] Finished processing order {}", ctx.order_id);
496        });
497
498    // Build transitions
499    builder
500        .external_transition()
501        .from(OrderState::New)
502        .to(OrderState::PaymentPending)
503        .on(OrderEvent::Pay)
504        .perform(|_s, _e, ctx| {
505            println!("Payment initiated for ${}", ctx.amount);
506        });
507
508    builder
509        .external_transition()
510        .from(OrderState::PaymentPending)
511        .to(OrderState::PaymentReceived)
512        .on(OrderEvent::ConfirmPayment)
513        .when(|_s, _e, ctx| ctx.amount > 0.0)
514        .perform(|_s, _e, ctx| {
515            println!("Payment confirmed: ${}", ctx.amount);
516        });
517
518    builder
519        .external_transition()
520        .from(OrderState::PaymentReceived)
521        .to(OrderState::Processing)
522        .on(OrderEvent::Process)
523        .perform(|_s, _e, _c| {});
524
525    builder
526        .external_transition()
527        .from(OrderState::Processing)
528        .to(OrderState::Shipped)
529        .on(OrderEvent::Ship)
530        .perform(|_s, _e, ctx| {
531            println!("Order {} shipped", ctx.order_id);
532        });
533
534    builder.set_fail_callback(Arc::new(|state, event, ctx| {
535        println!(
536            "FAILED: Cannot handle {:?} in state {:?} for order {}",
537            event, state, ctx.order_id
538        );
539    }));
540
541    let state_machine = builder.id("CompleteOrderMachine").build();
542
543    // Process an order through the complete flow
544    let context = OrderContext {
545        order_id: "ORD-COMPLETE".to_string(),
546        amount: 999.99,
547        customer_id: "CUST-VIP".to_string(),
548    };
549
550    println!("\nProcessing order through complete flow:");
551    let states = [
552        (OrderState::New, OrderEvent::Pay),
553        (OrderState::PaymentPending, OrderEvent::ConfirmPayment),
554        (OrderState::PaymentReceived, OrderEvent::Process),
555        (OrderState::Processing, OrderEvent::Ship),
556    ];
557
558    for (state, event) in &states {
559        let result = state_machine.fire_event(state.clone(), event.clone(), context.clone());
560        println!("  {:?} + {:?} = {:?}", state, event, result);
561    }
562
563    // Try an invalid transition
564    println!("\nTrying invalid transition:");
565    let _ = state_machine.fire_event(OrderState::Shipped, OrderEvent::Pay, context);
566
567    // Display collected data
568    println!("\nHistory:");
569    for record in state_machine.get_history() {
570        println!(
571            "  {:?} -> {:?} (success: {})",
572            record.from, record.to, record.success
573        );
574    }
575
576    println!("\nMetrics:");
577    let metrics = state_machine.get_metrics();
578    println!(
579        "  Total: {}, Success: {}, Failed: {}",
580        metrics.total_transitions, metrics.successful_transitions, metrics.failed_transitions
581    );
582}
Source

pub(crate) fn add_transition(&mut self, transition: Transition<S, E, C>)

Trait Implementations§

Source§

impl<S, E, C> Default for StateMachineBuilder<S, E, C>
where S: State, E: Event, C: Context,

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<S, E, C> Freeze for StateMachineBuilder<S, E, C>

§

impl<S, E, C> !RefUnwindSafe for StateMachineBuilder<S, E, C>

§

impl<S, E, C> Send for StateMachineBuilder<S, E, C>
where S: Send, E: Send,

§

impl<S, E, C> Sync for StateMachineBuilder<S, E, C>
where S: Sync, E: Sync,

§

impl<S, E, C> Unpin for StateMachineBuilder<S, E, C>
where S: Unpin, E: Unpin,

§

impl<S, E, C> !UnwindSafe for StateMachineBuilder<S, E, C>

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.