blob.go 2.64 KB
Newer Older
cznic's avatar
cznic committed
1
// Copyright 2014 The ql Authors. All rights reserved.
cznic's avatar
cznic committed
2 3 4
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

5
package ql // import "modernc.org/ql"
cznic's avatar
cznic committed
6 7 8 9 10

import (
	"bytes"
	"encoding/gob"
	"math/big"
cznic's avatar
cznic committed
11
	"sync"
cznic's avatar
cznic committed
12 13 14
	"time"
)

cznic's avatar
cznic committed
15
const shortBlob = 256 // bytes
cznic's avatar
cznic committed
16 17

var (
cznic's avatar
cznic committed
18 19 20 21
	gobInitDuration = time.Duration(278)
	gobInitInt      = big.NewInt(42)
	gobInitRat      = big.NewRat(355, 113)
	gobInitTime     time.Time
cznic's avatar
cznic committed
22 23 24 25 26 27 28
)

func init() {
	var err error
	if gobInitTime, err = time.ParseInLocation(
		"Jan 2, 2006 at 3:04pm (MST)",
		"Jul 9, 2012 at 5:02am (CEST)",
cznic's avatar
cznic committed
29
		time.FixedZone("XYZ", 1234),
cznic's avatar
cznic committed
30
	); err != nil {
cznic's avatar
cznic committed
31
		panic(err)
cznic's avatar
cznic committed
32
	}
33
	newGobCoder()
cznic's avatar
cznic committed
34
}
cznic's avatar
cznic committed
35

cznic's avatar
cznic committed
36 37 38 39 40
type gobCoder struct {
	buf bytes.Buffer
	dec *gob.Decoder
	enc *gob.Encoder
	mu  sync.Mutex
cznic's avatar
cznic committed
41 42
}

cznic's avatar
cznic committed
43 44 45 46
func newGobCoder() (g *gobCoder) {
	g = &gobCoder{}
	g.enc = gob.NewEncoder(&g.buf)
	if err := g.enc.Encode(gobInitInt); err != nil {
cznic's avatar
cznic committed
47
		panic(err)
cznic's avatar
cznic committed
48 49
	}

cznic's avatar
cznic committed
50
	if err := g.enc.Encode(gobInitRat); err != nil {
cznic's avatar
cznic committed
51
		panic(err)
cznic's avatar
cznic committed
52 53
	}

cznic's avatar
cznic committed
54
	if err := g.enc.Encode(gobInitTime); err != nil {
cznic's avatar
cznic committed
55
		panic(err)
cznic's avatar
cznic committed
56 57
	}

cznic's avatar
cznic committed
58
	if err := g.enc.Encode(gobInitDuration); err != nil {
cznic's avatar
cznic committed
59
		panic(err)
cznic's avatar
cznic committed
60
	}
cznic's avatar
cznic committed
61

cznic's avatar
cznic committed
62
	g.dec = gob.NewDecoder(&g.buf)
cznic's avatar
cznic committed
63
	i := big.NewInt(0)
cznic's avatar
cznic committed
64
	if err := g.dec.Decode(i); err != nil {
cznic's avatar
cznic committed
65
		panic(err)
cznic's avatar
cznic committed
66 67 68
	}

	r := big.NewRat(3, 5)
cznic's avatar
cznic committed
69
	if err := g.dec.Decode(r); err != nil {
cznic's avatar
cznic committed
70
		panic(err)
cznic's avatar
cznic committed
71 72 73
	}

	t := time.Now()
cznic's avatar
cznic committed
74
	if err := g.dec.Decode(&t); err != nil {
cznic's avatar
cznic committed
75
		panic(err)
cznic's avatar
cznic committed
76 77 78 79
	}

	var d time.Duration
	if err := g.dec.Decode(&d); err != nil {
cznic's avatar
cznic committed
80
		panic(err)
cznic's avatar
cznic committed
81 82 83 84
	}

	return
}
cznic's avatar
cznic committed
85

cznic's avatar
cznic committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
func isBlobType(v interface{}) (bool, Type) {
	switch v.(type) {
	case []byte:
		return true, Blob
	case *big.Int:
		return true, BigInt
	case *big.Rat:
		return true, BigRat
	case time.Time:
		return true, Time
	case time.Duration:
		return true, Duration
	default:
		return false, -1
	}
}

cznic's avatar
cznic committed
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
func (g *gobCoder) encode(v interface{}) (b []byte, err error) {
	g.mu.Lock()
	defer g.mu.Unlock()

	g.buf.Reset()
	switch x := v.(type) {
	case []byte:
		return x, nil
	case *big.Int:
		err = g.enc.Encode(x)
	case *big.Rat:
		err = g.enc.Encode(x)
	case time.Time:
		err = g.enc.Encode(x)
	case time.Duration:
cznic's avatar
cznic committed
118
		err = g.enc.Encode(int64(x))
cznic's avatar
cznic committed
119
	default:
cznic's avatar
cznic committed
120
		panic("internal error 002")
cznic's avatar
cznic committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
	}
	b = g.buf.Bytes()
	return
}

func (g *gobCoder) decode(b []byte, typ int) (v interface{}, err error) {
	g.mu.Lock()
	defer g.mu.Unlock()

	g.buf.Reset()
	g.buf.Write(b)
	switch typ {
	case qBlob:
		return b, nil
	case qBigInt:
		x := big.NewInt(0)
		err = g.dec.Decode(&x)
		v = x
	case qBigRat:
cznic's avatar
cznic committed
140
		x := big.NewRat(1, 1)
cznic's avatar
cznic committed
141 142 143 144 145 146 147
		err = g.dec.Decode(&x)
		v = x
	case qTime:
		var x time.Time
		err = g.dec.Decode(&x)
		v = x
	case qDuration:
cznic's avatar
cznic committed
148
		var x int64
cznic's avatar
cznic committed
149
		err = g.dec.Decode(&x)
cznic's avatar
cznic committed
150
		v = time.Duration(x)
cznic's avatar
cznic committed
151
	default:
cznic's avatar
cznic committed
152
		panic("internal error 003")
cznic's avatar
cznic committed
153 154 155
	}
	return
}