You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
486 lines
10 KiB
486 lines
10 KiB
2 years ago
|
// Copyright 2018 The ql 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 ql // import "modernc.org/ql"
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"fmt"
|
||
|
"math"
|
||
|
"math/big"
|
||
|
"time"
|
||
|
|
||
|
"modernc.org/internal/buffer"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
tag2null = iota
|
||
|
|
||
|
tag2bigInt
|
||
|
tag2bigIntZero
|
||
|
tag2bigRat
|
||
|
tag2bigRatZero
|
||
|
tag2bin
|
||
|
tag2binZero
|
||
|
tag2c128
|
||
|
tag2c64
|
||
|
tag2duration
|
||
|
tag2durationZero
|
||
|
tag2f32
|
||
|
tag2f64
|
||
|
tag2false
|
||
|
tag2i16
|
||
|
tag2i16Zero
|
||
|
tag2i32
|
||
|
tag2i32Zero
|
||
|
tag2i64
|
||
|
tag2i64Zero
|
||
|
tag2i8
|
||
|
tag2i8Zero
|
||
|
tag2string
|
||
|
tag2stringZero
|
||
|
tag2time
|
||
|
tag2timeZero
|
||
|
tag2true
|
||
|
tag2u16
|
||
|
tag2u16Zero
|
||
|
tag2u32
|
||
|
tag2u32Zero
|
||
|
tag2u64
|
||
|
tag2u64Zero
|
||
|
tag2u8
|
||
|
tag2u8Zero
|
||
|
)
|
||
|
|
||
|
func encode2(data []interface{}) (r buffer.Bytes, error error) {
|
||
|
p := buffer.Get(2*binary.MaxVarintLen64 + 1)
|
||
|
|
||
|
defer buffer.Put(p)
|
||
|
|
||
|
b := *p
|
||
|
for _, v := range data {
|
||
|
switch x := v.(type) {
|
||
|
case nil:
|
||
|
r.WriteByte(tag2null)
|
||
|
case bool:
|
||
|
switch x {
|
||
|
case false:
|
||
|
r.WriteByte(tag2false)
|
||
|
case true:
|
||
|
r.WriteByte(tag2true)
|
||
|
}
|
||
|
case complex64:
|
||
|
b[0] = tag2c64
|
||
|
n := binary.PutUvarint(b[1:], uint64(math.Float32bits(real(x))))
|
||
|
n += binary.PutUvarint(b[1+n:], uint64(math.Float32bits(imag(x))))
|
||
|
r.Write(b[:n+1])
|
||
|
case complex128:
|
||
|
b[0] = tag2c128
|
||
|
n := binary.PutUvarint(b[1:], math.Float64bits(real(x)))
|
||
|
n += binary.PutUvarint(b[1+n:], math.Float64bits(imag(x)))
|
||
|
r.Write(b[:n+1])
|
||
|
case float32:
|
||
|
b[0] = tag2f32
|
||
|
n := binary.PutUvarint(b[1:], uint64(math.Float32bits(x)))
|
||
|
r.Write(b[:n+1])
|
||
|
case float64:
|
||
|
b[0] = tag2f64
|
||
|
n := binary.PutUvarint(b[1:], math.Float64bits(x))
|
||
|
r.Write(b[:n+1])
|
||
|
case int:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2i64Zero)
|
||
|
default:
|
||
|
b[0] = tag2i64
|
||
|
n := binary.PutVarint(b[1:], int64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case int8:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2i8Zero)
|
||
|
default:
|
||
|
b[0] = tag2i8
|
||
|
n := binary.PutVarint(b[1:], int64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case int16:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2i16Zero)
|
||
|
default:
|
||
|
b[0] = tag2i16
|
||
|
n := binary.PutVarint(b[1:], int64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case int32:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2i32Zero)
|
||
|
default:
|
||
|
b[0] = tag2i32
|
||
|
n := binary.PutVarint(b[1:], int64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case int64:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2i64Zero)
|
||
|
default:
|
||
|
b[0] = tag2i64
|
||
|
n := binary.PutVarint(b[1:], x)
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case idealInt:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2i64Zero)
|
||
|
default:
|
||
|
b[0] = tag2i64
|
||
|
n := binary.PutVarint(b[1:], int64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case string:
|
||
|
switch {
|
||
|
case x == "":
|
||
|
r.WriteByte(tag2stringZero)
|
||
|
default:
|
||
|
b[0] = tag2string
|
||
|
n := binary.PutUvarint(b[1:], uint64(len(x)))
|
||
|
r.Write(b[:n+1])
|
||
|
r.WriteString(x)
|
||
|
}
|
||
|
case uint8:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2u8Zero)
|
||
|
default:
|
||
|
b[0] = tag2u8
|
||
|
n := binary.PutUvarint(b[1:], uint64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case uint16:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2u16Zero)
|
||
|
default:
|
||
|
b[0] = tag2u16
|
||
|
n := binary.PutUvarint(b[1:], uint64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case uint32:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2u32Zero)
|
||
|
default:
|
||
|
b[0] = tag2u32
|
||
|
n := binary.PutUvarint(b[1:], uint64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case uint64:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2u64Zero)
|
||
|
default:
|
||
|
b[0] = tag2u64
|
||
|
n := binary.PutUvarint(b[1:], x)
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
case []byte:
|
||
|
switch {
|
||
|
case len(x) == 0:
|
||
|
r.WriteByte(tag2binZero)
|
||
|
default:
|
||
|
b[0] = tag2bin
|
||
|
n := binary.PutUvarint(b[1:], uint64(len(x)))
|
||
|
r.Write(b[:n+1])
|
||
|
r.Write(x)
|
||
|
}
|
||
|
case *big.Int:
|
||
|
switch {
|
||
|
case x.Sign() == 0:
|
||
|
r.WriteByte(tag2bigIntZero)
|
||
|
default:
|
||
|
b[0] = tag2bigInt
|
||
|
buf, err := x.GobEncode()
|
||
|
if err != nil {
|
||
|
return r, err
|
||
|
}
|
||
|
|
||
|
n := binary.PutUvarint(b[1:], uint64(len(buf)))
|
||
|
r.Write(b[:n+1])
|
||
|
r.Write(buf)
|
||
|
}
|
||
|
case *big.Rat:
|
||
|
switch {
|
||
|
case x.Sign() == 0:
|
||
|
r.WriteByte(tag2bigRatZero)
|
||
|
default:
|
||
|
b[0] = tag2bigRat
|
||
|
buf, err := x.GobEncode()
|
||
|
if err != nil {
|
||
|
return r, err
|
||
|
}
|
||
|
|
||
|
n := binary.PutUvarint(b[1:], uint64(len(buf)))
|
||
|
r.Write(b[:n+1])
|
||
|
r.Write(buf)
|
||
|
}
|
||
|
case time.Time:
|
||
|
switch {
|
||
|
case x.IsZero():
|
||
|
r.WriteByte(tag2timeZero)
|
||
|
default:
|
||
|
b[0] = tag2time
|
||
|
buf, err := x.GobEncode()
|
||
|
if err != nil {
|
||
|
return r, err
|
||
|
}
|
||
|
|
||
|
n := binary.PutUvarint(b[1:], uint64(len(buf)))
|
||
|
r.Write(b[:n+1])
|
||
|
r.Write(buf)
|
||
|
}
|
||
|
case time.Duration:
|
||
|
switch {
|
||
|
case x == 0:
|
||
|
r.WriteByte(tag2durationZero)
|
||
|
default:
|
||
|
b[0] = tag2duration
|
||
|
n := binary.PutVarint(b[1:], int64(x))
|
||
|
r.Write(b[:n+1])
|
||
|
}
|
||
|
default:
|
||
|
return r, fmt.Errorf("encode2: unexpected data %T(%v)", x, x)
|
||
|
}
|
||
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
func decode2(dst []interface{}, b []byte) ([]interface{}, error) {
|
||
|
dst = dst[:0]
|
||
|
for len(b) != 0 {
|
||
|
tag := b[0]
|
||
|
b = b[1:]
|
||
|
switch tag {
|
||
|
case tag2null:
|
||
|
dst = append(dst, nil)
|
||
|
case tag2false:
|
||
|
dst = append(dst, false)
|
||
|
case tag2true:
|
||
|
dst = append(dst, true)
|
||
|
case tag2c64:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 || n > math.MaxUint32 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
n2, nlen2 := binary.Uvarint(b[nlen:])
|
||
|
if nlen2 <= 0 || n2 > math.MaxUint32 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, complex(math.Float32frombits(uint32(n)), math.Float32frombits(uint32(n2))))
|
||
|
b = b[nlen+nlen2:]
|
||
|
case tag2c128:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
n2, nlen2 := binary.Uvarint(b[nlen:])
|
||
|
if nlen2 <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, complex(math.Float64frombits(n), math.Float64frombits(n2)))
|
||
|
b = b[nlen+nlen2:]
|
||
|
case tag2f32:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 || n > math.MaxUint32 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, math.Float32frombits(uint32(n)))
|
||
|
b = b[nlen:]
|
||
|
case tag2f64:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, math.Float64frombits(n))
|
||
|
b = b[nlen:]
|
||
|
case tag2i8Zero:
|
||
|
dst = append(dst, int8(0))
|
||
|
case tag2i8:
|
||
|
n, nlen := binary.Varint(b)
|
||
|
if nlen <= 0 || n < math.MinInt16 || n > math.MaxInt8 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, int8(n))
|
||
|
b = b[nlen:]
|
||
|
case tag2i16Zero:
|
||
|
dst = append(dst, int16(0))
|
||
|
case tag2i16:
|
||
|
n, nlen := binary.Varint(b)
|
||
|
if nlen <= 0 || n < math.MinInt16 || n > math.MaxInt16 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, int16(n))
|
||
|
b = b[nlen:]
|
||
|
case tag2i32Zero:
|
||
|
dst = append(dst, int32(0))
|
||
|
case tag2i32:
|
||
|
n, nlen := binary.Varint(b)
|
||
|
if nlen <= 0 || n < math.MinInt32 || n > math.MaxInt32 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, int32(n))
|
||
|
b = b[nlen:]
|
||
|
case tag2i64Zero:
|
||
|
dst = append(dst, int64(0))
|
||
|
case tag2i64:
|
||
|
n, nlen := binary.Varint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, n)
|
||
|
b = b[nlen:]
|
||
|
case tag2stringZero:
|
||
|
dst = append(dst, "")
|
||
|
case tag2string:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
b = b[nlen:]
|
||
|
if uint64(len(b)) < n {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, string(b[:n]))
|
||
|
b = b[n:]
|
||
|
case tag2u8Zero:
|
||
|
dst = append(dst, byte(0))
|
||
|
case tag2u8:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 || n > math.MaxUint8 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, byte(n))
|
||
|
b = b[nlen:]
|
||
|
case tag2u16Zero:
|
||
|
dst = append(dst, uint16(0))
|
||
|
case tag2u16:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 || n > math.MaxUint16 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, uint16(n))
|
||
|
b = b[nlen:]
|
||
|
case tag2u32Zero:
|
||
|
dst = append(dst, uint32(0))
|
||
|
case tag2u32:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 || n > math.MaxUint32 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, uint32(n))
|
||
|
b = b[nlen:]
|
||
|
case tag2u64Zero:
|
||
|
dst = append(dst, uint64(0))
|
||
|
case tag2u64:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, n)
|
||
|
b = b[nlen:]
|
||
|
case tag2binZero:
|
||
|
dst = append(dst, []byte(nil))
|
||
|
case tag2bin:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
b = b[nlen:]
|
||
|
dst = append(dst, append([]byte(nil), b[:n]...))
|
||
|
b = b[n:]
|
||
|
case tag2bigIntZero:
|
||
|
dst = append(dst, big.NewInt(0))
|
||
|
case tag2bigInt:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
b = b[nlen:]
|
||
|
var z big.Int
|
||
|
if err := z.GobDecode(b[:n]); err != nil {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, &z)
|
||
|
b = b[n:]
|
||
|
case tag2bigRatZero:
|
||
|
dst = append(dst, &big.Rat{})
|
||
|
case tag2bigRat:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
b = b[nlen:]
|
||
|
var q big.Rat
|
||
|
if err := q.GobDecode(b[:n]); err != nil {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, &q)
|
||
|
b = b[n:]
|
||
|
case tag2timeZero:
|
||
|
dst = append(dst, time.Time{})
|
||
|
case tag2time:
|
||
|
n, nlen := binary.Uvarint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
b = b[nlen:]
|
||
|
var t time.Time
|
||
|
if err := t.GobDecode(b[:n]); err != nil {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, t)
|
||
|
b = b[n:]
|
||
|
case tag2durationZero:
|
||
|
dst = append(dst, time.Duration(0))
|
||
|
case tag2duration:
|
||
|
n, nlen := binary.Varint(b)
|
||
|
if nlen <= 0 {
|
||
|
return nil, fmt.Errorf("decode2: corrupted DB")
|
||
|
}
|
||
|
|
||
|
dst = append(dst, time.Duration(n))
|
||
|
b = b[nlen:]
|
||
|
default:
|
||
|
return nil, fmt.Errorf("decode2: unexpected tag %v", tag)
|
||
|
}
|
||
|
}
|
||
|
return dst, nil
|
||
|
}
|