From db5c77a4733b8124473e3f311026533d3a9acbda Mon Sep 17 00:00:00 2001 From: shamaton Date: Wed, 4 Aug 2021 22:12:11 +0900 Subject: [PATCH 1/2] not using unsafe to decode string --- internal/decoding/decoding.go | 4 ++-- internal/decoding/string.go | 18 +++++++++++++----- internal/decoding/struct.go | 36 +++++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/internal/decoding/decoding.go b/internal/decoding/decoding.go index 78b95b6..9e4eebb 100644 --- a/internal/decoding/decoding.go +++ b/internal/decoding/decoding.go @@ -120,7 +120,7 @@ func (d *decoder) decode(rv reflect.Value, offset int) (int, error) { if err != nil { return 0, err } - bs, offset := d.asStringByte(offset, l, k) + bs, offset := d.asStringByteByLength(offset, l, k) rv.SetBytes(bs) return offset, nil } @@ -201,7 +201,7 @@ func (d *decoder) decode(rv reflect.Value, offset int) (int, error) { if l > rv.Len() { return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements", rv.Type(), rv.Len(), l) } - bs, offset := d.asStringByte(offset, l, k) + bs, offset := d.asStringByteByLength(offset, l, k) for i, b := range bs { rv.Index(i).SetUint(uint64(b)) } diff --git a/internal/decoding/string.go b/internal/decoding/string.go index d2e0687..ae5a515 100644 --- a/internal/decoding/string.go +++ b/internal/decoding/string.go @@ -3,7 +3,6 @@ package decoding import ( "encoding/binary" "reflect" - "unsafe" "github.com/shamaton/msgpack/v2/def" ) @@ -42,15 +41,24 @@ func (d *decoder) stringByteLength(offset int, k reflect.Kind) (int, int, error) } func (d *decoder) asString(offset int, k reflect.Kind) (string, int, error) { - l, offset, err := d.stringByteLength(offset, k) + bs, offset, err := d.asStringByte(offset, k) if err != nil { return emptyString, 0, err } - bs, offset := d.asStringByte(offset, l, k) - return *(*string)(unsafe.Pointer(&bs)), offset, nil + return string(bs), offset, nil +} + +func (d *decoder) asStringByte(offset int, k reflect.Kind) ([]byte, int, error) { + l, offset, err := d.stringByteLength(offset, k) + if err != nil { + return emptyBytes, 0, err + } + + b, o := d.asStringByteByLength(offset, l, k) + return b, o, nil } -func (d *decoder) asStringByte(offset int, l int, k reflect.Kind) ([]byte, int) { +func (d *decoder) asStringByteByLength(offset int, l int, k reflect.Kind) ([]byte, int) { if l < 1 { return emptyBytes, offset } diff --git a/internal/decoding/struct.go b/internal/decoding/struct.go index 6caadc0..2169d39 100644 --- a/internal/decoding/struct.go +++ b/internal/decoding/struct.go @@ -9,7 +9,8 @@ import ( ) type structCacheTypeMap struct { - m map[string]int + keys [][]byte + indexes []int } type structCacheTypeArray struct { @@ -95,28 +96,47 @@ func (d *decoder) setStructFromMap(rv reflect.Value, offset int, k reflect.Kind) return 0, err } - // find or create reference var sctm *structCacheTypeMap cache, cacheFind := mapSCTM.Load(rv.Type()) if !cacheFind { - sctm = &structCacheTypeMap{m: map[string]int{}} + sctm = &structCacheTypeMap{} for i := 0; i < rv.NumField(); i++ { if ok, name := d.CheckField(rv.Type().Field(i)); ok { - sctm.m[name] = i + sctm.keys = append(sctm.keys, []byte(name)) + sctm.indexes = append(sctm.indexes, i) } } mapSCTM.Store(rv.Type(), sctm) } else { sctm = cache.(*structCacheTypeMap) } - // set value if string correct + for i := 0; i < l; i++ { - key, o2, err := d.asString(o, k) + dataKey, o2, err := d.asStringByte(o, k) if err != nil { return 0, err } - if _, ok := sctm.m[key]; ok { - o2, err = d.decode(rv.Field(sctm.m[key]), o2) + + fieldIndex := -1 + for keyIndex, keyBytes := range sctm.keys { + if len(keyBytes) != len(dataKey) { + continue + } + + fieldIndex = sctm.indexes[keyIndex] + for dataIndex := range dataKey { + if dataKey[dataIndex] != keyBytes[dataIndex] { + fieldIndex = -1 + break + } + } + if fieldIndex >= 0 { + break + } + } + + if fieldIndex >= 0 { + o2, err = d.decode(rv.Field(fieldIndex), o2) if err != nil { return 0, err } From 48efb601c1cf58c16e61c643f94280ddab55431b Mon Sep 17 00:00:00 2001 From: shamaton Date: Wed, 4 Aug 2021 22:13:06 +0900 Subject: [PATCH 2/2] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f217cd1..8a3a84f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ go get -u github.com/shamaton/msgpack package main import ( - "github.com/shamaton/msgpack" + "github.com/shamaton/msgpack/v2" ) func main() {