Repository: apache/dubbo-go-hessian2
Pull request #288 (2021-11-14 08:27:06)

fix EOF error check

**What this PR does**:
- fix EOF error check 

**Special notes for your reviewer**:
NONE

**Does this PR introduce a user-facing change?**:
```release-note
- fix EOF error check 
```

codecov-commenter: # [Codecov](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) Report
> Merging [#288](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (31e7f97) into [master](https://codecov.io/gh/apache/dubbo-go-hessian2/commit/3a4ef0be57cec0ab889e3a0b22e546df24e2e6a8?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (3a4ef0b) will **decrease** coverage by `0.17%`.
> The diff coverage is `68.75%`.

[![Impacted file tree graph](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288/graphs/tree.svg?width=650&height=150&src=pr&token=Yh82j7lS1W&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)

```diff
@@            Coverage Diff             @@
##           master     #288      +/-   ##
==========================================
- Coverage   70.26%   70.08%   -0.18%     
==========================================
  Files          27       27              
  Lines        3033     3032       -1     
==========================================
- Hits         2131     2125       -6     
- Misses        677      681       +4     
- Partials      225      226       +1     
```


| [Impacted Files](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | Coverage Δ | |
|---|---|---|
| [decode.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-ZGVjb2RlLmdv) | `69.46% <0.00%> (ø)` | |
| [java\_sql\_time.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-amF2YV9zcWxfdGltZS5nbw==) | `63.88% <50.00%> (-2.78%)` | :arrow_down: |
| [object.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-b2JqZWN0Lmdv) | `65.69% <50.00%> (-0.59%)` | :arrow_down: |
| [pojo.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-cG9qby5nbw==) | `63.28% <83.33%> (-0.66%)` | :arrow_down: |
| [list.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-bGlzdC5nbw==) | `84.61% <100.00%> (ø)` | |
| [map.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-bWFwLmdv) | `58.06% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Last update [3a4ef0b...31e7f97](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/288?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).

wongoo: @justxuewei  I have updated this pr, this pr contains only one fix for EOF error check.

Patch:
diff --git a/codec.go b/codec.go
index 5087efa..425468c 100644
--- a/codec.go
+++ b/codec.go
@@ -476,3 +476,10 @@ func ConvertSliceValueType(destTyp reflect.Type, v reflect.Value) (reflect.Value
 
 	return sl, nil
 }
+
+//PackPtrInterface pack struct interface to pointer interface
+func PackPtrInterface(s interface{}, value reflect.Value) interface{} {
+	vv := reflect.New(reflect.TypeOf(s))
+	vv.Elem().Set(value)
+	return vv.Interface()
+}
diff --git a/decode.go b/decode.go
index 00b8461..89af853 100644
--- a/decode.go
+++ b/decode.go
@@ -49,12 +49,12 @@ func NewDecoder(b []byte) *Decoder {
 	return &Decoder{reader: bufio.NewReader(bytes.NewReader(b)), typeRefs: &TypeRefs{records: map[string]bool{}}}
 }
 
-// NewDecoder generate a decoder instance
+// NewDecoderSize generate a decoder instance.
 func NewDecoderSize(b []byte, size int) *Decoder {
 	return &Decoder{reader: bufio.NewReaderSize(bytes.NewReader(b), size), typeRefs: &TypeRefs{records: map[string]bool{}}}
 }
 
-// NewDecoder generate a decoder instance with skip
+// NewDecoderWithSkip generate a decoder instance with skip.
 func NewDecoderWithSkip(b []byte) *Decoder {
 	return &Decoder{reader: bufio.NewReader(bytes.NewReader(b)), typeRefs: &TypeRefs{records: map[string]bool{}}, isSkip: true}
 }
@@ -224,7 +224,7 @@ func (d *Decoder) DecodeValue() (interface{}, error) {
 	)
 
 	tag, err = d.ReadByte()
-	if err == io.EOF {
+	if perrors.Is(err, io.EOF) {
 		return nil, err
 	}
 
diff --git a/encode.go b/encode.go
index c26832e..0daf3e0 100644
--- a/encode.go
+++ b/encode.go
@@ -160,7 +160,11 @@ func (e *Encoder) Encode(v interface{}) error {
 		switch t.Kind() {
 		case reflect.Struct:
 			vv := reflect.ValueOf(v)
-			vv = UnpackPtr(vv)
+			if vv.Kind() != reflect.Ptr {
+				v = PackPtrInterface(v, vv)
+			} else {
+				vv = UnpackPtr(vv)
+			}
 			if !vv.IsValid() {
 				e.buffer = EncNull(e.buffer)
 				return nil
diff --git a/java_sql_time.go b/java_sql_time.go
index 18c2a49..8edee13 100644
--- a/java_sql_time.go
+++ b/java_sql_time.go
@@ -124,7 +124,7 @@ func (JavaSqlTimeSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classI
 	d.appendRefs(vRef.Interface())
 
 	tag, err := d.ReadByte()
-	if err == io.EOF {
+	if perrors.Is(err, io.EOF) {
 		return nil, err
 	}
 	date, err := d.decDate(int32(tag))
diff --git a/list.go b/list.go
index b93f22e..94603c8 100644
--- a/list.go
+++ b/list.go
@@ -359,7 +359,7 @@ func (d *Decoder) readTypedListValue(length int, listTyp string, isVariableArr b
 	for j := 0; j < length || isVariableArr; j++ {
 		it, err := d.DecodeValue()
 		if err != nil {
-			if err == io.EOF && isVariableArr {
+			if perrors.Is(err, io.EOF) && isVariableArr {
 				break
 			}
 			return nil, perrors.WithStack(err)
@@ -414,7 +414,7 @@ func (d *Decoder) readUntypedList(tag byte) (interface{}, error) {
 	for j := 0; j < length || isVariableArr; j++ {
 		it, err := d.DecodeValue()
 		if err != nil {
-			if err == io.EOF && isVariableArr {
+			if perrors.Is(err, io.EOF) && isVariableArr {
 				break
 			}
 			return nil, perrors.WithStack(err)
diff --git a/map.go b/map.go
index cd340df..034ccb1 100644
--- a/map.go
+++ b/map.go
@@ -192,7 +192,7 @@ func (d *Decoder) decMapByValue(value reflect.Value) error {
 		entryKey, err = d.DecodeValue()
 		if err != nil {
 			// EOF means the end flag 'Z' of map is already read
-			if err == io.EOF {
+			if perrors.Is(err, io.EOF) {
 				break
 			} else {
 				return perrors.WithStack(err)
diff --git a/object.go b/object.go
index 84ee94e..45a7eb2 100644
--- a/object.go
+++ b/object.go
@@ -499,7 +499,7 @@ func (d *Decoder) decInstance(typ reflect.Type, cls *classInfo) (interface{}, er
 		case reflect.Slice, reflect.Array:
 			m, err := d.decList(TAG_READ)
 			if err != nil {
-				if err == io.EOF {
+				if perrors.Is(err, io.EOF) {
 					break
 				}
 				return nil, perrors.WithStack(err)
diff --git a/serialize.go b/serialize.go
index b57702b..ca738ea 100644
--- a/serialize.go
+++ b/serialize.go
@@ -69,7 +69,7 @@ func (IntegerSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classInfo)
 }
 
 func (IntegerSerializer) EncObject(e *Encoder, v POJO) error {
-	bigInt, ok := v.(bigInteger)
+	bigInt, ok := v.(*bigInteger)
 	if !ok {
 		return e.encObject(v)
 	}
@@ -80,7 +80,7 @@ func (IntegerSerializer) EncObject(e *Encoder, v POJO) error {
 type DecimalSerializer struct{}
 
 func (DecimalSerializer) EncObject(e *Encoder, v POJO) error {
-	decimal, ok := v.(big.Decimal)
+	decimal, ok := v.(*big.Decimal)
 	if !ok {
 		return e.encObject(v)
 	}


Test patch:
diff --git a/codec_test.go b/codec_test.go
index a4cdd1b..b2dd937 100644
--- a/codec_test.go
+++ b/codec_test.go
@@ -18,9 +18,14 @@
 package hessian
 
 import (
+	"reflect"
 	"testing"
 )
 
+import (
+	"github.com/stretchr/testify/assert"
+)
+
 // go test -v -run TestPackUint16
 func TestPackUint16(t *testing.T) {
 	// var arr []byte
@@ -57,3 +62,11 @@ func TestPackInt64(t *testing.T) {
 		t.Fatalf("v:0X%d, pack-unpack value:0X%x\n", v, r)
 	}
 }
+
+func TestPackPtrInterface(t *testing.T) {
+	v := "struct"
+	vv := reflect.ValueOf(v)
+	sPointer, ok := PackPtrInterface(v, vv).(*string)
+	assert.True(t, ok)
+	assert.True(t, *sPointer == "struct")
+}
diff --git a/date_test.go b/date_test.go
index 7e1d36a..f0a8b6f 100644
--- a/date_test.go
+++ b/date_test.go
@@ -105,6 +105,7 @@ func TestEncDateNull(t *testing.T) {
 		e   *Encoder
 		d   *Decoder
 		res interface{}
+		err error
 	)
 	v = "2014-02-09 06:15:23 +0800 CST"
 	tz, _ = time.Parse("2006-01-02 15:04:05 +0800 CST", v)
@@ -122,12 +123,16 @@ func TestEncDateNull(t *testing.T) {
 		Date3:   d3,
 	}
 	e = NewEncoder()
-	e.Encode(date)
+	err = e.Encode(date)
+	if err != nil {
+		t.Fatal(err)
+	}
 	if len(e.Buffer()) == 0 {
 		t.Fail()
 	}
 	d = NewDecoder(e.Buffer())
-	res, _ = d.Decode()
+	res, err = d.Decode()
+	assert.Nil(t, err)
 	assert.Equal(t, ZeroDate, res.(*DateDemo).Date)
 	assert.Equal(t, 2, len(res.(*DateDemo).Dates))
 	assert.Equal(t, tz.Local().String(), (*res.(*DateDemo).Dates[0]).String())
diff --git a/encode_test.go b/encode_test.go
index 543452f..6db3a98 100644
--- a/encode_test.go
+++ b/encode_test.go
@@ -87,3 +87,53 @@ func testSimpleEncode(t *testing.T, v interface{}) {
 	err := e.Encode(v)
 	assert.Nil(t, err)
 }
+
+type BenchData struct {
+	name string
+}
+
+func (b *BenchData) JavaClassName() string {
+	return "test.bench.BenchData"
+}
+
+// Benchmark_Struct_Encode  	 2231869	       506.8 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Struct_Encode(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		NewEncoder().Encode(BenchData{})
+	}
+}
+
+// Benchmark_Pointer_Encode   	 2565778	       476.1 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Pointer_Encode(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		NewEncoder().Encode(&BenchData{})
+	}
+}
+
+// Benchmark_Struct_Encode_8   	 2307214	       519.4 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Struct_Encode_8(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	b.SetParallelism(8)
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			NewEncoder().Encode(BenchData{})
+		}
+	})
+}
+
+// Benchmark_Pointer_Encode_8   	 2460842	       476.7 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Pointer_Encode_8(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	b.SetParallelism(8)
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			NewEncoder().Encode(&BenchData{})
+		}
+	})
+}