in merge.go [455:510]
func normalizeValue(
opts *options,
tagOpts tagOptions,
ctx context,
v reflect.Value,
) (value, Error) {
v = chaseValue(v)
switch v.Type() {
case tDuration:
d := v.Interface().(time.Duration)
return newString(ctx, opts.meta, d.String()), nil
case tRegexp:
r := v.Addr().Interface().(*regexp.Regexp)
return newString(ctx, opts.meta, r.String()), nil
}
// handle primitives
switch v.Kind() {
case reflect.Bool:
return newBool(ctx, opts.meta, v.Bool()), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i := v.Int()
if i > 0 {
return newUint(ctx, opts.meta, uint64(i)), nil
}
return newInt(ctx, opts.meta, i), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return newUint(ctx, opts.meta, v.Uint()), nil
case reflect.Float32, reflect.Float64:
f := v.Float()
return newFloat(ctx, opts.meta, f), nil
case reflect.String:
return normalizeString(ctx, opts, v.String())
case reflect.Array, reflect.Slice:
return normalizeArray(opts, tagOpts, ctx, v)
case reflect.Map:
return normalizeMapValue(opts, ctx, v)
case reflect.Struct:
if v, ok := tryTConfig(v); ok {
c := v.Addr().Interface().(*Config)
ret := cfgSub{c}
if ret.Context().parent != ctx.parent {
ret.SetContext(ctx)
}
return ret, nil
}
return normalizeStructValue(opts, ctx, v)
default:
if v.IsNil() {
return &cfgNil{cfgPrimitive{ctx, opts.meta}}, nil
}
return nil, raiseUnsupportedInputType(ctx, opts.meta, v)
}
}