]> Cypherpunks repositories - gostls13.git/commitdiff
math/big: move Int/Rat gob/json/xml functionality in separate files
authorRobert Griesemer <gri@golang.org>
Fri, 25 Sep 2015 21:56:19 +0000 (14:56 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 25 Sep 2015 22:25:36 +0000 (22:25 +0000)
Like int/rat/float conversions, move this functionality into separate
implementation and test files.

No implementation changes besides the move.

Change-Id: If19c45f5a72a57b95cbce2329724693ae5a4807d
Reviewed-on: https://go-review.googlesource.com/14997
Reviewed-by: Alan Donovan <adonovan@google.com>
src/math/big/int.go
src/math/big/int_test.go
src/math/big/intmarsh.go [new file with mode: 0644]
src/math/big/intmarsh_test.go [new file with mode: 0644]
src/math/big/rat.go
src/math/big/rat_test.go
src/math/big/ratmarsh.go [new file with mode: 0644]
src/math/big/ratmarsh_test.go [new file with mode: 0644]

index 84485a27502bd5c1cda16edab3daa561ebf1cf14..ac5c1f02244de4c4f7eb0fa0fec6ac774dac61a9 100644 (file)
@@ -929,65 +929,3 @@ func (z *Int) Not(x *Int) *Int {
        z.neg = true // z cannot be zero if x is positive
        return z
 }
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const intGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (x *Int) GobEncode() ([]byte, error) {
-       if x == nil {
-               return nil, nil
-       }
-       buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
-       i := x.abs.bytes(buf) - 1            // i >= 0
-       b := intGobVersion << 1              // make space for sign bit
-       if x.neg {
-               b |= 1
-       }
-       buf[i] = b
-       return buf[i:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Int) GobDecode(buf []byte) error {
-       if len(buf) == 0 {
-               // Other side sent a nil or default value.
-               *z = Int{}
-               return nil
-       }
-       b := buf[0]
-       if b>>1 != intGobVersion {
-               return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
-       }
-       z.neg = b&1 != 0
-       z.abs = z.abs.setBytes(buf[1:])
-       return nil
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-func (z *Int) MarshalJSON() ([]byte, error) {
-       // TODO(gri): get rid of the []byte/string conversions
-       return []byte(z.String()), nil
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface.
-func (z *Int) UnmarshalJSON(text []byte) error {
-       // TODO(gri): get rid of the []byte/string conversions
-       if _, ok := z.SetString(string(text), 0); !ok {
-               return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
-       }
-       return nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (z *Int) MarshalText() (text []byte, err error) {
-       return []byte(z.String()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (z *Int) UnmarshalText(text []byte) error {
-       if _, ok := z.SetString(string(text), 0); !ok {
-               return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
-       }
-       return nil
-}
index 5b80509a318f59f75e5d7bac01984625c24fd707..72c2c985c57e2bb04c53e784b714b72464501b3c 100644 (file)
@@ -6,10 +6,7 @@ package big
 
 import (
        "bytes"
-       "encoding/gob"
        "encoding/hex"
-       "encoding/json"
-       "encoding/xml"
        "fmt"
        "math/rand"
        "testing"
@@ -1453,138 +1450,6 @@ func TestJacobiPanic(t *testing.T) {
        panic(failureMsg)
 }
 
-var encodingTests = []string{
-       "-539345864568634858364538753846587364875430589374589",
-       "-678645873",
-       "-100",
-       "-2",
-       "-1",
-       "0",
-       "1",
-       "2",
-       "10",
-       "42",
-       "1234567890",
-       "298472983472983471903246121093472394872319615612417471234712061",
-}
-
-func TestIntGobEncoding(t *testing.T) {
-       var medium bytes.Buffer
-       enc := gob.NewEncoder(&medium)
-       dec := gob.NewDecoder(&medium)
-       for _, test := range encodingTests {
-               medium.Reset() // empty buffer for each test case (in case of failures)
-               var tx Int
-               tx.SetString(test, 10)
-               if err := enc.Encode(&tx); err != nil {
-                       t.Errorf("encoding of %s failed: %s", &tx, err)
-               }
-               var rx Int
-               if err := dec.Decode(&rx); err != nil {
-                       t.Errorf("decoding of %s failed: %s", &tx, err)
-               }
-               if rx.Cmp(&tx) != 0 {
-                       t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
-               }
-       }
-}
-
-// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
-// TODO: top-level nils.
-func TestGobEncodingNilIntInSlice(t *testing.T) {
-       buf := new(bytes.Buffer)
-       enc := gob.NewEncoder(buf)
-       dec := gob.NewDecoder(buf)
-
-       var in = make([]*Int, 1)
-       err := enc.Encode(&in)
-       if err != nil {
-               t.Errorf("gob encode failed: %q", err)
-       }
-       var out []*Int
-       err = dec.Decode(&out)
-       if err != nil {
-               t.Fatalf("gob decode failed: %q", err)
-       }
-       if len(out) != 1 {
-               t.Fatalf("wrong len; want 1 got %d", len(out))
-       }
-       var zero Int
-       if out[0].Cmp(&zero) != 0 {
-               t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
-       }
-}
-
-func TestIntJSONEncoding(t *testing.T) {
-       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)
-               }
-       }
-}
-
-var intVals = []string{
-       "-141592653589793238462643383279502884197169399375105820974944592307816406286",
-       "-1415926535897932384626433832795028841971",
-       "-141592653589793",
-       "-1",
-       "0",
-       "1",
-       "141592653589793",
-       "1415926535897932384626433832795028841971",
-       "141592653589793238462643383279502884197169399375105820974944592307816406286",
-}
-
-func TestIntJSONEncodingTextMarshaller(t *testing.T) {
-       for _, num := range intVals {
-               var tx Int
-               tx.SetString(num, 0)
-               b, err := json.Marshal(&tx)
-               if err != nil {
-                       t.Errorf("marshaling of %s failed: %s", &tx, err)
-                       continue
-               }
-               var rx Int
-               if err := json.Unmarshal(b, &rx); err != nil {
-                       t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-                       continue
-               }
-               if rx.Cmp(&tx) != 0 {
-                       t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-               }
-       }
-}
-
-func TestIntXMLEncodingTextMarshaller(t *testing.T) {
-       for _, num := range intVals {
-               var tx Int
-               tx.SetString(num, 0)
-               b, err := xml.Marshal(&tx)
-               if err != nil {
-                       t.Errorf("marshaling of %s failed: %s", &tx, err)
-                       continue
-               }
-               var rx Int
-               if err := xml.Unmarshal(b, &rx); err != nil {
-                       t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-                       continue
-               }
-               if rx.Cmp(&tx) != 0 {
-                       t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-               }
-       }
-}
-
 func TestIssue2607(t *testing.T) {
        // This code sequence used to hang.
        n := NewInt(10)
diff --git a/src/math/big/intmarsh.go b/src/math/big/intmarsh.go
new file mode 100644 (file)
index 0000000..3c1efec
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements encoding/decoding of Ints.
+
+package big
+
+import "fmt"
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const intGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (x *Int) GobEncode() ([]byte, error) {
+       if x == nil {
+               return nil, nil
+       }
+       buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
+       i := x.abs.bytes(buf) - 1            // i >= 0
+       b := intGobVersion << 1              // make space for sign bit
+       if x.neg {
+               b |= 1
+       }
+       buf[i] = b
+       return buf[i:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Int) GobDecode(buf []byte) error {
+       if len(buf) == 0 {
+               // Other side sent a nil or default value.
+               *z = Int{}
+               return nil
+       }
+       b := buf[0]
+       if b>>1 != intGobVersion {
+               return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
+       }
+       z.neg = b&1 != 0
+       z.abs = z.abs.setBytes(buf[1:])
+       return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (z *Int) MarshalJSON() ([]byte, error) {
+       // TODO(gri): get rid of the []byte/string conversions
+       return []byte(z.String()), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (z *Int) UnmarshalJSON(text []byte) error {
+       // TODO(gri): get rid of the []byte/string conversions
+       if _, ok := z.SetString(string(text), 0); !ok {
+               return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
+       }
+       return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (z *Int) MarshalText() (text []byte, err error) {
+       return []byte(z.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (z *Int) UnmarshalText(text []byte) error {
+       if _, ok := z.SetString(string(text), 0); !ok {
+               return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
+       }
+       return nil
+}
diff --git a/src/math/big/intmarsh_test.go b/src/math/big/intmarsh_test.go
new file mode 100644 (file)
index 0000000..c992f1c
--- /dev/null
@@ -0,0 +1,145 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+       "bytes"
+       "encoding/gob"
+       "encoding/json"
+       "encoding/xml"
+       "testing"
+)
+
+var encodingTests = []string{
+       "-539345864568634858364538753846587364875430589374589",
+       "-678645873",
+       "-100",
+       "-2",
+       "-1",
+       "0",
+       "1",
+       "2",
+       "10",
+       "42",
+       "1234567890",
+       "298472983472983471903246121093472394872319615612417471234712061",
+}
+
+func TestIntGobEncoding(t *testing.T) {
+       var medium bytes.Buffer
+       enc := gob.NewEncoder(&medium)
+       dec := gob.NewDecoder(&medium)
+       for _, test := range encodingTests {
+               medium.Reset() // empty buffer for each test case (in case of failures)
+               var tx Int
+               tx.SetString(test, 10)
+               if err := enc.Encode(&tx); err != nil {
+                       t.Errorf("encoding of %s failed: %s", &tx, err)
+               }
+               var rx Int
+               if err := dec.Decode(&rx); err != nil {
+                       t.Errorf("decoding of %s failed: %s", &tx, err)
+               }
+               if rx.Cmp(&tx) != 0 {
+                       t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+               }
+       }
+}
+
+// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilIntInSlice(t *testing.T) {
+       buf := new(bytes.Buffer)
+       enc := gob.NewEncoder(buf)
+       dec := gob.NewDecoder(buf)
+
+       var in = make([]*Int, 1)
+       err := enc.Encode(&in)
+       if err != nil {
+               t.Errorf("gob encode failed: %q", err)
+       }
+       var out []*Int
+       err = dec.Decode(&out)
+       if err != nil {
+               t.Fatalf("gob decode failed: %q", err)
+       }
+       if len(out) != 1 {
+               t.Fatalf("wrong len; want 1 got %d", len(out))
+       }
+       var zero Int
+       if out[0].Cmp(&zero) != 0 {
+               t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
+       }
+}
+
+func TestIntJSONEncoding(t *testing.T) {
+       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)
+               }
+       }
+}
+
+var intVals = []string{
+       "-141592653589793238462643383279502884197169399375105820974944592307816406286",
+       "-1415926535897932384626433832795028841971",
+       "-141592653589793",
+       "-1",
+       "0",
+       "1",
+       "141592653589793",
+       "1415926535897932384626433832795028841971",
+       "141592653589793238462643383279502884197169399375105820974944592307816406286",
+}
+
+func TestIntJSONEncodingTextMarshaller(t *testing.T) {
+       for _, num := range intVals {
+               var tx Int
+               tx.SetString(num, 0)
+               b, err := json.Marshal(&tx)
+               if err != nil {
+                       t.Errorf("marshaling of %s failed: %s", &tx, err)
+                       continue
+               }
+               var rx Int
+               if err := json.Unmarshal(b, &rx); err != nil {
+                       t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+                       continue
+               }
+               if rx.Cmp(&tx) != 0 {
+                       t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+               }
+       }
+}
+
+func TestIntXMLEncodingTextMarshaller(t *testing.T) {
+       for _, num := range intVals {
+               var tx Int
+               tx.SetString(num, 0)
+               b, err := xml.Marshal(&tx)
+               if err != nil {
+                       t.Errorf("marshaling of %s failed: %s", &tx, err)
+                       continue
+               }
+               var rx Int
+               if err := xml.Unmarshal(b, &rx); err != nil {
+                       t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+                       continue
+               }
+               if rx.Cmp(&tx) != 0 {
+                       t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+               }
+       }
+}
index fb16f18a964e7121dc3cb635887a6a8d37c3628b..2cd9ed09388aeb3dd8a6211217a7aa843ad7f2ea 100644 (file)
@@ -7,8 +7,6 @@
 package big
 
 import (
-       "encoding/binary"
-       "errors"
        "fmt"
        "math"
 )
@@ -510,61 +508,3 @@ func (z *Rat) Quo(x, y *Rat) *Rat {
        z.a.neg = a.neg != b.neg
        return z.norm()
 }
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const ratGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (x *Rat) GobEncode() ([]byte, error) {
-       if x == nil {
-               return nil, nil
-       }
-       buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
-       i := x.b.abs.bytes(buf)
-       j := x.a.abs.bytes(buf[:i])
-       n := i - j
-       if int(uint32(n)) != n {
-               // this should never happen
-               return nil, errors.New("Rat.GobEncode: numerator too large")
-       }
-       binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
-       j -= 1 + 4
-       b := ratGobVersion << 1 // make space for sign bit
-       if x.a.neg {
-               b |= 1
-       }
-       buf[j] = b
-       return buf[j:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Rat) GobDecode(buf []byte) error {
-       if len(buf) == 0 {
-               // Other side sent a nil or default value.
-               *z = Rat{}
-               return nil
-       }
-       b := buf[0]
-       if b>>1 != ratGobVersion {
-               return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
-       }
-       const j = 1 + 4
-       i := j + binary.BigEndian.Uint32(buf[j-4:j])
-       z.a.neg = b&1 != 0
-       z.a.abs = z.a.abs.setBytes(buf[j:i])
-       z.b.abs = z.b.abs.setBytes(buf[i:])
-       return nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (r *Rat) MarshalText() (text []byte, err error) {
-       return []byte(r.RatString()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (r *Rat) UnmarshalText(text []byte) error {
-       if _, ok := r.SetString(string(text)); !ok {
-               return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
-       }
-       return nil
-}
index 012d0c47ec4fb857553e9bb6de246f102dfd8348..3a06fca3c347f636369d861bfa528114f5777478 100644 (file)
@@ -5,10 +5,6 @@
 package big
 
 import (
-       "bytes"
-       "encoding/gob"
-       "encoding/json"
-       "encoding/xml"
        "math"
        "testing"
 )
@@ -280,116 +276,6 @@ func TestRatSetFrac64Rat(t *testing.T) {
        }
 }
 
-func TestRatGobEncoding(t *testing.T) {
-       var medium bytes.Buffer
-       enc := gob.NewEncoder(&medium)
-       dec := gob.NewDecoder(&medium)
-       for _, test := range encodingTests {
-               medium.Reset() // empty buffer for each test case (in case of failures)
-               var tx Rat
-               tx.SetString(test + ".14159265")
-               if err := enc.Encode(&tx); err != nil {
-                       t.Errorf("encoding of %s failed: %s", &tx, err)
-               }
-               var rx Rat
-               if err := dec.Decode(&rx); err != nil {
-                       t.Errorf("decoding of %s failed: %s", &tx, err)
-               }
-               if rx.Cmp(&tx) != 0 {
-                       t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
-               }
-       }
-}
-
-// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
-// TODO: top-level nils.
-func TestGobEncodingNilRatInSlice(t *testing.T) {
-       buf := new(bytes.Buffer)
-       enc := gob.NewEncoder(buf)
-       dec := gob.NewDecoder(buf)
-
-       var in = make([]*Rat, 1)
-       err := enc.Encode(&in)
-       if err != nil {
-               t.Errorf("gob encode failed: %q", err)
-       }
-       var out []*Rat
-       err = dec.Decode(&out)
-       if err != nil {
-               t.Fatalf("gob decode failed: %q", err)
-       }
-       if len(out) != 1 {
-               t.Fatalf("wrong len; want 1 got %d", len(out))
-       }
-       var zero Rat
-       if out[0].Cmp(&zero) != 0 {
-               t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
-       }
-}
-
-var ratNums = []string{
-       "-141592653589793238462643383279502884197169399375105820974944592307816406286",
-       "-1415926535897932384626433832795028841971",
-       "-141592653589793",
-       "-1",
-       "0",
-       "1",
-       "141592653589793",
-       "1415926535897932384626433832795028841971",
-       "141592653589793238462643383279502884197169399375105820974944592307816406286",
-}
-
-var ratDenoms = []string{
-       "1",
-       "718281828459045",
-       "7182818284590452353602874713526624977572",
-       "718281828459045235360287471352662497757247093699959574966967627724076630353",
-}
-
-func TestRatJSONEncoding(t *testing.T) {
-       for _, num := range ratNums {
-               for _, denom := range ratDenoms {
-                       var tx Rat
-                       tx.SetString(num + "/" + denom)
-                       b, err := json.Marshal(&tx)
-                       if err != nil {
-                               t.Errorf("marshaling of %s failed: %s", &tx, err)
-                               continue
-                       }
-                       var rx Rat
-                       if err := json.Unmarshal(b, &rx); err != nil {
-                               t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-                               continue
-                       }
-                       if rx.Cmp(&tx) != 0 {
-                               t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-                       }
-               }
-       }
-}
-
-func TestRatXMLEncoding(t *testing.T) {
-       for _, num := range ratNums {
-               for _, denom := range ratDenoms {
-                       var tx Rat
-                       tx.SetString(num + "/" + denom)
-                       b, err := xml.Marshal(&tx)
-                       if err != nil {
-                               t.Errorf("marshaling of %s failed: %s", &tx, err)
-                               continue
-                       }
-                       var rx Rat
-                       if err := xml.Unmarshal(b, &rx); err != nil {
-                               t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-                               continue
-                       }
-                       if rx.Cmp(&tx) != 0 {
-                               t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-                       }
-               }
-       }
-}
-
 func TestIssue2379(t *testing.T) {
        // 1) no aliasing
        q := NewRat(3, 2)
diff --git a/src/math/big/ratmarsh.go b/src/math/big/ratmarsh.go
new file mode 100644 (file)
index 0000000..b79cbe6
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements encoding/decoding of Rats.
+
+package big
+
+import (
+       "encoding/binary"
+       "errors"
+       "fmt"
+)
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const ratGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (x *Rat) GobEncode() ([]byte, error) {
+       if x == nil {
+               return nil, nil
+       }
+       buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
+       i := x.b.abs.bytes(buf)
+       j := x.a.abs.bytes(buf[:i])
+       n := i - j
+       if int(uint32(n)) != n {
+               // this should never happen
+               return nil, errors.New("Rat.GobEncode: numerator too large")
+       }
+       binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
+       j -= 1 + 4
+       b := ratGobVersion << 1 // make space for sign bit
+       if x.a.neg {
+               b |= 1
+       }
+       buf[j] = b
+       return buf[j:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Rat) GobDecode(buf []byte) error {
+       if len(buf) == 0 {
+               // Other side sent a nil or default value.
+               *z = Rat{}
+               return nil
+       }
+       b := buf[0]
+       if b>>1 != ratGobVersion {
+               return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
+       }
+       const j = 1 + 4
+       i := j + binary.BigEndian.Uint32(buf[j-4:j])
+       z.a.neg = b&1 != 0
+       z.a.abs = z.a.abs.setBytes(buf[j:i])
+       z.b.abs = z.b.abs.setBytes(buf[i:])
+       return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (r *Rat) MarshalText() (text []byte, err error) {
+       return []byte(r.RatString()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (r *Rat) UnmarshalText(text []byte) error {
+       if _, ok := r.SetString(string(text)); !ok {
+               return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
+       }
+       return nil
+}
diff --git a/src/math/big/ratmarsh_test.go b/src/math/big/ratmarsh_test.go
new file mode 100644 (file)
index 0000000..2e91e38
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+       "bytes"
+       "encoding/gob"
+       "encoding/json"
+       "encoding/xml"
+       "testing"
+)
+
+func TestRatGobEncoding(t *testing.T) {
+       var medium bytes.Buffer
+       enc := gob.NewEncoder(&medium)
+       dec := gob.NewDecoder(&medium)
+       for _, test := range encodingTests {
+               medium.Reset() // empty buffer for each test case (in case of failures)
+               var tx Rat
+               tx.SetString(test + ".14159265")
+               if err := enc.Encode(&tx); err != nil {
+                       t.Errorf("encoding of %s failed: %s", &tx, err)
+               }
+               var rx Rat
+               if err := dec.Decode(&rx); err != nil {
+                       t.Errorf("decoding of %s failed: %s", &tx, err)
+               }
+               if rx.Cmp(&tx) != 0 {
+                       t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+               }
+       }
+}
+
+// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilRatInSlice(t *testing.T) {
+       buf := new(bytes.Buffer)
+       enc := gob.NewEncoder(buf)
+       dec := gob.NewDecoder(buf)
+
+       var in = make([]*Rat, 1)
+       err := enc.Encode(&in)
+       if err != nil {
+               t.Errorf("gob encode failed: %q", err)
+       }
+       var out []*Rat
+       err = dec.Decode(&out)
+       if err != nil {
+               t.Fatalf("gob decode failed: %q", err)
+       }
+       if len(out) != 1 {
+               t.Fatalf("wrong len; want 1 got %d", len(out))
+       }
+       var zero Rat
+       if out[0].Cmp(&zero) != 0 {
+               t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
+       }
+}
+
+var ratNums = []string{
+       "-141592653589793238462643383279502884197169399375105820974944592307816406286",
+       "-1415926535897932384626433832795028841971",
+       "-141592653589793",
+       "-1",
+       "0",
+       "1",
+       "141592653589793",
+       "1415926535897932384626433832795028841971",
+       "141592653589793238462643383279502884197169399375105820974944592307816406286",
+}
+
+var ratDenoms = []string{
+       "1",
+       "718281828459045",
+       "7182818284590452353602874713526624977572",
+       "718281828459045235360287471352662497757247093699959574966967627724076630353",
+}
+
+func TestRatJSONEncoding(t *testing.T) {
+       for _, num := range ratNums {
+               for _, denom := range ratDenoms {
+                       var tx Rat
+                       tx.SetString(num + "/" + denom)
+                       b, err := json.Marshal(&tx)
+                       if err != nil {
+                               t.Errorf("marshaling of %s failed: %s", &tx, err)
+                               continue
+                       }
+                       var rx Rat
+                       if err := json.Unmarshal(b, &rx); err != nil {
+                               t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+                               continue
+                       }
+                       if rx.Cmp(&tx) != 0 {
+                               t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+                       }
+               }
+       }
+}
+
+func TestRatXMLEncoding(t *testing.T) {
+       for _, num := range ratNums {
+               for _, denom := range ratDenoms {
+                       var tx Rat
+                       tx.SetString(num + "/" + denom)
+                       b, err := xml.Marshal(&tx)
+                       if err != nil {
+                               t.Errorf("marshaling of %s failed: %s", &tx, err)
+                               continue
+                       }
+                       var rx Rat
+                       if err := xml.Unmarshal(b, &rx); err != nil {
+                               t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+                               continue
+                       }
+                       if rx.Cmp(&tx) != 0 {
+                               t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+                       }
+               }
+       }
+}