codex.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package codex
  2. import (
  3. "fmt"
  4. "gopkg.in/yaml.v3"
  5. "os"
  6. )
  7. type Codex interface {
  8. init(cfg map[string]interface{})
  9. ID() string
  10. Decode(data []byte, pos int, value interface{}) (int, error)
  11. }
  12. type CodexStruct struct {
  13. id string
  14. fields []Codex
  15. }
  16. func LoadCodex(fileName string) Codex {
  17. data, err := os.ReadFile(fileName)
  18. if err != nil {
  19. panic(fmt.Sprintf("Error read config %s: %s", fileName, err))
  20. }
  21. m := make(map[string]interface{})
  22. err = yaml.Unmarshal(data, &m)
  23. return parseType(m)
  24. }
  25. func parseType(cfg map[string]interface{}) Codex {
  26. var c Codex
  27. if ctype, ok := cfg["type"].(string); ok {
  28. switch ctype {
  29. case "struct":
  30. c = &CodexStruct{}
  31. case "string":
  32. c = &CodexString{}
  33. case "bitmap":
  34. c = &CodexBitmap{}
  35. case "llvar":
  36. c = &CodexLVar{PacketLength: 2}
  37. case "lllvar":
  38. c = &CodexLVar{PacketLength: 3}
  39. default:
  40. panic(fmt.Sprintf("Unknown type [%s]", ctype))
  41. }
  42. } else if cfg["type"] == nil {
  43. c = &CodexString{}
  44. } else {
  45. panic(fmt.Sprintf("Invalid Codex.Type %+v", cfg))
  46. }
  47. c.init(cfg)
  48. return c
  49. }
  50. func (c *CodexStruct) init(cfg map[string]interface{}) {
  51. if v, ok := cfg["id"].(string); ok {
  52. c.id = v
  53. } else {
  54. panic(fmt.Sprintf("Invalid CodexStruct.ID %+v", cfg))
  55. }
  56. if v, ok := cfg["fields"].([]interface{}); ok {
  57. c.fields = make([]Codex, len(v))
  58. for i,f := range v {
  59. if fm, ok := f.(map[string]interface{}); ok {
  60. c.fields[i] = parseType(fm)
  61. } else {
  62. panic(fmt.Sprintf("Invalid field %d %+v", i, f))
  63. }
  64. }
  65. } else {
  66. panic(fmt.Sprintf("Invalid CodexStruct.Fields %+v", cfg))
  67. }
  68. }
  69. func (c *CodexStruct) ID() string {
  70. return c.id
  71. }
  72. func (c *CodexStruct) Decode(data []byte, pos int, value interface{}) (int, error) {
  73. ppos := pos
  74. var err error
  75. for _, f := range c.fields {
  76. ppos, err = f.Decode(data, ppos, value)
  77. if err != nil {
  78. return pos, err
  79. }
  80. }
  81. return ppos, nil
  82. }