chore: simplify parsing numbers with overflow (#3610)
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user