Terminate pointer-only descriptor traversal

This commit is contained in:
2026-10-25 21:18:35 +00:00
parent 7889ebddfb
commit 2736ddfbf2
5 changed files with 165 additions and 30 deletions

View File

@@ -91,19 +91,30 @@ func decodeValue(node *document.Node, base reflect.Value, descriptor *typeDescri
}
}
if descriptor.kind == descriptorPointer {
var elementBase reflect.Value
if base.IsNil() {
elementBase = reflect.Zero(descriptor.typeOf.Elem())
} else {
elementBase = base.Elem()
terminal, ok := terminalDescriptor(descriptor)
if !ok {
return reflect.Value{}, []decodeIssue{newDecodeIssue(CodeDecodeType, path, node, "configuration type cannot represent a non-null value")}
}
decoded, issues := decodeValue(node, elementBase, descriptor.element, path, schema, context)
var pointers []*typeDescriptor
currentBase := base
for current := descriptor; current != terminal; current = current.element {
pointers = append(pointers, current)
if currentBase.IsNil() {
currentBase = reflect.Zero(current.typeOf.Elem())
} else {
currentBase = currentBase.Elem()
}
}
decoded, issues := decodeValue(node, currentBase, terminal, path, schema, context)
if len(issues) != 0 {
return reflect.Value{}, issues
}
result := reflect.New(descriptor.typeOf.Elem())
result.Elem().Set(decoded)
return result, nil
for i := len(pointers) - 1; i >= 0; i-- {
result := reflect.New(pointers[i].typeOf.Elem())
result.Elem().Set(decoded)
decoded = result
}
return decoded, nil
}
switch descriptor.kind {
@@ -392,10 +403,11 @@ func decodeDynamic(node *document.Node, base reflect.Value, path Path, schema *s
}
func acceptsMapping(descriptor *typeDescriptor) bool {
for descriptor != nil && descriptor.kind == descriptorPointer {
descriptor = descriptor.element
terminal, ok := terminalDescriptor(descriptor)
if !ok {
return false
}
return descriptor != nil && (descriptor.kind == descriptorStruct || descriptor.kind == descriptorMap || descriptor.kind == descriptorDynamic)
return terminal.kind == descriptorStruct || terminal.kind == descriptorMap || terminal.kind == descriptorDynamic
}
func fieldForDecode(root reflect.Value, index []int, allocate bool) (reflect.Value, bool) {