Unreader to unread bytes

This commit is contained in:
Jae Kwon
2014-12-29 15:14:54 -08:00
parent 946fa21dc7
commit 5bace5cce8
19 changed files with 84 additions and 57 deletions
+3 -2
View File
@@ -123,8 +123,9 @@ func GreeterEncoder(o interface{}, w io.Writer, n *int64, err *error) {
}
}
func GreeterDecoder(r io.Reader, n *int64, err *error) interface{} {
switch t := ReadByte(r, n, err); t {
func GreeterDecoder(r *bytes.Reader, n *int64, err *error) interface{} {
// We must peek the type byte because ReadBinary() expects it.
switch t := PeekByte(r, n, err); t {
case GreeterTypeDog:
return ReadBinary(Dog{}, r, n, err)
case GreeterTypeCat:
+6 -1
View File
@@ -5,7 +5,12 @@ import (
"reflect"
)
func ReadBinary(o interface{}, r io.Reader, n *int64, err *error) interface{} {
type Unreader interface {
io.Reader
UnreadByte() error
}
func ReadBinary(o interface{}, r Unreader, 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)
+2 -2
View File
@@ -9,7 +9,7 @@ import (
)
type Encoder func(o interface{}, w io.Writer, n *int64, err *error)
type Decoder func(r io.Reader, n *int64, err *error) interface{}
type Decoder func(r Unreader, n *int64, err *error) interface{}
type Comparator func(o1 interface{}, o2 interface{}) int
type Codec struct {
@@ -86,7 +86,7 @@ func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) {
}
}
func BasicCodecDecoder(r io.Reader, n *int64, err *error) (o interface{}) {
func BasicCodecDecoder(r Unreader, n *int64, err *error) (o interface{}) {
type_ := ReadByte(r, n, err)
switch type_ {
case typeByte:
+10
View File
@@ -18,6 +18,16 @@ func ReadByte(r io.Reader, n *int64, err *error) byte {
return buf[0]
}
// NOTE: may end up advancing the reader upon error.
func PeekByte(r Unreader, n *int64, err *error) byte {
byte_ := ReadByte(r, n, err)
if *err != nil {
return 0
}
*err = r.UnreadByte()
return byte_
}
// Int8
func WriteInt8(i int8, w io.Writer, n *int64, err *error) {
+23 -13
View File
@@ -47,34 +47,44 @@ func GetTypeInfo(rt reflect.Type) *TypeInfo {
// NOTE: not goroutine safe, so only call upon program init.
func RegisterType(info *TypeInfo) *TypeInfo {
// Register the type info
typeInfos[info.Type] = info
// Also register the underlying struct's info, if info.Type is a pointer.
// Or, if info.Type is not a pointer, register the pointer.
var rt, ptrRt reflect.Type
if info.Type.Kind() == reflect.Ptr {
rt := info.Type.Elem()
typeInfos[rt] = info
rt, ptrRt = info.Type.Elem(), info.Type
} else {
ptrRt := reflect.PtrTo(info.Type)
typeInfos[ptrRt] = info
rt, ptrRt = info.Type, reflect.PtrTo(info.Type)
}
// Register the type info
typeInfos[rt] = info
typeInfos[ptrRt] = info
// See if the type implements HasTypeByte
if info.Type.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
zero := reflect.Zero(info.Type)
if rt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
zero := reflect.Zero(rt)
typeByte := zero.Interface().(HasTypeByte).TypeByte()
if info.HasTypeByte && info.TypeByte != typeByte {
panic(fmt.Sprintf("Type %v expected TypeByte of %X", info.Type, typeByte))
panic(fmt.Sprintf("Type %v expected TypeByte of %X", rt, typeByte))
} else {
info.HasTypeByte = true
info.TypeByte = typeByte
}
} else if ptrRt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
zero := reflect.Zero(ptrRt)
typeByte := zero.Interface().(HasTypeByte).TypeByte()
if info.HasTypeByte && info.TypeByte != typeByte {
panic(fmt.Sprintf("Type %v expected TypeByte of %X", ptrRt, typeByte))
} else {
info.HasTypeByte = true
info.TypeByte = typeByte
}
info.HasTypeByte = true
info.TypeByte = typeByte
}
return info
}
func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *error) {
func readReflect(rv reflect.Value, rt reflect.Type, r Unreader, n *int64, err *error) {
// First, create a new struct if rv is nil pointer.
if rt.Kind() == reflect.Ptr && rv.IsNil() {