github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/math/big/ratmarsh.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file implements encoding/decoding of Rats. 6 7 package big 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 "math" 14 ) 15 16 // Gob codec version. Permits backward-compatible changes to the encoding. 17 const ratGobVersion byte = 1 18 19 // GobEncode implements the gob.GobEncoder interface. 20 func (x *Rat) GobEncode() ([]byte, error) { 21 if x == nil { 22 return nil, nil 23 } 24 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) 25 i := x.b.abs.bytes(buf) 26 j := x.a.abs.bytes(buf[:i]) 27 n := i - j 28 if int(uint32(n)) != n { 29 // this should never happen 30 return nil, errors.New("Rat.GobEncode: numerator too large") 31 } 32 binary.BigEndian.PutUint32(buf[j-4:j], uint32(n)) 33 j -= 1 + 4 34 b := ratGobVersion << 1 // make space for sign bit 35 if x.a.neg { 36 b |= 1 37 } 38 buf[j] = b 39 return buf[j:], nil 40 } 41 42 // GobDecode implements the gob.GobDecoder interface. 43 func (z *Rat) GobDecode(buf []byte) error { 44 if len(buf) == 0 { 45 // Other side sent a nil or default value. 46 *z = Rat{} 47 return nil 48 } 49 if len(buf) < 5 { 50 return errors.New("Rat.GobDecode: buffer too small") 51 } 52 b := buf[0] 53 if b>>1 != ratGobVersion { 54 return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1) 55 } 56 const j = 1 + 4 57 ln := binary.BigEndian.Uint32(buf[j-4 : j]) 58 if uint64(ln) > math.MaxInt-j { 59 return errors.New("Rat.GobDecode: invalid length") 60 } 61 i := j + int(ln) 62 if len(buf) < i { 63 return errors.New("Rat.GobDecode: buffer too small") 64 } 65 z.a.neg = b&1 != 0 66 z.a.abs = z.a.abs.setBytes(buf[j:i]) 67 z.b.abs = z.b.abs.setBytes(buf[i:]) 68 return nil 69 } 70 71 // MarshalText implements the encoding.TextMarshaler interface. 72 func (x *Rat) MarshalText() (text []byte, err error) { 73 if x.IsInt() { 74 return x.a.MarshalText() 75 } 76 return x.marshal(), nil 77 } 78 79 // UnmarshalText implements the encoding.TextUnmarshaler interface. 80 func (z *Rat) UnmarshalText(text []byte) error { 81 // TODO(gri): get rid of the []byte/string conversion 82 if _, ok := z.SetString(string(text)); !ok { 83 return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text) 84 } 85 return nil 86 }