Finite state machines in rust; bendns fork to add types.
lt generics
| -rw-r--r-- | rust-fsm-dsl/src/lib.rs | 16 | ||||
| -rw-r--r-- | rust-fsm-dsl/src/parser.rs | 25 | ||||
| -rw-r--r-- | rust-fsm/src/lib.rs | 14 |
3 files changed, 33 insertions, 22 deletions
diff --git a/rust-fsm-dsl/src/lib.rs b/rust-fsm-dsl/src/lib.rs index 40a487d..d73e0a2 100644 --- a/rust-fsm-dsl/src/lib.rs +++ b/rust-fsm-dsl/src/lib.rs @@ -166,12 +166,12 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream { .replace("Default", "def") .parse() .unwrap(); - + let input_generics = input_name.g(); let input_impl = variant::tokenize(&inputs, |x| { input_name.tokenize(|f| { quote! { #attrs - #visibility enum #f { + #visibility enum #f #input_generics { #(#x),* } } @@ -182,7 +182,7 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream { state_name.tokenize(|f| { quote! { #attrs - #visibility enum #f { + #visibility enum #f { #(#x),* } } @@ -226,12 +226,12 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream { #output_impl impl ::rust_fsm::StateMachine for #state_name { - type Input = #input_name; - type Output = #output_name; + type Input<'i> = #input_name #input_generics; + type Output<'o> = #output_name; - fn transition(self, input: Self::Input) -> ::core::result::Result< - (Self, ::core::option::Option<Self::Output>), - ::rust_fsm::TransitionImpossibleError<Self, Self::Input> + fn transition(self, input: Self::Input<'_>) -> ::core::result::Result< + (Self, ::core::option::Option<Self::Output<'_>>), + ::rust_fsm::TransitionImpossibleError<Self, Self::Input<'_>> > { match (self, input) { #(#transition_cases)* diff --git a/rust-fsm-dsl/src/parser.rs b/rust-fsm-dsl/src/parser.rs index 63dc9c0..869772d 100644 --- a/rust-fsm-dsl/src/parser.rs +++ b/rust-fsm-dsl/src/parser.rs @@ -127,21 +127,27 @@ pub struct StateMachineDef { } pub enum ImplementationRequired { - Yes(Type), + Yes(Ident, Generics), No(Path), } impl ImplementationRequired { - pub fn tokenize(&self, f: impl Fn(&Type) -> TokenStream) -> TokenStream { + pub fn tokenize(&self, f: impl Fn(&Ident) -> TokenStream) -> TokenStream { match self { - ImplementationRequired::Yes(ident) => f(ident), + ImplementationRequired::Yes(ident, _) => f(ident), ImplementationRequired::No(_) => TokenStream::default(), } } - pub fn path(self) -> TokenStream { + pub fn g(&self) -> TokenStream { match self { - ImplementationRequired::Yes(ident) => quote::quote! { #ident }, - ImplementationRequired::No(path) => quote::quote! { #path }, + ImplementationRequired::Yes(_, g) => quote::quote! {#g}, + ImplementationRequired::No(_) => TokenStream::default(), + } + } + pub fn path(self) -> Path { + match self { + ImplementationRequired::Yes(ident, _) => ident.into(), + ImplementationRequired::No(path) => path, } } } @@ -171,7 +177,12 @@ impl Parse for StateMachineDef { ImplementationRequired::No(x) }) }) - .unwrap_or_else(|| input.parse::<Type>().map(ImplementationRequired::Yes)) + .unwrap_or_else(|| { + let t = input.parse::<Ident>()?; + let g = input.parse::<Generics>()?; + dbg!(&g); + Ok(ImplementationRequired::Yes(t, g)) + }) }; let state_name = i()?; input.parse::<Token![=>]>()?; diff --git a/rust-fsm/src/lib.rs b/rust-fsm/src/lib.rs index 907e967..0dd44fc 100644 --- a/rust-fsm/src/lib.rs +++ b/rust-fsm/src/lib.rs @@ -229,9 +229,9 @@ pub use aquamarine::aquamarine; /// this library for more practical things. pub trait StateMachine: Sized { /// The input alphabet. - type Input; + type Input<'i>; /// The output alphabet. - type Output; + type Output<'o>; /// The transition fuction that outputs a new state based on the current /// state and the provided input. Outputs [`Err`] (allowing recovery of the state and input) /// when there is no transition for a given combination of the input and the state. @@ -240,17 +240,17 @@ pub trait StateMachine: Sized { /// This function is discouraged from panicking. fn transition( self, - input: Self::Input, - ) -> Result<(Self, Option<Self::Output>), TransitionImpossibleError<Self, Self::Input>>; + input: Self::Input<'_>, + ) -> Result<(Self, Option<Self::Output<'_>>), TransitionImpossibleError<Self, Self::Input<'_>>>; /// Consumes the provided input, gives an output and performs a state /// transition. If a state transition with the current state and the /// provided input is not allowed, returns an error containing the input. /// /// Aborts if `transition` panics. - fn consume( + fn consume<'l>( &mut self, - input: Self::Input, - ) -> Result<Option<Self::Output>, TransitionImpossibleError_<Self, Self::Input>> { + input: Self::Input<'l>, + ) -> Result<Option<Self::Output<'l>>, TransitionImpossibleError_<Self, Self::Input<'l>>> { replace_with_or_abort_and_return(self, |x| match x.transition(input) { Ok((state, ret)) => (Ok(ret), state), Err(TransitionImpossibleError { state, input }) => ( |