Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ The association between states and their handlers is then expressed in the `Stat

```rust
impl statig::State<Blinky> for State {
fn call_handler(&mut self, blinky: &mut Blinky, event: &Event) -> Outcome<Self> {
fn call_handler(&mut self, blinky: &mut Blinky, event: &Event, context: &mut ()) -> Outcome<Self> {
match self {
State::LedOn { counter } => blinky.led_on(counter, event),
State::LedOff { counter } => blinky.led_off(counter, event),
Expand All @@ -379,7 +379,7 @@ impl statig::State<Blinky> for State {
}

impl statig::Superstate<Blinky> for Superstate {
fn call_handler(&mut self, blinky: &mut Blinky, event: &Event) -> Outcome<Self> {
fn call_handler(&mut self, blinky: &mut Blinky, event: &Event, context: &mut ()) -> Outcome<Self> {
match self {
Superstate::Blinking { counter } => blinky.blinking(counter, event),
}
Expand All @@ -394,15 +394,15 @@ impl statig::State<Blinky> for State {

...

fn call_entry_action(&mut self, blinky: &mut Blinky) {
fn call_entry_action(&mut self, blinky: &mut Blinky, context: &mut ()) {
match self {
State::LedOn { counter } => blinky.enter_led_on(counter),
State::LedOff { counter } => blinky.enter_led_off(counter),
State::NotBlinking => blinky.enter_not_blinking()
}
}

fn call_exit_action(&mut self, blinky: &mut Blinky) {
fn call_exit_action(&mut self, blinky: &mut Blinky, context: &mut ()) {
match self {
State::LedOn { counter } => blinky.exit_led_on(counter),
State::LedOff { counter } => blinky.exit_led_off(counter),
Expand All @@ -415,13 +415,13 @@ impl statig::Superstate<Blinky> for Superstate {

...

fn call_entry_action(&mut self, blinky: &mut Blinky) {
fn call_entry_action(&mut self, blinky: &mut Blinky, context: &mut ()) {
match self {
Superstate::Blinking { counter } => blinky.enter_blinking(counter),
}
}

fn call_exit_action(&mut self, blinky: &mut Blinky) {
fn call_exit_action(&mut self, blinky: &mut Blinky, context: &mut ()) {
match self {
Superstate::Blinking { counter } => blinky.exit_blinking(counter),
}
Expand Down Expand Up @@ -490,7 +490,9 @@ impl IntoStateMachine for Blinky {

type Context<'ctx> = Context;

const INITIAL: fn() -> State = || State::off(10);
fn initial() -> Self::State {
State::off(10)
}
}
```

Expand Down
3 changes: 3 additions & 0 deletions macro/src/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,9 @@ pub fn analyze_superstate(method: &ImplItemFn, state_machine: &StateMachine) ->
Err(_) => abort!(meta, "initial state must be an expression"),
}
} else if meta.path().is_ident("local_storage") {
if !local_storage.is_empty() {
abort!(meta, "duplicate `local_storage` item")
}
match meta.require_list().and_then(|list| {
Punctuated::<LitStr, Token![,]>::parse_terminated.parse2(list.tokens.clone())
}) {
Expand Down
24 changes: 16 additions & 8 deletions macro/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
event: &Self::Event<'_>,
context: &mut Self::Context<'_>,
) {
#before_dispatch(self, state_or_superstate, event, context);
use statig::blocking::DispatchHook;
#before_dispatch.call_dispatch_hook(self, state_or_superstate, event, context);
}
),
Mode::Awaitable => quote!(
Expand All @@ -79,7 +80,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
event: &Self::Event<'_>,
context: &mut Self::Context<'_>,
) -> impl core::future::Future<Output = ()> {
#before_dispatch(self, state_or_superstate, event, context)
use statig::awaitable::DispatchHook;
#before_dispatch.call_dispatch_hook(self, state_or_superstate, event, context)
}
),
},
Expand All @@ -95,7 +97,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
event: &Self::Event<'_>,
context: &mut Self::Context<'_>,
) {
#after_dispatch(self, state_or_superstate, event, context);
use statig::blocking::DispatchHook;
#after_dispatch.call_dispatch_hook(self, state_or_superstate, event, context);
}
),
Mode::Awaitable => quote!(
Expand All @@ -105,7 +108,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
event: &Self::Event<'_>,
context: &mut Self::Context<'_>,
) -> impl core::future::Future<Output = ()> {
#after_dispatch(self, state_or_superstate, event, context)
use statig::awaitable::DispatchHook;
#after_dispatch.call_dispatch_hook(self, state_or_superstate, event, context)
}
),
},
Expand All @@ -121,7 +125,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
target: &Self::State,
context: &mut Self::Context<'_>,
) {
#before_transition(self, source, target, context);
use statig::blocking::TransitionHook;
#before_transition.call_transition_hook(self, source, target, context);
}
),
Mode::Awaitable => quote!(
Expand All @@ -131,7 +136,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
target: &Self::State,
context: &mut Self::Context<'_>,
) -> impl core::future::Future<Output = ()> {
#before_transition(self, source, target, context)
use statig::awaitable::TransitionHook;
#before_transition.call_transition_hook(self, source, target, context)
}
),
},
Expand All @@ -147,7 +153,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
target: &Self::State,
context: &mut Self::Context<'_>,
) {
#after_transition(self, source, target, context);
use statig::blocking::TransitionHook;
#after_transition.call_transition_hook(self, source, target, context);
}
),
Mode::Awaitable => quote!(
Expand All @@ -157,7 +164,8 @@ fn codegen_state_machine_impl(ir: &Ir) -> ItemImpl {
target: &Self::State,
context: &mut Self::Context<'_>,
) -> impl core::future::Future<Output = ()> {
#after_transition(self, source, target, context)
use statig::awaitable::TransitionHook;
#after_transition.call_transition_hook(self, source, target, context)
}
),
},
Expand Down
97 changes: 96 additions & 1 deletion statig/src/awaitable/into_state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::future::{self, Future};

use crate::StateOrSuperstate;

/// Trait for transorming a type into a state machine.
/// Trait for transforming a type into a state machine.
pub trait IntoStateMachine
where
Self: Sized,
Expand Down Expand Up @@ -66,3 +66,98 @@ where
future::ready(())
}
}

pub trait DispatchHook<T, P>
where
T: IntoStateMachine,
{
fn call_dispatch_hook(
self,
shared_storage: &mut T,
state_or_superstate: StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
event: &T::Event<'_>,
context: &mut T::Context<'_>,
) -> impl Future<Output = ()>;
}

impl<T, F> DispatchHook<T, ((),)> for F
where
T: IntoStateMachine,
F: AsyncFnOnce(&mut T, StateOrSuperstate<'_, T::State, T::Superstate<'_>>, &T::Event<'_>),
{
fn call_dispatch_hook(
self,
shared_storage: &mut T,
state_or_superstate: StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
event: &T::Event<'_>,
_context: &mut T::Context<'_>,
) -> impl Future<Output = ()> {
(self)(shared_storage, state_or_superstate, event)
}
}

impl<T, F> DispatchHook<T, ((), ())> for F
where
T: IntoStateMachine,
F: AsyncFnOnce(
&mut T,
StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
&T::Event<'_>,
&mut T::Context<'_>,
),
{
fn call_dispatch_hook(
self,
shared_storage: &mut T,
state_or_superstate: StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
event: &T::Event<'_>,
context: &mut T::Context<'_>,
) -> impl Future<Output = ()> {
(self)(shared_storage, state_or_superstate, event, context)
}
}

pub trait TransitionHook<T, P>
where
T: IntoStateMachine,
{
fn call_transition_hook(
self,
shared_storage: &mut T,
source: &T::State,
target: &T::State,
context: &mut T::Context<'_>,
) -> impl Future<Output = ()>;
}

impl<T, F> TransitionHook<T, ((),)> for F
where
T: IntoStateMachine,
F: AsyncFnOnce(&mut T, &T::State, &T::State),
{
fn call_transition_hook(
self,
shared_storage: &mut T,
source: &T::State,
target: &T::State,
_context: &mut T::Context<'_>,
) -> impl Future<Output = ()> {
(self)(shared_storage, source, target)
}
}

impl<T, F> TransitionHook<T, ((), ())> for F
where
T: IntoStateMachine,
F: AsyncFnOnce(&mut T, &T::State, &T::State, &mut T::Context<'_>),
{
fn call_transition_hook(
self,
shared_storage: &mut T,
source: &T::State,
target: &T::State,
context: &mut T::Context<'_>,
) -> impl Future<Output = ()> {
(self)(shared_storage, source, target, context)
}
}
97 changes: 96 additions & 1 deletion statig/src/blocking/into_state_machine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::StateOrSuperstate;

/// Trait for transorming a type into a state machine.
/// Trait for transforming a type into a state machine.
pub trait IntoStateMachine
where
Self: Sized,
Expand Down Expand Up @@ -60,3 +60,98 @@ where
) {
}
}

pub trait DispatchHook<T, P>
where
T: IntoStateMachine,
{
fn call_dispatch_hook(
&self,
shared_storage: &mut T,
state_or_superstate: StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
event: &T::Event<'_>,
context: &mut T::Context<'_>,
);
}

impl<T, F> DispatchHook<T, (T::Event<'_>,)> for F
where
T: IntoStateMachine,
F: Fn(&mut T, StateOrSuperstate<'_, T::State, T::Superstate<'_>>, &T::Event<'_>),
{
fn call_dispatch_hook(
&self,
shared_storage: &mut T,
state_or_superstate: StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
event: &T::Event<'_>,
_context: &mut T::Context<'_>,
) {
(self)(shared_storage, state_or_superstate, event)
}
}

impl<T, F> DispatchHook<T, (T::Event<'_>, T::Context<'_>)> for F
where
T: IntoStateMachine,
F: Fn(
&mut T,
StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
&T::Event<'_>,
&mut T::Context<'_>,
),
{
fn call_dispatch_hook(
&self,
shared_storage: &mut T,
state_or_superstate: StateOrSuperstate<'_, T::State, T::Superstate<'_>>,
event: &T::Event<'_>,
context: &mut T::Context<'_>,
) {
(self)(shared_storage, state_or_superstate, event, context)
}
}

pub trait TransitionHook<T, P>
where
T: IntoStateMachine,
{
fn call_transition_hook(
&self,
shared_storage: &mut T,
source: &T::State,
target: &T::State,
context: &mut T::Context<'_>,
);
}

impl<T, F> TransitionHook<T, ()> for F
where
T: IntoStateMachine,
F: Fn(&mut T, &T::State, &T::State),
{
fn call_transition_hook(
&self,
shared_storage: &mut T,
source: &T::State,
target: &T::State,
_context: &mut T::Context<'_>,
) {
(self)(shared_storage, source, target)
}
}

impl<T, F> TransitionHook<T, (T::Context<'_>,)> for F
where
T: IntoStateMachine,
F: Fn(&mut T, &T::State, &T::State, &mut T::Context<'_>),
{
fn call_transition_hook(
&self,
shared_storage: &mut T,
source: &T::State,
target: &T::State,
context: &mut T::Context<'_>,
) {
(self)(shared_storage, source, target, context)
}
}
3 changes: 1 addition & 2 deletions statig/tests/async_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ mod tests {
&mut self,
state_or_superstate: StateOrSuperstate<'_, State, Superstate>,
event: &Event,
_context: &mut (),
) {
self.before_dispatch = true;
}
Expand All @@ -55,7 +54,7 @@ mod tests {
self.after_dispatch = true;
}

async fn before_transition(&mut self, source: &State, target: &State, _context: &mut ()) {
async fn before_transition(&mut self, source: &State, target: &State) {
self.before_transition = true;
}

Expand Down
Loading
Loading