Skip to content

Commit e16fe30

Browse files
committed
fix: handle Inf and NaN in conversions
1 parent d829b47 commit e16fe30

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

conversion.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ func RequireConvert[NumOut Number, NumIn Input](t TestingT, orig NumIn) (convert
9797

9898
func convertFromNumber[NumOut Number, NumIn Number](orig NumIn) (NumOut, error) {
9999
converted := NumOut(orig)
100+
if isFloat64[NumIn]() {
101+
floatOrig := float64(orig)
102+
if math.IsInf(floatOrig, 1) || math.IsInf(floatOrig, -1) {
103+
return 0, getRangeError[NumOut](orig)
104+
}
105+
if math.IsNaN(floatOrig) {
106+
return 0, errorHelper[NumOut]{
107+
value: orig,
108+
err: ErrUnsupportedConversion,
109+
}
110+
}
111+
}
112+
100113
if isFloat64[NumOut]() {
101114
// float64 cannot overflow, so we don't have to worry about it
102115
return converted, nil

conversion_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,6 +1736,36 @@ func TestConvert(t *testing.T) {
17361736
})
17371737

17381738
for name, c := range map[string]TestRunner{
1739+
"math.Inf to float64": MapTest[float64, float64]{
1740+
Input: math.Inf(1),
1741+
ExpectedError: safecast.ErrExceedMaximumValue,
1742+
ErrorContains: "+Inf (float64) is greater than 1.7976931348623157e+308",
1743+
},
1744+
"-math.Inf to float64": MapTest[float64, float64]{
1745+
Input: math.Inf(-1),
1746+
ExpectedError: safecast.ErrExceedMinimumValue,
1747+
ErrorContains: "-Inf (float64) is less than -1.7976931348623157e+308",
1748+
},
1749+
"math.NaN to float64": MapTest[float64, float64]{
1750+
Input: math.NaN(),
1751+
ExpectedError: safecast.ErrUnsupportedConversion,
1752+
ErrorContains: "NaN (float64) is not supported",
1753+
},
1754+
"math.Inf to float32": MapTest[float64, float32]{
1755+
Input: math.Inf(1),
1756+
ExpectedError: safecast.ErrExceedMaximumValue,
1757+
ErrorContains: "+Inf (float64) is greater than 3.4028235e+38",
1758+
},
1759+
"-math.Inf to float32": MapTest[float64, float32]{
1760+
Input: math.Inf(-1),
1761+
ExpectedError: safecast.ErrExceedMinimumValue,
1762+
ErrorContains: "-Inf (float64) is less than -3.4028235e+38",
1763+
},
1764+
"math.NaN to float32": MapTest[float64, float32]{
1765+
Input: math.NaN(),
1766+
ExpectedError: safecast.ErrUnsupportedConversion,
1767+
ErrorContains: "NaN (float64) is not supported",
1768+
},
17391769
"upper bound overflows for int": MapTest[uint, int]{
17401770
Input: uint(math.MaxInt + 1),
17411771
ExpectedError: safecast.ErrExceedMaximumValue,

errors.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ func (e errorHelper[NumOut]) Error() string {
4141
case errors.Is(e.err, ErrExceedMinimumValue):
4242
boundary := minOf[NumOut]()
4343
errMessage = fmt.Sprintf("%s: %v (%T) is less than %v (%T)", errMessage, e.value, e.value, boundary, boundary)
44+
case errors.Is(e.err, ErrUnsupportedConversion):
45+
errMessage = fmt.Sprintf("%s: %v (%T) is not supported", errMessage, e.value, e.value)
4446
case errors.Is(e.err, ErrStringConversion):
4547
targetType := NumOut(0)
4648
return fmt.Sprintf("%s: cannot convert from string %s to %T (base auto-detection)", errMessage, e.value, targetType)

0 commit comments

Comments
 (0)