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.
dorm/vendor/modernc.org/ql/encode2.go

486 lines
10 KiB

// 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
}