Commit 13a59b8c authored by Robert Griesemer's avatar Robert Griesemer

math/big: implement JSON un/marshaling support for Ints

Also: simplified some existing tests.

No support for Rats for now because the precision-preserving
default notation (fractions of the form a/b) is not a valid
JSON value.

Fixes #3657.

R=golang-dev, bradfitz, rsc
CC=golang-dev
https://golang.org/cl/6211079
parent 4f7c33cd
...@@ -894,3 +894,19 @@ func (z *Int) GobDecode(buf []byte) error { ...@@ -894,3 +894,19 @@ func (z *Int) GobDecode(buf []byte) error {
z.abs = z.abs.setBytes(buf[1:]) z.abs = z.abs.setBytes(buf[1:])
return nil return nil
} }
// MarshalJSON implements the json.Marshaler interface.
func (x *Int) MarshalJSON() ([]byte, error) {
// TODO(gri): get rid of the []byte/string conversions
return []byte(x.String()), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (z *Int) UnmarshalJSON(x []byte) error {
// TODO(gri): get rid of the []byte/string conversions
_, ok := z.SetString(string(x), 0)
if !ok {
return fmt.Errorf("math/big: cannot unmarshal %s into a *big.Int", x)
}
return nil
}
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"math/rand" "math/rand"
"testing" "testing"
...@@ -1368,8 +1369,12 @@ func TestModInverse(t *testing.T) { ...@@ -1368,8 +1369,12 @@ func TestModInverse(t *testing.T) {
} }
} }
// used by TestIntGobEncoding and TestRatGobEncoding var encodingTests = []string{
var gobEncodingTests = []string{ "-539345864568634858364538753846587364875430589374589",
"-678645873",
"-100",
"-2",
"-1",
"0", "0",
"1", "1",
"2", "2",
...@@ -1383,26 +1388,37 @@ func TestIntGobEncoding(t *testing.T) { ...@@ -1383,26 +1388,37 @@ func TestIntGobEncoding(t *testing.T) {
var medium bytes.Buffer var medium bytes.Buffer
enc := gob.NewEncoder(&medium) enc := gob.NewEncoder(&medium)
dec := gob.NewDecoder(&medium) dec := gob.NewDecoder(&medium)
for i, test := range gobEncodingTests { for _, test := range encodingTests {
for j := 0; j < 2; j++ { medium.Reset() // empty buffer for each test case (in case of failures)
medium.Reset() // empty buffer for each test case (in case of failures) var tx Int
stest := test tx.SetString(test, 10)
if j != 0 { if err := enc.Encode(&tx); err != nil {
// negative numbers t.Errorf("encoding of %s failed: %s", &tx, err)
stest = "-" + test }
} var rx Int
var tx Int if err := dec.Decode(&rx); err != nil {
tx.SetString(stest, 10) t.Errorf("decoding of %s failed: %s", &tx, err)
if err := enc.Encode(&tx); err != nil { }
t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err) if rx.Cmp(&tx) != 0 {
} t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
var rx Int }
if err := dec.Decode(&rx); err != nil { }
t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err) }
}
if rx.Cmp(&tx) != 0 { func TestIntJSONEncoding(t *testing.T) {
t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx) for _, test := range encodingTests {
} var tx Int
tx.SetString(test, 10)
b, err := json.Marshal(&tx)
if err != nil {
t.Errorf("marshaling of %s failed: %s", &tx, err)
}
var rx Int
if err := json.Unmarshal(b, &rx); err != nil {
t.Errorf("unmarshaling of %s failed: %s", &tx, err)
}
if rx.Cmp(&tx) != 0 {
t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
} }
} }
} }
......
...@@ -387,30 +387,19 @@ func TestRatGobEncoding(t *testing.T) { ...@@ -387,30 +387,19 @@ func TestRatGobEncoding(t *testing.T) {
var medium bytes.Buffer var medium bytes.Buffer
enc := gob.NewEncoder(&medium) enc := gob.NewEncoder(&medium)
dec := gob.NewDecoder(&medium) dec := gob.NewDecoder(&medium)
for i, test := range gobEncodingTests { for _, test := range encodingTests {
for j := 0; j < 4; j++ { medium.Reset() // empty buffer for each test case (in case of failures)
medium.Reset() // empty buffer for each test case (in case of failures) var tx Rat
stest := test tx.SetString(test + ".14159265")
if j&1 != 0 { if err := enc.Encode(&tx); err != nil {
// negative numbers t.Errorf("encoding of %s failed: %s", &tx, err)
stest = "-" + test }
} var rx Rat
if j%2 != 0 { if err := dec.Decode(&rx); err != nil {
// fractions t.Errorf("decoding of %s failed: %s", &tx, err)
stest = stest + "." + test }
} if rx.Cmp(&tx) != 0 {
var tx Rat t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
tx.SetString(stest)
if err := enc.Encode(&tx); err != nil {
t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
}
var rx Rat
if err := dec.Decode(&rx); err != nil {
t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
}
if rx.Cmp(&tx) != 0 {
t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
}
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment