pub struct StateMachineBuilder<S, E, C>{
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>
impl<S, E, C> StateMachineBuilder<S, E, C>
Sourcepub fn id(self, id: impl Into<String>) -> Self
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
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}Sourcepub fn external_transition(&mut self) -> ExternalTransitionBuilder<'_, S, E, C>
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
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}Sourcepub fn internal_transition(&mut self) -> InternalTransitionBuilder<'_, S, E, C>
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}Sourcepub fn external_transitions(
&mut self,
) -> ExternalTransitionsBuilder<'_, S, E, C>
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
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}Sourcepub fn set_fail_callback(
&mut self,
callback: FailCallback<S, E, C>,
) -> &mut Self
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
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}Sourcepub fn with_entry_action<F>(&mut self, state: S, action: F) -> &mut Self
pub fn with_entry_action<F>(&mut self, state: S, action: F) -> &mut Self
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
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}Sourcepub fn with_exit_action<F>(&mut self, state: S, action: F) -> &mut Self
pub fn with_exit_action<F>(&mut self, state: S, action: F) -> &mut Self
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
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}Sourcepub fn with_state_timeout(
&mut self,
state: S,
duration: Duration,
target_state: S,
timeout_event: E,
) -> &mut Self
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}Sourcepub fn build(self) -> StateMachine<S, E, C>
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
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}