Skip to content

Instantly share code, notes, and snippets.

@scottymac
Last active May 8, 2022 21:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottymac/bc4de4fb345187c27e9a65d23f012021 to your computer and use it in GitHub Desktop.
Save scottymac/bc4de4fb345187c27e9a65d23f012021 to your computer and use it in GitHub Desktop.
// The MIT License
//
// Copyright (c) 2015-2021 Scott McMillin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
struct StateTransition<T: Equatable>: Equatable {
var fromState: T
var toState: T
var perform: () -> Void
static func == (lhs: StateTransition<T>, rhs: StateTransition<T>) -> Bool {
(lhs.fromState == rhs.fromState) && (lhs.toState == rhs.toState)
}
}
protocol StateMachine: AnyObject {
associatedtype StateType: Equatable
var _state: StateType { get set }
var state: StateType { get set }
var transitions: [StateTransition<StateType>] { get set }
func transitionTo(_ toState: StateType)
func addTransition(_ fromState: StateType, to toState: StateType, perform: @escaping () -> Void)
func getTransition(_ fromState: StateType, to toState: StateType) -> StateTransition<StateType>?
func hasTransition(_ fromState: StateType, to toState: StateType) -> Bool
}
extension StateMachine {
var state: StateType {
get { _state }
set { transitionTo(newValue) }
}
func transitionTo(_ toState: StateType) {
guard let transition = getTransition(state, to: toState) else { return }
_state = toState
transition.perform()
}
func addTransition(_ fromState: StateType, to toState: StateType, perform: @escaping () -> Void) {
if !hasTransition(fromState, to: toState) {
transitions.append(StateTransition(fromState: fromState, toState: toState, perform: perform))
}
}
func getTransition(_ fromState: StateType, to toState: StateType) -> StateTransition<StateType>? {
transitions.first {
$0.fromState == fromState && $0.toState == toState
}
}
func hasTransition(_ fromState: StateType, to toState: StateType) -> Bool {
getTransition(fromState, to: toState) != nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment