package binary 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: // SANITY CHECK panic("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: // SANITY CHECK panic(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: // SANITY CHECK panic(Fmt("Unsupported type: %v", reflect.TypeOf(o1))) } return 0 } var BasicCodec = Codec{ Encode: BasicCodecEncoder, Decode: BasicCodecDecoder, Compare: BasicCodecComparator, }