github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/vm/vmstate/state.go (about)

     1  /*
     2  Package vmstate contains a set of VM state flags along with appropriate type.
     3  It provides a set of conversion/marshaling functions/methods for this type as
     4  well. This package is made to make VM state reusable across all of the other
     5  components that need it without importing whole VM package.
     6  */
     7  package vmstate
     8  
     9  import (
    10  	"errors"
    11  	"strings"
    12  )
    13  
    14  // State of the VM. It's a set of flags stored in the integer number.
    15  type State uint8
    16  
    17  // Available States.
    18  const (
    19  	// Halt represents HALT VM state (finished normally).
    20  	Halt State = 1 << iota
    21  	// Fault represents FAULT VM state (finished with an error).
    22  	Fault
    23  	// Break represents BREAK VM state (running, debug mode).
    24  	Break
    25  	// None represents NONE VM state (not started yet).
    26  	None State = 0
    27  )
    28  
    29  // HasFlag checks for State flag presence.
    30  func (s State) HasFlag(f State) bool {
    31  	return s&f != 0
    32  }
    33  
    34  // String implements the fmt.Stringer interface.
    35  func (s State) String() string {
    36  	if s == None {
    37  		return "NONE"
    38  	}
    39  
    40  	ss := make([]string, 0, 3)
    41  	if s.HasFlag(Halt) {
    42  		ss = append(ss, "HALT")
    43  	}
    44  	if s.HasFlag(Fault) {
    45  		ss = append(ss, "FAULT")
    46  	}
    47  	if s.HasFlag(Break) {
    48  		ss = append(ss, "BREAK")
    49  	}
    50  	return strings.Join(ss, ", ")
    51  }
    52  
    53  // FromString converts a string into the State.
    54  func FromString(s string) (st State, err error) {
    55  	if s = strings.TrimSpace(s); s == "NONE" {
    56  		return None, nil
    57  	}
    58  
    59  	ss := strings.Split(s, ",")
    60  	for _, state := range ss {
    61  		switch state = strings.TrimSpace(state); state {
    62  		case "HALT":
    63  			st |= Halt
    64  		case "FAULT":
    65  			st |= Fault
    66  		case "BREAK":
    67  			st |= Break
    68  		default:
    69  			return 0, errors.New("unknown state")
    70  		}
    71  	}
    72  	return
    73  }
    74  
    75  // MarshalJSON implements the json.Marshaler interface.
    76  func (s State) MarshalJSON() (data []byte, err error) {
    77  	return []byte(`"` + s.String() + `"`), nil
    78  }
    79  
    80  // UnmarshalJSON implements the json.Marshaler interface.
    81  func (s *State) UnmarshalJSON(data []byte) (err error) {
    82  	l := len(data)
    83  	if l < 2 || data[0] != '"' || data[l-1] != '"' {
    84  		return errors.New("wrong format")
    85  	}
    86  
    87  	*s, err = FromString(string(data[1 : l-1]))
    88  	return
    89  }