Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support clean encoder/decoder, discard decode buffer #242

Merged
merged 5 commits into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion date.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (d *Decoder) decDate(flag int32) (time.Time, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
tag, _ = d.ReadByte()
}

switch {
Expand Down
29 changes: 17 additions & 12 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,22 @@ func NewCheapDecoderWithSkip(b []byte) *Decoder {
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
/////////////////////////////////////////

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
}

Expand All @@ -109,11 +109,16 @@ func (d *Decoder) len() int {
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()
Expand Down Expand Up @@ -198,7 +203,7 @@ func (d *Decoder) DecodeValue() (interface{}, error) {
tag byte
)

tag, err = d.readByte()
tag, err = d.ReadByte()
if err == io.EOF {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion double.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (d *Decoder) decDouble(flag int32) (interface{}, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
tag, _ = d.ReadByte()
}
switch tag {
case BC_LONG_INT:
Expand Down
8 changes: 8 additions & 0 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ func NewEncoder() *Encoder {
}
}

// 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[:]
Expand Down
136 changes: 136 additions & 0 deletions hessian_demo/loop_encode_decode_test.go
Original file line number Diff line number Diff line change
@@ -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 (
wongoo marked this conversation as resolved.
Show resolved Hide resolved
"github.com/stretchr/testify/assert"
)

import (
wongoo marked this conversation as resolved.
Show resolved Hide resolved
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))
}
2 changes: 1 addition & 1 deletion int.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (d *Decoder) decInt32(flag int32) (int32, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
tag, _ = d.ReadByte()
}

switch {
Expand Down
2 changes: 1 addition & 1 deletion java_sql_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (JavaSqlTimeSerializer) DecObject(d *Decoder, typ reflect.Type, cls classIn
// 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
}
Expand Down
2 changes: 1 addition & 1 deletion list.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ func (d *Decoder) decList(flag int32) (interface{}, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, err = d.readByte()
tag, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
Expand Down
4 changes: 2 additions & 2 deletions long.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (d *Decoder) decInt64(flag int32) (int64, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
tag, _ = d.ReadByte()
}

switch {
Expand Down Expand Up @@ -102,7 +102,7 @@ func (d *Decoder) decInt64(flag int32) (int64, error) {
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:
Expand Down
10 changes: 5 additions & 5 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (d *Decoder) decMapByValue(value reflect.Value) error {
)

//tag, _ = d.readBufByte()
tag, err = d.readByte()
tag, err = d.ReadByte()
// check error
if err != nil {
return perrors.WithStack(err)
Expand Down Expand Up @@ -236,7 +236,7 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
tag, _ = d.ReadByte()
}

switch {
Expand Down Expand Up @@ -277,7 +277,7 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
}
}
}
_, err = d.readByte()
_, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
Expand All @@ -299,7 +299,7 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
}
m[k] = v
}
_, err = d.readByte()
_, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
Expand All @@ -320,7 +320,7 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
}
m[k] = v
}
_, err = d.readByte()
_, err = d.ReadByte()
if err != nil {
return nil, perrors.WithStack(err)
}
Expand Down
2 changes: 1 addition & 1 deletion object.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ func (d *Decoder) decObject(flag int32) (interface{}, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
tag, _ = d.ReadByte()
}

switch {
Expand Down
2 changes: 1 addition & 1 deletion ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func (d *Decoder) decRef(flag int32) (interface{}, error) {
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
tag, _ = d.ReadByte()
}

switch {
Expand Down
Loading