Terminate pointer-only descriptor traversal
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user