Add statemachine module
parent
c8e33ad219
commit
1d40720bf6
|
|
@ -0,0 +1,66 @@
|
|||
module statemachine
|
||||
|
||||
pub type EventHandlerFn = fn (receiver voidptr)
|
||||
pub type ConditionFn = fn (receiver voidptr) bool
|
||||
|
||||
struct State {
|
||||
mut:
|
||||
entry_handler EventHandlerFn
|
||||
run_handler EventHandlerFn
|
||||
exit_handler EventHandlerFn
|
||||
}
|
||||
|
||||
struct Transition {
|
||||
mut:
|
||||
to string
|
||||
condition ConditionFn
|
||||
}
|
||||
|
||||
struct StateMachine {
|
||||
mut:
|
||||
states map[string]State
|
||||
transitions map[string]Transition
|
||||
current_state string
|
||||
}
|
||||
|
||||
|
||||
pub fn new() &StateMachine {
|
||||
return &StateMachine{}
|
||||
}
|
||||
|
||||
pub fn (mut s StateMachine) add_state(name string, entry EventHandlerFn, run EventHandlerFn, exit EventHandlerFn) {
|
||||
s.states [name] = State{
|
||||
entry_handler: entry
|
||||
run_handler: run
|
||||
exit_handler: exit
|
||||
}
|
||||
if s.states.len == 1 {
|
||||
s.current_state = name
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut s StateMachine) add_transition(from string, to string, condition ConditionFn) {
|
||||
s.transitions[from] = Transition{
|
||||
to: to
|
||||
condition: condition
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut s StateMachine) run(receiver voidptr){
|
||||
for from_state, transition in s.transitions{
|
||||
if from_state in s.states {
|
||||
if transition.condition(receiver){
|
||||
s.change_state(receiver, s.transitions[from_state].to)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut s StateMachine) change_state(receiver voidptr, newstate string){
|
||||
mut current_state := s.current_state
|
||||
s.states[current_state].exit_handler(receiver)
|
||||
current_state = newstate
|
||||
s.states[current_state].run_handler(receiver)
|
||||
s.states[current_state].entry_handler(receiver)
|
||||
s.current_state = current_state
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import statemachine
|
||||
|
||||
struct FakeReceiver {
|
||||
mut:
|
||||
data []string
|
||||
}
|
||||
|
||||
fn test_statemachine_works_when_typical() {
|
||||
mut receiver := &FakeReceiver{}
|
||||
mut s := statemachine.new()
|
||||
s.add_state("A",on_test_entry, on_test_run, on_test_exit)
|
||||
s.add_state("B",on_test_entry, on_test_run, on_test_exit)
|
||||
s.add_transition("A", "B", condition_a_b)
|
||||
s.run(receiver)
|
||||
|
||||
assert receiver.data[0] == "on_test_exit"
|
||||
assert receiver.data[1] == "on_test_run"
|
||||
assert receiver.data[2] == "on_test_entry"
|
||||
|
||||
}
|
||||
|
||||
fn on_test_entry(mut receiver &FakeReceiver) {
|
||||
receiver.data << "on_test_entry"
|
||||
}
|
||||
fn on_test_run(mut receiver &FakeReceiver) {
|
||||
receiver.data << "on_test_run"
|
||||
}
|
||||
fn on_test_exit(mut receiver &FakeReceiver) {
|
||||
receiver.data << "on_test_exit"
|
||||
}
|
||||
|
||||
fn condition_a_b(receiver &FakeReceiver) bool {
|
||||
return true
|
||||
}
|
||||
Loading…
Reference in New Issue