fix: resolve parameterized $compareTo types and fix array count type
- VisitNameAndData: return any instead of named struct when mergeCompareTo resolves $compareTo, fixing field type mismatches for switch/container types - ContainerCompareTo: traverse anon/bitfield fields for compareTo resolution, fixes entityMetadata 'field not found' errors - Array.Count: change from string to any to handle numeric count values - ArrayEncoder: fix nil check to correctly write length prefix for arrays - ArrayDecoder: use fmt.Sprint for safe Count conversion
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"io"
|
||||
"maps"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"slices"
|
||||
@@ -56,6 +57,7 @@ type Generator struct {
|
||||
EncoderNatives map[string]FunctionGeneratorFunc
|
||||
CompareToNatives map[string]CompareToGeneratorFunc
|
||||
Protocol Protocol
|
||||
RawTypes map[string]map[string]any
|
||||
File *ast.File
|
||||
|
||||
// These persist in the current GenerateType call
|
||||
@@ -129,6 +131,11 @@ func (g *Generator) VisitNameAndData(tName string, tData any) (e ast.Expr, err e
|
||||
}
|
||||
t, found := g.Protocol.Types.Types[tName]
|
||||
if t != "native" && found {
|
||||
if tData != nil {
|
||||
if _, ok := g.mergeCompareTo(tName, t, tData); ok {
|
||||
return Ident("any"), nil
|
||||
}
|
||||
}
|
||||
return Ident(util2.CamelCase(tName)), nil
|
||||
}
|
||||
t, found = g.CurrentlyGeneratingTypes.Types[tName]
|
||||
@@ -152,6 +159,14 @@ func (g *Generator) VisitDecoder(varToSet ast.Expr, data any, name string) (e []
|
||||
if found {
|
||||
return d(g, varToSet, tData, name)
|
||||
}
|
||||
if tData != nil {
|
||||
if merged, ok := g.mergeCompareTo(tName, g.Protocol.Types.Types[tName], tData); ok {
|
||||
s, found := g.DecoderNatives[merged.tName]
|
||||
if found {
|
||||
return s(g, varToSet, merged.data, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
t, found := g.Protocol.Types.Types[tName]
|
||||
if t == "native" {
|
||||
err = fmt.Errorf("decoder native not implemented %v", tName)
|
||||
@@ -160,6 +175,55 @@ func (g *Generator) VisitDecoder(varToSet ast.Expr, data any, name string) (e []
|
||||
return DefaultDecoder(g, varToSet, tData, name)
|
||||
}
|
||||
|
||||
type mergedType struct {
|
||||
tName string
|
||||
data any
|
||||
}
|
||||
|
||||
func (g *Generator) mergeCompareTo(tName string, t any, overrideData any) (mergedType, bool) {
|
||||
overrideMap, ok := overrideData.(map[string]any)
|
||||
if !ok {
|
||||
return mergedType{}, false
|
||||
}
|
||||
overrideCompareTo, hasOverride := overrideMap["compareTo"]
|
||||
if !hasOverride {
|
||||
return mergedType{}, false
|
||||
}
|
||||
if s, ok := overrideCompareTo.(string); ok && strings.HasPrefix(s, "$") {
|
||||
return mergedType{}, false
|
||||
}
|
||||
var typeMap map[string]any
|
||||
var nativeName string
|
||||
if m, ok := t.(map[string]any); ok {
|
||||
typeMap = m
|
||||
nativeName = "container"
|
||||
} else if a, ok := t.([]any); ok && len(a) >= 2 {
|
||||
if m, ok := a[1].(map[string]any); ok {
|
||||
typeMap = m
|
||||
}
|
||||
if s, ok := a[0].(string); ok {
|
||||
nativeName = s
|
||||
}
|
||||
} else {
|
||||
m, ok := g.RawTypes[tName]
|
||||
if !ok {
|
||||
return mergedType{}, false
|
||||
}
|
||||
typeMap = m
|
||||
nativeName = "switch"
|
||||
}
|
||||
typeCompareTo, hasType := typeMap["compareTo"]
|
||||
if !hasType {
|
||||
return mergedType{}, false
|
||||
}
|
||||
if s, ok := typeCompareTo.(string); !ok || !strings.HasPrefix(s, "$") {
|
||||
return mergedType{}, false
|
||||
}
|
||||
merged := maps.Clone(typeMap)
|
||||
merged["compareTo"] = overrideCompareTo
|
||||
return mergedType{tName: nativeName, data: merged}, true
|
||||
}
|
||||
|
||||
func (g *Generator) VisitEncoder(varToSet ast.Expr, data any, name string) (e []ast.Stmt, err error) {
|
||||
g.Depth += 1
|
||||
defer func() { g.Depth -= 1 }()
|
||||
@@ -172,6 +236,14 @@ func (g *Generator) VisitEncoder(varToSet ast.Expr, data any, name string) (e []
|
||||
if found {
|
||||
return d(g, varToSet, tData, name)
|
||||
}
|
||||
if tData != nil {
|
||||
if merged, ok := g.mergeCompareTo(tName, g.Protocol.Types.Types[tName], tData); ok {
|
||||
s, found := g.EncoderNatives[merged.tName]
|
||||
if found {
|
||||
return s(g, varToSet, merged.data, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
t, found := g.Protocol.Types.Types[tName]
|
||||
if t == "native" {
|
||||
err = fmt.Errorf("encoder native not implemented %v", tName)
|
||||
@@ -357,6 +429,20 @@ func Generate(version string, w io.Writer, sourceHash string) (packetInfos []Pac
|
||||
|
||||
g := &Generator{Protocol: protocol}
|
||||
|
||||
g.RawTypes = make(map[string]map[string]any)
|
||||
for k, v := range protocol.Types.Types {
|
||||
if m, ok := v.(map[string]any); ok {
|
||||
g.RawTypes[k] = m
|
||||
}
|
||||
if a, ok := v.([]any); ok && len(a) == 2 {
|
||||
if m, ok := a[1].(map[string]any); ok {
|
||||
if _, has := m["fields"]; has {
|
||||
g.RawTypes[k] = m
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g.File = NewFile("v" + strings.ReplaceAll(version, ".", "_"))
|
||||
|
||||
// Add file header comment for IDE recognition and reproducibility
|
||||
|
||||
Reference in New Issue
Block a user