Skip to content

Commit

Permalink
all: Refactor enums and add wall flags.
Browse files Browse the repository at this point in the history
  • Loading branch information
dennwc committed Dec 15, 2023
1 parent 89ddbb0 commit fb1dcc3
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 193 deletions.
56 changes: 37 additions & 19 deletions object/enums.go → enum/enums.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
package object
package enum

import (
"encoding/json"
"fmt"
"math/bits"
"strconv"
"strings"
)

type enum[T ~uint32] interface {
type number interface {
~uint64 | ~uint32 | ~uint16 | ~uint8
}

type Enum[T number] interface {
json.Marshaler
Has(c2 T) bool
HasAny(c2 T) bool
Split() []T
String() string
}

func splitBits[T ~uint32](v T) (out []T) {
for i := 0; i < 32; i++ {
v2 := T(1 << i)
func bitSize[T number]() int {
var zero T
return bits.OnesCount64(uint64(^zero))
}

func SplitBits[T number](v T) (out []T) {
for i := 0; i < bitSize[T](); i++ {
v2 := T(1) << i
if v&v2 != 0 {
out = append(out, v2)
}
}
return
}

func stringBits(v uint32, names []string) string {
func StringBits[T number](v T, names []string) string {
var out []string
for i := 0; i < 32; i++ {
v2 := uint32(1 << i)
for i := 0; i < bitSize[T](); i++ {
v2 := T(1) << i
if v&v2 != 0 {
if i < len(names) {
out = append(out, names[i])
Expand All @@ -40,18 +50,18 @@ func stringBits(v uint32, names []string) string {
return strings.Join(out, " | ")
}

func stringBitsRaw(v uint32) string {
func StringBitsRaw[T number](v T) string {
var out []string
for i := 0; i < 32; i++ {
v2 := uint32(1 << i)
for i := 0; i < bitSize[T](); i++ {
v2 := T(1) << i
if v&v2 != 0 {
out = append(out, "0x"+strconv.FormatUint(uint64(v2), 16))
}
}
return strings.Join(out, " | ")
}

func parseEnum(ename string, s string, names []string) (uint32, error) {
func Parse[T number](ename string, s string, names []string) (T, error) {
s = strings.ToUpper(s)
if s == "" || s == "NULL" {
return 0, nil
Expand All @@ -64,14 +74,14 @@ func parseEnum(ename string, s string, names []string) (uint32, error) {
return 0, fmt.Errorf("invalid %s name: %q", ename, s)
}

func parseEnumSet(ename string, s string, names []string) (uint32, error) {
func ParseSet[T number](ename string, s string, names []string) (T, error) {
var (
out uint32
out T
last error
)
for _, w := range strings.Split(s, "+") {
w = strings.TrimSpace(w)
v, err := parseEnum(ename, w, names)
v, err := Parse[T](ename, w, names)
if err != nil {
last = err
}
Expand All @@ -80,7 +90,7 @@ func parseEnumSet(ename string, s string, names []string) (uint32, error) {
return out, last
}

func parseEnumMulti(ename string, s string, lists [][]string) (uint32, error) {
func ParseMulti[T number](ename string, s string, lists [][]string) (T, error) {
s = strings.ToUpper(s)
if s == "" || s == "NULL" {
return 0, nil
Expand All @@ -95,18 +105,26 @@ func parseEnumMulti(ename string, s string, lists [][]string) (uint32, error) {
return 0, fmt.Errorf("invalid %s name: %q", ename, s)
}

func parseEnumSetMulti(ename string, s string, lists [][]string) (uint32, error) {
func ParseSetMulti[T number](ename string, s string, lists [][]string) (T, error) {
var (
out uint32
out T
last error
)
for _, w := range strings.Split(s, "+") {
w = strings.TrimSpace(w)
v, err := parseEnumMulti(ename, w, lists)
v, err := ParseMulti[T](ename, w, lists)
if err != nil {
last = err
}
out |= v
}
return out, last
}

func MarshalJSONArray[E interface{ Split() []T }, T interface{ String() string }](v E) ([]byte, error) {
var arr []string
for _, s := range v.Split() {
arr = append(arr, s.String())
}
return json.Marshal(arr)
}
22 changes: 8 additions & 14 deletions object/class.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package object

import (
"encoding/json"
"github.com/noxworld-dev/opennox-lib/enum"
)

var ClassNames = []string{
Expand Down Expand Up @@ -47,16 +47,14 @@ var goClassNames = []string{
"ClassPickup",
}

var _ enum[Class] = Class(0)
var _ enum.Enum[Class] = Class(0)

func ParseClass(s string) (Class, error) {
v, err := parseEnum("class", s, ClassNames)
return Class(v), err
return enum.Parse[Class]("class", s, ClassNames)
}

func ParseClassSet(s string) (Class, error) {
v, err := parseEnumSet("class", s, ClassNames)
return Class(v), err
return enum.ParseSet[Class]("class", s, ClassNames)
}

type Class uint32
Expand Down Expand Up @@ -110,21 +108,17 @@ func (c Class) HasAny(c2 Class) bool {
}

func (c Class) Split() []Class {
return splitBits(c)
return enum.SplitBits(c)
}

func (c Class) String() string {
return stringBits(uint32(c), ClassNames)
return enum.StringBits(uint32(c), ClassNames)
}

func (c Class) GoString() string {
return stringBits(uint32(c), goClassNames)
return enum.StringBits(uint32(c), goClassNames)
}

func (c Class) MarshalJSON() ([]byte, error) {
var arr []string
for _, s := range c.Split() {
arr = append(arr, s.String())
}
return json.Marshal(arr)
return enum.MarshalJSONArray(c)

Check failure on line 123 in object/class.go

View workflow job for this annotation

GitHub Actions / build

cannot infer T (/home/runner/work/opennox-lib/opennox-lib/enum/enums.go:124:51)
}
10 changes: 5 additions & 5 deletions object/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package object
import (
"encoding/json"
"strings"

"github.com/noxworld-dev/opennox-lib/enum"
)

var FlagsNames = []string{
Expand All @@ -16,16 +18,14 @@ var FlagsNames = []string{
"NO_AUTO_DROP", "FLICKER", "SELECTED", "MARKED",
}

var _ enum[Flags] = Flags(0)
var _ enum.Enum[Flags] = Flags(0)

func ParseFlag(s string) (Flags, error) {
v, err := parseEnum("flag", s, FlagsNames)
return Flags(v), err
return enum.Parse[Flags]("flag", s, FlagsNames)
}

func ParseFlagSet(s string) (Flags, error) {
v, err := parseEnumSet("flag", s, FlagsNames)
return Flags(v), err
return enum.ParseSet[Flags]("flag", s, FlagsNames)
}

type Flags uint32
Expand Down
20 changes: 7 additions & 13 deletions object/material.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package object

import (
"encoding/json"
"github.com/noxworld-dev/opennox-lib/enum"
)

var MaterialNames = []string{
"FLESH", "CLOTH", "ANIMAL_HIDE", "WOOD", "METAL", "STONE", "EARTH", "LIQUID",
"GLASS", "PAPER", "SNOW", "MUD", "MAGIC", "DIAMOND", "NONE",
}

var _ enum[Material] = Material(0)
var _ enum.Enum[Material] = Material(0)

func ParseMaterial(s string) (Material, error) {
v, err := parseEnum("material", s, MaterialNames)
return Material(v), err
return enum.Parse[Material]("material", s, MaterialNames)
}

func ParseMaterialSet(s string) (Material, error) {
v, err := parseEnumSet("material", s, MaterialNames)
return Material(v), err
return enum.ParseSet[Material]("material", s, MaterialNames)
}

type Material uint32
Expand Down Expand Up @@ -50,17 +48,13 @@ func (c Material) HasAny(c2 Material) bool {
}

func (c Material) Split() []Material {
return splitBits(c)
return enum.SplitBits(c)
}

func (c Material) String() string {
return stringBits(uint32(c), MaterialNames)
return enum.StringBits(c, MaterialNames)
}

func (c Material) MarshalJSON() ([]byte, error) {
var arr []string
for _, s := range c.Split() {
arr = append(arr, s.String())
}
return json.Marshal(arr)
return enum.MarshalJSONArray(c)

Check failure on line 59 in object/material.go

View workflow job for this annotation

GitHub Actions / build

cannot infer T (/home/runner/work/opennox-lib/opennox-lib/enum/enums.go:124:51)
}
22 changes: 9 additions & 13 deletions object/subclass.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package object

import "encoding/json"
import (
"github.com/noxworld-dev/opennox-lib/enum"
)

var SubClassNames = [][]string{
ArmorClassNames,
Expand All @@ -15,16 +17,14 @@ var SubClassNames = [][]string{
}

func ParseSubClass(s string) (SubClass, error) {
v, err := parseEnumMulti("subclass", s, SubClassNames)
return SubClass(v), err
return enum.ParseMulti[SubClass]("subclass", s, SubClassNames)
}

func ParseSubClassSet(s string) (SubClass, error) {
v, err := parseEnumSetMulti("subclass", s, SubClassNames)
return SubClass(v), err
return enum.ParseSetMulti[SubClass]("subclass", s, SubClassNames)
}

var _ enum[SubClass] = SubClass(0)
var _ enum.Enum[SubClass] = SubClass(0)

type SubClass uint32

Expand All @@ -37,17 +37,13 @@ func (c SubClass) HasAny(c2 SubClass) bool {
}

func (c SubClass) Split() []SubClass {
return splitBits(c)
return enum.SplitBits(c)
}

func (c SubClass) String() string {
return stringBitsRaw(uint32(c))
return enum.StringBitsRaw(c)
}

func (c SubClass) MarshalJSON() ([]byte, error) {
var arr []string
for _, s := range c.Split() {
arr = append(arr, s.String())
}
return json.Marshal(arr)
return enum.MarshalJSONArray(c)

Check failure on line 48 in object/subclass.go

View workflow job for this annotation

GitHub Actions / build

cannot infer T (/home/runner/work/opennox-lib/opennox-lib/enum/enums.go:124:51)
}
22 changes: 9 additions & 13 deletions object/subclass_armor.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package object

import "encoding/json"
import (
"github.com/noxworld-dev/opennox-lib/enum"
)

var ArmorClassNames = []string{
"HELMET", "SHIELD", "BREASTPLATE", "ARM_ARMOR", "PANTS", "BOOTS", "SHIRT", "LEG_ARMOR", "BACK",
Expand All @@ -11,16 +13,14 @@ func (c SubClass) AsArmor() ArmorClass {
}

func ParseArmorClass(s string) (ArmorClass, error) {
v, err := parseEnum("armor class", s, ArmorClassNames)
return ArmorClass(v), err
return enum.Parse[ArmorClass]("armor class", s, ArmorClassNames)
}

func ParseArmorClassSet(s string) (ArmorClass, error) {
v, err := parseEnumSet("armor class", s, ArmorClassNames)
return ArmorClass(v), err
return enum.ParseSet[ArmorClass]("armor class", s, ArmorClassNames)
}

var _ enum[ArmorClass] = ArmorClass(0)
var _ enum.Enum[ArmorClass] = ArmorClass(0)

type ArmorClass uint32

Expand All @@ -45,17 +45,13 @@ func (c ArmorClass) HasAny(c2 ArmorClass) bool {
}

func (c ArmorClass) Split() []ArmorClass {
return splitBits(c)
return enum.SplitBits(c)
}

func (c ArmorClass) String() string {
return stringBits(uint32(c), ArmorClassNames)
return enum.StringBits(c, ArmorClassNames)
}

func (c ArmorClass) MarshalJSON() ([]byte, error) {
var arr []string
for _, s := range c.Split() {
arr = append(arr, s.String())
}
return json.Marshal(arr)
return enum.MarshalJSONArray(c)

Check failure on line 56 in object/subclass_armor.go

View workflow job for this annotation

GitHub Actions / build

cannot infer T (/home/runner/work/opennox-lib/opennox-lib/enum/enums.go:124:51)
}
Loading

0 comments on commit fb1dcc3

Please sign in to comment.