hcl: All number parsing should use cty.ParseNumberVal
When dealing with numbers that have no finite representation in base 2, it is important that all parsers agree on the expected maximum precision. Previously we had agreement by convention, but for robustness here we'll centralize the handling of number parsing to cty.ParseNumberVal, which uses the same settings as we were previously using in the JSON parser and, for the native syntax parser, is just a shorthand to the same parsing we were previously doing with the cty/convert package. This should cause no behavior change since all of these callers were previously in agreement with the cty "standard", but this factoring helps establish that there _is_ a standard here.
This commit is contained in:
parent
96efb87de3
commit
a9ca194bcd
@ -9,7 +9,6 @@ import (
|
||||
"github.com/apparentlymart/go-textseg/textseg"
|
||||
"github.com/hashicorp/hcl2/hcl"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/convert"
|
||||
)
|
||||
|
||||
type parser struct {
|
||||
@ -1048,11 +1047,10 @@ func (p *parser) parseExpressionTerm() (Expression, hcl.Diagnostics) {
|
||||
}
|
||||
|
||||
func (p *parser) numberLitValue(tok Token) (cty.Value, hcl.Diagnostics) {
|
||||
// We'll lean on the cty converter to do the conversion, to ensure that
|
||||
// the behavior is the same as what would happen if converting a
|
||||
// non-literal string to a number.
|
||||
numStrVal := cty.StringVal(string(tok.Bytes))
|
||||
numVal, err := convert.Convert(numStrVal, cty.Number)
|
||||
// The cty.ParseNumberVal is always the same behavior as converting a
|
||||
// string to a number, ensuring we always interpret decimal numbers in
|
||||
// the same way.
|
||||
numVal, err := cty.ParseNumberVal(string(tok.Bytes))
|
||||
if err != nil {
|
||||
ret := cty.UnknownVal(cty.Number)
|
||||
return ret, hcl.Diagnostics{
|
||||
|
@ -3,9 +3,9 @@ package json
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/hashicorp/hcl2/hcl"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
func parseFileContent(buf []byte, filename string) (node, hcl.Diagnostics) {
|
||||
@ -370,10 +370,15 @@ func parseNumber(p *peeker) (node, hcl.Diagnostics) {
|
||||
}
|
||||
}
|
||||
|
||||
f, _, err := big.ParseFloat(string(num), 10, 512, big.ToNearestEven)
|
||||
// We want to guarantee that we parse numbers the same way as cty (and thus
|
||||
// native syntax HCL) would here, so we'll use the cty parser even though
|
||||
// in most other cases we don't actually introduce cty concepts until
|
||||
// decoding time. We'll unwrap the parsed float immediately afterwards, so
|
||||
// the cty value is just a temporary helper.
|
||||
nv, err := cty.ParseNumberVal(string(num))
|
||||
if err != nil {
|
||||
// Should never happen if above passed, since JSON numbers are a subset
|
||||
// of what big.Float can parse...
|
||||
// of what cty can parse...
|
||||
return nil, hcl.Diagnostics{
|
||||
{
|
||||
Severity: hcl.DiagError,
|
||||
@ -385,7 +390,7 @@ func parseNumber(p *peeker) (node, hcl.Diagnostics) {
|
||||
}
|
||||
|
||||
return &numberVal{
|
||||
Value: f,
|
||||
Value: nv.AsBigFloat(),
|
||||
SrcRange: tok.Range,
|
||||
}, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user