in reify.go [359:432]
func reifyValue(
opts fieldOptions,
t reflect.Type,
val value,
) (reflect.Value, Error) {
if t.Kind() == reflect.Interface && t.NumMethod() == 0 {
reified, err := val.reify(opts.opts)
if err != nil {
ctx := val.Context()
return reflect.Value{}, raisePathErr(err, val.meta(), "", ctx.path("."))
}
return reflect.ValueOf(reified), nil
}
baseType := chaseTypePointers(t)
if tConfig.ConvertibleTo(baseType) {
cfg, err := val.toConfig(opts.opts)
if err != nil {
return reflect.Value{}, raiseExpectedObject(opts.opts, val)
}
v := reflect.ValueOf(cfg).Convert(reflect.PtrTo(baseType))
if t == baseType { // copy config
v = v.Elem()
} else {
v = pointerize(t, baseType, v)
}
return v, nil
}
if baseType.Kind() == reflect.Struct {
sub, err := val.toConfig(opts.opts)
if err != nil {
return reifyPrimitive(opts, val, t, baseType)
}
newSt := reflect.New(baseType)
if err := reifyInto(opts.opts, newSt, sub); err != nil {
return reflect.Value{}, err
}
if t.Kind() != reflect.Ptr {
return newSt.Elem(), nil
}
return pointerize(t, baseType, newSt), nil
}
switch baseType.Kind() {
case reflect.Map:
sub, err := val.toConfig(opts.opts)
if err != nil {
return reflect.Value{}, raiseExpectedObject(opts.opts, val)
}
if baseType.Key().Kind() != reflect.String {
return reflect.Value{}, raiseKeyInvalidTypeUnpack(baseType, sub)
}
newMap := reflect.MakeMap(baseType)
if err := reifyInto(opts.opts, newMap, sub); err != nil {
return reflect.Value{}, err
}
return newMap, nil
case reflect.Slice:
v, err := reifySlice(opts, baseType, val)
if err != nil {
return reflect.Value{}, err
}
return pointerize(t, baseType, v), nil
}
return reifyPrimitive(opts, val, t, baseType)
}