@@ -10,6 +10,50 @@ pub trait MachineIntrospection {
1010 const GRAPH : & ' static MachineGraph < Self :: StateId , Self :: TransitionId > ;
1111}
1212
13+ /// Runtime accessor for transition descriptors that may be supplied by a
14+ /// distributed registration surface.
15+ #[ derive( Clone , Copy ) ]
16+ pub struct TransitionInventory < S : ' static , T : ' static > {
17+ get : fn ( ) -> & ' static [ TransitionDescriptor < S , T > ] ,
18+ }
19+
20+ impl < S , T > TransitionInventory < S , T > {
21+ /// Creates a transition inventory from a `'static` getter.
22+ pub const fn new ( get : fn ( ) -> & ' static [ TransitionDescriptor < S , T > ] ) -> Self {
23+ Self { get }
24+ }
25+
26+ /// Returns the transition descriptors as a slice.
27+ pub fn as_slice ( & self ) -> & ' static [ TransitionDescriptor < S , T > ] {
28+ ( self . get ) ( )
29+ }
30+ }
31+
32+ impl < S , T > core:: ops:: Deref for TransitionInventory < S , T > {
33+ type Target = [ TransitionDescriptor < S , T > ] ;
34+
35+ fn deref ( & self ) -> & Self :: Target {
36+ self . as_slice ( )
37+ }
38+ }
39+
40+ impl < S , T > core:: fmt:: Debug for TransitionInventory < S , T > {
41+ fn fmt (
42+ & self ,
43+ formatter : & mut core:: fmt:: Formatter < ' _ > ,
44+ ) -> core:: result:: Result < ( ) , core:: fmt:: Error > {
45+ formatter. debug_tuple ( "TransitionInventory" ) . finish ( )
46+ }
47+ }
48+
49+ impl < S , T > core:: cmp:: PartialEq for TransitionInventory < S , T > {
50+ fn eq ( & self , other : & Self ) -> bool {
51+ core:: ptr:: eq ( self . as_slice ( ) , other. as_slice ( ) )
52+ }
53+ }
54+
55+ impl < S , T > core:: cmp:: Eq for TransitionInventory < S , T > { }
56+
1357/// Identity for one concrete machine state.
1458pub trait MachineStateIdentity : MachineIntrospection {
1559 /// The state id for this concrete machine instantiation.
@@ -204,7 +248,7 @@ pub struct MachineGraph<S: 'static, T: 'static> {
204248 /// All states known to the machine.
205249 pub states : & ' static [ StateDescriptor < S > ] ,
206250 /// All transition sites known to the machine.
207- pub transitions : & ' static [ TransitionDescriptor < S , T > ] ,
251+ pub transitions : TransitionInventory < S , T > ,
208252}
209253
210254impl < S , T > MachineGraph < S , T >
@@ -300,7 +344,7 @@ mod tests {
300344 MachineDescriptor , MachineGraph , MachineIntrospection , MachinePresentation ,
301345 MachinePresentationDescriptor , MachineStateIdentity , MachineTransitionRecorder ,
302346 RecordedTransition , StateDescriptor , StatePresentation , TransitionDescriptor ,
303- TransitionPresentation ,
347+ TransitionInventory , TransitionPresentation ,
304348 } ;
305349 use core:: marker:: PhantomData ;
306350
@@ -311,14 +355,47 @@ mod tests {
311355 Published ,
312356 }
313357
314- #[ derive( Clone , Copy , Debug , Eq , PartialEq , Hash ) ]
315- enum TransitionId {
316- SubmitFromDraft ,
317- PublishFromReview ,
358+ #[ derive( Clone , Copy ) ]
359+ struct TransitionId ( & ' static crate :: __private:: TransitionToken ) ;
360+
361+ impl TransitionId {
362+ const fn from_token ( token : & ' static crate :: __private:: TransitionToken ) -> Self {
363+ Self ( token)
364+ }
365+ }
366+
367+ impl core:: fmt:: Debug for TransitionId {
368+ fn fmt (
369+ & self ,
370+ formatter : & mut core:: fmt:: Formatter < ' _ > ,
371+ ) -> core:: result:: Result < ( ) , core:: fmt:: Error > {
372+ formatter. write_str ( "TransitionId(..)" )
373+ }
374+ }
375+
376+ impl core:: cmp:: PartialEq for TransitionId {
377+ fn eq ( & self , other : & Self ) -> bool {
378+ core:: ptr:: eq ( self . 0 , other. 0 )
379+ }
380+ }
381+
382+ impl core:: cmp:: Eq for TransitionId { }
383+
384+ impl core:: hash:: Hash for TransitionId {
385+ fn hash < H : core:: hash:: Hasher > ( & self , state : & mut H ) {
386+ let ptr = core:: ptr:: from_ref ( self . 0 ) as usize ;
387+ <usize as core:: hash:: Hash >:: hash ( & ptr, state) ;
388+ }
318389 }
319390
320391 static REVIEW_TARGETS : [ StateId ; 1 ] = [ StateId :: Review ] ;
321392 static PUBLISH_TARGETS : [ StateId ; 1 ] = [ StateId :: Published ] ;
393+ static SUBMIT_FROM_DRAFT_TOKEN : crate :: __private:: TransitionToken =
394+ crate :: __private:: TransitionToken :: new ( ) ;
395+ static PUBLISH_FROM_REVIEW_TOKEN : crate :: __private:: TransitionToken =
396+ crate :: __private:: TransitionToken :: new ( ) ;
397+ const SUBMIT_FROM_DRAFT : TransitionId = TransitionId :: from_token ( & SUBMIT_FROM_DRAFT_TOKEN ) ;
398+ const PUBLISH_FROM_REVIEW : TransitionId = TransitionId :: from_token ( & PUBLISH_FROM_REVIEW_TOKEN ) ;
322399 static STATES : [ StateDescriptor < StateId > ; 3 ] = [
323400 StateDescriptor {
324401 id : StateId :: Draft ,
@@ -338,13 +415,13 @@ mod tests {
338415 ] ;
339416 static TRANSITIONS : [ TransitionDescriptor < StateId , TransitionId > ; 2 ] = [
340417 TransitionDescriptor {
341- id : TransitionId :: SubmitFromDraft ,
418+ id : SUBMIT_FROM_DRAFT ,
342419 method_name : "submit" ,
343420 from : StateId :: Draft ,
344421 to : & REVIEW_TARGETS ,
345422 } ,
346423 TransitionDescriptor {
347- id : TransitionId :: PublishFromReview ,
424+ id : PUBLISH_FROM_REVIEW ,
348425 method_name : "publish" ,
349426 from : StateId :: Review ,
350427 to : & PUBLISH_TARGETS ,
@@ -425,7 +502,7 @@ mod tests {
425502 ] ,
426503 transitions : & [
427504 TransitionPresentation {
428- id : TransitionId :: SubmitFromDraft ,
505+ id : SUBMIT_FROM_DRAFT ,
429506 label : Some ( "Submit" ) ,
430507 description : Some ( "Move work into review." ) ,
431508 metadata : TransitionMeta {
@@ -434,7 +511,7 @@ mod tests {
434511 } ,
435512 } ,
436513 TransitionPresentation {
437- id : TransitionId :: PublishFromReview ,
514+ id : PUBLISH_FROM_REVIEW ,
438515 label : Some ( "Publish" ) ,
439516 description : Some ( "Complete the workflow." ) ,
440517 metadata : TransitionMeta {
@@ -455,7 +532,7 @@ mod tests {
455532 rust_type_path : "workflow::Machine" ,
456533 } ,
457534 states : & STATES ,
458- transitions : & TRANSITIONS ,
535+ transitions : TransitionInventory :: new ( || & TRANSITIONS ) ,
459536 } ;
460537 }
461538
@@ -479,7 +556,7 @@ mod tests {
479556 rust_type_path : "workflow::Machine" ,
480557 } ,
481558 states : & STATES ,
482- transitions : & TRANSITIONS ,
559+ transitions : TransitionInventory :: new ( || & TRANSITIONS ) ,
483560 } ;
484561
485562 assert_eq ! (
@@ -488,18 +565,18 @@ mod tests {
488565 ) ;
489566 assert_eq ! (
490567 graph
491- . transition( TransitionId :: PublishFromReview )
568+ . transition( PUBLISH_FROM_REVIEW )
492569 . map( |transition| transition. method_name) ,
493570 Some ( "publish" )
494571 ) ;
495572 assert_eq ! (
496573 graph
497574 . transition_from_method( StateId :: Draft , "submit" )
498575 . map( |transition| transition. id) ,
499- Some ( TransitionId :: SubmitFromDraft )
576+ Some ( SUBMIT_FROM_DRAFT )
500577 ) ;
501578 assert_eq ! (
502- graph. legal_targets( TransitionId :: SubmitFromDraft ) ,
579+ graph. legal_targets( SUBMIT_FROM_DRAFT ) ,
503580 Some ( REVIEW_TARGETS . as_slice( ) )
504581 ) ;
505582 assert_eq ! ( graph. transitions_from( StateId :: Draft ) . count( ) , 1 ) ;
@@ -509,7 +586,7 @@ mod tests {
509586 #[ test]
510587 fn runtime_transition_recording_joins_back_to_static_graph ( ) {
511588 let event = Workflow :: < DraftMarker > :: try_record_transition_to :: < Workflow < ReviewMarker > > (
512- TransitionId :: SubmitFromDraft ,
589+ SUBMIT_FROM_DRAFT ,
513590 )
514591 . expect ( "valid runtime transition" ) ;
515592
@@ -521,7 +598,7 @@ mod tests {
521598 rust_type_path: "workflow::Machine" ,
522599 } ,
523600 StateId :: Draft ,
524- TransitionId :: SubmitFromDraft ,
601+ SUBMIT_FROM_DRAFT ,
525602 StateId :: Review ,
526603 )
527604 ) ;
@@ -544,13 +621,13 @@ mod tests {
544621 #[ test]
545622 fn runtime_transition_recording_rejects_illegal_target_or_site ( ) {
546623 assert ! ( Workflow :: <DraftMarker >:: try_record_transition(
547- TransitionId :: PublishFromReview ,
624+ PUBLISH_FROM_REVIEW ,
548625 StateId :: Published ,
549626 )
550627 . is_none( ) ) ;
551628 assert ! (
552629 Workflow :: <ReviewMarker >:: try_record_transition_to:: <Workflow <PublishedMarker >>(
553- TransitionId :: SubmitFromDraft ,
630+ SUBMIT_FROM_DRAFT ,
554631 )
555632 . is_none( )
556633 ) ;
@@ -559,7 +636,7 @@ mod tests {
559636 #[ test]
560637 fn presentation_queries_join_with_runtime_transitions ( ) {
561638 let event = Workflow :: < DraftMarker > :: try_record_transition_to :: < Workflow < ReviewMarker > > (
562- TransitionId :: SubmitFromDraft ,
639+ SUBMIT_FROM_DRAFT ,
563640 )
564641 . expect ( "valid runtime transition" ) ;
565642
@@ -576,7 +653,7 @@ mod tests {
576653 assert_eq ! (
577654 PRESENTATION . transition( event. transition) ,
578655 Some ( & TransitionPresentation {
579- id: TransitionId :: SubmitFromDraft ,
656+ id: SUBMIT_FROM_DRAFT ,
580657 label: Some ( "Submit" ) ,
581658 description: Some ( "Move work into review." ) ,
582659 metadata: TransitionMeta {
0 commit comments