Refactor to move common libraries out of project

This commit is contained in:
Jae Kwon
2015-10-22 17:39:06 -07:00
parent 7c12c5aee3
commit c4ed55d801
277 changed files with 406 additions and 11304 deletions
-138
View File
@@ -1,138 +0,0 @@
### NOTICE
This documentation is out of date.
* 0x00 is reserved as a nil byte for RegisterInterface
* moved TypeByte() into RegisterInterface/ConcreteType
* Pointers that don't have a declared TypeByte() are
encoded with a leading 0x00 (nil) or 0x01.
# `tendermint/wire`
The `binary` submodule encodes primary types and structs into bytes.
## Primary types
uint\*, int\*, string, time, byteslice and byteslice-slice types can be
encoded and decoded with the following methods:
The following writes `o uint64` to `w io.Writer`, and increments `n` and/or sets `err`
```go
WriteUint64(o uint64, w io.Writer, n *int64, err *error)
// Typical usage:
buf, n, err := new(bytes.Buffer), new(int64), new(error)
WriteUint64(uint64(x), buf, n, err)
if *err != nil {
panic(err)
}
```
The following reads a `uint64` from `r io.Reader`, and increments `n` and/or sets `err`
```go
var o = ReadUint64(r io.Reader, n *int64, err *error)
```
Similar methods for `uint32`, `uint16`, `uint8`, `int64`, `int32`, `int16`, `int8` exist.
Protobuf variable length encoding is done with `uint` and `int` types:
```go
WriteUvarint(o uint, w io.Writer, n *int64, err *error)
var o = ReadUvarint(r io.Reader, n *int64, err *error)
```
Byteslices can be written with:
```go
WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error)
```
Byteslices (and all slices such as byteslice-slices) are prepended with
`uvarint` encoded length, so `ReadByteSlice()` knows how many bytes to read.
Note that there is no type information encoded -- the caller is assumed to know what types
to decode.
## Struct Types
Struct types can be automatically encoded with reflection. Unlike json-encoding, no field
name or type information is encoded. Field values are simply encoded in order.
```go
type Foo struct {
MyString string
MyUint32 uint32
myPrivateBytes []byte
}
foo := Foo{"my string", math.MaxUint32, []byte("my private bytes")}
buf, n, err := new(bytes.Buffer), new(int64), new(error)
WriteBinary(foo, buf, n, err)
// fmt.Printf("%X", buf.Bytes()) gives:
// 096D7920737472696E67FFFFFFFF
// 09: uvarint encoded length of string "my string"
// 6D7920737472696E67: bytes of string "my string"
// FFFFFFFF: bytes for MaxUint32
// Note that the unexported "myPrivateBytes" isn't encoded.
foo2 := ReadBinary(Foo{}, buf, n, err).(Foo)
// Or, to decode onto a pointer:
foo2 := ReadBinaryPtr(&Foo{}, buf, n, err).(*Foo)
```
WriteBinary and ReadBinary can encode/decode structs recursively. However, interface field
values are a bit more complicated.
```go
type Greeter interface {
Greet() string
}
type Dog struct{}
func (d Dog) Greet() string { return "Woof!" }
type Cat struct{}
func (c Cat) Greet() string { return "Meow!" }
type Foo struct {
Greeter
}
foo := Foo{Dog{}}
buf, n, err := new(bytes.Buffer), new(int64), new(error)
WriteBinary(foo, buf, n, err)
// This errors because we don't know whether to read a Dog or Cat.
foo2 := ReadBinary(Foo{}, buf, n, err)
```
In the above example, `ReadBinary()` fails because the `Greeter` field for `Foo{}`
is ambiguous -- it could be either a `Dog{}` or a `Cat{}`, like a union structure.
The solution is to declare the concrete implementation types for interfaces:
```go
type Dog struct{}
func (d Dog) TypeByte() byte { return GreeterTypeDog }
func (d Dog) Greet() string { return "Woof!" }
type Cat struct{}
func (c Cat) TypeByte() byte { return GreeterTypeCat }
func (c Cat) Greet() string { return "Meow!" }
var _ = RegisterInterface(
struct{Greeter}{},
ConcreteType{Dog{}},
ConcreteType{Cat{}},
})
```
NOTE: The TypeByte() is written and expected to be read even when the struct
is encoded or decoded directly:
```go
WriteBinary(Dog{}, buf, n, err) // Writes GreeterTypeDog byte
dog_ := ReadBinary(Dog{}, buf, n, err) // Expects to read GreeterTypeDog byte
dog := dog_.(Dog) // ok if *err != nil, otherwise dog_ == nil.
```
-68
View File
@@ -1,68 +0,0 @@
package wire
import (
"io"
. "github.com/tendermint/tendermint/common"
)
func WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error) {
WriteVarint(len(bz), w, n, err)
WriteTo(bz, w, n, err)
}
func ReadByteSlice(r io.Reader, n *int64, err *error) []byte {
length := ReadVarint(r, n, err)
if *err != nil {
return nil
}
if length < 0 {
*err = ErrBinaryReadSizeUnderflow
return nil
}
if MaxBinaryReadSize < MaxInt64(int64(length), *n+int64(length)) {
*err = ErrBinaryReadSizeOverflow
return nil
}
buf := make([]byte, length)
ReadFull(buf, r, n, err)
return buf
}
//-----------------------------------------------------------------------------
func WriteByteSlices(bzz [][]byte, w io.Writer, n *int64, err *error) {
WriteVarint(len(bzz), w, n, err)
for _, bz := range bzz {
WriteByteSlice(bz, w, n, err)
if *err != nil {
return
}
}
}
func ReadByteSlices(r io.Reader, n *int64, err *error) [][]byte {
length := ReadVarint(r, n, err)
if *err != nil {
return nil
}
if length < 0 {
*err = ErrBinaryReadSizeUnderflow
return nil
}
if MaxBinaryReadSize < MaxInt64(int64(length), *n+int64(length)) {
*err = ErrBinaryReadSizeOverflow
return nil
}
bzz := make([][]byte, length)
for i := 0; i < length; i++ {
bz := ReadByteSlice(r, n, err)
if *err != nil {
return nil
}
bzz[i] = bz
}
return bzz
}
-171
View File
@@ -1,171 +0,0 @@
package wire
import (
"bytes"
"errors"
"fmt"
. "github.com/tendermint/tendermint/common"
"io"
"reflect"
"time"
)
type Encoder func(o interface{}, w io.Writer, n *int64, err *error)
type Decoder func(r io.Reader, n *int64, err *error) interface{}
type Comparator func(o1 interface{}, o2 interface{}) int
type Codec struct {
Encode Encoder
Decode Decoder
Compare Comparator
}
const (
typeByte = byte(0x01)
typeInt8 = byte(0x02)
// typeUint8 = byte(0x03)
typeInt16 = byte(0x04)
typeUint16 = byte(0x05)
typeInt32 = byte(0x06)
typeUint32 = byte(0x07)
typeInt64 = byte(0x08)
typeUint64 = byte(0x09)
typeVarint = byte(0x0A)
typeUvarint = byte(0x0B)
typeString = byte(0x10)
typeByteSlice = byte(0x11)
typeTime = byte(0x20)
)
func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) {
switch o := o.(type) {
case nil:
PanicSanity("nil type unsupported")
case byte:
WriteByte(typeByte, w, n, err)
WriteByte(o, w, n, err)
case int8:
WriteByte(typeInt8, w, n, err)
WriteInt8(o, w, n, err)
//case uint8:
// WriteByte( typeUint8, w, n, err)
// WriteUint8( o, w, n, err)
case int16:
WriteByte(typeInt16, w, n, err)
WriteInt16(o, w, n, err)
case uint16:
WriteByte(typeUint16, w, n, err)
WriteUint16(o, w, n, err)
case int32:
WriteByte(typeInt32, w, n, err)
WriteInt32(o, w, n, err)
case uint32:
WriteByte(typeUint32, w, n, err)
WriteUint32(o, w, n, err)
case int64:
WriteByte(typeInt64, w, n, err)
WriteInt64(o, w, n, err)
case uint64:
WriteByte(typeUint64, w, n, err)
WriteUint64(o, w, n, err)
case int:
WriteByte(typeVarint, w, n, err)
WriteVarint(o, w, n, err)
case uint:
WriteByte(typeUvarint, w, n, err)
WriteUvarint(o, w, n, err)
case string:
WriteByte(typeString, w, n, err)
WriteString(o, w, n, err)
case []byte:
WriteByte(typeByteSlice, w, n, err)
WriteByteSlice(o, w, n, err)
case time.Time:
WriteByte(typeTime, w, n, err)
WriteTime(o, w, n, err)
default:
PanicSanity(fmt.Sprintf("Unsupported type: %v", reflect.TypeOf(o)))
}
}
func BasicCodecDecoder(r io.Reader, n *int64, err *error) (o interface{}) {
type_ := ReadByte(r, n, err)
if *err != nil {
return
}
switch type_ {
case typeByte:
o = ReadByte(r, n, err)
case typeInt8:
o = ReadInt8(r, n, err)
//case typeUint8:
// o = ReadUint8(r, n, err)
case typeInt16:
o = ReadInt16(r, n, err)
case typeUint16:
o = ReadUint16(r, n, err)
case typeInt32:
o = ReadInt32(r, n, err)
case typeUint32:
o = ReadUint32(r, n, err)
case typeInt64:
o = ReadInt64(r, n, err)
case typeUint64:
o = ReadUint64(r, n, err)
case typeVarint:
o = ReadVarint(r, n, err)
case typeUvarint:
o = ReadUvarint(r, n, err)
case typeString:
o = ReadString(r, n, err)
case typeByteSlice:
o = ReadByteSlice(r, n, err)
case typeTime:
o = ReadTime(r, n, err)
default:
*err = errors.New(Fmt("Unsupported type byte: %X", type_))
}
return
}
// Contract: Caller must ensure that types match.
func BasicCodecComparator(o1 interface{}, o2 interface{}) int {
switch o1.(type) {
case byte:
return int(o1.(byte) - o2.(byte))
case int8:
return int(o1.(int8) - o2.(int8))
//case uint8:
case int16:
return int(o1.(int16) - o2.(int16))
case uint16:
return int(o1.(uint16) - o2.(uint16))
case int32:
return int(o1.(int32) - o2.(int32))
case uint32:
return int(o1.(uint32) - o2.(uint32))
case int64:
return int(o1.(int64) - o2.(int64))
case uint64:
return int(o1.(uint64) - o2.(uint64))
case int:
return o1.(int) - o2.(int)
case uint:
return int(o1.(uint)) - int(o2.(uint))
case string:
return bytes.Compare([]byte(o1.(string)), []byte(o2.(string)))
case []byte:
return bytes.Compare(o1.([]byte), o2.([]byte))
case time.Time:
return int(o1.(time.Time).UnixNano() - o2.(time.Time).UnixNano())
default:
PanicSanity(Fmt("Unsupported type: %v", reflect.TypeOf(o1)))
}
return 0
}
var BasicCodec = Codec{
Encode: BasicCodecEncoder,
Decode: BasicCodecDecoder,
Compare: BasicCodecComparator,
}
-270
View File
@@ -1,270 +0,0 @@
package wire
import (
"encoding/binary"
"errors"
"io"
)
// Byte
func WriteByte(b byte, w io.Writer, n *int64, err *error) {
WriteTo([]byte{b}, w, n, err)
}
func ReadByte(r io.Reader, n *int64, err *error) byte {
buf := make([]byte, 1)
ReadFull(buf, r, n, err)
return buf[0]
}
// Int8
func WriteInt8(i int8, w io.Writer, n *int64, err *error) {
WriteByte(byte(i), w, n, err)
}
func ReadInt8(r io.Reader, n *int64, err *error) int8 {
return int8(ReadByte(r, n, err))
}
// Uint8
func WriteUint8(i uint8, w io.Writer, n *int64, err *error) {
WriteByte(byte(i), w, n, err)
}
func ReadUint8(r io.Reader, n *int64, err *error) uint8 {
return uint8(ReadByte(r, n, err))
}
// Int16
func WriteInt16(i int16, w io.Writer, n *int64, err *error) {
buf := make([]byte, 2)
binary.BigEndian.PutUint16(buf, uint16(i))
*n += 2
WriteTo(buf, w, n, err)
}
func ReadInt16(r io.Reader, n *int64, err *error) int16 {
buf := make([]byte, 2)
ReadFull(buf, r, n, err)
return int16(binary.BigEndian.Uint16(buf))
}
// Uint16
func WriteUint16(i uint16, w io.Writer, n *int64, err *error) {
buf := make([]byte, 2)
binary.BigEndian.PutUint16(buf, uint16(i))
*n += 2
WriteTo(buf, w, n, err)
}
func ReadUint16(r io.Reader, n *int64, err *error) uint16 {
buf := make([]byte, 2)
ReadFull(buf, r, n, err)
return uint16(binary.BigEndian.Uint16(buf))
}
// []Uint16
func WriteUint16s(iz []uint16, w io.Writer, n *int64, err *error) {
WriteUint32(uint32(len(iz)), w, n, err)
for _, i := range iz {
WriteUint16(i, w, n, err)
if *err != nil {
return
}
}
}
func ReadUint16s(r io.Reader, n *int64, err *error) []uint16 {
length := ReadUint32(r, n, err)
if *err != nil {
return nil
}
iz := make([]uint16, length)
for j := uint32(0); j < length; j++ {
ii := ReadUint16(r, n, err)
if *err != nil {
return nil
}
iz[j] = ii
}
return iz
}
// Int32
func WriteInt32(i int32, w io.Writer, n *int64, err *error) {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, uint32(i))
*n += 4
WriteTo(buf, w, n, err)
}
func ReadInt32(r io.Reader, n *int64, err *error) int32 {
buf := make([]byte, 4)
ReadFull(buf, r, n, err)
return int32(binary.BigEndian.Uint32(buf))
}
// Uint32
func WriteUint32(i uint32, w io.Writer, n *int64, err *error) {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, uint32(i))
*n += 4
WriteTo(buf, w, n, err)
}
func ReadUint32(r io.Reader, n *int64, err *error) uint32 {
buf := make([]byte, 4)
ReadFull(buf, r, n, err)
return uint32(binary.BigEndian.Uint32(buf))
}
// Int64
func WriteInt64(i int64, w io.Writer, n *int64, err *error) {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
*n += 8
WriteTo(buf, w, n, err)
}
func ReadInt64(r io.Reader, n *int64, err *error) int64 {
buf := make([]byte, 8)
ReadFull(buf, r, n, err)
return int64(binary.BigEndian.Uint64(buf))
}
// Uint64
func WriteUint64(i uint64, w io.Writer, n *int64, err *error) {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
*n += 8
WriteTo(buf, w, n, err)
}
func ReadUint64(r io.Reader, n *int64, err *error) uint64 {
buf := make([]byte, 8)
ReadFull(buf, r, n, err)
return uint64(binary.BigEndian.Uint64(buf))
}
// Varint
func uvarintSize(i uint64) int {
if i == 0 {
return 0
}
if i < 1<<8 {
return 1
}
if i < 1<<16 {
return 2
}
if i < 1<<24 {
return 3
}
if i < 1<<32 {
return 4
}
if i < 1<<40 {
return 5
}
if i < 1<<48 {
return 6
}
if i < 1<<56 {
return 7
}
return 8
}
func WriteVarint(i int, w io.Writer, n *int64, err *error) {
var negate = false
if i < 0 {
negate = true
i = -i
}
var size = uvarintSize(uint64(i))
if negate {
// e.g. 0xF1 for a single negative byte
WriteUint8(uint8(size+0xF0), w, n, err)
} else {
WriteUint8(uint8(size), w, n, err)
}
if size > 0 {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
WriteTo(buf[(8-size):], w, n, err)
}
*n += int64(1 + size)
}
func ReadVarint(r io.Reader, n *int64, err *error) int {
var size = ReadUint8(r, n, err)
var negate = false
if (size >> 4) == 0xF {
negate = true
size = size & 0x0F
}
if size > 8 {
setFirstErr(err, errors.New("Varint overflow"))
return 0
}
if size == 0 {
if negate {
setFirstErr(err, errors.New("Varint does not allow negative zero"))
}
return 0
}
buf := make([]byte, 8)
ReadFull(buf[(8-size):], r, n, err)
*n += int64(1 + size)
var i = int(binary.BigEndian.Uint64(buf))
if negate {
return -i
} else {
return i
}
}
// Uvarint
func WriteUvarint(i uint, w io.Writer, n *int64, err *error) {
var size = uvarintSize(uint64(i))
WriteUint8(uint8(size), w, n, err)
if size > 0 {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
WriteTo(buf[(8-size):], w, n, err)
}
*n += int64(1 + size)
}
func ReadUvarint(r io.Reader, n *int64, err *error) uint {
var size = ReadUint8(r, n, err)
if size > 8 {
setFirstErr(err, errors.New("Uvarint overflow"))
return 0
}
if size == 0 {
return 0
}
buf := make([]byte, 8)
ReadFull(buf[(8-size):], r, n, err)
*n += int64(1 + size)
return uint(binary.BigEndian.Uint64(buf))
}
func setFirstErr(err *error, newErr error) {
if *err == nil && newErr != nil {
*err = newErr
}
}
-79
View File
@@ -1,79 +0,0 @@
package wire
import (
"bytes"
"fmt"
"testing"
)
func TestVarint(t *testing.T) {
check := func(i int, s string) {
buf := new(bytes.Buffer)
n, err := new(int64), new(error)
WriteVarint(i, buf, n, err)
bufBytes := buf.Bytes() // Read before consuming below.
i_ := ReadVarint(buf, n, err)
if i != i_ {
fmt.Println(bufBytes)
t.Fatalf("Encoded %v and got %v", i, i_)
}
if s != "" {
if bufHex := fmt.Sprintf("%X", bufBytes); bufHex != s {
t.Fatalf("Encoded %v, expected %v", bufHex, s)
}
}
}
// 123457 is some prime.
for i := -(2 << 33); i < (2 << 33); i += 123457 {
check(i, "")
}
// Near zero
check(-1, "F101")
check(0, "00")
check(1, "0101")
// Positives
check(1<<32-1, "04FFFFFFFF")
check(1<<32+0, "050100000000")
check(1<<32+1, "050100000001")
check(1<<53-1, "071FFFFFFFFFFFFF")
// Negatives
check(-1<<32+1, "F4FFFFFFFF")
check(-1<<32-0, "F50100000000")
check(-1<<32-1, "F50100000001")
check(-1<<53+1, "F71FFFFFFFFFFFFF")
}
func TestUvarint(t *testing.T) {
check := func(i uint, s string) {
buf := new(bytes.Buffer)
n, err := new(int64), new(error)
WriteUvarint(i, buf, n, err)
bufBytes := buf.Bytes()
i_ := ReadUvarint(buf, n, err)
if i != i_ {
fmt.Println(buf.Bytes())
t.Fatalf("Encoded %v and got %v", i, i_)
}
if s != "" {
if bufHex := fmt.Sprintf("%X", bufBytes); bufHex != s {
t.Fatalf("Encoded %v, expected %v", bufHex, s)
}
}
}
// 123457 is some prime.
for i := 0; i < (2 << 33); i += 123457 {
check(uint(i), "")
}
check(1, "0101")
check(1<<32-1, "04FFFFFFFF")
check(1<<32+0, "050100000000")
check(1<<32+1, "050100000001")
check(1<<53-1, "071FFFFFFFFFFFFF")
}
-18
View File
@@ -1,18 +0,0 @@
package wire
import (
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/tendermint/log15"
"github.com/tendermint/tendermint/logger"
)
var log = logger.New("module", "binary")
func init() {
log.SetHandler(
log15.LvlFilterHandler(
log15.LvlWarn,
//log15.LvlDebug,
logger.RootHandler(),
),
)
}
-954
View File
@@ -1,954 +0,0 @@
package wire
import (
"encoding/hex"
"encoding/json"
"errors"
"io"
"reflect"
"sync"
"time"
. "github.com/tendermint/tendermint/common"
)
const (
ReflectSliceChunk = 1024
)
type TypeInfo struct {
Type reflect.Type // The type
// If Type is kind reflect.Interface, is registered
IsRegisteredInterface bool
ByteToType map[byte]reflect.Type
TypeToByte map[reflect.Type]byte
// If Type is concrete
Byte byte
// If Type is kind reflect.Struct
Fields []StructFieldInfo
}
type Options struct {
JSONName string // (JSON) Corresponding JSON field name. (override with `json=""`)
Varint bool // (Binary) Use length-prefixed encoding for (u)int*
}
func getOptionsFromField(field reflect.StructField) (skip bool, opts Options) {
jsonName := field.Tag.Get("json")
if jsonName == "-" {
skip = true
return
} else if jsonName == "" {
jsonName = field.Name
}
varint := false
binTag := field.Tag.Get("binary")
if binTag == "varint" { // TODO: extend
varint = true
}
opts = Options{
JSONName: jsonName,
Varint: varint,
}
return
}
type StructFieldInfo struct {
Index int // Struct field index
Type reflect.Type // Struct field type
Options // Encoding options
}
func (info StructFieldInfo) unpack() (int, reflect.Type, Options) {
return info.Index, info.Type, info.Options
}
// e.g. If o is struct{Foo}{}, return is the Foo reflection type.
func GetTypeFromStructDeclaration(o interface{}) reflect.Type {
rt := reflect.TypeOf(o)
if rt.NumField() != 1 {
PanicSanity("Unexpected number of fields in struct-wrapped declaration of type")
}
return rt.Field(0).Type
}
func SetByteForType(typeByte byte, rt reflect.Type) {
typeInfo := GetTypeInfo(rt)
if typeInfo.Byte != 0x00 && typeInfo.Byte != typeByte {
PanicSanity(Fmt("Type %v already registered with type byte %X", rt, typeByte))
}
typeInfo.Byte = typeByte
// If pointer, we need to set it for the concrete type as well.
if rt.Kind() == reflect.Ptr {
SetByteForType(typeByte, rt.Elem())
}
}
// Predeclaration of common types
var (
timeType = GetTypeFromStructDeclaration(struct{ time.Time }{})
)
const (
iso8601 = "2006-01-02T15:04:05.000Z" // forced microseconds
)
// NOTE: do not access typeInfos directly, but call GetTypeInfo()
var typeInfosMtx sync.Mutex
var typeInfos = map[reflect.Type]*TypeInfo{}
func GetTypeInfo(rt reflect.Type) *TypeInfo {
typeInfosMtx.Lock()
defer typeInfosMtx.Unlock()
info := typeInfos[rt]
if info == nil {
info = MakeTypeInfo(rt)
typeInfos[rt] = info
}
return info
}
// For use with the RegisterInterface declaration
type ConcreteType struct {
O interface{}
Byte byte
}
// Must use this to register an interface to properly decode the
// underlying concrete type.
func RegisterInterface(o interface{}, ctypes ...ConcreteType) *TypeInfo {
it := GetTypeFromStructDeclaration(o)
if it.Kind() != reflect.Interface {
PanicSanity("RegisterInterface expects an interface")
}
toType := make(map[byte]reflect.Type, 0)
toByte := make(map[reflect.Type]byte, 0)
for _, ctype := range ctypes {
crt := reflect.TypeOf(ctype.O)
typeByte := ctype.Byte
SetByteForType(typeByte, crt)
if typeByte == 0x00 {
PanicSanity(Fmt("Byte of 0x00 is reserved for nil (%v)", ctype))
}
if toType[typeByte] != nil {
PanicSanity(Fmt("Duplicate Byte for type %v and %v", ctype, toType[typeByte]))
}
toType[typeByte] = crt
toByte[crt] = typeByte
}
typeInfo := &TypeInfo{
Type: it,
IsRegisteredInterface: true,
ByteToType: toType,
TypeToByte: toByte,
}
typeInfos[it] = typeInfo
return typeInfo
}
func MakeTypeInfo(rt reflect.Type) *TypeInfo {
info := &TypeInfo{Type: rt}
// If struct, register field name options
if rt.Kind() == reflect.Struct {
numFields := rt.NumField()
structFields := []StructFieldInfo{}
for i := 0; i < numFields; i++ {
field := rt.Field(i)
if field.PkgPath != "" {
continue
}
skip, opts := getOptionsFromField(field)
if skip {
continue
}
structFields = append(structFields, StructFieldInfo{
Index: i,
Type: field.Type,
Options: opts,
})
}
info.Fields = structFields
}
return info
}
// Contract: Caller must ensure that rt is supported
// (e.g. is recursively composed of supported native types, and structs and slices.)
func readReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, r io.Reader, n *int64, err *error) {
// Get typeInfo
typeInfo := GetTypeInfo(rt)
if rt.Kind() == reflect.Interface {
if !typeInfo.IsRegisteredInterface {
// There's no way we can read such a thing.
*err = errors.New(Fmt("Cannot read unregistered interface type %v", rt))
return
}
typeByte := ReadByte(r, n, err)
if *err != nil {
return
}
if typeByte == 0x00 {
return // nil
}
crt, ok := typeInfo.ByteToType[typeByte]
if !ok {
*err = errors.New(Fmt("Unexpected type byte %X for type %v", typeByte, rt))
return
}
crv := reflect.New(crt).Elem()
r = NewPrefixedReader([]byte{typeByte}, r)
readReflectBinary(crv, crt, opts, r, n, err)
rv.Set(crv) // NOTE: orig rv is ignored.
return
}
if rt.Kind() == reflect.Ptr {
typeByte := ReadByte(r, n, err)
if *err != nil {
return
}
if typeByte == 0x00 {
return // nil
}
// Create new if rv is nil.
if rv.IsNil() {
newRv := reflect.New(rt.Elem())
rv.Set(newRv)
rv = newRv
}
// Dereference pointer
rv, rt = rv.Elem(), rt.Elem()
typeInfo = GetTypeInfo(rt)
if typeInfo.Byte != 0x00 {
r = NewPrefixedReader([]byte{typeByte}, r)
} else if typeByte != 0x01 {
*err = errors.New(Fmt("Unexpected type byte %X for ptr of untyped thing", typeByte))
return
}
// continue...
}
// Read Byte prefix
if typeInfo.Byte != 0x00 {
typeByte := ReadByte(r, n, err)
if typeByte != typeInfo.Byte {
*err = errors.New(Fmt("Expected Byte of %X but got %X", typeInfo.Byte, typeByte))
return
}
}
switch rt.Kind() {
case reflect.Array:
elemRt := rt.Elem()
length := rt.Len()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Bytearrays
buf := make([]byte, length)
ReadFull(buf, r, n, err)
if *err != nil {
return
}
log.Info("Read bytearray", "bytes", buf)
reflect.Copy(rv, reflect.ValueOf(buf))
} else {
for i := 0; i < length; i++ {
elemRv := rv.Index(i)
readReflectBinary(elemRv, elemRt, opts, r, n, err)
if *err != nil {
return
}
if MaxBinaryReadSize < *n {
*err = ErrBinaryReadSizeOverflow
return
}
}
log.Info(Fmt("Read %v-array", elemRt), "length", length)
}
case reflect.Slice:
elemRt := rt.Elem()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Byteslices
byteslice := ReadByteSlice(r, n, err)
log.Info("Read byteslice", "bytes", byteslice)
rv.Set(reflect.ValueOf(byteslice))
} else {
var sliceRv reflect.Value
// Read length
length := ReadVarint(r, n, err)
log.Info(Fmt("Read length: %v", length))
sliceRv = reflect.MakeSlice(rt, 0, 0)
// read one ReflectSliceChunk at a time and append
for i := 0; i*ReflectSliceChunk < length; i++ {
l := MinInt(ReflectSliceChunk, length-i*ReflectSliceChunk)
tmpSliceRv := reflect.MakeSlice(rt, l, l)
for j := 0; j < l; j++ {
elemRv := tmpSliceRv.Index(j)
readReflectBinary(elemRv, elemRt, opts, r, n, err)
if *err != nil {
return
}
if MaxBinaryReadSize < *n {
*err = ErrBinaryReadSizeOverflow
return
}
}
sliceRv = reflect.AppendSlice(sliceRv, tmpSliceRv)
}
rv.Set(sliceRv)
}
case reflect.Struct:
if rt == timeType {
// Special case: time.Time
t := ReadTime(r, n, err)
log.Info(Fmt("Read time: %v", t))
rv.Set(reflect.ValueOf(t))
} else {
for _, fieldInfo := range typeInfo.Fields {
i, fieldType, opts := fieldInfo.unpack()
fieldRv := rv.Field(i)
readReflectBinary(fieldRv, fieldType, opts, r, n, err)
}
}
case reflect.String:
str := ReadString(r, n, err)
log.Info(Fmt("Read string: %v", str))
rv.SetString(str)
case reflect.Int64:
if opts.Varint {
num := ReadVarint(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetInt(int64(num))
} else {
num := ReadInt64(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetInt(int64(num))
}
case reflect.Int32:
num := ReadUint32(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetInt(int64(num))
case reflect.Int16:
num := ReadUint16(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetInt(int64(num))
case reflect.Int8:
num := ReadUint8(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetInt(int64(num))
case reflect.Int:
num := ReadVarint(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetInt(int64(num))
case reflect.Uint64:
if opts.Varint {
num := ReadVarint(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetUint(uint64(num))
} else {
num := ReadUint64(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetUint(uint64(num))
}
case reflect.Uint32:
num := ReadUint32(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetUint(uint64(num))
case reflect.Uint16:
num := ReadUint16(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetUint(uint64(num))
case reflect.Uint8:
num := ReadUint8(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetUint(uint64(num))
case reflect.Uint:
num := ReadVarint(r, n, err)
log.Info(Fmt("Read num: %v", num))
rv.SetUint(uint64(num))
case reflect.Bool:
num := ReadUint8(r, n, err)
log.Info(Fmt("Read bool: %v", num))
rv.SetBool(num > 0)
default:
PanicSanity(Fmt("Unknown field type %v", rt.Kind()))
}
}
// rv: the reflection value of the thing to write
// rt: the type of rv as declared in the container, not necessarily rv.Type().
func writeReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, w io.Writer, n *int64, err *error) {
// Get typeInfo
typeInfo := GetTypeInfo(rt)
if rt.Kind() == reflect.Interface {
if rv.IsNil() {
// XXX ensure that typeByte 0 is reserved.
WriteByte(0x00, w, n, err)
return
}
crv := rv.Elem() // concrete reflection value
crt := crv.Type() // concrete reflection type
if typeInfo.IsRegisteredInterface {
// See if the crt is registered.
// If so, we're more restrictive.
_, ok := typeInfo.TypeToByte[crt]
if !ok {
switch crt.Kind() {
case reflect.Ptr:
*err = errors.New(Fmt("Unexpected pointer type %v for registered interface %v. "+
"Was it registered as a value receiver rather than as a pointer receiver?", crt, rt.Name()))
case reflect.Struct:
*err = errors.New(Fmt("Unexpected struct type %v for registered interface %v. "+
"Was it registered as a pointer receiver rather than as a value receiver?", crt, rt.Name()))
default:
*err = errors.New(Fmt("Unexpected type %v for registered interface %v. "+
"If this is intentional, please register it.", crt, rt.Name()))
}
return
}
} else {
// We support writing unsafely for convenience.
}
// We don't have to write the typeByte here,
// the writeReflectBinary() call below will write it.
writeReflectBinary(crv, crt, opts, w, n, err)
return
}
if rt.Kind() == reflect.Ptr {
// Dereference pointer
rv, rt = rv.Elem(), rt.Elem()
typeInfo = GetTypeInfo(rt)
if !rv.IsValid() {
// For better compatibility with other languages,
// as far as tendermint/wire is concerned,
// pointers to nil values are the same as nil.
WriteByte(0x00, w, n, err)
return
}
if typeInfo.Byte == 0x00 {
WriteByte(0x01, w, n, err)
// continue...
} else {
// continue...
}
}
// Write type byte
if typeInfo.Byte != 0x00 {
WriteByte(typeInfo.Byte, w, n, err)
}
// All other types
switch rt.Kind() {
case reflect.Array:
elemRt := rt.Elem()
length := rt.Len()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Bytearrays
if rv.CanAddr() {
byteslice := rv.Slice(0, length).Bytes()
WriteTo(byteslice, w, n, err)
} else {
buf := make([]byte, length)
reflect.Copy(reflect.ValueOf(buf), rv)
WriteTo(buf, w, n, err)
}
} else {
// Write elems
for i := 0; i < length; i++ {
elemRv := rv.Index(i)
writeReflectBinary(elemRv, elemRt, opts, w, n, err)
}
}
case reflect.Slice:
elemRt := rt.Elem()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Byteslices
byteslice := rv.Bytes()
WriteByteSlice(byteslice, w, n, err)
} else {
// Write length
length := rv.Len()
WriteVarint(length, w, n, err)
// Write elems
for i := 0; i < length; i++ {
elemRv := rv.Index(i)
writeReflectBinary(elemRv, elemRt, opts, w, n, err)
}
}
case reflect.Struct:
if rt == timeType {
// Special case: time.Time
WriteTime(rv.Interface().(time.Time), w, n, err)
} else {
for _, fieldInfo := range typeInfo.Fields {
i, fieldType, opts := fieldInfo.unpack()
fieldRv := rv.Field(i)
writeReflectBinary(fieldRv, fieldType, opts, w, n, err)
}
}
case reflect.String:
WriteString(rv.String(), w, n, err)
case reflect.Int64:
if opts.Varint {
WriteVarint(int(rv.Int()), w, n, err)
} else {
WriteInt64(rv.Int(), w, n, err)
}
case reflect.Int32:
WriteInt32(int32(rv.Int()), w, n, err)
case reflect.Int16:
WriteInt16(int16(rv.Int()), w, n, err)
case reflect.Int8:
WriteInt8(int8(rv.Int()), w, n, err)
case reflect.Int:
WriteVarint(int(rv.Int()), w, n, err)
case reflect.Uint64:
if opts.Varint {
WriteUvarint(uint(rv.Uint()), w, n, err)
} else {
WriteUint64(rv.Uint(), w, n, err)
}
case reflect.Uint32:
WriteUint32(uint32(rv.Uint()), w, n, err)
case reflect.Uint16:
WriteUint16(uint16(rv.Uint()), w, n, err)
case reflect.Uint8:
WriteUint8(uint8(rv.Uint()), w, n, err)
case reflect.Uint:
WriteUvarint(uint(rv.Uint()), w, n, err)
case reflect.Bool:
if rv.Bool() {
WriteUint8(uint8(1), w, n, err)
} else {
WriteUint8(uint8(0), w, n, err)
}
default:
PanicSanity(Fmt("Unknown field type %v", rt.Kind()))
}
}
//-----------------------------------------------------------------------------
func readByteJSON(o interface{}) (typeByte byte, rest interface{}, err error) {
oSlice, ok := o.([]interface{})
if !ok {
err = errors.New(Fmt("Expected type [Byte,?] but got type %v", reflect.TypeOf(o)))
return
}
if len(oSlice) != 2 {
err = errors.New(Fmt("Expected [Byte,?] len 2 but got len %v", len(oSlice)))
return
}
typeByte_, ok := oSlice[0].(float64)
typeByte = byte(typeByte_)
rest = oSlice[1]
return
}
// Contract: Caller must ensure that rt is supported
// (e.g. is recursively composed of supported native types, and structs and slices.)
// rv and rt refer to the object we're unmarhsaling into, whereas o is the result of naiive json unmarshal (map[string]interface{})
func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *error) {
// Get typeInfo
typeInfo := GetTypeInfo(rt)
if rt.Kind() == reflect.Interface {
if !typeInfo.IsRegisteredInterface {
// There's no way we can read such a thing.
*err = errors.New(Fmt("Cannot read unregistered interface type %v", rt))
return
}
if o == nil {
return // nil
}
typeByte, _, err_ := readByteJSON(o)
if err_ != nil {
*err = err_
return
}
crt, ok := typeInfo.ByteToType[typeByte]
if !ok {
*err = errors.New(Fmt("Byte %X not registered for interface %v", typeByte, rt))
return
}
crv := reflect.New(crt).Elem()
readReflectJSON(crv, crt, o, err)
rv.Set(crv) // NOTE: orig rv is ignored.
return
}
if rt.Kind() == reflect.Ptr {
if o == nil {
return // nil
}
// Create new struct if rv is nil.
if rv.IsNil() {
newRv := reflect.New(rt.Elem())
rv.Set(newRv)
rv = newRv
}
// Dereference pointer
rv, rt = rv.Elem(), rt.Elem()
typeInfo = GetTypeInfo(rt)
// continue...
}
// Read Byte prefix
if typeInfo.Byte != 0x00 {
typeByte, rest, err_ := readByteJSON(o)
if err_ != nil {
*err = err_
return
}
if typeByte != typeInfo.Byte {
*err = errors.New(Fmt("Expected Byte of %X but got %X", typeInfo.Byte, byte(typeByte)))
return
}
o = rest
}
switch rt.Kind() {
case reflect.Array:
elemRt := rt.Elem()
length := rt.Len()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Bytearrays
oString, ok := o.(string)
if !ok {
*err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o)))
return
}
buf, err_ := hex.DecodeString(oString)
if err_ != nil {
*err = err_
return
}
if len(buf) != length {
*err = errors.New(Fmt("Expected bytearray of length %v but got %v", length, len(buf)))
return
}
log.Info("Read bytearray", "bytes", buf)
reflect.Copy(rv, reflect.ValueOf(buf))
} else {
oSlice, ok := o.([]interface{})
if !ok {
*err = errors.New(Fmt("Expected array of %v but got type %v", rt, reflect.TypeOf(o)))
return
}
if len(oSlice) != length {
*err = errors.New(Fmt("Expected array of length %v but got %v", length, len(oSlice)))
return
}
for i := 0; i < length; i++ {
elemRv := rv.Index(i)
readReflectJSON(elemRv, elemRt, oSlice[i], err)
}
log.Info(Fmt("Read %v-array", elemRt), "length", length)
}
case reflect.Slice:
elemRt := rt.Elem()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Byteslices
oString, ok := o.(string)
if !ok {
*err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o)))
return
}
byteslice, err_ := hex.DecodeString(oString)
if err_ != nil {
*err = err_
return
}
log.Info("Read byteslice", "bytes", byteslice)
rv.Set(reflect.ValueOf(byteslice))
} else {
// Read length
oSlice, ok := o.([]interface{})
if !ok {
*err = errors.New(Fmt("Expected array of %v but got type %v", rt, reflect.TypeOf(o)))
return
}
length := len(oSlice)
log.Info(Fmt("Read length: %v", length))
sliceRv := reflect.MakeSlice(rt, length, length)
// Read elems
for i := 0; i < length; i++ {
elemRv := sliceRv.Index(i)
readReflectJSON(elemRv, elemRt, oSlice[i], err)
}
rv.Set(sliceRv)
}
case reflect.Struct:
if rt == timeType {
// Special case: time.Time
str, ok := o.(string)
if !ok {
*err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o)))
return
}
log.Info(Fmt("Read time: %v", str))
t, err_ := time.Parse(iso8601, str)
if err_ != nil {
*err = err_
return
}
rv.Set(reflect.ValueOf(t))
} else {
oMap, ok := o.(map[string]interface{})
if !ok {
*err = errors.New(Fmt("Expected map but got type %v", reflect.TypeOf(o)))
return
}
// TODO: ensure that all fields are set?
// TODO: disallow unknown oMap fields?
for _, fieldInfo := range typeInfo.Fields {
i, fieldType, opts := fieldInfo.unpack()
value, ok := oMap[opts.JSONName]
if !ok {
continue // Skip missing fields.
}
fieldRv := rv.Field(i)
readReflectJSON(fieldRv, fieldType, value, err)
}
}
case reflect.String:
str, ok := o.(string)
if !ok {
*err = errors.New(Fmt("Expected string but got type %v", reflect.TypeOf(o)))
return
}
log.Info(Fmt("Read string: %v", str))
rv.SetString(str)
case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
num, ok := o.(float64)
if !ok {
*err = errors.New(Fmt("Expected numeric but got type %v", reflect.TypeOf(o)))
return
}
log.Info(Fmt("Read num: %v", num))
rv.SetInt(int64(num))
case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
num, ok := o.(float64)
if !ok {
*err = errors.New(Fmt("Expected numeric but got type %v", reflect.TypeOf(o)))
return
}
if num < 0 {
*err = errors.New(Fmt("Expected unsigned numeric but got %v", num))
return
}
log.Info(Fmt("Read num: %v", num))
rv.SetUint(uint64(num))
case reflect.Bool:
bl, ok := o.(bool)
if !ok {
*err = errors.New(Fmt("Expected boolean but got type %v", reflect.TypeOf(o)))
return
}
log.Info(Fmt("Read boolean: %v", bl))
rv.SetBool(bl)
default:
PanicSanity(Fmt("Unknown field type %v", rt.Kind()))
}
}
func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) {
log.Info(Fmt("writeReflectJSON(%v, %v, %v, %v, %v)", rv, rt, w, n, err))
// Get typeInfo
typeInfo := GetTypeInfo(rt)
if rt.Kind() == reflect.Interface {
if rv.IsNil() {
// XXX ensure that typeByte 0 is reserved.
WriteTo([]byte("null"), w, n, err)
return
}
crv := rv.Elem() // concrete reflection value
crt := crv.Type() // concrete reflection type
if typeInfo.IsRegisteredInterface {
// See if the crt is registered.
// If so, we're more restrictive.
_, ok := typeInfo.TypeToByte[crt]
if !ok {
switch crt.Kind() {
case reflect.Ptr:
*err = errors.New(Fmt("Unexpected pointer type %v for registered interface %v. "+
"Was it registered as a value receiver rather than as a pointer receiver?", crt, rt.Name()))
case reflect.Struct:
*err = errors.New(Fmt("Unexpected struct type %v for registered interface %v. "+
"Was it registered as a pointer receiver rather than as a value receiver?", crt, rt.Name()))
default:
*err = errors.New(Fmt("Unexpected type %v for registered interface %v. "+
"If this is intentional, please register it.", crt, rt.Name()))
}
return
}
} else {
// We support writing unsafely for convenience.
}
// We don't have to write the typeByte here,
// the writeReflectJSON() call below will write it.
writeReflectJSON(crv, crt, w, n, err)
return
}
if rt.Kind() == reflect.Ptr {
// Dereference pointer
rv, rt = rv.Elem(), rt.Elem()
typeInfo = GetTypeInfo(rt)
if !rv.IsValid() {
// For better compatibility with other languages,
// as far as tendermint/wire is concerned,
// pointers to nil values are the same as nil.
WriteTo([]byte("null"), w, n, err)
return
}
// continue...
}
// Write Byte
if typeInfo.Byte != 0x00 {
WriteTo([]byte(Fmt("[%v,", typeInfo.Byte)), w, n, err)
defer WriteTo([]byte("]"), w, n, err)
}
// All other types
switch rt.Kind() {
case reflect.Array:
elemRt := rt.Elem()
length := rt.Len()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Bytearray
bytearray := reflect.ValueOf(make([]byte, length))
reflect.Copy(bytearray, rv)
WriteTo([]byte(Fmt("\"%X\"", bytearray.Interface())), w, n, err)
} else {
WriteTo([]byte("["), w, n, err)
// Write elems
for i := 0; i < length; i++ {
elemRv := rv.Index(i)
writeReflectJSON(elemRv, elemRt, w, n, err)
if i < length-1 {
WriteTo([]byte(","), w, n, err)
}
}
WriteTo([]byte("]"), w, n, err)
}
case reflect.Slice:
elemRt := rt.Elem()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Byteslices
byteslice := rv.Bytes()
WriteTo([]byte(Fmt("\"%X\"", byteslice)), w, n, err)
} else {
WriteTo([]byte("["), w, n, err)
// Write elems
length := rv.Len()
for i := 0; i < length; i++ {
elemRv := rv.Index(i)
writeReflectJSON(elemRv, elemRt, w, n, err)
if i < length-1 {
WriteTo([]byte(","), w, n, err)
}
}
WriteTo([]byte("]"), w, n, err)
}
case reflect.Struct:
if rt == timeType {
// Special case: time.Time
t := rv.Interface().(time.Time).UTC()
str := t.Format(iso8601)
jsonBytes, err_ := json.Marshal(str)
if err_ != nil {
*err = err_
return
}
WriteTo(jsonBytes, w, n, err)
} else {
WriteTo([]byte("{"), w, n, err)
wroteField := false
for _, fieldInfo := range typeInfo.Fields {
i, fieldType, opts := fieldInfo.unpack()
fieldRv := rv.Field(i)
if wroteField {
WriteTo([]byte(","), w, n, err)
} else {
wroteField = true
}
WriteTo([]byte(Fmt("\"%v\":", opts.JSONName)), w, n, err)
writeReflectJSON(fieldRv, fieldType, w, n, err)
}
WriteTo([]byte("}"), w, n, err)
}
case reflect.String:
fallthrough
case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
fallthrough
case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
fallthrough
case reflect.Bool:
jsonBytes, err_ := json.Marshal(rv.Interface())
if err_ != nil {
*err = err_
return
}
WriteTo(jsonBytes, w, n, err)
default:
PanicSanity(Fmt("Unknown field type %v", rt.Kind()))
}
}
-508
View File
@@ -1,508 +0,0 @@
package wire
import (
"bytes"
"fmt"
"reflect"
"testing"
"time"
. "github.com/tendermint/tendermint/common"
)
type SimpleStruct struct {
String string
Bytes []byte
Time time.Time
}
type Animal interface{}
const (
AnimalTypeCat = byte(0x01)
AnimalTypeDog = byte(0x02)
AnimalTypeSnake = byte(0x03)
AnimalTypeViper = byte(0x04)
)
// Implements Animal
type Cat struct {
SimpleStruct
}
// Implements Animal
type Dog struct {
SimpleStruct
}
// Implements Animal
type Snake []byte
// Implements Animal
type Viper struct {
Bytes []byte
}
var _ = RegisterInterface(
struct{ Animal }{},
ConcreteType{Cat{}, AnimalTypeCat},
ConcreteType{Dog{}, AnimalTypeDog},
ConcreteType{Snake{}, AnimalTypeSnake},
ConcreteType{&Viper{}, AnimalTypeViper},
)
// TODO: add assertions here ...
func TestAnimalInterface(t *testing.T) {
var foo Animal
// Type of pointer to Animal
rt := reflect.TypeOf(&foo)
fmt.Printf("rt: %v\n", rt)
// Type of Animal itself.
// NOTE: normally this is acquired through other means
// like introspecting on method signatures, or struct fields.
rte := rt.Elem()
fmt.Printf("rte: %v\n", rte)
// Get a new pointer to the interface
// NOTE: calling .Interface() is to get the actual value,
// instead of reflection values.
ptr := reflect.New(rte).Interface()
fmt.Printf("ptr: %v", ptr)
// Make a binary byteslice that represents a *snake.
foo = Snake([]byte("snake"))
snakeBytes := BinaryBytes(foo)
snakeReader := bytes.NewReader(snakeBytes)
// Now you can read it.
n, err := new(int64), new(error)
it := ReadBinary(foo, snakeReader, n, err).(Animal)
fmt.Println(it, reflect.TypeOf(it))
}
//-------------------------------------
type Constructor func() interface{}
type Instantiator func() (o interface{}, ptr interface{})
type Validator func(o interface{}, t *testing.T)
type TestCase struct {
Constructor
Instantiator
Validator
}
//-------------------------------------
func constructBasic() interface{} {
cat := Cat{
SimpleStruct{
String: "String",
Bytes: []byte("Bytes"),
Time: time.Unix(123, 456789999),
},
}
return cat
}
func instantiateBasic() (interface{}, interface{}) {
return Cat{}, &Cat{}
}
func validateBasic(o interface{}, t *testing.T) {
cat := o.(Cat)
if cat.String != "String" {
t.Errorf("Expected cat.String == 'String', got %v", cat.String)
}
if string(cat.Bytes) != "Bytes" {
t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
}
if cat.Time.UnixNano() != 123456000000 { // Only milliseconds
t.Errorf("Expected cat.Time.UnixNano() == 123456000000, got %v", cat.Time.UnixNano())
}
}
//-------------------------------------
type NilTestStruct struct {
IntPtr *int
CatPtr *Cat
Animal Animal
}
func constructNilTestStruct() interface{} {
return NilTestStruct{}
}
func instantiateNilTestStruct() (interface{}, interface{}) {
return NilTestStruct{}, &NilTestStruct{}
}
func validateNilTestStruct(o interface{}, t *testing.T) {
nts := o.(NilTestStruct)
if nts.IntPtr != nil {
t.Errorf("Expected nts.IntPtr to be nil, got %v", nts.IntPtr)
}
if nts.CatPtr != nil {
t.Errorf("Expected nts.CatPtr to be nil, got %v", nts.CatPtr)
}
if nts.Animal != nil {
t.Errorf("Expected nts.Animal to be nil, got %v", nts.Animal)
}
}
//-------------------------------------
type ComplexStruct struct {
Name string
Animal Animal
}
func constructComplex() interface{} {
c := ComplexStruct{
Name: "Complex",
Animal: constructBasic(),
}
return c
}
func instantiateComplex() (interface{}, interface{}) {
return ComplexStruct{}, &ComplexStruct{}
}
func validateComplex(o interface{}, t *testing.T) {
c2 := o.(ComplexStruct)
if cat, ok := c2.Animal.(Cat); ok {
validateBasic(cat, t)
} else {
t.Errorf("Expected c2.Animal to be of type cat, got %v", reflect.ValueOf(c2.Animal).Elem().Type())
}
}
//-------------------------------------
type ComplexStruct2 struct {
Cat Cat
Dog *Dog
Snake Snake
Snake2 *Snake
Viper Viper
Viper2 *Viper
}
func constructComplex2() interface{} {
snake_ := Snake([]byte("hiss"))
snakePtr_ := &snake_
c := ComplexStruct2{
Cat: Cat{
SimpleStruct{
String: "String",
Bytes: []byte("Bytes"),
},
},
Dog: &Dog{
SimpleStruct{
String: "Woof",
Bytes: []byte("Bark"),
},
},
Snake: Snake([]byte("hiss")),
Snake2: snakePtr_,
Viper: Viper{Bytes: []byte("hizz")},
Viper2: &Viper{Bytes: []byte("hizz")},
}
return c
}
func instantiateComplex2() (interface{}, interface{}) {
return ComplexStruct2{}, &ComplexStruct2{}
}
func validateComplex2(o interface{}, t *testing.T) {
c2 := o.(ComplexStruct2)
cat := c2.Cat
if cat.String != "String" {
t.Errorf("Expected cat.String == 'String', got %v", cat.String)
}
if string(cat.Bytes) != "Bytes" {
t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
}
dog := c2.Dog
if dog.String != "Woof" {
t.Errorf("Expected dog.String == 'Woof', got %v", dog.String)
}
if string(dog.Bytes) != "Bark" {
t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes)
}
snake := c2.Snake
if string(snake) != "hiss" {
t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake))
}
snake2 := c2.Snake2
if string(*snake2) != "hiss" {
t.Errorf("Expected string(snake2) == 'hiss', got %v", string(*snake2))
}
viper := c2.Viper
if string(viper.Bytes) != "hizz" {
t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes))
}
viper2 := c2.Viper2
if string(viper2.Bytes) != "hizz" {
t.Errorf("Expected string(viper2.Bytes) == 'hizz', got %v", string(viper2.Bytes))
}
}
//-------------------------------------
type ComplexStructArray struct {
Animals []Animal
Bytes [5]byte
Ints [5]int
Array SimpleArray
}
func constructComplexArray() interface{} {
c := ComplexStructArray{
Animals: []Animal{
Cat{
SimpleStruct{
String: "String",
Bytes: []byte("Bytes"),
},
},
Dog{
SimpleStruct{
String: "Woof",
Bytes: []byte("Bark"),
},
},
Snake([]byte("hiss")),
&Viper{
Bytes: []byte("hizz"),
},
},
Bytes: [5]byte{1, 10, 50, 100, 200},
Ints: [5]int{1, 2, 3, 4, 5},
Array: SimpleArray([5]byte{1, 10, 50, 100, 200}),
}
return c
}
func instantiateComplexArray() (interface{}, interface{}) {
return ComplexStructArray{}, &ComplexStructArray{}
}
func validateComplexArray(o interface{}, t *testing.T) {
c2 := o.(ComplexStructArray)
if cat, ok := c2.Animals[0].(Cat); ok {
if cat.String != "String" {
t.Errorf("Expected cat.String == 'String', got %v", cat.String)
}
if string(cat.Bytes) != "Bytes" {
t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
}
} else {
t.Errorf("Expected c2.Animals[0] to be of type cat, got %v", reflect.ValueOf(c2.Animals[0]).Elem().Type())
}
if dog, ok := c2.Animals[1].(Dog); ok {
if dog.String != "Woof" {
t.Errorf("Expected dog.String == 'Woof', got %v", dog.String)
}
if string(dog.Bytes) != "Bark" {
t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes)
}
} else {
t.Errorf("Expected c2.Animals[1] to be of type dog, got %v", reflect.ValueOf(c2.Animals[1]).Elem().Type())
}
if snake, ok := c2.Animals[2].(Snake); ok {
if string(snake) != "hiss" {
t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake))
}
} else {
t.Errorf("Expected c2.Animals[2] to be of type Snake, got %v", reflect.ValueOf(c2.Animals[2]).Elem().Type())
}
if viper, ok := c2.Animals[3].(*Viper); ok {
if string(viper.Bytes) != "hizz" {
t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes))
}
} else {
t.Errorf("Expected c2.Animals[3] to be of type *Viper, got %v", reflect.ValueOf(c2.Animals[3]).Elem().Type())
}
}
//-----------------------------------------------------------------------------
var testCases = []TestCase{}
func init() {
testCases = append(testCases, TestCase{constructBasic, instantiateBasic, validateBasic})
testCases = append(testCases, TestCase{constructComplex, instantiateComplex, validateComplex})
testCases = append(testCases, TestCase{constructComplex2, instantiateComplex2, validateComplex2})
testCases = append(testCases, TestCase{constructComplexArray, instantiateComplexArray, validateComplexArray})
testCases = append(testCases, TestCase{constructNilTestStruct, instantiateNilTestStruct, validateNilTestStruct})
}
func TestBinary(t *testing.T) {
for i, testCase := range testCases {
log.Notice(fmt.Sprintf("Running test case %v", i))
// Construct an object
o := testCase.Constructor()
// Write the object
data := BinaryBytes(o)
t.Logf("Binary: %X", data)
instance, instancePtr := testCase.Instantiator()
// Read onto a struct
n, err := new(int64), new(error)
res := ReadBinary(instance, bytes.NewReader(data), n, err)
if *err != nil {
t.Fatalf("Failed to read into instance: %v", *err)
}
// Validate object
testCase.Validator(res, t)
// Read onto a pointer
n, err = new(int64), new(error)
res = ReadBinaryPtr(instancePtr, bytes.NewReader(data), n, err)
if *err != nil {
t.Fatalf("Failed to read into instance: %v", *err)
}
if res != instancePtr {
t.Errorf("Expected pointer to pass through")
}
// Validate object
testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t)
}
}
func TestJSON(t *testing.T) {
for i, testCase := range testCases {
log.Notice(fmt.Sprintf("Running test case %v", i))
// Construct an object
o := testCase.Constructor()
// Write the object
data := JSONBytes(o)
t.Logf("JSON: %v", string(data))
instance, instancePtr := testCase.Instantiator()
// Read onto a struct
err := new(error)
res := ReadJSON(instance, data, err)
if *err != nil {
t.Fatalf("Failed to read cat: %v", *err)
}
// Validate object
testCase.Validator(res, t)
// Read onto a pointer
res = ReadJSON(instancePtr, data, err)
if *err != nil {
t.Fatalf("Failed to read cat: %v", *err)
}
if res != instancePtr {
t.Errorf("Expected pointer to pass through")
}
// Validate object
testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t)
}
}
//------------------------------------------------------------------------------
type Foo struct {
FieldA string `json:"fieldA"` // json field name is "fieldA"
FieldB string // json field name is "FieldB"
fieldC string // not exported, not serialized.
}
func TestJSONFieldNames(t *testing.T) {
for i := 0; i < 20; i++ { // Try to ensure deterministic success.
foo := Foo{"a", "b", "c"}
stringified := string(JSONBytes(foo))
expected := `{"fieldA":"a","FieldB":"b"}`
if stringified != expected {
t.Fatalf("JSONFieldNames error: expected %v, got %v",
expected, stringified)
}
}
}
//------------------------------------------------------------------------------
func TestBadAlloc(t *testing.T) {
n, err := new(int64), new(error)
instance := new([]byte)
data := RandBytes(100 * 1024)
b := new(bytes.Buffer)
// this slice of data claims to be much bigger than it really is
WriteUvarint(uint(10000000000000000), b, n, err)
b.Write(data)
res := ReadBinary(instance, b, n, err)
fmt.Println(res, *err)
}
//------------------------------------------------------------------------------
type SimpleArray [5]byte
func TestSimpleArray(t *testing.T) {
var foo SimpleArray
// Type of pointer to array
rt := reflect.TypeOf(&foo)
fmt.Printf("rt: %v\n", rt) // *binary.SimpleArray
// Type of array itself.
// NOTE: normally this is acquired through other means
// like introspecting on method signatures, or struct fields.
rte := rt.Elem()
fmt.Printf("rte: %v\n", rte) // binary.SimpleArray
// Get a new pointer to the array
// NOTE: calling .Interface() is to get the actual value,
// instead of reflection values.
ptr := reflect.New(rte).Interface()
fmt.Printf("ptr: %v\n", ptr) // &[0 0 0 0 0]
// Make a simple int aray
fooArray := SimpleArray([5]byte{1, 10, 50, 100, 200})
fooBytes := BinaryBytes(fooArray)
fooReader := bytes.NewReader(fooBytes)
// Now you can read it.
n, err := new(int64), new(error)
it := ReadBinary(foo, fooReader, n, err).(SimpleArray)
if !bytes.Equal(it[:], fooArray[:]) {
t.Errorf("Expected %v but got %v", fooArray, it)
}
}
-33
View File
@@ -1,33 +0,0 @@
package wire
import (
"io"
. "github.com/tendermint/tendermint/common"
)
// String
func WriteString(s string, w io.Writer, n *int64, err *error) {
WriteVarint(len(s), w, n, err)
WriteTo([]byte(s), w, n, err)
}
func ReadString(r io.Reader, n *int64, err *error) string {
length := ReadVarint(r, n, err)
if *err != nil {
return ""
}
if length < 0 {
*err = ErrBinaryReadSizeUnderflow
return ""
}
if MaxBinaryReadSize < MaxInt64(int64(length), *n+int64(length)) {
*err = ErrBinaryReadSizeOverflow
return ""
}
buf := make([]byte, length)
ReadFull(buf, r, n, err)
return string(buf)
}
-27
View File
@@ -1,27 +0,0 @@
package wire
import (
"io"
"time"
. "github.com/tendermint/tendermint/common"
)
/*
Writes nanoseconds since epoch but with millisecond precision.
This is to ease compatibility with Javascript etc.
*/
func WriteTime(t time.Time, w io.Writer, n *int64, err *error) {
nanosecs := t.UnixNano()
millisecs := nanosecs / 1000000
WriteInt64(millisecs*1000000, w, n, err)
}
func ReadTime(r io.Reader, n *int64, err *error) time.Time {
t := ReadInt64(r, n, err)
if t%1000000 != 0 {
PanicSanity("Time cannot have sub-millisecond precision")
}
return time.Unix(0, t)
}
-78
View File
@@ -1,78 +0,0 @@
package wire
import (
"bytes"
"crypto/sha256"
"encoding/json"
"github.com/tendermint/tendermint/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160"
. "github.com/tendermint/tendermint/common"
)
func BinaryBytes(o interface{}) []byte {
w, n, err := new(bytes.Buffer), new(int64), new(error)
WriteBinary(o, w, n, err)
if *err != nil {
PanicSanity(*err)
}
return w.Bytes()
}
func JSONBytes(o interface{}) []byte {
w, n, err := new(bytes.Buffer), new(int64), new(error)
WriteJSON(o, w, n, err)
if *err != nil {
PanicSanity(*err)
}
return w.Bytes()
}
// NOTE: inefficient
func JSONBytesPretty(o interface{}) []byte {
jsonBytes := JSONBytes(o)
var object interface{}
err := json.Unmarshal(jsonBytes, &object)
if err != nil {
PanicSanity(err)
}
jsonBytes, err = json.MarshalIndent(object, "", "\t")
if err != nil {
PanicSanity(err)
}
return jsonBytes
}
// NOTE: does not care about the type, only the binary representation.
func BinaryEqual(a, b interface{}) bool {
aBytes := BinaryBytes(a)
bBytes := BinaryBytes(b)
return bytes.Equal(aBytes, bBytes)
}
// NOTE: does not care about the type, only the binary representation.
func BinaryCompare(a, b interface{}) int {
aBytes := BinaryBytes(a)
bBytes := BinaryBytes(b)
return bytes.Compare(aBytes, bBytes)
}
// NOTE: only use this if you need 32 bytes.
func BinarySha256(o interface{}) []byte {
hasher, n, err := sha256.New(), new(int64), new(error)
WriteBinary(o, hasher, n, err)
if *err != nil {
PanicSanity(*err)
}
return hasher.Sum(nil)
}
// NOTE: The default hash function is Ripemd160.
func BinaryRipemd160(o interface{}) []byte {
hasher, n, err := ripemd160.New(), new(int64), new(error)
WriteBinary(o, hasher, n, err)
if *err != nil {
PanicSanity(*err)
}
return hasher.Sum(nil)
}
-3
View File
@@ -1,3 +0,0 @@
package wire
const Version = "0.5.0"
-134
View File
@@ -1,134 +0,0 @@
package wire
import (
"encoding/json"
"errors"
"io"
"reflect"
. "github.com/tendermint/tendermint/common"
)
// TODO document and maybe make it configurable.
const MaxBinaryReadSize = 21 * 1024 * 1024
var ErrBinaryReadSizeOverflow = errors.New("Error: binary read size overflow")
var ErrBinaryReadSizeUnderflow = errors.New("Error: binary read size underflow")
func ReadBinary(o interface{}, r io.Reader, n *int64, err *error) interface{} {
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
if rv.Kind() == reflect.Ptr {
if rv.IsNil() {
// This allows ReadBinaryObject() to return a nil pointer,
// if the value read is nil.
rvPtr := reflect.New(rt)
ReadBinaryPtr(rvPtr.Interface(), r, n, err)
return rvPtr.Elem().Interface()
} else {
readReflectBinary(rv, rt, Options{}, r, n, err)
return o
}
} else {
ptrRv := reflect.New(rt)
readReflectBinary(ptrRv.Elem(), rt, Options{}, r, n, err)
return ptrRv.Elem().Interface()
}
}
func ReadBinaryPtr(o interface{}, r io.Reader, n *int64, err *error) interface{} {
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
if rv.Kind() == reflect.Ptr {
readReflectBinary(rv.Elem(), rt.Elem(), Options{}, r, n, err)
} else {
PanicSanity("ReadBinaryPtr expects o to be a pointer")
}
return o
}
func WriteBinary(o interface{}, w io.Writer, n *int64, err *error) {
rv := reflect.ValueOf(o)
rt := reflect.TypeOf(o)
writeReflectBinary(rv, rt, Options{}, w, n, err)
}
func ReadJSON(o interface{}, bytes []byte, err *error) interface{} {
var object interface{}
*err = json.Unmarshal(bytes, &object)
if *err != nil {
return o
}
return ReadJSONObject(o, object, err)
}
func ReadJSONPtr(o interface{}, bytes []byte, err *error) interface{} {
var object interface{}
*err = json.Unmarshal(bytes, &object)
if *err != nil {
return o
}
return ReadJSONObjectPtr(o, object, err)
}
// o is the ultimate destination, object is the result of json unmarshal
func ReadJSONObject(o interface{}, object interface{}, err *error) interface{} {
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
if rv.Kind() == reflect.Ptr {
if rv.IsNil() {
// This allows ReadJSONObject() to return a nil pointer
// if the value read is nil.
rvPtr := reflect.New(rt)
ReadJSONObjectPtr(rvPtr.Interface(), object, err)
return rvPtr.Elem().Interface()
} else {
readReflectJSON(rv, rt, object, err)
return o
}
} else {
ptrRv := reflect.New(rt)
readReflectJSON(ptrRv.Elem(), rt, object, err)
return ptrRv.Elem().Interface()
}
}
func ReadJSONObjectPtr(o interface{}, object interface{}, err *error) interface{} {
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
if rv.Kind() == reflect.Ptr {
readReflectJSON(rv.Elem(), rt.Elem(), object, err)
} else {
PanicSanity("ReadJSON(Object)Ptr expects o to be a pointer")
}
return o
}
func WriteJSON(o interface{}, w io.Writer, n *int64, err *error) {
rv := reflect.ValueOf(o)
rt := reflect.TypeOf(o)
if rv.Kind() == reflect.Ptr {
rv, rt = rv.Elem(), rt.Elem()
}
writeReflectJSON(rv, rt, w, n, err)
}
// Write all of bz to w
// Increment n and set err accordingly.
func WriteTo(bz []byte, w io.Writer, n *int64, err *error) {
if *err != nil {
return
}
n_, err_ := w.Write(bz)
*n += int64(n_)
*err = err_
}
// Read len(buf) from r
// Increment n and set err accordingly.
func ReadFull(buf []byte, r io.Reader, n *int64, err *error) {
if *err != nil {
return
}
n_, err_ := io.ReadFull(r, buf)
*n += int64(n_)
*err = err_
}