72 lines
1.9 KiB
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
|
|
}
|