From f01fc1cc290655b97662ef2aa3187d0747784d0b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 6 Dec 2019 18:15:33 +0300 Subject: [PATCH] io: optimize BinWriter.WriteArray() Replace reflect.MethodByName with a simple interface cast. --- pkg/io/binaryWriter.go | 23 ++++++++--------------- pkg/io/binaryrw_test.go | 3 +-- pkg/io/serializable.go | 4 ++++ 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/pkg/io/binaryWriter.go b/pkg/io/binaryWriter.go index 16e9dfc77..5b6ccade9 100644 --- a/pkg/io/binaryWriter.go +++ b/pkg/io/binaryWriter.go @@ -39,33 +39,26 @@ func (w *BinWriter) WriteBE(v interface{}) { func (w *BinWriter) WriteArray(arr interface{}) { switch val := reflect.ValueOf(arr); val.Kind() { case reflect.Slice, reflect.Array: - typ := val.Type().Elem() - method, ok := typ.MethodByName("EncodeBinary") - if !ok || !isEncodeBinaryMethod(method) { - panic(typ.String() + " does not have EncodeBinary(*BinWriter)") - } - if w.Err != nil { return } + typ := val.Type().Elem() + w.WriteVarUint(uint64(val.Len())) for i := 0; i < val.Len(); i++ { - method := val.Index(i).MethodByName("EncodeBinary") - method.Call([]reflect.Value{reflect.ValueOf(w)}) + el, ok := val.Index(i).Interface().(encodable) + if !ok { + panic(typ.String() + "is not encodable") + } + + el.EncodeBinary(w) } default: panic("not an array") } } -func isEncodeBinaryMethod(method reflect.Method) bool { - t := method.Type - return t != nil && - t.NumIn() == 2 && t.In(1) == reflect.TypeOf((*BinWriter)(nil)) && - t.NumOut() == 0 -} - // WriteVarUint writes a uint64 into the underlying writer using variable-length encoding. func (w *BinWriter) WriteVarUint(val uint64) { if w.Err != nil { diff --git a/pkg/io/binaryrw_test.go b/pkg/io/binaryrw_test.go index 4ce265d2a..8c6d64c6e 100644 --- a/pkg/io/binaryrw_test.go +++ b/pkg/io/binaryrw_test.go @@ -267,8 +267,7 @@ func TestBinWriter_WriteArray(t *testing.T) { require.Equal(t, w.Bytes(), []byte(nil)) w.Reset() - w.Err = errors.New("error") - require.Panics(t, func() { w.WriteArray([]int{}) }) + require.Panics(t, func() { w.WriteArray([]int{1}) }) w.Reset() w.Err = errors.New("error") diff --git a/pkg/io/serializable.go b/pkg/io/serializable.go index c878d8ddb..43e659731 100644 --- a/pkg/io/serializable.go +++ b/pkg/io/serializable.go @@ -14,3 +14,7 @@ type Serializable interface { type decodable interface { DecodeBinary(*BinReader) } + +type encodable interface { + EncodeBinary(*BinWriter) +}