github.com/runner-mei/ql@v1.1.0/blob.go (about) 1 // Copyright 2014 The ql 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 package ql 6 7 import ( 8 "bytes" 9 "encoding/gob" 10 "math/big" 11 "sync" 12 "time" 13 ) 14 15 const shortBlob = 256 // bytes 16 17 var ( 18 gobInitDuration = time.Duration(278) 19 gobInitInt = big.NewInt(42) 20 gobInitRat = big.NewRat(355, 113) 21 gobInitTime time.Time 22 ) 23 24 func init() { 25 var err error 26 if gobInitTime, err = time.ParseInLocation( 27 "Jan 2, 2006 at 3:04pm (MST)", 28 "Jul 9, 2012 at 5:02am (CEST)", 29 time.FixedZone("XYZ", 1234), 30 ); err != nil { 31 panic(err) 32 } 33 newGobCoder() 34 } 35 36 type gobCoder struct { 37 buf bytes.Buffer 38 dec *gob.Decoder 39 enc *gob.Encoder 40 mu sync.Mutex 41 } 42 43 func newGobCoder() (g *gobCoder) { 44 g = &gobCoder{} 45 g.enc = gob.NewEncoder(&g.buf) 46 if err := g.enc.Encode(gobInitInt); err != nil { 47 panic(err) 48 } 49 50 if err := g.enc.Encode(gobInitRat); err != nil { 51 panic(err) 52 } 53 54 if err := g.enc.Encode(gobInitTime); err != nil { 55 panic(err) 56 } 57 58 if err := g.enc.Encode(gobInitDuration); err != nil { 59 panic(err) 60 } 61 62 g.dec = gob.NewDecoder(&g.buf) 63 i := big.NewInt(0) 64 if err := g.dec.Decode(i); err != nil { 65 panic(err) 66 } 67 68 r := big.NewRat(3, 5) 69 if err := g.dec.Decode(r); err != nil { 70 panic(err) 71 } 72 73 t := time.Now() 74 if err := g.dec.Decode(&t); err != nil { 75 panic(err) 76 } 77 78 var d time.Duration 79 if err := g.dec.Decode(&d); err != nil { 80 panic(err) 81 } 82 83 return 84 } 85 86 func isBlobType(v interface{}) (bool, Type) { 87 switch v.(type) { 88 case []byte: 89 return true, Blob 90 case *big.Int: 91 return true, BigInt 92 case *big.Rat: 93 return true, BigRat 94 case time.Time: 95 return true, Time 96 case time.Duration: 97 return true, Duration 98 default: 99 return false, -1 100 } 101 } 102 103 func (g *gobCoder) encode(v interface{}) (b []byte, err error) { 104 g.mu.Lock() 105 defer g.mu.Unlock() 106 107 g.buf.Reset() 108 switch x := v.(type) { 109 case []byte: 110 return x, nil 111 case *big.Int: 112 err = g.enc.Encode(x) 113 case *big.Rat: 114 err = g.enc.Encode(x) 115 case time.Time: 116 err = g.enc.Encode(x) 117 case time.Duration: 118 err = g.enc.Encode(int64(x)) 119 default: 120 panic("internal error 002") 121 } 122 b = g.buf.Bytes() 123 return 124 } 125 126 func (g *gobCoder) decode(b []byte, typ int) (v interface{}, err error) { 127 g.mu.Lock() 128 defer g.mu.Unlock() 129 130 g.buf.Reset() 131 g.buf.Write(b) 132 switch typ { 133 case qBlob: 134 return b, nil 135 case qBigInt: 136 x := big.NewInt(0) 137 err = g.dec.Decode(&x) 138 v = x 139 case qBigRat: 140 x := big.NewRat(1, 1) 141 err = g.dec.Decode(&x) 142 v = x 143 case qTime: 144 var x time.Time 145 err = g.dec.Decode(&x) 146 v = x 147 case qDuration: 148 var x int64 149 err = g.dec.Decode(&x) 150 v = time.Duration(x) 151 default: 152 panic("internal error 003") 153 } 154 return 155 }