Expand the numeric conversions to template funcs/methods

So the example mentioned in #14079 also works for TOML and JSON front matter.

See #14079
This commit is contained in:
Bjørn Erik Pedersen
2025-10-22 19:12:11 +02:00
parent df4f80d54f
commit e08278d165
3 changed files with 88 additions and 3 deletions
+16
View File
@@ -315,6 +315,7 @@ func IsContextType(tp reflect.Type) bool {
// This is currently only implemented for int kinds,
// added to handle the move to a new YAML library which produces uint64 for unsigned integers.
// We can expand on this later if needed.
// This conversion is lossless.
// See Issue 14079.
func ConvertIfPossible(val reflect.Value, typ reflect.Type) (reflect.Value, bool) {
if IsInt(typ.Kind()) {
@@ -333,6 +334,21 @@ func ConvertIfPossible(val reflect.Value, typ reflect.Type) (reflect.Value, bool
}
return val.Convert(typ), true
}
if IsFloat(val.Kind()) {
f := val.Float()
if f < float64(math.MinInt64) || f > float64(math.MaxInt64) {
return reflect.Value{}, false
}
i := int64(f)
if typ.OverflowInt(i) {
return reflect.Value{}, false
}
// Check for lossless conversion.
if float64(i) != f {
return reflect.Value{}, false
}
return val.Convert(typ), true
}
}
return reflect.Value{}, false
}
+27
View File
@@ -231,6 +231,33 @@ func TestCastIfPossible(t *testing.T) {
ok: true,
expected: int(math.MaxInt16),
},
// From float to int.
{
name: "float64(1.5) to int",
value: float64(1.5),
typ: int(0),
ok: false, // loss of precision
},
{
name: "float64(1.0) to int",
value: float64(1.0),
typ: int(0),
ok: true,
expected: int(1),
},
{
name: "float64(math.MaxFloat64) to int16",
value: float64(math.MaxFloat64),
typ: int16(0),
ok: false, // overflow
},
{
name: "float64(32767) to int16",
value: float64(32767),
typ: int16(0),
ok: true,
expected: int16(32767),
},
} {
v, ok := ConvertIfPossible(reflect.ValueOf(test.value), reflect.TypeOf(test.typ))