eq2go/internal/packets/parser/version_registry.go

72 lines
1.9 KiB
Go

package parser
import (
"fmt"
"reflect"
)
// VersionRegistry manages version-specific struct types
type VersionRegistry struct {
structs map[string]map[string]reflect.Type // [structName][version] = Type
}
// NewVersionRegistry creates a new version registry
func NewVersionRegistry() *VersionRegistry {
return &VersionRegistry{
structs: make(map[string]map[string]reflect.Type),
}
}
// RegisterStruct registers a struct type for a specific version
func (vr *VersionRegistry) RegisterStruct(name, version string, structType reflect.Type) {
if vr.structs[name] == nil {
vr.structs[name] = make(map[string]reflect.Type)
}
vr.structs[name][version] = structType
}
// GetStruct returns the appropriate struct type for a version
func (vr *VersionRegistry) GetStruct(name, version string) (reflect.Type, bool) {
if versions, exists := vr.structs[name]; exists {
if structType, exists := versions[version]; exists {
return structType, true
}
return vr.findNearestVersion(name, version)
}
return nil, false
}
// findNearestVersion finds the closest version <= requested version
func (vr *VersionRegistry) findNearestVersion(name, targetVersion string) (reflect.Type, bool) {
versions := vr.structs[name]
var bestVersion string
var bestType reflect.Type
for version, structType := range versions {
if version <= targetVersion && version > bestVersion {
bestVersion = version
bestType = structType
}
}
return bestType, bestVersion != ""
}
// ParseWithVersion parses using version-specific struct
func (p *Parser) ParseWithVersion(registry *VersionRegistry, structName, version string) (any, error) {
structType, exists := registry.GetStruct(structName, version)
if !exists {
return nil, fmt.Errorf("no struct found for %s version %s", structName, version)
}
ptr := reflect.New(structType)
elem := ptr.Elem()
err := p.ParseStruct(ptr.Interface())
if err != nil {
return nil, err
}
return elem.Interface(), nil
}