1#[macro_export]
10macro_rules! def_machine {
11 ( machine $machine:ident
15 $(<$(
16 $type_var:ident $(: { $($type_constraint:path),+ })*
17 ),+>)*
18 {
19 STATES [
20 $(state $state:ident (
21 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
22 ) $({
23 $(entry $entry:block)*
24 $(exit $exit:block)*
25 })*)+
26 ]
27 EVENTS [
28 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
29 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
30 $({ $($state_data:ident),* } => $action:block)*
31 )*
32 ]
33 EXTENDED [
34 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
35 ]
36 $(self_reference: $self_reference:ident)*
37 initial_state: $initial:ident $({
38 $(initial_action: $initial_action:block)*
39 })*
40 $(terminal_state: $terminal:ident $({
41 $(terminate_success: $terminate_success:block)*
42 $(terminate_failure: $terminate_failure:block)*
43 })*)*
44 }
45
46 ) => {
47
48 $crate::def_machine!{
49 @base
50 machine $machine
51 $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
52 {
53 STATES [
54 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
55 $({
56 $(entry $entry)*
57 $(exit $exit)*
58 })*)+
59 ]
60 EVENTS [
61 $(event $event <$source> $(=> <$target>)*
62 ($($param_name : $param_type $(= $param_default)*),*)
63 $({$($state_data),*} => $action)*
64 )*
65 ]
66 EXTENDED [
67 $($ext_name : $ext_type $(= $ext_default)*),*
68 ]
69 $(self_reference: $self_reference)*
70 initial_state: $initial $({
71 $(initial_action: $initial_action)*
72 })*
73 $(terminal_state: $terminal $({
74 $(terminate_success: $terminate_success)*
75 $(terminate_failure: $terminate_failure)*
76 })*)*
77 }
78 }
79
80 impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
81 $($(
82 $($($type_var : $type_constraint),+)*
83 ),+)*
84 {
85 pub fn initial() -> Self {
86 $crate::log::debug!(
87 machine=stringify!($machine), state=stringify!($initial);
88 "initialize state machine");
89 let mut extended_state = ExtendedState::initial();
90 let state = StateId::$initial.to_state (&mut extended_state);
91 let mut initial = Self { state, extended_state };
92 {
93 $(#[allow(unused_variables)]
94 let $self_reference = &mut initial;)*
95 $($($initial_action)*)*
96 }
97 initial.state_entry();
98 initial
99 }
100 }
101
102 impl $(<$($type_var),+>)* $crate::MachineDotfile
103 for $machine $(<$($type_var),+>)*
104 where
105 $($(
106 $($($type_var : $type_constraint),+)*
107 ),+)*
108 {
109 fn name() -> &'static str {
110 stringify!($machine)
111 }
112 fn type_vars() -> Vec <String> {
113 let mut _v = Vec::new();
114 $($(
115 _v.push (format!(
116 "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
117 )+)*
118 _v
119 }
120 fn extended_state_names() -> Vec <&'static str> {
121 vec![$(stringify!($ext_name)),*]
122 }
123 fn extended_state_types() -> Vec <&'static str> {
124 vec![$(stringify!($ext_type)),*]
125 }
126 fn extended_state_defaults() -> Vec <&'static str> {
127 let mut _v = Vec::new();
128 $(
129 _v.push ({
130 let default_expr = stringify!($($ext_default)*);
131 if !default_expr.is_empty() {
132 default_expr
133 } else {
134 concat!(stringify!($ext_type), "::default()")
135 }
136 });
137 )*
138 _v
139 }
140 fn self_reference() -> &'static str {
141 stringify!($($self_reference)*)
142 }
143 fn states() -> Vec <&'static str> {
144 vec![$(stringify!($state)),+]
145 }
146 fn state_initial() -> &'static str {
147 stringify!($initial)
148 }
149 fn state_terminal() -> &'static str {
150 stringify!($($terminal)*)
151 }
152 fn state_data_names() -> Vec <Vec <&'static str>> {
153 let mut v = Vec::new();
154 $({
155 let mut _w = Vec::new();
156 $(_w.push (stringify!($data_name));)*
157 v.push (_w);
158 })+
159 v
160 }
161 fn state_data_types() -> Vec <Vec <&'static str>> {
162 let mut v = Vec::new();
163 $({
164 let mut _w = Vec::new();
165 $(_w.push (stringify!($data_type));)*
166 v.push (_w);
167 })+
168 v
169 }
170 fn state_data_defaults() -> Vec <Vec <&'static str>> {
171 let mut v = Vec::new();
172 $({
173 let mut _w = Vec::new();
174 $(
175 _w.push ({
176 let default_expr = stringify!($($data_default)*);
177 if !default_expr.is_empty() {
178 default_expr
179 } else {
180 concat!(stringify!($data_type), "::default()")
181 }
182 });
183 )*
184 v.push (_w);
185 })+
186 v
187 }
188 fn state_data_pretty_defaults() -> Vec <Vec <String>> {
191 let mut v = Vec::new();
192 $({
193 let mut _w = Vec::new();
194 $(
195 let default_val : $data_type
196 = $crate::def_machine!(@expr_default $($data_default)*);
197 _w.push (format!("{:#?}", default_val));
198 )*
199 v.push (_w);
200 })+
201 v
202 }
203 fn events() -> Vec <&'static str> {
204 vec![$(stringify!($event)),*]
205 }
206 fn event_sources() -> Vec <&'static str> {
207 vec![$(stringify!($source)),*]
208 }
209 fn event_targets() -> Vec <&'static str> {
210 vec![$(stringify!($($target)*)),*]
211 }
212 fn event_actions() -> Vec <&'static str> {
213 vec![$(stringify!($($action)*)),*]
214 }
215 } impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
218 $($(
219 $($($type_var : $type_constraint),+)*
220 ),+)*
221 {
222 pub fn initial() -> Self {
223 Self {
224 $($ext_name: $crate::def_machine!(@expr_default $($ext_default)*)),*
225 }
226 }
227
228 pub fn new ($($ext_name : Option <$ext_type>),*) -> Self {
230 Self {
231 $($ext_name: $ext_name.unwrap_or (
232 $crate::def_machine!(@expr_default $($ext_default)*))
233 ),*
234 }
235 }
236 }
237
238 impl <'event> From <EventId> for Event <'event> {
239 fn from (id : EventId) -> Self {
241 let _params = id.clone().into();
242 Event { id, params: _params }
243 }
244 }
245
246 impl <'event> From <EventId> for EventParams <'event> {
247 fn from (id : EventId) -> Self {
248 match id {
249 $(EventId::$event => EventParams::$event {
250 $($param_name:
251 $crate::def_machine!(@expr_default $($param_default)*)
252 ),*
253 }),*
254 }
255 }
256 }
257
258 };
259 ( $machine:ident
265 $(<$(
266 $type_var:ident $(: { $($type_constraint:path),+ })*
267 ),+>)*
268 $(($(
269 $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
270 ),*))*
271 $(@ $self_reference:ident)*
272 {
273 STATES [
274 $(state $state:ident (
275 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
276 ) $({
277 $(entry $entry:block)*
278 $(exit $exit:block)*
279 })*)+
280 ]
281 EVENTS [
282 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
283 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
284 $({ $($state_data:ident),* } => $action:block)*
285 )*
286 ]
287 initial_state: $initial:ident $({
288 $(initial_action: $initial_action:block)*
289 })*
290 $(terminal_state: $terminal:ident $({
291 $(terminate_success: $terminate_success:block)*
292 $(terminate_failure: $terminate_failure:block)*
293 })*)*
294 }
295
296 ) => {
297
298 $crate::def_machine!{
299 machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
300 STATES [
301 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
302 $({
303 $(entry $entry)*
304 $(exit $exit)*
305 })*)+
306 ]
307 EVENTS [
308 $(event $event <$source> $(=> <$target>)*
309 ($($param_name : $param_type $(= $param_default)*),*)
310 $({$($state_data),*} => $action)*
311 )*
312 ]
313 EXTENDED [
314 $($($ext_name : $ext_type $(= $ext_default)*),*)*
315 ]
316 $(self_reference: $self_reference)*
317 initial_state: $initial $({
318 $(initial_action: $initial_action)*
319 })*
320 $(terminal_state: $terminal $({
321 $(terminate_success: $terminate_success)*
322 $(terminate_failure: $terminate_failure)*
323 })*)*
324 }
325 }
326
327 };
328
329 ( @impl_fn_handle_event
333 machine $machine:ident {
334 EVENTS [
335 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
336 ($($param_name:ident),*)
337 $({ $($state_data:ident),* } => $action:block)*
338 )*
339 ]
340 EXTENDED [
341 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
342 ]
343 $(self_reference: $self_reference:ident)*
344 }
345
346 ) => {
347
348 pub fn handle_event (&mut self, mut _event : Event)
349 -> Result <(), $crate::HandleEventException>
350 {
351 #[allow(unreachable_code)]
354 match _event.transition() {
355 Transition::Universal (target_id) => {
356 $crate::log::debug!(
357 machine=stringify!($machine), state:?=self.state.id,
358 event:?=_event.id, transition="Universal", target:?=target_id;
359 "handle state machine event");
360 self.state_exit();
361 { #[allow(unused_variables)]
364 match &mut self.extended_state {
365 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
366 match _event.params {
368 $(EventParams::$event { $(mut $param_name,)*.. } => {
369 $crate::def_machine!{
371 @event_action_universal
372 event $event <$source> $(=> <$target>)* $($action)*
373 }
374 })*
375 _ => unreachable!("unreachable phantom data variant")
376 }
377 }
378 }
379 }
380 let state = target_id.to_state (&mut self.extended_state);
381 self.state = state;
382 self.state_entry();
383 Ok (())
384 }
385 Transition::Internal (source_id) => {
386 if self.state.id == source_id {
387 $crate::log::debug!(
388 machine=stringify!($machine), state:?=self.state.id,
389 event:?=_event.id, transition="Internal", source_state:?=source_id;
390 "handle state machine event");
391 #[allow(unused_variables)]
393 match &mut self.extended_state {
394 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
395 match _event.params {
397 $(EventParams::$event { $(mut $param_name,)*.. } => {
398 #[allow(unreachable_patterns)]
403 match &mut self.state.data {
404 $crate::def_machine!{
405 @event_internal_state_pattern
406 $source { $($($state_data),*)* }
407 } => {
408 $crate::def_machine!{
410 @event_action_internal
411 event $event <$source> $(=> <$target>)* $($action)*
412 }
413 }
414 _ => unreachable!("current state should match event source")
415 }
416 })*
417 _ => unreachable!("unreachable phantom data variant")
418 }
419 }
420 }
421 Ok (())
422 } else {
423 let exception = $crate::HandleEventException::WrongState;
424 $crate::log::warn!(
425 machine=stringify!($machine), state:?=self.state.id,
426 event:?=_event.id, transition="Internal", source:?=source_id,
427 exception:?;
428 "handle state machine event exception");
429 Err (exception)
430 }
431 }
432 Transition::External (source_id, target_id) => {
433 if self.state.id == source_id {
434 $crate::log::debug!(
435 machine=stringify!($machine), state:?=self.state.id,
436 event:?=_event.id, transition="External", source:?=source_id,
437 target:?=target_id;
438 "handle state machine event");
439 self.state_exit();
440 { #[allow(unused_variables)]
443 match &mut self.extended_state {
444 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
445 match _event.params {
447 $(EventParams::$event { $(mut $param_name,)*.. } => {
448 $crate::def_machine!{
450 @event_action_external
451 event $event <$source> $(=> <$target>)* $($action)*
452 }
453 })*
454 _ => unreachable!("unreachable phantom data variant")
455 }
456 }
457 }
458 }
459 let state = target_id.to_state (&mut self.extended_state);
460 self.state = state;
461 self.state_entry();
462 Ok (())
463 } else {
464 let exception = $crate::HandleEventException::WrongState;
465 $crate::log::warn!(
466 machine=stringify!($machine), state:?=self.state.id,
467 event:?=_event.id, transition="External", source:?=source_id,
468 target:?=target_id, exception:?;
469 "handle state machine event exception");
470 Err (exception)
471 }
472 }
473 } } }; ( @event_internal_state_pattern
482 $source:ident { $($state_data:ident),* }
483 ) => {
484 &mut StateData::$source {$(ref mut $state_data,)*..}
485 };
486
487 ( @event_internal_state_pattern
491 * { $($state_data:ident),* }
492 ) => {
493 _
494 };
495
496 ( @event_action_external
500 event $event:ident <$source:ident> => <$target:ident> $($action:block)*
501 ) => {
502 $($action)*
503 };
504
505 ( @event_action_external
509 event $event:ident <$source:ident> $($action:block)*
510 ) => { unreachable!("not an external event") };
511
512 ( @event_action_external
516 event $event:ident <*> => <$target:ident> $($action:block)*
517 ) => { unreachable!("not an external event") };
518
519 ( @event_action_universal
523 event $event:ident <*> => <$target:ident> $($action:block)*
524 ) => {
525 $($action)*
526 };
527
528 ( @event_action_universal
532 event $event:ident <$source:ident> $(=> <$target:ident>)* $($action:block)*
533 ) => { unreachable!("not an universal event") };
534
535 ( @event_action_internal
539 event $event:ident <$source:ident> $($action:block)*
540 ) => {
541 $($action)*
542 };
543
544 ( @event_action_internal
548 event $event:ident <$source:tt> => <$target:ident> $($action:block)*
549 ) => { unreachable!("not an internal event") };
550
551 ( @event_transition <$source:ident> => <$target:ident> ) => {
555 Transition::External (StateId::$source, StateId::$target)
556 };
557
558 ( @event_transition <$source:ident> ) => {
562 Transition::Internal (StateId::$source)
563 };
564
565 ( @event_transition <*> => <$target:ident> ) => {
569 Transition::Universal (StateId::$target)
570 };
571
572 ( @expr_default $default:expr ) => { $default };
576
577 ( @expr_default ) => { Default::default() };
581
582 ( @expr_option $default:expr ) => { Some ($default) };
586
587 ( @expr_option ) => { None };
591
592 ( @base
596 machine $machine:ident
597 $(<$(
598 $type_var:ident $(: { $($type_constraint:path),+ })*
599 ),+>)*
600 {
601 STATES [
602 $(state $state:ident (
603 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
604 ) $({
605 $(entry $entry:block)*
606 $(exit $exit:block)*
607 })*)+
608 ]
609 EVENTS [
610 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
611 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
612 $({ $($state_data:ident),* } => $action:block)*
613 )*
614 ]
615 EXTENDED [
616 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
617 ]
618 $(self_reference: $self_reference:ident)*
619 initial_state: $initial:ident $({
620 $(initial_action: $initial_action:block)*
621 })*
622 $(terminal_state: $terminal:ident $({
623 $(terminate_success: $terminate_success:block)*
624 $(terminate_failure: $terminate_failure:block)*
625 })*)*
626 }
627
628 ) => {
629
630 pub struct $machine $(<$($type_var),+>)* where
631 $($(
632 $($($type_var : $type_constraint),+)*
633 ),+)*
634 {
635 state : State,
636 extended_state : ExtendedState $(<$($type_var),+>)*
637 }
638
639 pub struct State {
640 id : StateId,
641 data : StateData
642 }
643
644 pub struct ExtendedState $(<$($type_var),+>)* where
645 $($(
646 $($($type_var : $type_constraint),+)*
647 ),+)*
648 {
649 $(pub $ext_name : $ext_type),*
650 }
651
652 pub struct Event <'event> {
653 id : EventId,
654 params : EventParams <'event>
655 }
656
657 #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
658 pub enum StateId {
659 $($state),+
660 }
661
662 pub enum StateData {
663 $($state {
664 $($data_name : $data_type),*
665 }),+
666 }
667
668 #[derive(Debug, Eq, PartialEq)]
669 pub enum Transition {
670 Internal (StateId),
671 External (StateId, StateId),
672 Universal (StateId)
673 }
674
675 #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
676 pub enum EventId {
677 $($event),*
678 }
679
680 pub enum EventParams <'event> {
681 $($event {
682 $($param_name : $param_type),*
683 },)*
684 _PhantomData (::std::marker::PhantomData <&'event ()>)
685 }
686
687 impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
688 $($(
689 $($($type_var : $type_constraint),+)*
690 ),+)*
691 {
692 pub fn report_sizes() where $($($type_var : 'static),+)* {
693 let machine_name = stringify!($machine);
694 let machine_type = std::any::type_name::<Self>();
695 println!("{}::report_sizes...", machine_name);
696 println!(" size of {}: {}", machine_type,
697 std::mem::size_of::<Self>());
698 println!("...{}::report_sizes", machine_name);
699 }
700
701 pub fn new (mut extended_state : ExtendedState $(<$($type_var),+>)*)
702 -> Self
703 {
704 let state = StateId::$initial.to_state (&mut extended_state);
705 let mut new = Self { state, extended_state };
706 {
707 $(#[allow(unused_variables)]
708 let $self_reference = &mut new;)*
709 $($($initial_action)*)*
710 }
711 new.state_entry();
712 new
713 }
714
715 #[allow(dead_code)]
716 #[inline]
717 pub fn state (&self) -> &State {
718 &self.state
719 }
720
721 #[allow(dead_code)]
722 #[inline]
723 pub fn state_id (&self) -> StateId {
724 self.state().id().clone()
725 }
726
727 #[allow(dead_code)]
728 #[inline]
729 pub fn state_data (&self) -> &StateData {
730 self.state().data()
731 }
732
733 #[allow(dead_code)]
734 #[inline]
735 pub fn extended_state (&self) -> &ExtendedState $(<$($type_var),+>)* {
736 &self.extended_state
737 }
738
739 #[allow(dead_code)]
740 #[inline]
741 pub fn extended_state_mut (&mut self)
742 -> &mut ExtendedState $(<$($type_var),+>)*
743 {
744 &mut self.extended_state
745 }
746
747 $crate::def_machine!{
748 @impl_fn_handle_event
749 machine $machine {
750 EVENTS [
751 $(event $event <$source> $(=> <$target>)*
752 ($($param_name),*)
753 $({$($state_data),*} => $action)*
754 )*
755 ]
756 EXTENDED [
757 $($ext_name : $ext_type $(= $ext_default)*),*
758 ]
759 $(self_reference: $self_reference)*
760 }
761 }
762
763 fn state_entry (&mut self) {
764 #[allow(unused_variables)]
766 match &mut self.extended_state {
767 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
768 match self.state.data {
769 $(StateData::$state { $(ref mut $data_name,)*.. } => {
771 $($($entry)*)*
772 })+
773 }
774 }
775 }
776 }
777 fn state_exit (&mut self) {
778 #[allow(unused_variables)]
780 match &mut self.extended_state {
781 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
782 match self.state.data {
783 $(StateData::$state { $(ref mut $data_name,)*.. } => {
785 $($($exit)*)*
786 })+
787 }
788 }
789 }
790 }
791
792 } impl $(<$($type_var),+>)* AsRef <ExtendedState $(<$($type_var),+>)*>
795 for $machine $(<$($type_var),+>)*
796 where
797 $($(
798 $($($type_var : $type_constraint),+)*
799 ),+)*
800 {
801 #[inline]
802 fn as_ref (&self) -> &ExtendedState $(<$($type_var),+>)* {
803 &self.extended_state
804 }
805 }
806
807 impl $(<$($type_var),+>)* AsMut <ExtendedState $(<$($type_var),+>)*>
808 for $machine $(<$($type_var),+>)*
809 where
810 $($(
811 $($($type_var : $type_constraint),+)*
812 ),+)*
813 {
814 #[inline]
815 fn as_mut (&mut self) -> &mut ExtendedState $(<$($type_var),+>)* {
816 &mut self.extended_state
817 }
818 }
819
820 impl $(<$($type_var),+>)* Drop for $machine $(<$($type_var),+>)* where
821 $($(
822 $($($type_var : $type_constraint),+)*
823 ),+)*
824 {
825 fn drop (&mut self) {
826 self.state_exit();
827 let _state_id = self.state.id.clone();
828 $(#[allow(unused_variables)]
829 let $self_reference = &mut *self;)*
830 $(
831 if _state_id != StateId::$terminal {
832 $crate::log::warn!(
833 machine=stringify!($machine), state:?=_state_id,
834 terminal:?=StateId::$terminal;
835 "terminate state machine failure: not in terminal state");
836 $($($terminate_failure)*)*
837 } else {
838 $crate::log::debug!(
839 machine=stringify!($machine), state:?=_state_id;
840 "terminate state machine success");
841 $($($terminate_success)*)*
842 }
843 )*
844 }
845 }
846
847 impl State {
848 #[inline]
849 pub fn id (&self) -> &StateId {
850 &self.id
851 }
852
853 #[inline]
854 pub fn data (&self) -> &StateData {
855 &self.data
856 }
857 }
858
859 impl StateId {
860 #[inline]
861 pub const fn initial() -> Self {
862 StateId::$initial
863 }
864 $(
865 #[inline]
866 pub const fn terminal() -> Self {
867 StateId::$terminal
868 }
869 )*
870 #[expect(clippy::wrong_self_convention)]
871 pub fn to_state $(<$($type_var),+>)* (self,
872 extended_state : &mut ExtendedState$(<$($type_var),+>)*) -> State
873 where
874 $($(
875 $($($type_var : $type_constraint),+)*
876 ),+)*
877 {
878 #[allow(unused_variables)]
880 match extended_state {
881 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
882 match self {
883 $(StateId::$state => {
884 State {
885 id: self,
886 data: StateData::$state {
887 $($data_name:
888 $crate::def_machine!(@expr_default $($data_default)*)
889 ),*
890 }
891 }
892 })+
893 }
894 }
895 }
896 }
897 }
898
899 impl EventId {
900 pub fn transition (&self) -> Transition {
901 #[allow(clippy::uninhabited_references)]
902 match *self {
903 $(
904 EventId::$event =>
905 $crate::def_machine!(@event_transition <$source> $(=> <$target>)*)
906 ),*
907 }
908 }
909 }
910
911 impl <'event> EventParams <'event> {
912 pub fn id (&self) -> EventId {
913 match *self {
914 $(EventParams::$event {..} => EventId::$event,)*
915 _ => unreachable!("unreachable phantom data variant")
916 }
917 }
918 }
919
920 impl <'event> Event <'event> {
921 #[inline]
922 pub fn transition (&self) -> Transition {
923 self.id.transition()
924 }
925
926 #[inline]
927 #[allow(clippy::uninhabited_references)]
928 pub fn id (&self) -> &EventId {
929 &self.id
930 }
931
932 #[inline]
933 #[expect(mismatched_lifetime_syntaxes)]
934 pub fn params (&self) -> &EventParams {
935 &self.params
936 }
937 }
938
939 impl <'event> From <EventParams <'event>> for Event <'event> {
940 fn from (params : EventParams <'event>) -> Self {
941 let _id = params.id();
942 Event { id: _id, params }
943 }
944 }
945
946 }; } #[macro_export]
952macro_rules! def_machine_nodefault {
953 ( machine $machine:ident
957 $(<$(
958 $type_var:ident $(: { $($type_constraint:path),+ })*
959 ),+>)*
960 {
961 STATES [
962 $(state $state:ident (
963 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
964 ) $({
965 $(entry $entry:block)*
966 $(exit $exit:block)*
967 })*)+
968 ]
969 EVENTS [
970 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
971 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
972 $({ $($state_data:ident),* } => $action:block)*
973 )*
974 ]
975 EXTENDED [
976 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
977 ]
978 $(self_reference: $self_reference:ident)*
979 initial_state: $initial:ident $({
980 $(initial_action: $initial_action:block)*
981 })*
982 $(terminal_state: $terminal:ident $({
983 $(terminate_success: $terminate_success:block)*
984 $(terminate_failure: $terminate_failure:block)*
985 })*)*
986 }
987
988 ) => {
989
990 $crate::def_machine!{
991 @base
992 machine $machine
993 $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
994 {
995 STATES [
996 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
997 $({
998 $(entry $entry)*
999 $(exit $exit)*
1000 })*)+
1001 ]
1002 EVENTS [
1003 $(event $event <$source> $(=> <$target>)*
1004 ($($param_name : $param_type $(= $param_default)*),*)
1005 $({$($state_data),*} => $action)*
1006 )*
1007 ]
1008 EXTENDED [
1009 $($ext_name : $ext_type $(= $ext_default)*),*
1010 ]
1011 $(self_reference: $self_reference)*
1012 initial_state: $initial $({
1013 $(initial_action: $initial_action)*
1014 })*
1015 $(terminal_state: $terminal $({
1016 $(terminate_success: $terminate_success)*
1017 $(terminate_failure: $terminate_failure)*
1018 })*)*
1019 }
1020 }
1021
1022 impl $(<$($type_var),+>)* $crate::MachineDotfile
1023 for $machine $(<$($type_var),+>)*
1024 where
1025 $($(
1026 $($($type_var : $type_constraint),+)*
1027 ),+)*
1028 {
1029 fn name() -> &'static str {
1030 stringify!($machine)
1031 }
1032 fn type_vars() -> Vec <String> {
1033 let mut _v = Vec::new();
1034 $($(
1035 _v.push (format!(
1036 "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
1037 )+)*
1038 _v
1039 }
1040 fn extended_state_names() -> Vec <&'static str> {
1041 let mut _v = Vec::new();
1042 $(
1043 _v.push (stringify!($ext_name));
1044 )*
1045 _v
1046 }
1047 fn extended_state_types() -> Vec <&'static str> {
1048 let mut _v = Vec::new();
1049 $(
1050 _v.push (stringify!($ext_type));
1051 )*
1052 _v
1053 }
1054 fn extended_state_defaults() -> Vec <&'static str> {
1055 let mut _v = Vec::new();
1056 $(
1057 _v.push (stringify!($($ext_default)*));
1058 )*
1059 _v
1060 }
1061 fn self_reference() -> &'static str {
1062 stringify!($($self_reference)*)
1063 }
1064 fn states() -> Vec <&'static str> {
1065 vec![$(stringify!($state)),+]
1066 }
1067 fn state_initial() -> &'static str {
1068 stringify!($initial)
1069 }
1070 fn state_terminal() -> &'static str {
1071 stringify!($($terminal)*)
1072 }
1073 fn state_data_names() -> Vec <Vec <&'static str>> {
1074 let mut v = Vec::new();
1075 $({
1076 let mut _w = Vec::new();
1077 $(_w.push (stringify!($data_name));)*
1078 v.push (_w);
1079 })+
1080 v
1081 }
1082 fn state_data_types() -> Vec <Vec <&'static str>> {
1083 let mut v = Vec::new();
1084 $({
1085 let mut _w = Vec::new();
1086 $(_w.push (stringify!($data_type));)*
1087 v.push (_w);
1088 })+
1089 v
1090 }
1091 fn state_data_defaults() -> Vec <Vec <&'static str>> {
1092 let mut v = Vec::new();
1093 $({
1094 let mut _w = Vec::new();
1095 $(_w.push (stringify!($($data_default)*));)*
1096 v.push (_w);
1097 })+
1098 v
1099 }
1100 fn state_data_pretty_defaults() -> Vec <Vec <String>> {
1102 let mut v = Vec::new();
1103 $({
1104 let mut _w = Vec::new();
1105 $(
1106 _w.push (format!("{:#?}", stringify!($($data_default)*)));
1107 )*
1108 v.push (_w);
1109 })+
1110 v
1111 }
1112 fn events() -> Vec <&'static str> {
1113 vec![$(stringify!($event)),*]
1114 }
1115 fn event_sources() -> Vec <&'static str> {
1116 vec![$(stringify!($source)),*]
1117 }
1118 fn event_targets() -> Vec <&'static str> {
1119 vec![$(stringify!($($target)*)),*]
1120 }
1121 fn event_actions() -> Vec <&'static str> {
1122 vec![$(stringify!($($action)*)),*]
1123 }
1124 } impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
1127 $($(
1128 $($($type_var : $type_constraint),+)*
1129 ),+)*
1130 {
1131 pub fn new ($($ext_name : Option <$ext_type>),*) -> Option <Self> {
1136 Some (Self {
1137 $($ext_name: {
1138 if let Some ($ext_name) = $ext_name {
1139 $ext_name
1140 } else {
1141 $crate::def_machine!(@expr_option $($ext_default)*)?
1142 }
1143 }),*
1144 })
1145 }
1146 }
1147 };
1148
1149 ( $machine:ident
1153 $(<$(
1154 $type_var:ident $(: { $($type_constraint:path),+ })*
1155 ),+>)*
1156 $(($(
1157 $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
1158 ),*))*
1159 $(@ $self_reference:ident)*
1160 {
1161 STATES [
1162 $(state $state:ident (
1163 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1164 ) $({
1165 $(entry $entry:block)*
1166 $(exit $exit:block)*
1167 })*)+
1168 ]
1169 EVENTS [
1170 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1171 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1172 $({ $($state_data:ident),* } => $action:block)*
1173 )*
1174 ]
1175 initial_state: $initial:ident $({
1176 $(initial_action: $initial_action:block)*
1177 })*
1178 $(terminal_state: $terminal:ident $({
1179 $(terminate_success: $terminate_success:block)*
1180 $(terminate_failure: $terminate_failure:block)*
1181 })*)*
1182 }
1183
1184 ) => {
1185
1186 $crate::def_machine_nodefault!{
1187 machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
1188 STATES [
1189 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
1190 $({
1191 $(entry $entry)*
1192 $(exit $exit)*
1193 })*)+
1194 ]
1195 EVENTS [
1196 $(event $event <$source> $(=> <$target>)*
1197 ($($param_name : $param_type $(= $param_default)*),*)
1198 $({$($state_data),*} => $action)*
1199 )*
1200 ]
1201 EXTENDED [
1202 $($($ext_name : $ext_type $(= $ext_default)*),*)*
1203 ]
1204 $(self_reference: $self_reference)*
1205 initial_state: $initial $({
1206 $(initial_action: $initial_action)*
1207 })*
1208 $(terminal_state: $terminal $({
1209 $(terminate_success: $terminate_success)*
1210 $(terminate_failure: $terminate_failure)*
1211 })*)*
1212 }
1213 }
1214
1215 };
1216
1217} #[macro_export]
1228macro_rules! def_machine_debug {
1229 ( machine $machine:ident
1233 $(<$(
1234 $type_var:ident $(: { $($type_constraint:path),+ })*
1235 ),+>)*
1236 {
1237 STATES [
1238 $(state $state:ident (
1239 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1240 ) $({
1241 $(entry $entry:block)*
1242 $(exit $exit:block)*
1243 })*)+
1244 ]
1245 EVENTS [
1246 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1247 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1248 $({ $($state_data:ident),* } => $action:block)*
1249 )*
1250 ]
1251 EXTENDED [
1252 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
1253 ]
1254 $(self_reference: $self_reference:ident)*
1255 initial_state: $initial:ident $({
1256 $(initial_action: $initial_action:block)*
1257 })*
1258 $(terminal_state: $terminal:ident $({
1259 $(terminate_success: $terminate_success:block)*
1260 $(terminate_failure: $terminate_failure:block)*
1261 })*)*
1262 }
1263
1264 ) => {
1265
1266 $crate::def_machine_debug!{
1267 @base
1268 machine $machine
1269 $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
1270 {
1271 STATES [
1272 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
1273 $({
1274 $(entry $entry)*
1275 $(exit $exit)*
1276 })*)+
1277 ]
1278 EVENTS [
1279 $(event $event <$source> $(=> <$target>)*
1280 ($($param_name : $param_type $(= $param_default)*),*)
1281 $({$($state_data),*} => $action)*
1282 )*
1283 ]
1284 EXTENDED [
1285 $($ext_name : $ext_type $(= $ext_default)*),*
1286 ]
1287 $(self_reference: $self_reference)*
1288 initial_state: $initial $({
1289 $(initial_action: $initial_action)*
1290 })*
1291 $(terminal_state: $terminal $({
1292 $(terminate_success: $terminate_success)*
1293 $(terminate_failure: $terminate_failure)*
1294 })*)*
1295 }
1296 }
1297
1298 impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
1299 $($(
1300 $type_var : std::fmt::Debug,
1301 $($($type_var : $type_constraint),+)*
1302 ),+)*
1303 {
1304 pub fn initial() -> Self {
1305 $crate::log::debug!(
1306 machine=stringify!($machine), state=stringify!($initial);
1307 "initialize state machine");
1308 let mut extended_state = ExtendedState::initial();
1309 let state = StateId::$initial.to_state (&mut extended_state);
1310 let mut initial = Self { state, extended_state };
1311 {
1312 $(#[allow(unused_variables)]
1313 let $self_reference = &mut initial;)*
1314 $($($initial_action)*)*
1315 }
1316 initial.state_entry();
1317 initial
1318 }
1319 }
1320
1321 impl $(<$($type_var),+>)* $crate::MachineDotfile
1322 for $machine $(<$($type_var),+>)*
1323 where
1324 $($(
1325 $type_var : std::fmt::Debug,
1326 $($($type_var : $type_constraint),+)*
1327 ),+)*
1328 {
1329 fn name() -> &'static str {
1330 stringify!($machine)
1331 }
1332 fn type_vars() -> Vec <String> {
1333 let mut _v = Vec::new();
1334 $($(
1335 _v.push (format!(
1336 "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
1337 )+)*
1338 _v
1339 }
1340 fn extended_state_names() -> Vec <&'static str> {
1341 let mut _v = Vec::new();
1342 $(
1343 _v.push (stringify!($ext_name));
1344 )*
1345 _v
1346 }
1347 fn extended_state_types() -> Vec <&'static str> {
1348 let mut _v = Vec::new();
1349 $(
1350 _v.push (stringify!($ext_type));
1351 )*
1352 _v
1353 }
1354 fn extended_state_defaults() -> Vec <&'static str> {
1355 let mut _v = Vec::new();
1356 $(
1357 _v.push ({
1358 let default_expr = stringify!($($ext_default)*);
1359 if !default_expr.is_empty() {
1360 default_expr
1361 } else {
1362 concat!(stringify!($ext_type), "::default()")
1363 }
1364 });
1365 )*
1366 _v
1367 }
1368 fn self_reference() -> &'static str {
1369 stringify!($($self_reference)*)
1370 }
1371 fn states() -> Vec <&'static str> {
1372 vec![$(stringify!($state)),+]
1373 }
1374 fn state_initial() -> &'static str {
1375 stringify!($initial)
1376 }
1377 fn state_terminal() -> &'static str {
1378 stringify!($($terminal)*)
1379 }
1380 fn state_data_names() -> Vec <Vec <&'static str>> {
1381 let mut v = Vec::new();
1382 $({
1383 let mut _w = Vec::new();
1384 $(_w.push (stringify!($data_name));)*
1385 v.push (_w);
1386 })+
1387 v
1388 }
1389 fn state_data_types() -> Vec <Vec <&'static str>> {
1390 let mut v = Vec::new();
1391 $({
1392 let mut _w = Vec::new();
1393 $(_w.push (stringify!($data_type));)*
1394 v.push (_w);
1395 })+
1396 v
1397 }
1398 fn state_data_defaults() -> Vec <Vec <&'static str>> {
1399 let mut v = Vec::new();
1400 $({
1401 let mut _w = Vec::new();
1402 $(
1403 _w.push ({
1404 let default_expr = stringify!($($data_default)*);
1405 if !default_expr.is_empty() {
1406 default_expr
1407 } else {
1408 concat!(stringify!($data_type), "::default()")
1409 }
1410 });
1411 )*
1412 v.push (_w);
1413 })+
1414 v
1415 }
1416 fn state_data_pretty_defaults() -> Vec <Vec <String>> {
1419 let mut v = Vec::new();
1420 $({
1421 let mut _w = Vec::new();
1422 $(
1423 let default_val : $data_type
1424 = $crate::def_machine_debug!(@expr_default $($data_default)*);
1425 _w.push (format!("{:#?}", default_val));
1426 )*
1427 v.push (_w);
1428 })+
1429 v
1430 }
1431 fn events() -> Vec <&'static str> {
1432 vec![$(stringify!($event)),*]
1433 }
1434 fn event_sources() -> Vec <&'static str> {
1435 vec![$(stringify!($source)),*]
1436 }
1437 fn event_targets() -> Vec <&'static str> {
1438 vec![$(stringify!($($target)*)),*]
1439 }
1440 fn event_actions() -> Vec <&'static str> {
1441 vec![$(stringify!($($action)*)),*]
1442 }
1443 } impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
1446 $($(
1447 $type_var : std::fmt::Debug,
1448 $($($type_var : $type_constraint),+)*
1449 ),+)*
1450 {
1451 pub fn initial() -> Self {
1452 Self {
1453 $($ext_name: $crate::def_machine_debug!(@expr_default $($ext_default)*)),*
1454 }
1455 }
1456
1457 pub fn new ($($ext_name : Option <$ext_type>),*) -> Self {
1459 Self {
1460 $($ext_name: $ext_name.unwrap_or (
1461 $crate::def_machine_debug!(@expr_default $($ext_default)*))
1462 ),*
1463 }
1464 }
1465 }
1466
1467 impl <'event> From <EventId> for Event <'event> {
1468 fn from (id : EventId) -> Self {
1470 let _params = id.clone().into();
1471 Event { id, params: _params }
1472 }
1473 }
1474
1475 impl <'event> From <EventId> for EventParams <'event> {
1476 fn from (id : EventId) -> Self {
1477 match id {
1478 $(EventId::$event => EventParams::$event {
1479 $($param_name:
1480 $crate::def_machine_debug!(@expr_default $($param_default)*)
1481 ),*
1482 }),*
1483 }
1484 }
1485 }
1486
1487 };
1488 ( $machine:ident
1494 $(<$(
1495 $type_var:ident $(: { $($type_constraint:path),+ })*
1496 ),+>)*
1497 $(($(
1498 $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
1499 ),*))*
1500 $(@ $self_reference:ident)*
1501 {
1502 STATES [
1503 $(state $state:ident (
1504 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1505 ) $({
1506 $(entry $entry:block)*
1507 $(exit $exit:block)*
1508 })*)+
1509 ]
1510 EVENTS [
1511 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1512 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1513 $({ $($state_data:ident),* } => $action:block)*
1514 )*
1515 ]
1516 initial_state: $initial:ident $({
1517 $(initial_action: $initial_action:block)*
1518 })*
1519 $(terminal_state: $terminal:ident $({
1520 $(terminate_success: $terminate_success:block)*
1521 $(terminate_failure: $terminate_failure:block)*
1522 })*)*
1523 }
1524
1525 ) => {
1526
1527 $crate::def_machine_debug!{
1528 machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
1529 STATES [
1530 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
1531 $({
1532 $(entry $entry)*
1533 $(exit $exit)*
1534 })*)+
1535 ]
1536 EVENTS [
1537 $(event $event <$source> $(=> <$target>)*
1538 ($($param_name : $param_type $(= $param_default)*),*)
1539 $({$($state_data),*} => $action)*
1540 )*
1541 ]
1542 EXTENDED [
1543 $($($ext_name : $ext_type $(= $ext_default)*),*)*
1544 ]
1545 $(self_reference: $self_reference)*
1546 initial_state: $initial $({
1547 $(initial_action: $initial_action)*
1548 })*
1549 $(terminal_state: $terminal $({
1550 $(terminate_success: $terminate_success)*
1551 $(terminate_failure: $terminate_failure)*
1552 })*)*
1553 }
1554 }
1555
1556 };
1557
1558 ( @impl_fn_handle_event
1562 machine $machine:ident {
1563 EVENTS [
1564 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1565 ($($param_name:ident),*)
1566 $({ $($state_data:ident),* } => $action:block)*
1567 )*
1568 ]
1569 EXTENDED [
1570 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
1571 ]
1572 $(self_reference: $self_reference:ident)*
1573 }
1574
1575 ) => {
1576
1577 pub fn handle_event (&mut self, mut _event : Event)
1578 -> Result <(), $crate::HandleEventException>
1579 {
1580 #[allow(unreachable_code)]
1583 match _event.transition() {
1584 Transition::Universal (target_id) => {
1585 $crate::log::debug!(
1586 machine=stringify!($machine), state:?=self.state.id,
1587 event:?=_event.id, transition="Universal", target:?=target_id;
1588 "handle state machine event");
1589 self.state_exit();
1590 { #[allow(unused_variables)]
1593 match &mut self.extended_state {
1594 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
1595 match _event.params {
1597 $(EventParams::$event { $(mut $param_name,)*.. } => {
1598 $crate::def_machine_debug!{
1600 @event_action_universal
1601 event $event <$source> $(=> <$target>)* $($action)*
1602 }
1603 })*
1604 _ => unreachable!("unreachable phantom data variant")
1605 }
1606 }
1607 }
1608 }
1609 let state = target_id.to_state (&mut self.extended_state);
1610 self.state = state;
1611 self.state_entry();
1612 Ok (())
1613 }
1614 Transition::Internal (source_id) => {
1615 if self.state.id == source_id {
1616 $crate::log::debug!(
1617 machine=stringify!($machine), state:?=self.state.id,
1618 event:?=_event.id, transition="Internal", source:?=source_id;
1619 "handle state machine event");
1620 #[allow(unused_variables)]
1622 match &mut self.extended_state {
1623 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
1624 match _event.params {
1626 $(EventParams::$event { $(mut $param_name,)*.. } => {
1627 #[allow(unreachable_patterns)]
1632 match &mut self.state.data {
1633 $crate::def_machine_debug!{
1634 @event_internal_state_pattern
1635 $source { $($($state_data),*)* }
1636 } => {
1637 $crate::def_machine_debug!{
1639 @event_action_internal
1640 event $event <$source> $(=> <$target>)* $($action)*
1641 }
1642 }
1643 _ => unreachable!("current state should match event source")
1644 }
1645 })*
1646 _ => unreachable!("unreachable phantom data variant")
1647 }
1648 }
1649 }
1650 Ok (())
1651 } else {
1652 let exception = $crate::HandleEventException::WrongState;
1653 $crate::log::warn!(
1654 machine=stringify!($machine), state:?=self.state.id,
1655 event:?=_event.id, transition="Internal", source:?=source_id,
1656 exception:?;
1657 "handle state machine event exception");
1658 Err (exception)
1659 }
1660 }
1661 Transition::External (source_id, target_id) => {
1662 if self.state.id == source_id {
1663 $crate::log::debug!(
1664 machine=stringify!($machine), state:?=self.state.id,
1665 event:?=_event.id, transition="External", source:?=source_id,
1666 target:?=target_id;
1667 "handle state machine event");
1668 self.state_exit();
1669 { #[allow(unused_variables)]
1672 match &mut self.extended_state {
1673 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
1674 match _event.params {
1676 $(EventParams::$event { $(mut $param_name,)*.. } => {
1677 $crate::def_machine_debug!{
1679 @event_action_external
1680 event $event <$source> $(=> <$target>)* $($action)*
1681 }
1682 })*
1683 _ => unreachable!("unreachable phantom data variant")
1684 }
1685 }
1686 }
1687 }
1688 let state = target_id.to_state (&mut self.extended_state);
1689 self.state = state;
1690 self.state_entry();
1691 Ok (())
1692 } else {
1693 let exception = $crate::HandleEventException::WrongState;
1694 $crate::log::warn!(
1695 machine=stringify!($machine), state:?=self.state.id,
1696 event:?=_event.id, transition="External", source:?=source_id,
1697 target:?=target_id, exception:?;
1698 "handle state machine event exception");
1699 Err ($crate::HandleEventException::WrongState)
1700 }
1701 }
1702 }
1703 } }; ( @event_internal_state_pattern
1711 $source:ident { $($state_data:ident),* }
1712 ) => {
1713 &mut StateData::$source {$(ref mut $state_data,)*..}
1714 };
1715
1716 ( @event_internal_state_pattern
1720 * { $($state_data:ident),* }
1721 ) => {
1722 _
1723 };
1724
1725 ( @event_action_external
1729 event $event:ident <$source:ident> => <$target:ident> $($action:block)*
1730 ) => {
1731 $($action)*
1732 };
1733
1734 ( @event_action_external
1738 event $event:ident <$source:tt> $($action:block)*
1739 ) => { unreachable!("not an external event") };
1740
1741 ( @event_action_external
1745 event $event:ident <*> => <$target:ident> $($action:block)*
1746 ) => { unreachable!("not an external event") };
1747
1748 ( @event_action_universal
1752 event $event:ident <*> => <$target:ident> $($action:block)*
1753 ) => {
1754 $($action)*
1755 };
1756
1757 ( @event_action_universal
1761 event $event:ident <$source:ident> $(=> <$target:ident>)* $($action:block)*
1762 ) => { unreachable!("not an universal event") };
1763
1764 ( @event_action_internal
1768 event $event:ident <$source:ident> $($action:block)*
1769 ) => {
1770 $($action)*
1771 };
1772
1773 ( @event_action_internal
1777 event $event:ident <$source:tt> => <$target:ident> $($action:block)*
1778 ) => { unreachable!("not an internal event") };
1779
1780 ( @event_transition <$source:ident> => <$target:ident> ) => {
1784 Transition::External (StateId::$source, StateId::$target)
1785 };
1786
1787 ( @event_transition <$source:ident> ) => {
1791 Transition::Internal (StateId::$source)
1792 };
1793
1794 ( @event_transition <*> => <$target:ident> ) => {
1798 Transition::Universal (StateId::$target)
1799 };
1800
1801 ( @expr_default $default:expr ) => { $default };
1805
1806 ( @expr_default ) => { Default::default() };
1810
1811 ( @expr_option $default:expr ) => { Some ($default) };
1815
1816 ( @expr_option ) => { None };
1820
1821 ( @base
1825 machine $machine:ident
1826 $(<$(
1827 $type_var:ident $(: { $($type_constraint:path),+ })*
1828 ),+>)*
1829 {
1830 STATES [
1831 $(state $state:ident (
1832 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1833 ) $({
1834 $(entry $entry:block)*
1835 $(exit $exit:block)*
1836 })*)+
1837 ]
1838 EVENTS [
1839 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1840 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1841 $({ $($state_data:ident),* } => $action:block)*
1842 )*
1843 ]
1844 EXTENDED [
1845 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
1846 ]
1847 $(self_reference: $self_reference:ident)*
1848 initial_state: $initial:ident $({
1849 $(initial_action: $initial_action:block)*
1850 })*
1851 $(terminal_state: $terminal:ident $({
1852 $(terminate_success: $terminate_success:block)*
1853 $(terminate_failure: $terminate_failure:block)*
1854 })*)*
1855 }
1856
1857 ) => {
1858
1859 #[derive(Debug)]
1860 pub struct $machine $(<$($type_var),+>)* where
1861 $($(
1862 $type_var : std::fmt::Debug,
1863 $($($type_var : $type_constraint),+)*
1864 ),+)*
1865 {
1866 state : State,
1867 extended_state : ExtendedState $(<$($type_var),+>)*
1868 }
1869
1870 #[derive(Debug)]
1871 pub struct State {
1872 id : StateId,
1873 data : StateData
1874 }
1875
1876 #[derive(Debug)]
1877 pub struct ExtendedState $(<$($type_var),+>)* where
1878 $($(
1879 $type_var : std::fmt::Debug,
1880 $($($type_var : $type_constraint),+)*
1881 ),+)*
1882 {
1883 $(pub $ext_name : $ext_type),*
1884 }
1885
1886 #[derive(Debug)]
1887 pub struct Event <'event> {
1888 id : EventId,
1889 params : EventParams <'event>
1890 }
1891
1892 #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
1893 pub enum StateId {
1894 $($state),+
1895 }
1896
1897 #[derive(Debug)]
1898 pub enum StateData {
1899 $($state {
1900 $($data_name : $data_type),*
1901 }),+
1902 }
1903
1904 #[derive(Debug, Eq, PartialEq)]
1905 pub enum Transition {
1906 Internal (StateId),
1907 External (StateId, StateId),
1908 Universal (StateId)
1909 }
1910
1911 #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
1912 pub enum EventId {
1913 $($event),*
1914 }
1915
1916 #[derive(Debug)]
1917 pub enum EventParams <'event> {
1918 $($event {
1919 $($param_name : $param_type),*
1920 },)*
1921 _PhantomData (::std::marker::PhantomData <&'event ()>)
1922 }
1923
1924 impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
1925 $($(
1926 $type_var : std::fmt::Debug,
1927 $($($type_var : $type_constraint),+)*
1928 ),+)*
1929 {
1930 pub fn report_sizes() where $($($type_var : 'static),+)* {
1931 let machine_name = stringify!($machine);
1932 let machine_type = std::any::type_name::<Self>();
1933 println!("{} report sizes...", machine_name);
1934 println!(" size of {}: {}", machine_type, std::mem::size_of::<Self>());
1935 println!("...{} report sizes", machine_name);
1936 }
1937
1938 pub fn new (mut extended_state : ExtendedState $(<$($type_var),+>)*)
1939 -> Self
1940 {
1941 let state = StateId::$initial.to_state (&mut extended_state);
1942 let mut new = Self { state, extended_state };
1943 {
1944 $(#[allow(unused_variables)]
1945 let $self_reference = &mut new;)*
1946 $($($initial_action)*)*
1947 }
1948 new.state_entry();
1949 new
1950 }
1951
1952 #[allow(dead_code)]
1953 #[inline]
1954 pub fn state (&self) -> &State {
1955 &self.state
1956 }
1957
1958 #[allow(dead_code)]
1959 #[inline]
1960 pub fn state_id (&self) -> StateId {
1961 self.state().id().clone()
1962 }
1963
1964 #[allow(dead_code)]
1965 #[inline]
1966 pub fn state_data (&self) -> &StateData {
1967 self.state().data()
1968 }
1969
1970 #[allow(dead_code)]
1971 #[inline]
1972 pub fn extended_state (&self) -> &ExtendedState $(<$($type_var),+>)* {
1973 &self.extended_state
1974 }
1975
1976 #[allow(dead_code)]
1977 #[inline]
1978 pub fn extended_state_mut (&mut self)
1979 -> &mut ExtendedState $(<$($type_var),+>)*
1980 {
1981 &mut self.extended_state
1982 }
1983
1984 $crate::def_machine_debug!{
1985 @impl_fn_handle_event
1986 machine $machine {
1987 EVENTS [
1988 $(event $event <$source> $(=> <$target>)*
1989 ($($param_name),*)
1990 $({$($state_data),*} => $action)*
1991 )*
1992 ]
1993 EXTENDED [
1994 $($ext_name : $ext_type $(= $ext_default)*),*
1995 ]
1996 $(self_reference: $self_reference)*
1997 }
1998 }
1999
2000 fn state_entry (&mut self) {
2001 #[allow(unused_variables)]
2003 match &mut self.extended_state {
2004 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
2005 match self.state.data {
2006 $(StateData::$state { $(ref mut $data_name,)*.. } => {
2008 $($($entry)*)*
2009 })+
2010 }
2011 }
2012 }
2013 }
2014 fn state_exit (&mut self) {
2015 #[allow(unused_variables)]
2017 match &mut self.extended_state {
2018 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
2019 match self.state.data {
2020 $(StateData::$state { $(ref mut $data_name,)*.. } => {
2022 $($($exit)*)*
2023 })+
2024 }
2025 }
2026 }
2027 }
2028
2029 } impl $(<$($type_var),+>)* AsRef <ExtendedState $(<$($type_var),+>)*>
2032 for $machine $(<$($type_var),+>)*
2033 where
2034 $($(
2035 $type_var : std::fmt::Debug,
2036 $($($type_var : $type_constraint),+)*
2037 ),+)*
2038 {
2039 #[inline]
2040 fn as_ref (&self) -> &ExtendedState $(<$($type_var),+>)* {
2041 &self.extended_state
2042 }
2043 }
2044
2045 impl $(<$($type_var),+>)* AsMut <ExtendedState $(<$($type_var),+>)*>
2046 for $machine $(<$($type_var),+>)*
2047 where
2048 $($(
2049 $type_var : std::fmt::Debug,
2050 $($($type_var : $type_constraint),+)*
2051 ),+)*
2052 {
2053 #[inline]
2054 fn as_mut (&mut self) -> &mut ExtendedState $(<$($type_var),+>)* {
2055 &mut self.extended_state
2056 }
2057 }
2058
2059 impl $(<$($type_var),+>)* Drop for $machine $(<$($type_var),+>)* where
2060 $($(
2061 $type_var : std::fmt::Debug,
2062 $($($type_var : $type_constraint),+)*
2063 ),+)*
2064 {
2065 fn drop (&mut self) {
2066 self.state_exit();
2067 let _state_id = self.state.id.clone();
2068 $(#[allow(unused_variables)]
2069 let $self_reference = &mut *self;)*
2070 $(
2071 if _state_id != StateId::$terminal {
2072 $crate::log::warn!(
2073 machine=stringify!($machine), state:?=_state_id,
2074 terminal:?=StateId::$terminal;
2075 "terminate state machine failure: not in terminal state");
2076 $($($terminate_failure)*)*
2077 } else {
2078 $crate::log::debug!(
2079 machine=stringify!($machine), state:?=_state_id;
2080 "terminate state machine success");
2081 $($($terminate_success)*)*
2082 }
2083 )*
2084 }
2085 }
2086
2087 impl State {
2088 #[inline]
2089 pub fn id (&self) -> &StateId {
2090 &self.id
2091 }
2092
2093 #[inline]
2094 pub fn data (&self) -> &StateData {
2095 &self.data
2096 }
2097 }
2098
2099 impl StateId {
2100 #[inline]
2101 pub const fn initial() -> Self {
2102 StateId::$initial
2103 }
2104 $(
2105 #[inline]
2106 pub const fn terminal() -> Self {
2107 StateId::$terminal
2108 }
2109 )*
2110 #[expect(clippy::wrong_self_convention)]
2111 pub fn to_state $(<$($type_var),+>)* (self,
2112 extended_state : &mut ExtendedState$(<$($type_var),+>)*) -> State
2113 where
2114 $($(
2115 $type_var : std::fmt::Debug,
2116 $($($type_var : $type_constraint),+)*
2117 ),+)*
2118 {
2119 #[allow(unused_variables)]
2121 match extended_state {
2122 &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
2123 match self {
2124 $(StateId::$state => {
2125 State {
2126 id: self,
2127 data: StateData::$state {
2128 $($data_name:
2129 $crate::def_machine_debug!(@expr_default $($data_default)*)
2130 ),*
2131 }
2132 }
2133 })+
2134 }
2135 }
2136 }
2137 }
2138 }
2139
2140 impl EventId {
2141 pub fn transition (&self) -> Transition {
2142 #[allow(clippy::uninhabited_references)]
2143 match *self {
2144 $(
2145 EventId::$event =>
2146 $crate::def_machine_debug!(@event_transition <$source> $(=> <$target>)*)
2147 ),*
2148 }
2149 }
2150 }
2151
2152 impl <'event> EventParams <'event> {
2153 pub fn id (&self) -> EventId {
2154 match *self {
2155 $(EventParams::$event {..} => EventId::$event,)*
2156 _ => unreachable!("unreachable phantom data variant")
2157 }
2158 }
2159 }
2160
2161 impl <'event> Event <'event> {
2162 #[inline]
2163 pub fn transition (&self) -> Transition {
2164 self.id.transition()
2165 }
2166
2167 #[inline]
2168 #[allow(clippy::uninhabited_references)]
2169 pub fn id (&self) -> &EventId {
2170 &self.id
2171 }
2172
2173 #[inline]
2174 #[expect(mismatched_lifetime_syntaxes)]
2175 pub fn params (&self) -> &EventParams {
2176 &self.params
2177 }
2178 }
2179
2180 impl <'event> From <EventParams <'event>> for Event <'event> {
2181 fn from (params : EventParams <'event>) -> Self {
2182 let _id = params.id();
2183 Event { id: _id, params }
2184 }
2185 }
2186
2187 }; } #[macro_export]
2193macro_rules! def_machine_nodefault_debug {
2194 ( machine $machine:ident
2198 $(<$(
2199 $type_var:ident $(: { $($type_constraint:path),+ })*
2200 ),+>)*
2201 {
2202 STATES [
2203 $(state $state:ident (
2204 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
2205 ) $({
2206 $(entry $entry:block)*
2207 $(exit $exit:block)*
2208 })*)+
2209 ]
2210 EVENTS [
2211 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
2212 ($($param_name:ident : $param_type:ty $(=> $param_default:expr)*),*)
2213 $({ $($state_data:ident),* } => $action:block)*
2214 )*
2215 ]
2216 EXTENDED [
2217 $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
2218 ]
2219 $(self_reference: $self_reference:ident)*
2220 initial_state: $initial:ident $({
2221 $(initial_action: $initial_action:block)*
2222 })*
2223 $(terminal_state: $terminal:ident $({
2224 $(terminate_success: $terminate_success:block)*
2225 $(terminate_failure: $terminate_failure:block)*
2226 })*)*
2227 }
2228
2229 ) => {
2230
2231 $crate::def_machine_debug!{
2232 @base
2233 machine $machine
2234 $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
2235 {
2236 STATES [
2237 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
2238 $({
2239 $(entry $entry)*
2240 $(exit $exit)*
2241 })*)+
2242 ]
2243 EVENTS [
2244 $(event $event <$source> $(=> <$target>)*
2245 ($($param_name : $param_type $(=> $param_default)*),*)
2246 $({$($state_data),*} => $action)*
2247 )*
2248 ]
2249 EXTENDED [
2250 $($ext_name : $ext_type $(= $ext_default)*),*
2251 ]
2252 $(self_reference: $self_reference)*
2253 initial_state: $initial $({
2254 $(initial_action: $initial_action)*
2255 })*
2256 $(terminal_state: $terminal $({
2257 $(terminate_success: $terminate_success)*
2258 $(terminate_failure: $terminate_failure)*
2259 })*)*
2260 }
2261 }
2262
2263 impl $(<$($type_var),+>)* $crate::MachineDotfile
2264 for $machine $(<$($type_var),+>)*
2265 where
2266 $($(
2267 $type_var : std::fmt::Debug,
2268 $($($type_var : $type_constraint),+)*
2269 ),+)*
2270 {
2271 fn name() -> &'static str {
2272 stringify!($machine)
2273 }
2274 fn type_vars() -> Vec <String> {
2275 let mut _v = Vec::new();
2276 $($(
2277 _v.push (format!(
2278 "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
2279 )+)*
2280 _v
2281 }
2282 fn extended_state_names() -> Vec <&'static str> {
2283 vec![$(stringify!($ext_name)),*]
2284 }
2285 fn extended_state_types() -> Vec <&'static str> {
2286 vec![$(stringify!($ext_type)),*]
2287 }
2288 fn extended_state_defaults() -> Vec <&'static str> {
2289 vec![$(stringify!($($ext_default)*)),*]
2290 }
2291 fn self_reference() -> &'static str {
2292 stringify!($($self_reference)*)
2293 }
2294 fn states() -> Vec <&'static str> {
2295 vec![$(stringify!($state)),+]
2296 }
2297 fn state_initial() -> &'static str {
2298 stringify!($initial)
2299 }
2300 fn state_terminal() -> &'static str {
2301 stringify!($($terminal)*)
2302 }
2303 fn state_data_names() -> Vec <Vec <&'static str>> {
2304 let mut v = Vec::new();
2305 $({
2306 let mut _w = Vec::new();
2307 $(_w.push (stringify!($data_name));)*
2308 v.push (_w);
2309 })+
2310 v
2311 }
2312 fn state_data_types() -> Vec <Vec <&'static str>> {
2313 let mut v = Vec::new();
2314 $({
2315 let mut _w = Vec::new();
2316 $(_w.push (stringify!($data_type));)*
2317 v.push (_w);
2318 })+
2319 v
2320 }
2321 fn state_data_defaults() -> Vec <Vec <&'static str>> {
2322 let mut v = Vec::new();
2323 $({
2324 let mut _w = Vec::new();
2325 $(_w.push (stringify!($($data_default)*));)*
2326 v.push (_w);
2327 })+
2328 v
2329 }
2330 fn state_data_pretty_defaults() -> Vec <Vec <String>> {
2332 let mut v = Vec::new();
2333 $({
2334 let mut _w = Vec::new();
2335 $(
2336 _w.push (format!("{:#?}", stringify!($($data_default)*)));
2337 )*
2338 v.push (_w);
2339 })+
2340 v
2341 }
2342
2343 fn events() -> Vec <&'static str> {
2344 vec![$(stringify!($event)),*]
2345 }
2346 fn event_sources() -> Vec <&'static str> {
2347 vec![$(stringify!($source)),*]
2348 }
2349 fn event_targets() -> Vec <&'static str> {
2350 vec![$(stringify!($($target)*)),*]
2351 }
2352 fn event_actions() -> Vec <&'static str> {
2353 vec![$(stringify!($($action)*)),*]
2354 }
2355 }
2356
2357 impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
2358 $($(
2359 $type_var : std::fmt::Debug,
2360 $($($type_var : $type_constraint),+)*
2361 ),+)*
2362 {
2363 pub fn new ($($ext_name : Option <$ext_type>),*) -> Option <Self> {
2368 Some (Self {
2369 $($ext_name: {
2370 if let Some ($ext_name) = $ext_name {
2371 $ext_name
2372 } else {
2373 $crate::def_machine_debug!(@expr_option $($ext_default)*)?
2374 }
2375 }),*
2376 })
2377 }
2378 }
2379
2380 };
2381
2382 ( $machine:ident
2386 $(<$(
2387 $type_var:ident $(: { $($type_constraint:path),+ })*
2388 ),+>)*
2389 $(($(
2390 $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
2391 ),*))*
2392 $(@ $self_reference:ident)*
2393 {
2394 STATES [
2395 $(state $state:ident (
2396 $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
2397 ) $({
2398 $(entry $entry:block)*
2399 $(exit $exit:block)*
2400 })*)+
2401 ]
2402 EVENTS [
2403 $(event $event:ident <$source:tt> $(=> <$target:ident>)*
2404 ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
2405 $({ $($state_data:ident),* } => $action:block)*
2406 )*
2407 ]
2408 initial_state: $initial:ident $({
2409 $(initial_action: $initial_action:block)*
2410 })*
2411 $(terminal_state: $terminal:ident $({
2412 $(terminate_success: $terminate_success:block)*
2413 $(terminate_failure: $terminate_failure:block)*
2414 })*)*
2415 }
2416
2417 ) => {
2418
2419 $crate::def_machine_nodefault_debug!{
2420 machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
2421 STATES [
2422 $(state $state ($($data_name : $data_type $(= $data_default)*),*)
2423 $({
2424 $(entry $entry)*
2425 $(exit $exit)*
2426 })*)+
2427 ]
2428 EVENTS [
2429 $(event $event <$source> $(=> <$target>)*
2430 ($($param_name : $param_type $(= $param_default)*),*)
2431 $({$($state_data),*} => $action)*
2432 )*
2433 ]
2434 EXTENDED [
2435 $($($ext_name : $ext_type $(= $ext_default)*),*)*
2436 ]
2437 $(self_reference: $self_reference)*
2438 initial_state: $initial $({
2439 $(initial_action: $initial_action)*
2440 })*
2441 $(terminal_state: $terminal $({
2442 $(terminate_success: $terminate_success)*
2443 $(terminate_failure: $terminate_failure)*
2444 })*)*
2445 }
2446 }
2447
2448 };
2449
2450}