chore: simplify parsing numbers with overflow (#3610)

master
Kevin Wan 1 year ago committed by GitHub
parent ff230c4b1d
commit 5aedd9c076
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -622,7 +622,7 @@ func (u *Unmarshaler) processFieldPrimitiveWithJSONNumber(fieldType reflect.Type
} }
if fValue > math.MaxFloat32 { if fValue > math.MaxFloat32 {
return float32OverflowError(v.String()) return fmt.Errorf("parsing %q as float32: value out of range", v.String())
} }
target.SetFloat(fValue) target.SetFloat(fValue)

@ -30,6 +30,7 @@ const (
leftSquareBracket = '[' leftSquareBracket = '['
rightSquareBracket = ']' rightSquareBracket = ']'
segmentSeparator = ',' segmentSeparator = ','
intSize = 32 << (^uint(0) >> 63)
) )
var ( var (
@ -42,10 +43,6 @@ var (
) )
type ( type (
integer interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
optionsCacheValue struct { optionsCacheValue struct {
key string key string
options *fieldOptions options *fieldOptions
@ -104,38 +101,30 @@ func convertTypeFromString(kind reflect.Kind, str string) (any, error) {
default: default:
return false, errTypeMismatch return false, errTypeMismatch
} }
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int:
intValue, err := strconv.ParseInt(str, 10, 64) return strconv.ParseInt(str, 10, intSize)
if err != nil { case reflect.Int8:
return 0, err return strconv.ParseInt(str, 10, 8)
} case reflect.Int16:
return strconv.ParseInt(str, 10, 16)
return intValue, nil case reflect.Int32:
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return strconv.ParseInt(str, 10, 32)
uintValue, err := strconv.ParseUint(str, 10, 64) case reflect.Int64:
if err != nil { return strconv.ParseInt(str, 10, 64)
return 0, err case reflect.Uint:
} return strconv.ParseUint(str, 10, intSize)
case reflect.Uint8:
return uintValue, nil return strconv.ParseUint(str, 10, 8)
case reflect.Uint16:
return strconv.ParseUint(str, 10, 16)
case reflect.Uint32:
return strconv.ParseUint(str, 10, 32)
case reflect.Uint64:
return strconv.ParseUint(str, 10, 64)
case reflect.Float32: case reflect.Float32:
floatValue, err := strconv.ParseFloat(str, 64) return strconv.ParseFloat(str, 32)
if err != nil {
return 0, err
}
if floatValue > math.MaxFloat32 {
return 0, float32OverflowError(str)
}
return floatValue, nil
case reflect.Float64: case reflect.Float64:
floatValue, err := strconv.ParseFloat(str, 64) return strconv.ParseFloat(str, 64)
if err != nil {
return 0, err
}
return floatValue, nil
case reflect.String: case reflect.String:
return str, nil return str, nil
default: default:
@ -230,10 +219,6 @@ func implicitValueRequiredStruct(tag string, tp reflect.Type) (bool, error) {
return false, nil return false, nil
} }
func intOverflowError[T integer](v T, kind reflect.Kind) error {
return fmt.Errorf("parsing \"%d\" as %s: value out of range", v, kind.String())
}
func isLeftInclude(b byte) (bool, error) { func isLeftInclude(b byte) (bool, error) {
switch b { switch b {
case '[': case '[':
@ -256,10 +241,6 @@ func isRightInclude(b byte) (bool, error) {
} }
} }
func float32OverflowError(str string) error {
return fmt.Errorf("parsing %q as float32: value out of range", str)
}
func maybeNewValue(fieldType reflect.Type, value reflect.Value) { func maybeNewValue(fieldType reflect.Type, value reflect.Value) {
if fieldType.Kind() == reflect.Ptr && value.IsNil() { if fieldType.Kind() == reflect.Ptr && value.IsNil() {
value.Set(reflect.New(value.Type().Elem())) value.Set(reflect.New(value.Type().Elem()))
@ -505,41 +486,15 @@ func parseSegments(val string) []string {
return segments return segments
} }
func setIntValue(value reflect.Value, v any, min, max int64) error {
iv := v.(int64)
if iv < min || iv > max {
return intOverflowError(iv, value.Kind())
}
value.SetInt(iv)
return nil
}
func setMatchedPrimitiveValue(kind reflect.Kind, value reflect.Value, v any) error { func setMatchedPrimitiveValue(kind reflect.Kind, value reflect.Value, v any) error {
switch kind { switch kind {
case reflect.Bool: case reflect.Bool:
value.SetBool(v.(bool)) value.SetBool(v.(bool))
return nil return nil
case reflect.Int: // int depends on int size, 32 or 64 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return setIntValue(value, v, math.MinInt, math.MaxInt)
case reflect.Int8:
return setIntValue(value, v, math.MinInt8, math.MaxInt8)
case reflect.Int16:
return setIntValue(value, v, math.MinInt16, math.MaxInt16)
case reflect.Int32:
return setIntValue(value, v, math.MinInt32, math.MaxInt32)
case reflect.Int64:
value.SetInt(v.(int64)) value.SetInt(v.(int64))
return nil return nil
case reflect.Uint: // uint depends on int size, 32 or 64 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return setUintValue(value, v, math.MaxUint)
case reflect.Uint8:
return setUintValue(value, v, math.MaxUint8)
case reflect.Uint16:
return setUintValue(value, v, math.MaxUint16)
case reflect.Uint32:
return setUintValue(value, v, math.MaxUint32)
case reflect.Uint64:
value.SetUint(v.(uint64)) value.SetUint(v.(uint64))
return nil return nil
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
@ -553,16 +508,6 @@ func setMatchedPrimitiveValue(kind reflect.Kind, value reflect.Value, v any) err
} }
} }
func setUintValue(value reflect.Value, v any, boundary uint64) error {
iv := v.(uint64)
if iv > boundary {
return intOverflowError(iv, value.Kind())
}
value.SetUint(iv)
return nil
}
func setValueFromString(kind reflect.Kind, value reflect.Value, str string) error { func setValueFromString(kind reflect.Kind, value reflect.Value, str string) error {
if !value.CanSet() { if !value.CanSet() {
return errValueNotSettable return errValueNotSettable

Loading…
Cancel
Save