Finite state machines in rust; bendns fork to add types.
lt generics
bendn 4 months ago
parent c2775b8 · commit 45fd897
-rw-r--r--rust-fsm-dsl/src/lib.rs16
-rw-r--r--rust-fsm-dsl/src/parser.rs25
-rw-r--r--rust-fsm/src/lib.rs14
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 }) => (