Merge pull request #242 from wongoo/loop_encode_decode
support clean encoder/decoder, discard decode buffer
diff --git a/date.go b/date.go
index f3db553..e1af345 100644
--- a/date.go
+++ b/date.go
@@ -73,7 +73,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch {
diff --git a/decode.go b/decode.go
index f10456c..35de60e 100644
--- a/decode.go
+++ b/decode.go
@@ -79,6 +79,14 @@
return &Decoder{reader: bufio.NewReader(bytes.NewReader(b)), isSkip: true}
}
+// Clean clean the Decoder (room) for a new object decoding.
+// Notice it won't reset reader buffer and will continue to read data from it.
+func (d *Decoder) Clean() {
+ d.typeRefs = &TypeRefs{records: map[string]bool{}}
+ d.refs = nil
+ d.classInfoList = nil
+}
+
/////////////////////////////////////////
// utilities
/////////////////////////////////////////
@@ -86,15 +94,7 @@
func (d *Decoder) Reset(b []byte) *Decoder {
// reuse reader buf, avoid allocate
d.reader.Reset(bytes.NewReader(b))
- d.typeRefs = &TypeRefs{records: map[string]bool{}}
-
- if d.refs != nil {
- d.refs = nil
- }
- if d.classInfoList != nil {
- d.classInfoList = nil
- }
-
+ d.Clean()
return d
}
@@ -109,11 +109,16 @@
return d.reader.Buffered()
}
-// read a byte from Decoder, advance the ptr
-func (d *Decoder) readByte() (byte, error) {
+// ReadByte read a byte from Decoder, advance the ptr
+func (d *Decoder) ReadByte() (byte, error) {
return d.reader.ReadByte()
}
+// Discard skips the next n bytes
+func (d *Decoder) Discard(n int) (int, error) {
+ return d.reader.Discard(n)
+}
+
// unread a byte
func (d *Decoder) unreadByte() error {
return d.reader.UnreadByte()
@@ -198,7 +203,7 @@
tag byte
)
- tag, err = d.readByte()
+ tag, err = d.ReadByte()
if err == io.EOF {
return nil, err
}
diff --git a/double.go b/double.go
index 376a1f4..751af91 100644
--- a/double.go
+++ b/double.go
@@ -115,7 +115,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch tag {
case BC_LONG_INT:
diff --git a/encode.go b/encode.go
index 2ae6791..b0344d1 100644
--- a/encode.go
+++ b/encode.go
@@ -48,6 +48,14 @@
}
}
+// Clean clean the Encoder (room) for a new object encoding.
+func (e *Encoder) Clean() {
+ var buffer = make([]byte, 64)
+ e.classInfoList = nil
+ e.buffer = buffer[:0]
+ e.refMap = make(map[unsafe.Pointer]_refElem, 7)
+}
+
// Buffer returns byte buffer
func (e *Encoder) Buffer() []byte {
return e.buffer[:]
diff --git a/hessian_demo/loop_encode_decode_test.go b/hessian_demo/loop_encode_decode_test.go
new file mode 100644
index 0000000..f6acc0d
--- /dev/null
+++ b/hessian_demo/loop_encode_decode_test.go
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hessian_demo
+
+import (
+ "reflect"
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+import (
+ hessian "github.com/apache/dubbo-go-hessian2"
+)
+
+type User struct {
+ Name string
+ Age int
+}
+
+func (User) JavaClassName() string {
+ return "hessian.demo.User"
+}
+
+type Location struct {
+ Address string
+ Postcode string
+}
+
+func (Location) JavaClassName() string {
+ return "hessian.demo.Location"
+}
+
+func TestLoopEncodeDecode(t *testing.T) {
+ u := &User{
+ Name: "wongoo",
+ Age: 18,
+ }
+ loc := &Location{
+ Address: "xiamen",
+ Postcode: "361000",
+ }
+
+ // demo a bytes buffer from client to server
+ var bytes []byte
+ e := hessian.NewEncoder()
+
+ // -------- encode 1
+ bytes = append(bytes, encodeWithFlagAndLength(e, 'D', u)...)
+
+ // -------- encode 2
+ bytes = append(bytes, encodeWithFlagAndLength(e, 'S', 12345)...)
+
+ // -------- encode 3
+ bytes = append(bytes, encodeWithFlagAndLength(e, 'D', loc)...)
+
+ // -------- encode 4
+ bytes = append(bytes, encodeWithFlagAndLength(e, 'D', "hello")...)
+
+ // demo a decoder to decode buffer from client
+ d := hessian.NewDecoder(bytes)
+
+ // -------- decode 1
+ decodeFlagAndLengthAndData(t, d, u)
+
+ // -------- decode 2
+ decodeFlagAndLengthAndData(t, d, 12345)
+
+ // -------- decode 3
+ decodeFlagAndLengthAndData(t, d, loc)
+
+ // -------- decode 4
+ decodeFlagAndLengthAndData(t, d, "hello")
+}
+
+// encode format: [flag][length][binary data]
+func encodeWithFlagAndLength(e *hessian.Encoder, flag byte, obj interface{}) []byte {
+ var bytes []byte
+ bytes = append(bytes, flag)
+
+ e.Clean()
+ _ = e.Encode(obj)
+ dataBytes := e.Buffer()
+
+ length := len(dataBytes)
+
+ e.Clean()
+ _ = e.Encode(length)
+ lengthBytes := e.Buffer()
+
+ bytes = append(bytes, lengthBytes...)
+ bytes = append(bytes, dataBytes...)
+
+ return bytes
+}
+
+func decodeFlagAndLengthAndData(t *testing.T, d *hessian.Decoder, expect interface{}) {
+ // decode flag
+ d.Clean()
+ flag, _ := d.ReadByte()
+
+ // decode length
+ d.Clean()
+ lengthObj, _ := d.Decode()
+ length := lengthObj.(int64)
+
+ // skip data when flag='S'
+ if flag == 'S' {
+ _, _ = d.Discard(int(length))
+ return
+ }
+
+ // decode data
+ d.Clean()
+ res, _ := d.Decode()
+
+ // check
+ assert.True(t, reflect.DeepEqual(expect, res))
+}
diff --git a/int.go b/int.go
index 0581170..dd06d11 100644
--- a/int.go
+++ b/int.go
@@ -66,7 +66,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch {
diff --git a/java_sql_time.go b/java_sql_time.go
index e6861bb..a359e8b 100644
--- a/java_sql_time.go
+++ b/java_sql_time.go
@@ -126,7 +126,7 @@
// add pointer ref so that ref the same object
d.appendRefs(vRef.Interface())
- tag, err := d.readByte()
+ tag, err := d.ReadByte()
if err == io.EOF {
return nil, err
}
diff --git a/list.go b/list.go
index 0eed874..d8ed019 100644
--- a/list.go
+++ b/list.go
@@ -269,7 +269,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, err = d.readByte()
+ tag, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
diff --git a/long.go b/long.go
index d8d2005..e170700 100644
--- a/long.go
+++ b/long.go
@@ -70,7 +70,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch {
@@ -102,7 +102,7 @@
return int64(tag-BC_INT_SHORT_ZERO)<<16 + int64(buf[0])<<8 + int64(buf[1]), nil
case tag == BC_DOUBLE_BYTE:
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
return int64(tag), nil
case tag == BC_DOUBLE_SHORT:
diff --git a/map.go b/map.go
index dc7a21b..c6e3044 100644
--- a/map.go
+++ b/map.go
@@ -159,7 +159,7 @@
)
//tag, _ = d.readBufByte()
- tag, err = d.readByte()
+ tag, err = d.ReadByte()
// check error
if err != nil {
return perrors.WithStack(err)
@@ -236,7 +236,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch {
@@ -277,7 +277,7 @@
}
}
}
- _, err = d.readByte()
+ _, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
@@ -299,7 +299,7 @@
}
m[k] = v
}
- _, err = d.readByte()
+ _, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
@@ -320,7 +320,7 @@
}
m[k] = v
}
- _, err = d.readByte()
+ _, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
diff --git a/object.go b/object.go
index 033db94..bec2de4 100644
--- a/object.go
+++ b/object.go
@@ -619,7 +619,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch {
diff --git a/ref.go b/ref.go
index 9987325..9900a7a 100644
--- a/ref.go
+++ b/ref.go
@@ -157,7 +157,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch {
diff --git a/string.go b/string.go
index a2a24ce..2581585 100644
--- a/string.go
+++ b/string.go
@@ -225,7 +225,7 @@
return int(tag - 0x00), nil
case tag >= 0x30 && tag <= 0x33:
- b, err := d.readByte()
+ b, err := d.ReadByte()
if err != nil {
return -1, perrors.WithStack(err)
}
@@ -234,12 +234,12 @@
return length, nil
case tag == BC_STRING_CHUNK || tag == BC_STRING:
- b0, err := d.readByte()
+ b0, err := d.ReadByte()
if err != nil {
return -1, perrors.WithStack(err)
}
- b1, err := d.readByte()
+ b1, err := d.ReadByte()
if err != nil {
return -1, perrors.WithStack(err)
}
@@ -262,7 +262,7 @@
if flag != TAG_READ {
tag = byte(flag)
} else {
- tag, _ = d.readByte()
+ tag, _ = d.ReadByte()
}
switch {
@@ -325,7 +325,7 @@
return *(*string)(unsafe.Pointer(&b)), nil
}
- b, _ := d.readByte()
+ b, _ := d.ReadByte()
switch {
case (tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX) ||
(tag >= 0x30 && tag <= 0x33) ||
@@ -484,7 +484,7 @@
if remain := offset - prev - nread; remain > 0 {
if remain == 1 {
- ch, err := d.readByte()
+ ch, err := d.ReadByte()
if err != nil {
return s, perrors.WithStack(err)
}
@@ -514,7 +514,7 @@
}
// decode byte
- ch, err := d.readByte()
+ ch, err := d.ReadByte()
if err != nil {
if err == io.EOF {
break
@@ -526,7 +526,7 @@
bytesBuf[offset] = ch
offset++
} else if (ch & 0xe0) == 0xc0 {
- ch1, err := d.readByte()
+ ch1, err := d.ReadByte()
if err != nil {
return s, perrors.WithStack(err)
}