Skip to content

Commit

Permalink
#2 remove unnecessary serializer check
Browse files Browse the repository at this point in the history
  • Loading branch information
vipally committed Dec 24, 2017
1 parent 9f103a7 commit 9b78648
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 29 deletions.
4 changes: 2 additions & 2 deletions coder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ func TestEncodeDonotSupportedType(t *testing.T) {
//fmt.Printf("Decode error: %#v\n%s\n", tv.Field(i).Addr().Type().String(), err.Error())
}

if err := decoder.value(tv.Field(i), true, false); err == nil {
if err := decoder.value(tv.Field(i), true, false, true); err == nil {
t.Errorf("EncodeDonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type())
} else {
//fmt.Println(err)
Expand Down Expand Up @@ -935,7 +935,7 @@ func TestBinarySerializer(t *testing.T) {
if got != v.err {
t.Errorf("case %d %#v wanterror=%v got err=%v", i+1, v.data, v.err, err)
} else {
fmt.Println(i+1, err)
//fmt.Println(i+1, err)
}
}
}
Expand Down
22 changes: 14 additions & 8 deletions decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func (decoder *Decoder) Value(x interface{}) (err error) {
// }

if v.Kind() == reflect.Ptr { //only support decode for pointer interface
return decoder.value(v, true, false)
return decoder.value(v, true, false, true)
}

return typeError("binary.Decoder.Value: non-pointer type %s", v.Type(), true)
Expand All @@ -309,7 +309,7 @@ func (decoder *Decoder) useSerializer(v reflect.Value) error {
panic(typeError("expect BinarySerializer %s", v.Type(), true))
}

func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed bool) error {
func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed, checkSerializer bool) error {
// check Packer interface for every value is perfect
// but decoder is too costly
//
Expand Down Expand Up @@ -340,7 +340,7 @@ func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed bool) error
// }

k := v.Kind()
if k != reflect.Ptr && querySerializer(v.Type()) {
if checkSerializer && k != reflect.Ptr && querySerializer(v.Type()) {
return decoder.useSerializer(v.Addr())
}

Expand Down Expand Up @@ -386,9 +386,12 @@ func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed bool) error
v.SetString(decoder.String())

case reflect.Slice, reflect.Array:
if !validUserType(v.Type().Elem()) { //verify array element is valid
elemT := v.Type().Elem()
if !validUserType(elemT) { //verify array element is valid
return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String())
}

elemSerializer := querySerializer(indirectType(elemT))
if decoder.boolArray(v) < 0 { //deal with bool array first
s, _ := decoder.Uvarint()
size := int(s)
Expand All @@ -400,7 +403,7 @@ func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed bool) error
l := v.Len()
for i := 0; i < size; i++ {
if i < l {
assert(decoder.value(v.Index(i), false, packed) == nil, "")
assert(decoder.value(v.Index(i), false, packed, elemSerializer) == nil, "")
} else {
skiped := decoder.skipByType(v.Type().Elem(), packed)
assert(skiped >= 0, v.Type().Elem().String()) //I'm sure here cannot find unsupported type
Expand All @@ -421,13 +424,16 @@ func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed bool) error
v.Set(newmap)
}

keySerilaizer := querySerializer(indirectType(kt))
valueSerilaizer := querySerializer(indirectType(vt))

s, _ := decoder.Uvarint()
size := int(s)
for i := 0; i < size; i++ {
key := reflect.New(kt).Elem()
value := reflect.New(vt).Elem()
assert(decoder.value(key, false, packed) == nil, "")
assert(decoder.value(value, false, packed) == nil, "")
assert(decoder.value(key, false, packed, keySerilaizer) == nil, "")
assert(decoder.value(value, false, packed, valueSerilaizer) == nil, "")
v.SetMapIndex(key, value)
}
case reflect.Struct:
Expand All @@ -436,7 +442,7 @@ func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed bool) error
default:
if newPtr(v, decoder, topLevel) {
if !v.IsNil() {
return decoder.value(v.Elem(), false, packed)
return decoder.value(v.Elem(), false, packed, checkSerializer)
}
} else {
return typeError("binary.Decoder.Value: unsupported type %s", v.Type(), true)
Expand Down
21 changes: 13 additions & 8 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func (encoder *Encoder) Value(x interface{}) (err error) {
// panic(fmt.Errorf("unexpected BinarySizer: %s", v.Type().String()))
// }

return encoder.value(reflect.Indirect(v), false)
return encoder.value(reflect.Indirect(v), false, true)
}

func (encoder *Encoder) fastValue(x interface{}) bool {
Expand Down Expand Up @@ -412,7 +412,7 @@ func (encoder *Encoder) useSerializer(v reflect.Value) error {
panic(typeError("expect BinarySerializer %s", v.Type(), true))
}

func (encoder *Encoder) value(v reflect.Value, packed bool) error {
func (encoder *Encoder) value(v reflect.Value, packed, checkSerializer bool) error {
// check Packer interface for every value is perfect
// but encoder is too costly
//
Expand All @@ -433,7 +433,7 @@ func (encoder *Encoder) value(v reflect.Value, packed bool) error {
// }

k := v.Kind()
if k != reflect.Ptr && querySerializer(v.Type()) {
if checkSerializer && k != reflect.Ptr && querySerializer(v.Type()) {
return encoder.useSerializer(v)
}

Expand Down Expand Up @@ -481,14 +481,16 @@ func (encoder *Encoder) value(v reflect.Value, packed bool) error {
encoder.String(v.String())

case reflect.Slice, reflect.Array:
if !validUserType(v.Type().Elem()) { //verify array element is valid
elemT := v.Type().Elem()
if !validUserType(elemT) { //verify array element is valid
return fmt.Errorf("binary.Encoder.Value: unsupported type %s", v.Type().String())
}
elemSerializer := querySerializer(indirectType(elemT))
if encoder.boolArray(v) < 0 { //deal with bool array first
l := v.Len()
encoder.Uvarint(uint64(l))
for i := 0; i < l; i++ {
assert(encoder.value(v.Index(i), packed) == nil, "")
assert(encoder.value(v.Index(i), packed, elemSerializer) == nil, "")
}
}
case reflect.Map:
Expand All @@ -500,13 +502,16 @@ func (encoder *Encoder) value(v reflect.Value, packed bool) error {
return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String())
}

keySerilaizer := querySerializer(indirectType(kt))
valueSerilaizer := querySerializer(indirectType(vt))

keys := v.MapKeys()
l := len(keys)
encoder.Uvarint(uint64(l))
for i := 0; i < l; i++ {
key := keys[i]
assert(encoder.value(key, packed) == nil, "")
assert(encoder.value(v.MapIndex(key), packed) == nil, "")
assert(encoder.value(key, packed, keySerilaizer) == nil, "")
assert(encoder.value(v.MapIndex(key), packed, valueSerilaizer) == nil, "")
}
case reflect.Struct:
return queryStruct(v.Type()).encode(encoder, v)
Expand All @@ -518,7 +523,7 @@ func (encoder *Encoder) value(v reflect.Value, packed bool) error {
if !v.IsNil() {
encoder.Bool(true)
if e := v.Elem(); e.Kind() != reflect.Ptr {
return encoder.value(e, packed)
return encoder.value(e, packed, checkSerializer)
}
} else {
encoder.Bool(false)
Expand Down
7 changes: 7 additions & 0 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,10 @@ func sizeofFixArray(_len, elemLen int) int {
func validUserType(t reflect.Type) bool {
return sizeofNilPointer(t) >= 0
}

func indirectType(t reflect.Type) reflect.Type {
if t.Kind() == reflect.Ptr {
return t.Elem()
}
return t
}
27 changes: 16 additions & 11 deletions regist.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (
"reflect"
)

// RegsterType regist type info to improve encoding/decoding efficiency.
// RegisterType regist type info to improve encoding/decoding efficiency.
// Only BinarySerializer or struct is regable.
// Regist by a nil pointer is aviable.
// RegsterType((*SomeType)(nil)) is recommended usage.
// RegisterType((*SomeType)(nil)) is recommended usage.
func RegisterType(x interface{}) error {
return _regedTypeMgr.regist(reflect.TypeOf(x), true)
}
Expand All @@ -25,7 +25,6 @@ var (
)

func init() {

var sizer BinarySizer
tSizer = reflect.TypeOf(&sizer).Elem()
var encoder BinaryEncoder
Expand Down Expand Up @@ -111,8 +110,8 @@ func typeError(fmt_ string, t reflect.Type, needErr bool) error {

//informatin of a struct
type structInfo struct {
identify string //reflect.Type.String()
fields []*fieldInfo
t reflect.Type //type of this struct(for debug)
fields []*fieldInfo
}

func (info *structInfo) encode(encoder *Encoder, v reflect.Value) error {
Expand All @@ -122,7 +121,7 @@ func (info *structInfo) encode(encoder *Encoder, v reflect.Value) error {
// see comment for corresponding code in decoder.value()
finfo := info.field(i)
if f := v.Field(i); finfo.isValid(i, t) {
if err := encoder.value(f, finfo.isPacked()); err != nil {
if err := encoder.value(f, finfo.isPacked(), finfo.checkSerializer()); err != nil {
return err
}
}
Expand All @@ -136,7 +135,7 @@ func (info *structInfo) decode(decoder *Decoder, v reflect.Value) error {
for i, n := 0, v.NumField(); i < n; i++ {
finfo := info.field(i)
if f := v.Field(i); finfo.isValid(i, t) {
if err := decoder.value(f, false, finfo.isPacked()); err != nil {
if err := decoder.value(f, false, finfo.isPacked(), finfo.checkSerializer()); err != nil {
return err
}
}
Expand Down Expand Up @@ -203,7 +202,7 @@ func (info *structInfo) fieldNum(t reflect.Type) int {

func (info *structInfo) parse(mgr *regedTypeMgr, t reflect.Type) bool {
//assert(t.Kind() == reflect.Struct, t.String())
info.identify = t.String()
info.t = t
for i, n := 0, t.NumField(); i < n; i++ {
f := t.Field(i)

Expand All @@ -212,6 +211,7 @@ func (info *structInfo) parse(mgr *regedTypeMgr, t reflect.Type) bool {
tag := f.Tag.Get("binary")
field.ignore = !isExported(f.Name) || tag == "ignore"
field.packed = tag == "packed"
_, field.serializer, _, _ = deepRegableType(f.Type, false)

info.fields = append(info.fields, field)

Expand All @@ -237,9 +237,10 @@ func (info *structInfo) numField() int {

//informatin of a struct field
type fieldInfo struct {
field reflect.StructField
ignore bool //if this field is ignored
packed bool //if this ints field encode as varint/uvarint
field reflect.StructField
ignore bool //if this field is ignored
packed bool //if this ints field encode as varint/uvarint
serializer bool //if this filed implements BinarySerializer
}

func (field *fieldInfo) Type(i int, t reflect.Type) reflect.Type {
Expand All @@ -265,6 +266,10 @@ func (field *fieldInfo) isPacked() bool {
return field != nil && field.packed
}

func (field *fieldInfo) checkSerializer() bool {
return !(field != nil && !field.serializer)
}

func deepRegableType(t reflect.Type, needErr bool) (deept reflect.Type, isSerializer, ok bool, err error) {
_t := t
for _t.Kind() == reflect.Ptr {
Expand Down

0 comments on commit 9b78648

Please sign in to comment.