mirror of
https://github.com/tendermint/tendermint.git
synced 2026-05-29 10:30:20 +00:00
Refactor Tx, Validator, and Account structure
This commit is contained in:
@@ -1,23 +1,31 @@
|
||||
package binary
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Binary interface {
|
||||
WriteTo(w io.Writer) (int64, error)
|
||||
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 {
|
||||
readReflect(rv.Elem(), rt.Elem(), r, n, err)
|
||||
return o
|
||||
} else {
|
||||
ptrRv := reflect.New(rt)
|
||||
readReflect(ptrRv.Elem(), rt, r, n, err)
|
||||
return ptrRv.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
func WriteBinary(w io.Writer, b Binary, n *int64, err *error) {
|
||||
if *err != nil {
|
||||
return
|
||||
}
|
||||
n_, err_ := b.WriteTo(w)
|
||||
*n += int64(n_)
|
||||
*err = err_
|
||||
func WriteBinary(o interface{}, w io.Writer, n *int64, err *error) {
|
||||
rv := reflect.ValueOf(o)
|
||||
rt := reflect.TypeOf(o)
|
||||
writeReflect(rv, rt, w, n, err)
|
||||
}
|
||||
|
||||
// Write all of bz to w
|
||||
// Increment n and set err accordingly.
|
||||
func WriteTo(w io.Writer, bz []byte, n *int64, err *error) {
|
||||
func WriteTo(bz []byte, w io.Writer, n *int64, err *error) {
|
||||
if *err != nil {
|
||||
return
|
||||
}
|
||||
@@ -28,7 +36,7 @@ func WriteTo(w io.Writer, bz []byte, n *int64, err *error) {
|
||||
|
||||
// Read len(buf) from r
|
||||
// Increment n and set err accordingly.
|
||||
func ReadFull(r io.Reader, buf []byte, n *int64, err *error) {
|
||||
func ReadFull(buf []byte, r io.Reader, n *int64, err *error) {
|
||||
if *err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,27 +4,27 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func WriteByteSlice(w io.Writer, bz []byte, n *int64, err *error) {
|
||||
WriteUInt32(w, uint32(len(bz)), n, err)
|
||||
WriteTo(w, bz, n, err)
|
||||
func WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error) {
|
||||
WriteUVarInt(uint(len(bz)), w, n, err)
|
||||
WriteTo(bz, w, n, err)
|
||||
}
|
||||
|
||||
func ReadByteSlice(r io.Reader, n *int64, err *error) []byte {
|
||||
length := ReadUInt32(r, n, err)
|
||||
length := ReadUVarInt(r, n, err)
|
||||
if *err != nil {
|
||||
return nil
|
||||
}
|
||||
buf := make([]byte, int(length))
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return buf
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
func WriteByteSlices(w io.Writer, bzz [][]byte, n *int64, err *error) {
|
||||
WriteUInt32(w, uint32(len(bzz)), n, err)
|
||||
func WriteByteSlices(bzz [][]byte, w io.Writer, n *int64, err *error) {
|
||||
WriteUVarInt(uint(len(bzz)), w, n, err)
|
||||
for _, bz := range bzz {
|
||||
WriteByteSlice(w, bz, n, err)
|
||||
WriteByteSlice(bz, w, n, err)
|
||||
if *err != nil {
|
||||
return
|
||||
}
|
||||
@@ -32,12 +32,12 @@ func WriteByteSlices(w io.Writer, bzz [][]byte, n *int64, err *error) {
|
||||
}
|
||||
|
||||
func ReadByteSlices(r io.Reader, n *int64, err *error) [][]byte {
|
||||
length := ReadUInt32(r, n, err)
|
||||
length := ReadUVarInt(r, n, err)
|
||||
if *err != nil {
|
||||
return nil
|
||||
}
|
||||
bzz := make([][]byte, length)
|
||||
for i := uint32(0); i < length; i++ {
|
||||
for i := uint(0); i < length; i++ {
|
||||
bz := ReadByteSlice(r, n, err)
|
||||
if *err != nil {
|
||||
return nil
|
||||
|
||||
@@ -6,10 +6,14 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Codec interface {
|
||||
Encode(o interface{}, w io.Writer, n *int64, err *error)
|
||||
Decode(r io.Reader, n *int64, err *error) interface{}
|
||||
Compare(o1 interface{}, o2 interface{}) int
|
||||
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 (
|
||||
@@ -29,62 +33,58 @@ const (
|
||||
typeTime = byte(0x20)
|
||||
)
|
||||
|
||||
var BasicCodec = basicCodec{}
|
||||
|
||||
type basicCodec struct{}
|
||||
|
||||
func (bc basicCodec) Encode(o interface{}, w io.Writer, n *int64, err *error) {
|
||||
func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) {
|
||||
switch o.(type) {
|
||||
case nil:
|
||||
panic("nil type unsupported")
|
||||
case byte:
|
||||
WriteByte(w, typeByte, n, err)
|
||||
WriteByte(w, o.(byte), n, err)
|
||||
WriteByte(typeByte, w, n, err)
|
||||
WriteByte(o.(byte), w, n, err)
|
||||
case int8:
|
||||
WriteByte(w, typeInt8, n, err)
|
||||
WriteInt8(w, o.(int8), n, err)
|
||||
WriteByte(typeInt8, w, n, err)
|
||||
WriteInt8(o.(int8), w, n, err)
|
||||
//case uint8:
|
||||
// WriteByte(w, typeUInt8, n, err)
|
||||
// WriteUInt8(w, o.(uint8), n, err)
|
||||
// WriteByte( typeUInt8, w, n, err)
|
||||
// WriteUInt8( o.(uint8), w, n, err)
|
||||
case int16:
|
||||
WriteByte(w, typeInt16, n, err)
|
||||
WriteInt16(w, o.(int16), n, err)
|
||||
WriteByte(typeInt16, w, n, err)
|
||||
WriteInt16(o.(int16), w, n, err)
|
||||
case uint16:
|
||||
WriteByte(w, typeUInt16, n, err)
|
||||
WriteUInt16(w, o.(uint16), n, err)
|
||||
WriteByte(typeUInt16, w, n, err)
|
||||
WriteUInt16(o.(uint16), w, n, err)
|
||||
case int32:
|
||||
WriteByte(w, typeInt32, n, err)
|
||||
WriteInt32(w, o.(int32), n, err)
|
||||
WriteByte(typeInt32, w, n, err)
|
||||
WriteInt32(o.(int32), w, n, err)
|
||||
case uint32:
|
||||
WriteByte(w, typeUInt32, n, err)
|
||||
WriteUInt32(w, o.(uint32), n, err)
|
||||
WriteByte(typeUInt32, w, n, err)
|
||||
WriteUInt32(o.(uint32), w, n, err)
|
||||
case int64:
|
||||
WriteByte(w, typeInt64, n, err)
|
||||
WriteInt64(w, o.(int64), n, err)
|
||||
WriteByte(typeInt64, w, n, err)
|
||||
WriteInt64(o.(int64), w, n, err)
|
||||
case uint64:
|
||||
WriteByte(w, typeUInt64, n, err)
|
||||
WriteUInt64(w, o.(uint64), n, err)
|
||||
WriteByte(typeUInt64, w, n, err)
|
||||
WriteUInt64(o.(uint64), w, n, err)
|
||||
case int:
|
||||
WriteByte(w, typeVarInt, n, err)
|
||||
WriteVarInt(w, o.(int), n, err)
|
||||
WriteByte(typeVarInt, w, n, err)
|
||||
WriteVarInt(o.(int), w, n, err)
|
||||
case uint:
|
||||
WriteByte(w, typeUVarInt, n, err)
|
||||
WriteUVarInt(w, o.(uint), n, err)
|
||||
WriteByte(typeUVarInt, w, n, err)
|
||||
WriteUVarInt(o.(uint), w, n, err)
|
||||
case string:
|
||||
WriteByte(w, typeString, n, err)
|
||||
WriteString(w, o.(string), n, err)
|
||||
WriteByte(typeString, w, n, err)
|
||||
WriteString(o.(string), w, n, err)
|
||||
case []byte:
|
||||
WriteByte(w, typeByteSlice, n, err)
|
||||
WriteByteSlice(w, o.([]byte), n, err)
|
||||
WriteByte(typeByteSlice, w, n, err)
|
||||
WriteByteSlice(o.([]byte), w, n, err)
|
||||
case time.Time:
|
||||
WriteByte(w, typeTime, n, err)
|
||||
WriteTime(w, o.(time.Time), n, err)
|
||||
WriteByte(typeTime, w, n, err)
|
||||
WriteTime(o.(time.Time), w, n, err)
|
||||
default:
|
||||
panic("Unsupported type")
|
||||
}
|
||||
}
|
||||
|
||||
func (bc basicCodec) Decode(r io.Reader, n *int64, err *error) (o interface{}) {
|
||||
func BasicCodecDecoder(r io.Reader, n *int64, err *error) (o interface{}) {
|
||||
type_ := ReadByte(r, n, err)
|
||||
switch type_ {
|
||||
case typeByte:
|
||||
@@ -121,7 +121,7 @@ func (bc basicCodec) Decode(r io.Reader, n *int64, err *error) (o interface{}) {
|
||||
return o
|
||||
}
|
||||
|
||||
func (bc basicCodec) Compare(o1 interface{}, o2 interface{}) int {
|
||||
func BasicCodecComparator(o1 interface{}, o2 interface{}) int {
|
||||
switch o1.(type) {
|
||||
case byte:
|
||||
return int(o1.(byte) - o2.(byte))
|
||||
@@ -154,3 +154,9 @@ func (bc basicCodec) Compare(o1 interface{}, o2 interface{}) int {
|
||||
panic("Unsupported type")
|
||||
}
|
||||
}
|
||||
|
||||
var BasicCodec = Codec{
|
||||
Encode: BasicCodecEncoder,
|
||||
Decode: BasicCodecDecoder,
|
||||
Compare: BasicCodecComparator,
|
||||
}
|
||||
|
||||
@@ -8,20 +8,20 @@ import (
|
||||
|
||||
// Byte
|
||||
|
||||
func WriteByte(w io.Writer, b byte, n *int64, err *error) {
|
||||
WriteTo(w, []byte{b}, n, err)
|
||||
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(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return buf[0]
|
||||
}
|
||||
|
||||
// Int8
|
||||
|
||||
func WriteInt8(w io.Writer, i int8, n *int64, err *error) {
|
||||
WriteByte(w, byte(i), n, err)
|
||||
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 {
|
||||
@@ -30,8 +30,8 @@ func ReadInt8(r io.Reader, n *int64, err *error) int8 {
|
||||
|
||||
// UInt8
|
||||
|
||||
func WriteUInt8(w io.Writer, i uint8, n *int64, err *error) {
|
||||
WriteByte(w, byte(i), n, err)
|
||||
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 {
|
||||
@@ -40,40 +40,40 @@ func ReadUInt8(r io.Reader, n *int64, err *error) uint8 {
|
||||
|
||||
// Int16
|
||||
|
||||
func WriteInt16(w io.Writer, i int16, n *int64, err *error) {
|
||||
func WriteInt16(i int16, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 2)
|
||||
binary.LittleEndian.PutUint16(buf, uint16(i))
|
||||
*n += 2
|
||||
WriteTo(w, buf, n, err)
|
||||
WriteTo(buf, w, n, err)
|
||||
}
|
||||
|
||||
func ReadInt16(r io.Reader, n *int64, err *error) int16 {
|
||||
buf := make([]byte, 2)
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return int16(binary.LittleEndian.Uint16(buf))
|
||||
}
|
||||
|
||||
// UInt16
|
||||
|
||||
func WriteUInt16(w io.Writer, i uint16, n *int64, err *error) {
|
||||
func WriteUInt16(i uint16, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 2)
|
||||
binary.LittleEndian.PutUint16(buf, uint16(i))
|
||||
*n += 2
|
||||
WriteTo(w, buf, n, err)
|
||||
WriteTo(buf, w, n, err)
|
||||
}
|
||||
|
||||
func ReadUInt16(r io.Reader, n *int64, err *error) uint16 {
|
||||
buf := make([]byte, 2)
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return uint16(binary.LittleEndian.Uint16(buf))
|
||||
}
|
||||
|
||||
// []UInt16
|
||||
|
||||
func WriteUInt16s(w io.Writer, iz []uint16, n *int64, err *error) {
|
||||
WriteUInt32(w, uint32(len(iz)), n, err)
|
||||
func WriteUInt16s(iz []uint16, w io.Writer, n *int64, err *error) {
|
||||
WriteUInt32(uint32(len(iz)), w, n, err)
|
||||
for _, i := range iz {
|
||||
WriteUInt16(w, i, n, err)
|
||||
WriteUInt16(i, w, n, err)
|
||||
if *err != nil {
|
||||
return
|
||||
}
|
||||
@@ -98,71 +98,71 @@ func ReadUInt16s(r io.Reader, n *int64, err *error) []uint16 {
|
||||
|
||||
// Int32
|
||||
|
||||
func WriteInt32(w io.Writer, i int32, n *int64, err *error) {
|
||||
func WriteInt32(i int32, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(buf, uint32(i))
|
||||
*n += 4
|
||||
WriteTo(w, buf, n, err)
|
||||
WriteTo(buf, w, n, err)
|
||||
}
|
||||
|
||||
func ReadInt32(r io.Reader, n *int64, err *error) int32 {
|
||||
buf := make([]byte, 4)
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return int32(binary.LittleEndian.Uint32(buf))
|
||||
}
|
||||
|
||||
// UInt32
|
||||
|
||||
func WriteUInt32(w io.Writer, i uint32, n *int64, err *error) {
|
||||
func WriteUInt32(i uint32, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(buf, uint32(i))
|
||||
*n += 4
|
||||
WriteTo(w, buf, n, err)
|
||||
WriteTo(buf, w, n, err)
|
||||
}
|
||||
|
||||
func ReadUInt32(r io.Reader, n *int64, err *error) uint32 {
|
||||
buf := make([]byte, 4)
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return uint32(binary.LittleEndian.Uint32(buf))
|
||||
}
|
||||
|
||||
// Int64
|
||||
|
||||
func WriteInt64(w io.Writer, i int64, n *int64, err *error) {
|
||||
func WriteInt64(i int64, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(buf, uint64(i))
|
||||
*n += 8
|
||||
WriteTo(w, buf, n, err)
|
||||
WriteTo(buf, w, n, err)
|
||||
}
|
||||
|
||||
func ReadInt64(r io.Reader, n *int64, err *error) int64 {
|
||||
buf := make([]byte, 8)
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return int64(binary.LittleEndian.Uint64(buf))
|
||||
}
|
||||
|
||||
// UInt64
|
||||
|
||||
func WriteUInt64(w io.Writer, i uint64, n *int64, err *error) {
|
||||
func WriteUInt64(i uint64, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(buf, uint64(i))
|
||||
*n += 8
|
||||
WriteTo(w, buf, n, err)
|
||||
WriteTo(buf, w, n, err)
|
||||
}
|
||||
|
||||
func ReadUInt64(r io.Reader, n *int64, err *error) uint64 {
|
||||
buf := make([]byte, 8)
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return uint64(binary.LittleEndian.Uint64(buf))
|
||||
}
|
||||
|
||||
// VarInt
|
||||
|
||||
func WriteVarInt(w io.Writer, i int, n *int64, err *error) {
|
||||
func WriteVarInt(i int, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 9)
|
||||
n_ := int64(binary.PutVarint(buf, int64(i)))
|
||||
*n += n_
|
||||
WriteTo(w, buf[:n_], n, err)
|
||||
WriteTo(buf[:n_], w, n, err)
|
||||
}
|
||||
|
||||
func ReadVarInt(r io.Reader, n *int64, err *error) int {
|
||||
@@ -174,11 +174,11 @@ func ReadVarInt(r io.Reader, n *int64, err *error) int {
|
||||
|
||||
// UVarInt
|
||||
|
||||
func WriteUVarInt(w io.Writer, i uint, n *int64, err *error) {
|
||||
func WriteUVarInt(i uint, w io.Writer, n *int64, err *error) {
|
||||
buf := make([]byte, 9)
|
||||
n_ := int64(binary.PutUvarint(buf, uint64(i)))
|
||||
*n += n_
|
||||
WriteTo(w, buf[:n_], n, err)
|
||||
WriteTo(buf[:n_], w, n, err)
|
||||
}
|
||||
|
||||
func ReadUVarInt(r io.Reader, n *int64, err *error) uint {
|
||||
|
||||
198
binary/reflect.go
Normal file
198
binary/reflect.go
Normal file
@@ -0,0 +1,198 @@
|
||||
package binary
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type TypeInfo struct {
|
||||
Type reflect.Type // The type
|
||||
Encoder Encoder // Optional custom encoder function
|
||||
Decoder Decoder // Optional custom decoder function
|
||||
}
|
||||
|
||||
// If a type implements TypeByte, the byte is included
|
||||
// as the first byte for encoding. This is used to encode
|
||||
// interfaces/union types. In this case the decoding should
|
||||
// be done manually with a switch statement, and so the
|
||||
// reflection-based decoder provided here does not expect this
|
||||
// prefix byte.
|
||||
// See the reactor implementations for use-cases.
|
||||
type HasTypeByte interface {
|
||||
TypeByte() byte
|
||||
}
|
||||
|
||||
var typeInfos = map[reflect.Type]*TypeInfo{}
|
||||
|
||||
func RegisterType(info *TypeInfo) bool {
|
||||
|
||||
// Register the type info
|
||||
typeInfos[info.Type] = info
|
||||
|
||||
// Also register the underlying struct's info, if info.Type is a pointer.
|
||||
if info.Type.Kind() == reflect.Ptr {
|
||||
rt := info.Type.Elem()
|
||||
typeInfos[rt] = info
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *error) {
|
||||
|
||||
// First, create a new struct if rv is nil pointer.
|
||||
if rt.Kind() == reflect.Ptr && rv.IsNil() {
|
||||
newRv := reflect.New(rt.Elem())
|
||||
rv.Set(newRv)
|
||||
rv = newRv
|
||||
}
|
||||
|
||||
// Dereference pointer
|
||||
// Still addressable, thus settable!
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv, rt = rv.Elem(), rt.Elem()
|
||||
}
|
||||
|
||||
// Custom decoder
|
||||
typeInfo := typeInfos[rt]
|
||||
if typeInfo != nil && typeInfo.Decoder != nil {
|
||||
decoded := typeInfo.Decoder(r, n, err)
|
||||
decodedRv := reflect.Indirect(reflect.ValueOf(decoded))
|
||||
rv.Set(decodedRv)
|
||||
return
|
||||
}
|
||||
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
elemRt := rt.Elem()
|
||||
if elemRt.Kind() == reflect.Uint8 {
|
||||
// Special case: Byteslices
|
||||
byteslice := ReadByteSlice(r, n, err)
|
||||
rv.Set(reflect.ValueOf(byteslice))
|
||||
} else {
|
||||
// Read length
|
||||
length := int(ReadUVarInt(r, n, err))
|
||||
sliceRv := reflect.MakeSlice(rt, length, length)
|
||||
// Read elems
|
||||
for i := 0; i < length; i++ {
|
||||
elemRv := sliceRv.Index(i)
|
||||
readReflect(elemRv, elemRt, r, n, err)
|
||||
}
|
||||
rv.Set(sliceRv)
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
numFields := rt.NumField()
|
||||
for i := 0; i < numFields; i++ {
|
||||
field := rt.Field(i)
|
||||
if field.Anonymous {
|
||||
continue
|
||||
}
|
||||
fieldRv := rv.Field(i)
|
||||
readReflect(fieldRv, field.Type, r, n, err)
|
||||
}
|
||||
|
||||
case reflect.String:
|
||||
str := ReadString(r, n, err)
|
||||
rv.SetString(str)
|
||||
|
||||
case reflect.Uint64:
|
||||
num := ReadUInt64(r, n, err)
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint32:
|
||||
num := ReadUInt32(r, n, err)
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint16:
|
||||
num := ReadUInt16(r, n, err)
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint8:
|
||||
num := ReadUInt8(r, n, err)
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint:
|
||||
num := ReadUVarInt(r, n, err)
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown field type %v", rt.Kind()))
|
||||
}
|
||||
}
|
||||
|
||||
func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) {
|
||||
|
||||
// Custom encoder
|
||||
typeInfo := typeInfos[rt]
|
||||
if typeInfo != nil && typeInfo.Encoder != nil {
|
||||
typeInfo.Encoder(rv.Interface(), w, n, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Dereference pointer or interface
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
rv = rv.Elem()
|
||||
} else if rt.Kind() == reflect.Interface {
|
||||
rv = rv.Elem()
|
||||
rt = rv.Type()
|
||||
}
|
||||
|
||||
// Write TypeByte prefix
|
||||
if rt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
|
||||
WriteByte(rv.Interface().(HasTypeByte).TypeByte(), w, n, err)
|
||||
}
|
||||
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
elemRt := rt.Elem()
|
||||
if elemRt.Kind() == reflect.Uint8 {
|
||||
// Special case: Byteslices
|
||||
byteslice := rv.Interface().([]byte)
|
||||
WriteByteSlice(byteslice, w, n, err)
|
||||
} else {
|
||||
// Write length
|
||||
length := rv.Len()
|
||||
WriteUVarInt(uint(length), w, n, err)
|
||||
// Write elems
|
||||
for i := 0; i < length; i++ {
|
||||
elemRv := rv.Index(i)
|
||||
writeReflect(elemRv, elemRt, w, n, err)
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
numFields := rt.NumField()
|
||||
for i := 0; i < numFields; i++ {
|
||||
field := rt.Field(i)
|
||||
if field.Anonymous {
|
||||
continue
|
||||
}
|
||||
fieldRv := rv.Field(i)
|
||||
writeReflect(fieldRv, field.Type, w, n, err)
|
||||
}
|
||||
|
||||
case reflect.String:
|
||||
WriteString(rv.String(), w, n, err)
|
||||
|
||||
case reflect.Uint64:
|
||||
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)
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown field type %v", rt.Kind()))
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@ import "io"
|
||||
|
||||
// String
|
||||
|
||||
func WriteString(w io.Writer, s string, n *int64, err *error) {
|
||||
WriteUInt32(w, uint32(len(s)), n, err)
|
||||
WriteTo(w, []byte(s), n, err)
|
||||
func WriteString(s string, w io.Writer, n *int64, err *error) {
|
||||
WriteUInt32(uint32(len(s)), w, n, err)
|
||||
WriteTo([]byte(s), w, n, err)
|
||||
}
|
||||
|
||||
func ReadString(r io.Reader, n *int64, err *error) string {
|
||||
@@ -15,6 +15,6 @@ func ReadString(r io.Reader, n *int64, err *error) string {
|
||||
return ""
|
||||
}
|
||||
buf := make([]byte, int(length))
|
||||
ReadFull(r, buf, n, err)
|
||||
ReadFull(buf, r, n, err)
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
|
||||
// Time
|
||||
|
||||
func WriteTime(w io.Writer, t time.Time, n *int64, err *error) {
|
||||
WriteInt64(w, t.UnixNano(), n, err)
|
||||
func WriteTime(t time.Time, w io.Writer, n *int64, err *error) {
|
||||
WriteInt64(t.UnixNano(), w, n, err)
|
||||
}
|
||||
|
||||
func ReadTime(r io.Reader, n *int64, err *error) time.Time {
|
||||
|
||||
@@ -2,36 +2,46 @@ package binary
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go.crypto/ripemd160"
|
||||
"crypto/sha256"
|
||||
)
|
||||
|
||||
func BinaryBytes(b Binary) []byte {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_, err := b.WriteTo(buf)
|
||||
if err != nil {
|
||||
func BinaryBytes(o interface{}) []byte {
|
||||
w, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||
WriteBinary(o, w, n, err)
|
||||
if *err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return buf.Bytes()
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
// NOTE: does not care about the type, only the binary representation.
|
||||
func BinaryEqual(a, b Binary) bool {
|
||||
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 Binary) int {
|
||||
func BinaryCompare(a, b interface{}) int {
|
||||
aBytes := BinaryBytes(a)
|
||||
bBytes := BinaryBytes(b)
|
||||
return bytes.Compare(aBytes, bBytes)
|
||||
}
|
||||
|
||||
func BinaryHash(b Binary) []byte {
|
||||
hasher := sha256.New()
|
||||
_, err := b.WriteTo(hasher)
|
||||
if err != nil {
|
||||
func BinarySha256(o interface{}) []byte {
|
||||
hasher, n, err := sha256.New(), new(int64), new(error)
|
||||
WriteBinary(o, hasher, n, err)
|
||||
if *err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
func BinaryRipemd160(o interface{}) []byte {
|
||||
hasher, n, err := ripemd160.New(), new(int64), new(error)
|
||||
WriteBinary(o, hasher, n, err)
|
||||
if *err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hasher.Sum(nil)
|
||||
|
||||
Reference in New Issue
Block a user