зеркало из https://github.com/github/vitess-gh.git
356 строки
8.4 KiB
Go
356 строки
8.4 KiB
Go
// Copyright 2012, Google Inc. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Utility functions for custom decoders
|
|
|
|
package bson
|
|
|
|
import (
|
|
"bytes"
|
|
"math"
|
|
"time"
|
|
|
|
"github.com/youtube/vitess/go/hack"
|
|
)
|
|
|
|
// VerifyObject verifies kind to make sure it's
|
|
// either a top level document (EOO) or an Object.
|
|
// TODO(sougou): deprecate this function.
|
|
func VerifyObject(kind byte) {
|
|
if kind != EOO && kind != Object {
|
|
panic(NewBsonError("unexpected kind: %v", kind))
|
|
}
|
|
}
|
|
|
|
// DecodeString decodes a string from buf.
|
|
// Allowed types: String, Binary, Null,
|
|
func DecodeString(buf *bytes.Buffer, kind byte) string {
|
|
switch kind {
|
|
case String:
|
|
l := int(Pack.Uint32(Next(buf, 4)))
|
|
s := Next(buf, l-1)
|
|
NextByte(buf)
|
|
return string(s)
|
|
case Binary:
|
|
l := int(Pack.Uint32(Next(buf, 4)))
|
|
NextByte(buf)
|
|
return string(Next(buf, l))
|
|
case Null:
|
|
return ""
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for string", kind))
|
|
}
|
|
|
|
// DecodeBinary decodes a []byte from buf.
|
|
// Allowed types: String, Binary, Null.
|
|
func DecodeBinary(buf *bytes.Buffer, kind byte) []byte {
|
|
switch kind {
|
|
case String:
|
|
l := int(Pack.Uint32(Next(buf, 4)))
|
|
b := Next(buf, l-1)
|
|
NextByte(buf)
|
|
return b
|
|
case Binary:
|
|
l := int(Pack.Uint32(Next(buf, 4)))
|
|
NextByte(buf)
|
|
return Next(buf, l)
|
|
case Null:
|
|
return nil
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for []byte", kind))
|
|
}
|
|
|
|
// DecodeInt64 decodes a int64 from buf.
|
|
// Allowed types: Int, Long, Ulong, Null.
|
|
func DecodeInt64(buf *bytes.Buffer, kind byte) int64 {
|
|
switch kind {
|
|
case Int:
|
|
return int64(int32(Pack.Uint32(Next(buf, 4))))
|
|
case Long, Ulong:
|
|
return int64(Pack.Uint64(Next(buf, 8)))
|
|
case Null:
|
|
return 0
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for int64", kind))
|
|
}
|
|
|
|
// DecodeInt32 decodes a int32 from buf.
|
|
// Allowed types: Int, Long, Null.
|
|
func DecodeInt32(buf *bytes.Buffer, kind byte) int32 {
|
|
switch kind {
|
|
case Int:
|
|
return int32(Pack.Uint32(Next(buf, 4)))
|
|
case Long:
|
|
return int32(Pack.Uint64(Next(buf, 8)))
|
|
case Null:
|
|
return 0
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for int32", kind))
|
|
}
|
|
|
|
// DecodeInt decodes a int64 from buf.
|
|
// Allowed types: Int, Long, Ulong, Null.
|
|
func DecodeInt(buf *bytes.Buffer, kind byte) int {
|
|
switch kind {
|
|
case Int:
|
|
return int(Pack.Uint32(Next(buf, 4)))
|
|
case Long, Ulong:
|
|
return int(Pack.Uint64(Next(buf, 8)))
|
|
case Null:
|
|
return 0
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for int", kind))
|
|
}
|
|
|
|
// DecodeUint64 decodes a uint64 from buf.
|
|
// Allowed types: Int, Long, Ulong, Null.
|
|
func DecodeUint64(buf *bytes.Buffer, kind byte) uint64 {
|
|
switch kind {
|
|
case Int:
|
|
return uint64(Pack.Uint32(Next(buf, 4)))
|
|
case Long, Ulong:
|
|
return Pack.Uint64(Next(buf, 8))
|
|
case Null:
|
|
return 0
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for uint64", kind))
|
|
}
|
|
|
|
// DecodeUint32 decodes a uint32 from buf.
|
|
// Allowed types: Int, Long, Null.
|
|
func DecodeUint32(buf *bytes.Buffer, kind byte) uint32 {
|
|
switch kind {
|
|
case Int:
|
|
return Pack.Uint32(Next(buf, 4))
|
|
case Ulong, Long:
|
|
return uint32(Pack.Uint64(Next(buf, 8)))
|
|
case Null:
|
|
return 0
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for uint32", kind))
|
|
}
|
|
|
|
// DecodeUint decodes a uint64 from buf.
|
|
// Allowed types: Int, Long, Ulong, Null.
|
|
func DecodeUint(buf *bytes.Buffer, kind byte) uint {
|
|
switch kind {
|
|
case Int:
|
|
return uint(Pack.Uint32(Next(buf, 4)))
|
|
case Long, Ulong:
|
|
return uint(Pack.Uint64(Next(buf, 8)))
|
|
case Null:
|
|
return 0
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for uint", kind))
|
|
}
|
|
|
|
// DecodeFloat64 decodes a float64 from buf.
|
|
// Allowed types: Number, Null.
|
|
func DecodeFloat64(buf *bytes.Buffer, kind byte) float64 {
|
|
switch kind {
|
|
case Number:
|
|
return float64(math.Float64frombits(Pack.Uint64(Next(buf, 8))))
|
|
case Null:
|
|
return 0
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for float64", kind))
|
|
}
|
|
|
|
// DecodeBool decodes a bool from buf.
|
|
// Allowed types: Boolean, Int, Long, Ulong, Null.
|
|
func DecodeBool(buf *bytes.Buffer, kind byte) bool {
|
|
switch kind {
|
|
case Boolean:
|
|
b, _ := buf.ReadByte()
|
|
return (b != 0)
|
|
case Int:
|
|
return (Pack.Uint32(Next(buf, 4)) != 0)
|
|
case Long, Ulong:
|
|
return (Pack.Uint64(Next(buf, 8)) != 0)
|
|
case Null:
|
|
return false
|
|
default:
|
|
panic(NewBsonError("unexpected kind %v for bool", kind))
|
|
}
|
|
}
|
|
|
|
// DecodeTime decodes a time.Time from buf.
|
|
// Allowed types: Datetime, Null.
|
|
func DecodeTime(buf *bytes.Buffer, kind byte) time.Time {
|
|
switch kind {
|
|
case Datetime:
|
|
ui64 := Pack.Uint64(Next(buf, 8))
|
|
return time.Unix(0, int64(ui64)*1e6).UTC()
|
|
case Null:
|
|
return time.Time{}
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for time.Time", kind))
|
|
}
|
|
|
|
// DecodeInterface decodes the next object into an interface.
|
|
// Object is decoded as map[string]interface{}.
|
|
// Array is decoded as []interface{}
|
|
func DecodeInterface(buf *bytes.Buffer, kind byte) interface{} {
|
|
switch kind {
|
|
case Number:
|
|
return DecodeFloat64(buf, kind)
|
|
case String:
|
|
return DecodeString(buf, kind)
|
|
case Object:
|
|
return DecodeMap(buf, kind)
|
|
case Array:
|
|
return DecodeArray(buf, kind)
|
|
case Binary:
|
|
return DecodeBinary(buf, kind)
|
|
case Boolean:
|
|
return DecodeBool(buf, kind)
|
|
case Datetime:
|
|
return DecodeTime(buf, kind)
|
|
case Null:
|
|
return nil
|
|
case Int:
|
|
return DecodeInt32(buf, kind)
|
|
case Long:
|
|
return DecodeInt64(buf, kind)
|
|
case Ulong:
|
|
return DecodeUint64(buf, kind)
|
|
}
|
|
panic(NewBsonError("unexpected kind %v for interface{}", kind))
|
|
}
|
|
|
|
// DecodeMap decodes a map[string]interface{} from buf.
|
|
// Allowed types: Object, Null.
|
|
func DecodeMap(buf *bytes.Buffer, kind byte) map[string]interface{} {
|
|
switch kind {
|
|
case Object:
|
|
// valid
|
|
case Null:
|
|
return nil
|
|
default:
|
|
panic(NewBsonError("unexpected kind %v for map", kind))
|
|
}
|
|
|
|
result := make(map[string]interface{})
|
|
Next(buf, 4)
|
|
for kind := NextByte(buf); kind != EOO; kind = NextByte(buf) {
|
|
key := ReadCString(buf)
|
|
if kind == Null {
|
|
result[key] = nil
|
|
continue
|
|
}
|
|
result[key] = DecodeInterface(buf, kind)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// DecodeArray decodes a []interface{} from buf.
|
|
// Allowed types: Array, Null.
|
|
func DecodeArray(buf *bytes.Buffer, kind byte) []interface{} {
|
|
switch kind {
|
|
case Array:
|
|
// valid
|
|
case Null:
|
|
return nil
|
|
default:
|
|
panic(NewBsonError("unexpected kind %v for slice", kind))
|
|
}
|
|
|
|
result := make([]interface{}, 0, 8)
|
|
Next(buf, 4)
|
|
for kind := NextByte(buf); kind != EOO; kind = NextByte(buf) {
|
|
ReadCString(buf)
|
|
if kind == Null {
|
|
result = append(result, nil)
|
|
continue
|
|
}
|
|
result = append(result, DecodeInterface(buf, kind))
|
|
}
|
|
return result
|
|
}
|
|
|
|
// DecodeStringArray decodes a []string from buf.
|
|
// Allowed types: Array, Null.
|
|
func DecodeStringArray(buf *bytes.Buffer, kind byte) []string {
|
|
switch kind {
|
|
case Array:
|
|
// valid
|
|
case Null:
|
|
return nil
|
|
default:
|
|
panic(NewBsonError("unexpected kind %v for []string", kind))
|
|
}
|
|
|
|
result := make([]string, 0, 8)
|
|
Next(buf, 4)
|
|
for kind := NextByte(buf); kind != EOO; kind = NextByte(buf) {
|
|
if kind != Binary {
|
|
panic(NewBsonError("unexpected kind %v for string", kind))
|
|
}
|
|
SkipIndex(buf)
|
|
result = append(result, DecodeString(buf, kind))
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Skip will skip the next field we don't want to read.
|
|
func Skip(buf *bytes.Buffer, kind byte) {
|
|
switch kind {
|
|
case Number, Datetime, Long, Ulong:
|
|
Next(buf, 8)
|
|
case String:
|
|
// length of a string includes the 0 at the end, but not the size
|
|
l := int(Pack.Uint32(Next(buf, 4)))
|
|
Next(buf, l)
|
|
case Object, Array:
|
|
// the encoded length includes the 4 bytes for the size
|
|
l := int(Pack.Uint32(Next(buf, 4)))
|
|
if l < 4 {
|
|
panic(NewBsonError("Object or Array should at least be 4 bytes long"))
|
|
}
|
|
Next(buf, l-4)
|
|
case Binary:
|
|
// length of a binary doesn't include the subtype
|
|
l := int(Pack.Uint32(Next(buf, 4)))
|
|
Next(buf, l+1)
|
|
case Boolean:
|
|
buf.ReadByte()
|
|
case Int:
|
|
Next(buf, 4)
|
|
case Null:
|
|
// no op
|
|
default:
|
|
panic(NewBsonError("unexpected kind %v for skip", kind))
|
|
}
|
|
}
|
|
|
|
// SkipIndex must be used to skip indexes in arrays.
|
|
func SkipIndex(buf *bytes.Buffer) {
|
|
ReadCString(buf)
|
|
}
|
|
|
|
// ReadCString reads the the bson document tag.
|
|
func ReadCString(buf *bytes.Buffer) string {
|
|
index := bytes.IndexByte(buf.Bytes(), 0)
|
|
if index < 0 {
|
|
panic(NewBsonError("unexpected EOF"))
|
|
}
|
|
// Read including null termination, but
|
|
// return the string without the null.
|
|
return hack.String(Next(buf, index+1)[:index])
|
|
}
|
|
|
|
// Next returns the next n bytes from buf.
|
|
func Next(buf *bytes.Buffer, n int) []byte {
|
|
b := buf.Next(n)
|
|
if len(b) != n {
|
|
panic(NewBsonError("unexpected EOF"))
|
|
}
|
|
return b[:n:n]
|
|
}
|
|
|
|
// NextByte returns the next byte from buf.
|
|
func NextByte(buf *bytes.Buffer) byte {
|
|
return Next(buf, 1)[0]
|
|
}
|