123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- package codex
- import (
- "fmt"
- "gopkg.in/yaml.v3"
- "os"
- )
- type Codex interface {
- init(cfg map[string]interface{})
- ID() string
- Decode(data []byte, pos int, value interface{}) (int, error)
- Encode(data []byte, pos int, value interface{}) (int, error)
- }
- type CodexStruct struct {
- id string
- fields []Codex
- }
- func LoadCodex(fileName string) Codex {
- data, err := os.ReadFile(fileName)
- if err != nil {
- panic(fmt.Sprintf("Error read config %s: %s", fileName, err))
- }
- m := make(map[string]interface{})
- err = yaml.Unmarshal(data, &m)
- return parseType(m)
- }
- func parseType(cfg map[string]interface{}) Codex {
- var c Codex
- if ctype, ok := cfg["type"].(string); ok {
- switch ctype {
- case "struct":
- c = &CodexStruct{}
- case "string":
- c = &CodexString{}
- case "bitmap":
- c = &CodexBitmap{}
- case "llvar":
- c = &CodexLVar{PacketLength: 2}
- case "lllvar":
- c = &CodexLVar{PacketLength: 3}
- default:
- panic(fmt.Sprintf("Unknown type [%s]", ctype))
- }
- } else if cfg["type"] == nil {
- c = &CodexString{}
- } else {
- panic(fmt.Sprintf("Invalid Codex.Type %+v", cfg))
- }
- c.init(cfg)
- return c
- }
- func (c *CodexStruct) init(cfg map[string]interface{}) {
- if v, ok := cfg["id"].(string); ok {
- c.id = v
- } else {
- panic(fmt.Sprintf("Invalid CodexStruct.ID %+v", cfg))
- }
- if v, ok := cfg["fields"].([]interface{}); ok {
- c.fields = make([]Codex, len(v))
- for i,f := range v {
- if fm, ok := f.(map[string]interface{}); ok {
- c.fields[i] = parseType(fm)
- } else {
- panic(fmt.Sprintf("Invalid field %d %+v", i, f))
- }
- }
- } else {
- panic(fmt.Sprintf("Invalid CodexStruct.Fields %+v", cfg))
- }
- }
- func (c *CodexStruct) ID() string {
- return c.id
- }
- func (c *CodexStruct) Decode(data []byte, pos int, value interface{}) (int, error) {
- ppos := pos
- var err error
- for _, f := range c.fields {
- ppos, err = f.Decode(data, ppos, value)
- if err != nil {
- return pos, err
- }
- }
- return ppos, nil
- }
- func (c *CodexStruct) Encode(data []byte, pos int, value interface{}) (int, error) {
- ppos := pos
- var err error
- for _, f := range c.fields {
- ppos, err = f.Encode(data, ppos, value)
- if err != nil {
- return pos, err
- }
- }
- return ppos, nil
- }
|