Skip to content

Commit

Permalink
fix: prevent formating issues with decimal
Browse files Browse the repository at this point in the history
  • Loading branch information
dunglas committed Nov 22, 2022
1 parent 3609e94 commit 05d3e0b
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 7 deletions.
7 changes: 4 additions & 3 deletions decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"math"
"strconv"
"strings"
)

const maxDecDigit = 3
Expand All @@ -21,18 +22,18 @@ func marshalDecimal(b io.StringWriter, d float64) error {
const TH = 0.001

rounded := math.RoundToEven(d/TH) * TH
i, frac := math.Modf(math.RoundToEven(d/TH) * TH)
i, frac := math.Modf(rounded)

if i < -999999999999 || i > 999999999999 {
return ErrInvalidDecimal
}

if _, err := b.WriteString(strconv.FormatFloat(rounded, 'f', -1, 64)); err != nil {
if _, err := b.WriteString(strings.TrimRight(strconv.FormatFloat(rounded, 'f', 3, 64), "0")); err != nil {
return err
}

if frac == 0 {
_, err := b.WriteString(".0")
_, err := b.WriteString("0")

return err
}
Expand Down
1 change: 1 addition & 0 deletions decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestDecimalMarshalSFV(t *testing.T) {
{9999999999999, "", false},
{-9999999999999.0, "", false},
{9999999999999.0, "", false},
{1.9, "1.9", true},
}

var b strings.Builder
Expand Down
18 changes: 14 additions & 4 deletions list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,31 @@ func FuzzUnmarshalList(f *testing.F) {
`("é")`,
`(""`,
`(`,
"1.9",
}

for _, t := range testCases {
f.Add(t)
}

f.Fuzz(func(t *testing.T, b string) {
l, err := UnmarshalList([]string{b})

unmarshaled, err := UnmarshalList([]string{b})
if err != nil {
return
}

if _, err := Marshal(l); err != nil {
t.Errorf("Unexpected marshaling error %q for %q, %#v", err, b, l)
reMarshaled, err := Marshal(unmarshaled)
if err != nil {
t.Errorf("Unexpected marshaling error %q for %q, %#v", err, b, unmarshaled)
}

reUnmarshaled, err := UnmarshalList([]string{reMarshaled})
if err != nil {
t.Errorf("Unexpected remarshaling error %q for %q; original %q", err, reMarshaled, b)
}

if !reflect.DeepEqual(unmarshaled, reUnmarshaled) {
t.Errorf("Unmarshaled and re-unmarshaled doesn't match: %#v; %#v", unmarshaled, reUnmarshaled)
}
})
}

0 comments on commit 05d3e0b

Please sign in to comment.