2018-03-30 16:15:06 +00:00
|
|
|
package vm
|
|
|
|
|
2019-02-19 11:47:25 +00:00
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
// State of the VM.
|
2019-02-19 11:47:25 +00:00
|
|
|
type State uint8
|
2018-03-30 16:15:06 +00:00
|
|
|
|
|
|
|
// Available States.
|
|
|
|
const (
|
2020-07-27 14:57:53 +00:00
|
|
|
// NoneState represents NONE VM state.
|
|
|
|
NoneState State = 0
|
|
|
|
// HaltState represents HALT VM state.
|
|
|
|
HaltState State = 1 << iota
|
|
|
|
// FaultState represents FAULT VM state.
|
|
|
|
FaultState
|
|
|
|
// BreakState represents BREAK VM state.
|
|
|
|
BreakState
|
2018-03-30 16:15:06 +00:00
|
|
|
)
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// HasFlag checks for State flag presence.
|
2019-02-19 11:47:25 +00:00
|
|
|
func (s State) HasFlag(f State) bool {
|
|
|
|
return s&f != 0
|
|
|
|
}
|
|
|
|
|
2019-09-03 14:51:37 +00:00
|
|
|
// String implements the stringer interface.
|
2018-03-30 16:15:06 +00:00
|
|
|
func (s State) String() string {
|
2020-07-27 14:57:53 +00:00
|
|
|
if s == NoneState {
|
2018-03-30 16:15:06 +00:00
|
|
|
return "NONE"
|
|
|
|
}
|
2019-02-19 11:47:25 +00:00
|
|
|
|
|
|
|
ss := make([]string, 0, 3)
|
2020-07-27 14:57:53 +00:00
|
|
|
if s.HasFlag(HaltState) {
|
2019-02-19 11:47:25 +00:00
|
|
|
ss = append(ss, "HALT")
|
|
|
|
}
|
2020-07-27 14:57:53 +00:00
|
|
|
if s.HasFlag(FaultState) {
|
2019-02-19 11:47:25 +00:00
|
|
|
ss = append(ss, "FAULT")
|
|
|
|
}
|
2020-07-27 14:57:53 +00:00
|
|
|
if s.HasFlag(BreakState) {
|
2019-02-19 11:47:25 +00:00
|
|
|
ss = append(ss, "BREAK")
|
|
|
|
}
|
|
|
|
return strings.Join(ss, ", ")
|
|
|
|
}
|
|
|
|
|
2019-09-03 14:51:37 +00:00
|
|
|
// StateFromString converts string into the VM State.
|
2019-02-19 11:47:25 +00:00
|
|
|
func StateFromString(s string) (st State, err error) {
|
|
|
|
if s = strings.TrimSpace(s); s == "NONE" {
|
2020-07-27 14:57:53 +00:00
|
|
|
return NoneState, nil
|
2019-02-19 11:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ss := strings.Split(s, ",")
|
|
|
|
for _, state := range ss {
|
|
|
|
switch state = strings.TrimSpace(state); state {
|
|
|
|
case "HALT":
|
2020-07-27 14:57:53 +00:00
|
|
|
st |= HaltState
|
2019-02-19 11:47:25 +00:00
|
|
|
case "FAULT":
|
2020-07-27 14:57:53 +00:00
|
|
|
st |= FaultState
|
2019-02-19 11:47:25 +00:00
|
|
|
case "BREAK":
|
2020-07-27 14:57:53 +00:00
|
|
|
st |= BreakState
|
2019-02-19 11:47:25 +00:00
|
|
|
default:
|
|
|
|
return 0, errors.New("unknown state")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// MarshalJSON implements the json.Marshaler interface.
|
2019-02-19 11:47:25 +00:00
|
|
|
func (s State) MarshalJSON() (data []byte, err error) {
|
|
|
|
return []byte(`"` + s.String() + `"`), nil
|
|
|
|
}
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// UnmarshalJSON implements the json.Marshaler interface.
|
2019-02-19 11:47:25 +00:00
|
|
|
func (s *State) UnmarshalJSON(data []byte) (err error) {
|
|
|
|
l := len(data)
|
|
|
|
if l < 2 || data[0] != '"' || data[l-1] != '"' {
|
|
|
|
return errors.New("wrong format")
|
|
|
|
}
|
|
|
|
|
|
|
|
*s, err = StateFromString(string(data[1 : l-1]))
|
|
|
|
return
|
2018-03-30 16:15:06 +00:00
|
|
|
}
|