You cannot handle only valid events, because of StateMachine
. To do that you would need type of the event
parameter depend on the value of state
property. It is not possible in today’s Swift, and even if it would be - I don’t see how it would be usable. It’s just too hard for the client code to proof that event type is correct.
So effectively you need to handle all MxN combinations of (State, Event)
. Throwing an error counts as handling.
With this mindset, it is pretty straightforward to design a system with runtime checking for validity of events.
You can make states return optional type, with nil indicating invalid transition:
enum Event {
case start
case stop
case receiveConnection(Connection)
}
protocol State {
func handle(event: Event) -> Optional<any State>
}
struct StateMachine {
var state: any State
mutating func handle(event: some Event) throws {
if let newState = state.handle(event: event) {
state = newState
} else {
print("\(event) invalid for \(state)")
throw StateMachineError()
}
}