func normalizeValue()

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)
	}
}