codex.go 2.3 KB

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