optimize exception bug
diff --git a/.gitignore b/.gitignore
index 1363720..fc62e8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.idea
+vendor
coverage.txt
diff --git a/CHANGE.md b/CHANGE.md
index a3f32e4..492220c 100644
--- a/CHANGE.md
+++ b/CHANGE.md
@@ -1,5 +1,18 @@
# Release Notes
+## v1.6.0
+
+### New Features
+- ignore non-exist fields when decoding. [#201](https://github.com/apache/dubbo-go-hessian2/pull/201)
+
+### Enhancement
+- add cache in reflection to improve performance. [#179](https://github.com/apache/dubbo-go-hessian2/pull/179)
+- string decode performance improvement. [#188](https://github.com/apache/dubbo-go-hessian2/pull/188)
+
+### Bugfixes
+- fix attachment lost for nil value. [#191](https://github.com/apache/dubbo-go-hessian2/pull/191)
+- fix float32 accuracy issue. [#196](https://github.com/apache/dubbo-go-hessian2/pull/196)
+
## v1.5.0
### New Features
diff --git a/README.md b/README.md
index 9c12941..6bc9b78 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,15 @@
---
+> **Notice: When decoding, the java version of hessian will default skip and ignore non-exist fields.**
+> **From the version of v1.6.0 , dubbo-go-hessian2 will skip non-exist fields too, while that before v1.6.0 will return errors.**
+
It's a golang hessian library used by [Apache/dubbo-go](https://github.com/apache/dubbo-go).
+There is a big performance improvement, and some bugs fix for v1.6.0,
+thanks to [micln](https://github.com/micln), [pantianying](https://github.com/pantianying), [zonghaishang](https://github.com/zonghaishang),
+ [willson-chen](https://github.com/willson-chen), [champly](https://github.com/champly).
+
## Feature List
* [All JDK Exceptions](https://github.com/apache/dubbo-go-hessian2/issues/59)
diff --git a/binary_test.go b/binary_test.go
index dafda34..c145e13 100644
--- a/binary_test.go
+++ b/binary_test.go
@@ -20,8 +20,6 @@
import (
"bytes"
"fmt"
-
- // "fmt"
"testing"
)
diff --git a/double.go b/double.go
index d70c682..376a1f4 100644
--- a/double.go
+++ b/double.go
@@ -20,6 +20,7 @@
import (
"encoding/binary"
"math"
+ "strconv"
)
import (
@@ -62,6 +63,38 @@
byte(bits>>32), byte(bits>>24), byte(bits>>16), byte(bits>>8), byte(bits))
}
+func encFloat32(b []byte, v float32) []byte {
+ fv := float32(int32(v))
+ if fv == v {
+ iv := int32(v)
+ switch iv {
+ case 0:
+ return encByte(b, BC_DOUBLE_ZERO)
+ case 1:
+ return encByte(b, BC_DOUBLE_ONE)
+ }
+ if iv >= -0x80 && iv < 0x80 {
+ return encByte(b, BC_DOUBLE_BYTE, byte(iv))
+ } else if iv >= -0x8000 && iv < 0x8000 {
+ return encByte(b, BC_DOUBLE_SHORT, byte(iv>>8), byte(iv))
+ }
+
+ goto END
+ }
+
+END:
+ if float32(int32(v*1000)) == v*1000 {
+ iv := int32(v * 1000)
+ return encByte(b, BC_DOUBLE_MILL, byte(iv>>24), byte(iv>>16), byte(iv>>8), byte(iv))
+ } else {
+ str := strconv.FormatFloat(float64(v), 'f', -1, 32)
+ d, _ := strconv.ParseFloat(str, 64)
+ bits := math.Float64bits(d)
+ return encByte(b, BC_DOUBLE, byte(bits>>56), byte(bits>>48), byte(bits>>40),
+ byte(bits>>32), byte(bits>>24), byte(bits>>16), byte(bits>>8), byte(bits))
+ }
+}
+
/////////////////////////////////////////
// Double
/////////////////////////////////////////
diff --git a/double_test.go b/double_test.go
index 111124b..43e9391 100644
--- a/double_test.go
+++ b/double_test.go
@@ -42,6 +42,33 @@
t.Logf("decode(%v) = %v, %v\n", v, res, err)
}
+func TestIssue181(t *testing.T) {
+ var (
+ v float32
+ err error
+ e *Encoder
+ d *Decoder
+ res interface{}
+ )
+
+ e = NewEncoder()
+ v = 99.8
+ e.Encode(v)
+ if len(e.Buffer()) == 0 {
+ t.Fail()
+ }
+
+ // res would be '99.800003' without patches in PR #196
+ d = NewDecoder(e.Buffer())
+ res, err = d.Decode()
+ f := res.(float64)
+ if float32(f) != v {
+ t.Errorf("decode(%v) = %v, %v\n", v, res, err)
+ return
+ }
+ t.Logf("decode(%v) = %v\n", v, res)
+}
+
func TestDouble(t *testing.T) {
testDecodeFramework(t, "replyDouble_0_0", 0.0)
testDecodeFramework(t, "replyDouble_0_001", 0.001)
diff --git a/encode.go b/encode.go
index fbeae99..ad9d5c6 100644
--- a/encode.go
+++ b/encode.go
@@ -112,7 +112,7 @@
}
case float32:
- e.buffer = encFloat(e.buffer, float64(val))
+ e.buffer = encFloat32(e.buffer, val)
case float64:
e.buffer = encFloat(e.buffer, val)
diff --git a/int_test.go b/int_test.go
index 726a11f..082f399 100644
--- a/int_test.go
+++ b/int_test.go
@@ -18,10 +18,13 @@
package hessian
import (
- "github.com/stretchr/testify/assert"
"testing"
)
+import (
+ "github.com/stretchr/testify/assert"
+)
+
func TestEncInt32Len1B(t *testing.T) {
var (
v int32
diff --git a/object.go b/object.go
index 72353de..2a86820 100644
--- a/object.go
+++ b/object.go
@@ -380,7 +380,6 @@
// skip field
d.DecodeValue()
continue
- //return nil, perrors.Errorf("can not find field %s", fieldName)
}
// skip unexported anonymous field
@@ -398,8 +397,8 @@
// unpack pointer to enable value setting
fldRawValue := UnpackPtrValue(field)
-
kind := fldTyp.Kind()
+
switch kind {
case reflect.String:
str, err := d.decString(TAG_READ)
diff --git a/object_test.go b/object_test.go
index 76654c7..db66596 100644
--- a/object_test.go
+++ b/object_test.go
@@ -25,6 +25,10 @@
"time"
)
+import (
+ "github.com/stretchr/testify/assert"
+)
+
type Department struct {
Name string
}
@@ -749,3 +753,18 @@
}
}
}
+
+type Person183 struct {
+ Name string
+}
+
+func (Person183) JavaClassName() string {
+ return `test.Person183`
+}
+
+func TestIssue183_DecodeExcessStructField(t *testing.T) {
+ RegisterPOJO(&Person183{})
+ got, err := decodeJavaResponse(`customReplyPerson183`, ``, false)
+ assert.NoError(t, err)
+ t.Logf("%T %+v", got, got)
+}
diff --git a/string.go b/string.go
index 6a217c5..a2a24ce 100644
--- a/string.go
+++ b/string.go
@@ -218,10 +218,7 @@
// ::= [x00-x1f] <utf8-data> # string of length 0-31
// ::= [x30-x34] <utf8-data> # string of length 0-1023
func (d *Decoder) getStringLength(tag byte) (int, error) {
- var (
- err error
- length int
- )
+ var length int
switch {
case tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX:
@@ -251,16 +248,15 @@
return length, nil
default:
- return -1, perrors.WithStack(err)
+ return -1, perrors.Errorf("string decode: unknown tag %b", tag)
}
}
func (d *Decoder) decString(flag int32) (string, error) {
var (
- tag byte
- chunkLen int
- last bool
- s string
+ tag byte
+ last bool
+ s string
)
if flag != TAG_READ {
@@ -315,11 +311,10 @@
last = true
}
- charLen, err := d.getStringLength(tag)
+ chunkLen, err := d.getStringLength(tag)
if err != nil {
return s, perrors.WithStack(err)
}
- chunkLen = charLen
bytesBuf := make([]byte, chunkLen<<2)
offset := 0
@@ -342,20 +337,11 @@
last = true
}
- charLen, err = d.getStringLength(b)
+ chunkLen, err = d.getStringLength(b)
if err != nil {
return s, perrors.WithStack(err)
}
-
- if chunkLen < 0 {
- chunkLen = 0
- }
- if charLen < 0 {
- charLen = 0
- }
-
- chunkLen += charLen
- remain, cap := len(bytesBuf)-offset, charLen<<2
+ remain, cap := len(bytesBuf)-offset, chunkLen<<2
if remain < cap {
grow := len(bytesBuf) + cap
bs := make([]byte, grow)
diff --git a/test_hessian/src/main/java/test/TestCustomReply.java b/test_hessian/src/main/java/test/TestCustomReply.java
index 4586e24..12fc411 100644
--- a/test_hessian/src/main/java/test/TestCustomReply.java
+++ b/test_hessian/src/main/java/test/TestCustomReply.java
@@ -425,6 +425,18 @@
output.flush();
}
+ public void customReplyPerson183() throws Exception {
+ Person183 p = new Person183();
+ p.name = "pname";
+ p.age = 13;
+ InnerPerson innerPerson = new InnerPerson();
+ innerPerson.name = "pname2";
+ innerPerson.age = 132;
+ p.innerPerson = innerPerson;
+ output.writeObject(p);
+ output.flush();
+ }
+
public void customReplyComplexString() throws Exception {
output.writeObject(TestString.getComplexString());
output.flush();
@@ -491,3 +503,14 @@
}
}
+
+class Person183 implements Serializable {
+ public String name;
+ public Integer age;
+ public InnerPerson innerPerson;
+}
+
+class InnerPerson implements Serializable {
+ public String name;
+ public Integer age;
+}
diff --git a/test_hessian/src/main/java/test/TestString.java b/test_hessian/src/main/java/test/TestString.java
index a19cb73..c026796 100644
--- a/test_hessian/src/main/java/test/TestString.java
+++ b/test_hessian/src/main/java/test/TestString.java
@@ -30,8 +30,8 @@
return s + ",max" + maxUnicode;
}
- public static String getComplexString() {
- String s = "킐\u0088中国你好!\u0088\u0088\u0088\u0088\u0088\u0088";
- return s;
- }
+ public static String getComplexString() {
+ String s = "킐\u0088中国你好!\u0088\u0088\u0088\u0088\u0088\u0088";
+ return s;
+ }
}