errors.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package fsm
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "log"
  7. )
  8. type (
  9. // ErrorString is a specific error type used to recognize FSM errors.
  10. ErrorString string
  11. // OnError is the type of FSM optional error handlers.
  12. OnError[SK, EK comparable] func(SK, EK, error) error
  13. )
  14. const (
  15. ErrUnavailableEvent ErrorString = "unavailable event"
  16. ErrGuardFailure ErrorString = "guard failure"
  17. ErrActionFailure ErrorString = "action failure"
  18. ErrEnterFailure ErrorString = "enter failure"
  19. ErrLeaveFailure ErrorString = "leave failure"
  20. )
  21. func (e ErrorString) Error() string {
  22. return string(e)
  23. }
  24. func MakeFailureError[SK, EK comparable](sk SK, ek EK, err error) error {
  25. var es ErrorString
  26. if ok := errors.As(err, &es); !ok {
  27. return fmt.Errorf("generic error at state %s / event %s: %w", sk, ek, err)
  28. }
  29. var format string
  30. switch es {
  31. case ErrUnavailableEvent:
  32. format = "unavailable event %s received on state %s: %w"
  33. case ErrGuardFailure:
  34. format = "guard failed for event %s received on state %s: %w"
  35. case ErrActionFailure:
  36. format = "action failed after event %s received on state %s: %w"
  37. case ErrEnterFailure:
  38. format = "enter failed entering state %s after event %s: %w"
  39. case ErrLeaveFailure:
  40. format = "leave failed leaving state %s on event %s: %w"
  41. default:
  42. format = "custom error at state %s / event %s: %w"
  43. }
  44. return fmt.Errorf(format, sk, ek, es)
  45. }
  46. // OnErrorIgnore silently ignores errors. Usually not recommended: mostly useful in tests.
  47. func OnErrorIgnore[SK, EK comparable](_ SK, _ EK, _ error) error { return nil }
  48. // OnErrorReturn returns the received error and, allowing the FSM to act on it.
  49. func OnErrorReturn[SK, EK comparable](sk SK, ek EK, err error) error {
  50. return MakeFailureError(sk, ek, err)
  51. }
  52. // OnErrorPanic panics when receiving an error. Not recommended.
  53. func OnErrorPanic[SK, EK comparable](sk SK, ek EK, err error) error {
  54. panic(MakeFailureError(sk, ek, err))
  55. }
  56. // MakeOnErrorWrite logs the error to the specified writer and returns success.
  57. func MakeOnErrorWrite[SK, EK comparable](w io.Writer) OnError[SK, EK] {
  58. return func(sk SK, ek EK, err error) error {
  59. fmt.Fprintln(w, MakeFailureError(sk, ek, err))
  60. return nil
  61. }
  62. }
  63. // _ is a compile-time verification of the type conformity for OnError handlers
  64. func _() {
  65. var fsm FSM[string, string, string]
  66. fsm.SetOnUnavailable(OnErrorIgnore[string, string])
  67. fsm.SetOnUnavailable(OnErrorReturn[string, string])
  68. fsm.SetOnUnavailable(OnErrorPanic[string, string])
  69. fsm.SetOnUnavailable(MakeOnErrorWrite[string, string](log.Default().Writer()))
  70. }