Skip to content

Commit

Permalink
Merge pull request #73 from dkumsh/master
Browse files Browse the repository at this point in the history
Fallible actions support
  • Loading branch information
ryan-summers committed Jul 2, 2024
2 parents 832a366 + 675763b commit 6a2188c
Show file tree
Hide file tree
Showing 23 changed files with 152 additions and 120 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ process.
- `StateMachine::new` and `StateMachine::new_with_state` are now const functions
- Fixed clippy warnings
- [breaking] Changed guard functions return type from Result<(),_> to Result<bool,_>
- [breaking] Changed action functions return type from () to Result<NextStateData,_>
- [breaking] Disallow guards mutable access to the context
- [breaking] Renamed GuardError to Error as it is now used for both guards and actions

## [v0.6.0] - 2022-11-02

Expand Down
16 changes: 9 additions & 7 deletions examples/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,41 @@ pub struct Context {

#[async_trait]
impl StateMachineContext for Context {
fn guard3(&mut self) -> Result<bool, ()> {
fn guard3(&self) -> Result<bool, ()> {
println!("`guard3` called from async context");
Ok(true)
}

async fn guard2(&mut self) -> Result<bool, ()> {
async fn guard2(&self) -> Result<bool, ()> {
println!("`guard2` called from async context");
let mut lock = self.lock.write().await;
*lock = false;
Ok(true)
}

fn guard1(&mut self) -> Result<bool, ()> {
fn guard1(&self) -> Result<bool, ()> {
println!("`guard1` called from sync context");
Ok(true)
}

async fn action2(&mut self) -> () {
async fn action2(&mut self) -> Result<(), ()> {
println!("`action2` called from async context");
if !*self.lock.read().await {
self.done = true;
}
Ok(())
}

async fn action1(&mut self) -> () {
async fn action1(&mut self) -> Result<(), ()> {
println!("`action1` called from async context");
let mut lock = self.lock.write().await;
*lock = true;
Ok(())
}

fn action3(&mut self) -> bool {
fn action3(&mut self) -> Result<bool, ()> {
println!("`action3` called from sync context, done = `{}`", self.done);
self.done
Ok(self.done)
}
}

Expand Down
6 changes: 4 additions & 2 deletions examples/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ pub struct Context {
}

impl StateMachineContext for Context {
fn count_transition1(&mut self) {
fn count_transition1(&mut self) -> Result<(), ()> {
self.num_transitions += 1;
Ok(())
}

fn count_transition2(&mut self) {
fn count_transition2(&mut self) -> Result<(), ()> {
self.num_transitions += 1;
Ok(())
}
}

Expand Down
16 changes: 8 additions & 8 deletions examples/dominos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ statemachine! {
pub struct Context;

impl StateMachineContext for Context {
fn to_d2(&mut self) -> Option<Events> {
Some(Events::ToD2)
fn to_d2(&mut self) -> Result<Option<Events>, ()> {
Ok(Some(Events::ToD2))
}

fn to_d3(&mut self, _state_data: &Option<Events>) -> Option<Events> {
Some(Events::ToD3)
fn to_d3(&mut self, _state_data: &Option<Events>) -> Result<Option<Events>, ()> {
Ok(Some(Events::ToD3))
}

fn to_d4(&mut self, _state_data: &Option<Events>) -> Option<Events> {
Some(Events::ToD4)
fn to_d4(&mut self, _state_data: &Option<Events>) -> Result<Option<Events>, ()> {
Ok(Some(Events::ToD4))
}

fn to_d5(&mut self, _state_data: &Option<Events>) -> Option<Events> {
Some(Events::ToD5)
fn to_d5(&mut self, _state_data: &Option<Events>) -> Result<Option<Events>, ()> {
Ok(Some(Events::ToD5))
}
}

Expand Down
5 changes: 3 additions & 2 deletions examples/event_with_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ statemachine! {
pub struct Context;

impl StateMachineContext for Context {
fn guard(&mut self, event_data: &MyEventData) -> Result<bool, ()> {
fn guard(&self, event_data: &MyEventData) -> Result<bool, ()> {
Ok(event_data == &MyEventData(42))
}

fn action(&mut self, event_data: MyEventData) {
fn action(&mut self, event_data: MyEventData) -> Result<(), ()> {
println!("Got valid Event Data = {}", event_data.0);
Ok(())
}
}

Expand Down
5 changes: 3 additions & 2 deletions examples/event_with_mutable_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ statemachine! {
pub struct Context;

impl StateMachineContext for Context {
fn guard(&mut self, event_data: &mut MyEventData) -> Result<bool, ()> {
fn guard(&self, event_data: &mut MyEventData) -> Result<bool, ()> {
event_data.0 = 55;
Ok(true)
}

fn action(&mut self, event_data: &mut MyEventData) {
fn action(&mut self, event_data: &mut MyEventData) -> Result<(), ()> {
println!("Got valid Event Data = {}", event_data.0);
Ok(())
}
}

Expand Down
10 changes: 6 additions & 4 deletions examples/event_with_reference_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,23 @@ statemachine! {
pub struct Context;

impl StateMachineContext for Context {
fn guard1(&mut self, event_data: &[u8]) -> Result<bool, ()> {
fn guard1(&self, event_data: &[u8]) -> Result<bool, ()> {
// Only ok if the slice is not empty
Ok(!event_data.is_empty())
}

fn action1(&mut self, event_data: &[u8]) {
fn action1(&mut self, event_data: &[u8]) -> Result<(), ()> {
println!("Got valid Event Data = {:?}", event_data);
Ok(())
}

fn guard2(&mut self, event_data: &MyReferenceWrapper) -> Result<bool, ()> {
fn guard2(&self, event_data: &MyReferenceWrapper) -> Result<bool, ()> {
Ok(*event_data.0 > 9000)
}

fn action2(&mut self, event_data: MyReferenceWrapper) {
fn action2(&mut self, event_data: MyReferenceWrapper) -> Result<(), ()> {
println!("Got valid Event Data = {}", event_data.0);
Ok(())
}
}

Expand Down
10 changes: 6 additions & 4 deletions examples/ex3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,24 @@ statemachine! {
pub struct Context;

impl StateMachineContext for Context {
fn guard(&mut self) -> Result<bool, ()> {
fn guard(&self) -> Result<bool, ()> {
// Always ok
Ok(true)
}

fn guard_fail(&mut self) -> Result<bool, ()> {
fn guard_fail(&self) -> Result<bool, ()> {
// Always fail
Ok(false)
}

fn action1(&mut self) {
fn action1(&mut self) -> Result<(), ()> {
//println!("Action 1");
Ok(())
}

fn action2(&mut self) {
fn action2(&mut self) -> Result<(), ()> {
//println!("Action 1");
Ok(())
}
}

Expand Down
8 changes: 4 additions & 4 deletions examples/guard_action_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ pub struct Context;

impl StateMachineContext for Context {
// Guard1 has access to the data from Event1
fn guard1(&mut self, _event_data: &MyEventData) -> Result<bool, ()> {
fn guard1(&self, _event_data: &MyEventData) -> Result<bool, ()> {
todo!()
}

// Action1 has access to the data from Event1, and need to return the state data for State2
fn action1(&mut self, _event_data: MyEventData) -> MyStateData {
fn action1(&mut self, _event_data: MyEventData) -> Result<MyStateData, ()> {
todo!()
}

// Guard2 has access to the data from State2
fn guard2(&mut self, _state_data: &MyStateData) -> Result<bool, ()> {
fn guard2(&self, _state_data: &MyStateData) -> Result<bool, ()> {
todo!()
}

// Action2 has access to the data from State2
fn action2(&mut self, _state_data: &MyStateData) {
fn action2(&mut self, _state_data: &MyStateData) -> Result<(), ()> {
todo!()
}
}
Expand Down
15 changes: 10 additions & 5 deletions examples/guard_action_syntax_with_temporary_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,34 @@ pub struct Context;

impl StateMachineContext for Context {
// Guard1 has access to the data from Event1
fn guard1(&mut self, temp_context: &mut u16, _event_data: &MyEventData) -> Result<bool, ()> {
fn guard1(&self, temp_context: &mut u16, _event_data: &MyEventData) -> Result<bool, ()> {
*temp_context += 1;

Ok(true)
}

// Action1 has access to the data from Event1, and need to return the state data for State2
fn action1(&mut self, temp_context: &mut u16, _event_data: MyEventData) -> MyStateData {
fn action1(
&mut self,
temp_context: &mut u16,
_event_data: MyEventData,
) -> Result<MyStateData, ()> {
*temp_context += 1;

MyStateData(1)
Ok(MyStateData(1))
}

// Guard2 has access to the data from State2
fn guard2(&mut self, temp_context: &mut u16, _state_data: &MyStateData) -> Result<bool, ()> {
fn guard2(&self, temp_context: &mut u16, _state_data: &MyStateData) -> Result<bool, ()> {
*temp_context += 1;

Ok(true)
}

// Action2 has access to the data from State2
fn action2(&mut self, temp_context: &mut u16, _state_data: &MyStateData) {
fn action2(&mut self, temp_context: &mut u16, _state_data: &MyStateData) -> Result<(), ()> {
*temp_context += 1;
Ok(())
}
}

Expand Down
10 changes: 5 additions & 5 deletions examples/guard_custom_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,23 @@ statemachine! {
pub struct Context;

impl StateMachineContext for Context {
type GuardError = GuardError; // Guard1 has access to the data from Event1
fn guard1(&mut self, _event_data: &MyEventData) -> Result<bool, GuardError> {
type Error = GuardError; // Guard1 has access to the data from Event1
fn guard1(&self, _event_data: &MyEventData) -> Result<bool, GuardError> {
Err(GuardError::Custom)
}

// Action1 has access to the data from Event1, and need to return the state data for State2
fn action1(&mut self, _event_data: MyEventData) -> MyStateData {
fn action1(&mut self, _event_data: MyEventData) -> Result<MyStateData, Self::Error> {
todo!()
}

// Guard2 has access to the data from State2
fn guard2(&mut self, _state_data: &MyStateData) -> Result<bool, GuardError> {
fn guard2(&self, _state_data: &MyStateData) -> Result<bool, GuardError> {
todo!()
}

// Action2 has access to the data from State2
fn action2(&mut self, _state_data: &MyStateData) {
fn action2(&mut self, _state_data: &MyStateData) -> Result<(), Self::Error> {
todo!()
}
}
Expand Down
20 changes: 11 additions & 9 deletions examples/named_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,36 @@ pub struct Context {

#[async_trait]
impl AsyncSimpleStateMachineContext for Context {
fn guard1(&mut self) -> Result<bool, ()> {
fn guard1(&self) -> Result<bool, ()> {
println!("`guard1` called from sync context");
Ok(true)
}

async fn guard2(&mut self) -> Result<bool, ()> {
async fn guard2(&self) -> Result<bool, ()> {
println!("`guard2` called from async context");
let mut lock = self.lock.write().await;
*lock = false;
Ok(true)
}

async fn action1(&mut self) -> () {
fn action3(&mut self) -> Result<bool, ()> {
println!("`action3` called from sync context, done = `{}`", self.done);
Ok(self.done)
}

async fn action1(&mut self) -> Result<(), ()> {
println!("`action1` called from async context");
let mut lock = self.lock.write().await;
*lock = true;
Ok(())
}

fn action3(&mut self) -> bool {
println!("`action3` called from sync context, done = `{}`", self.done);
self.done
}

async fn action2(&mut self) -> () {
async fn action2(&mut self) -> Result<(), ()> {
println!("`action2` called from async context");
if !*self.lock.read().await {
self.done = true;
}
Ok(())
}
}

Expand Down
16 changes: 8 additions & 8 deletions examples/named_dominos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ statemachine! {
pub struct Context;

impl DominosStateMachineContext for Context {
fn to_d2(&mut self) -> Option<DominosEvents> {
Some(DominosEvents::ToD2)
fn to_d2(&mut self) -> Result<Option<DominosEvents>, ()> {
Ok(Some(DominosEvents::ToD2))
}

fn to_d3(&mut self, _state_data: &Option<DominosEvents>) -> Option<DominosEvents> {
Some(DominosEvents::ToD3)
fn to_d3(&mut self, _state_data: &Option<DominosEvents>) -> Result<Option<DominosEvents>, ()> {
Ok(Some(DominosEvents::ToD3))
}

fn to_d4(&mut self, _state_data: &Option<DominosEvents>) -> Option<DominosEvents> {
Some(DominosEvents::ToD4)
fn to_d4(&mut self, _state_data: &Option<DominosEvents>) -> Result<Option<DominosEvents>, ()> {
Ok(Some(DominosEvents::ToD4))
}

fn to_d5(&mut self, _state_data: &Option<DominosEvents>) -> Option<DominosEvents> {
Some(DominosEvents::ToD5)
fn to_d5(&mut self, _state_data: &Option<DominosEvents>) -> Result<Option<DominosEvents>, ()> {
Ok(Some(DominosEvents::ToD5))
}
}

Expand Down
10 changes: 6 additions & 4 deletions examples/named_ex3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,24 @@ statemachine! {
pub struct Context;

impl LoopingWithGuardsStateMachineContext for Context {
fn guard(&mut self) -> Result<bool, ()> {
fn guard(&self) -> Result<bool, ()> {
// Always ok
Ok(true)
}

fn guard_fail(&mut self) -> Result<bool, ()> {
fn guard_fail(&self) -> Result<bool, ()> {
// Always fail
Ok(false)
}

fn action1(&mut self) {
fn action1(&mut self) -> Result<(), ()> {
//println!("Action 1");
Ok(())
}

fn action2(&mut self) {
fn action2(&mut self) -> Result<(), ()> {
//println!("Action 1");
Ok(())
}
}

Expand Down
Loading

0 comments on commit 6a2188c

Please sign in to comment.