summaryrefslogtreecommitdiff
path: root/vendor/github.com/bytedance/sonic/internal/decoder/optdec
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/bytedance/sonic/internal/decoder/optdec')
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/compiler.go23
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/errors.go6
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/functor.go13
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/interface.go47
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/map.go56
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/native.go7
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/node.go64
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/slice.go27
-rw-r--r--vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go3
9 files changed, 170 insertions, 76 deletions
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/compiler.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/compiler.go
index 7d9d60a01..b3ca7a4ee 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/compiler.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/compiler.go
@@ -1,7 +1,6 @@
package optdec
import (
- "encoding/json"
"fmt"
"reflect"
@@ -169,7 +168,9 @@ func (c *compiler) compileBasic(vt reflect.Type) decFunc {
case reflect.Struct:
return c.compileStruct(vt)
default:
- panic(&json.UnmarshalTypeError{Type: vt})
+ return &unsupportedTypeDecoder{
+ typ: rt.UnpackType(vt),
+ }
}
}
@@ -263,7 +264,7 @@ func (c *compiler) compileSlice(vt reflect.Type) decFunc {
if et.IsUint64() {
return &sliceU64Decoder{}
}
- if et.Kind() == reflect.String {
+ if et.Kind() == reflect.String && et != rt.JsonNumberType {
return &sliceStringDecoder{}
}
@@ -343,7 +344,7 @@ func (c *compiler) compileMap(vt reflect.Type) decFunc {
// Some common integer map later
mt := rt.MapType(rt.UnpackType(vt))
- if mt.Key.Kind() == reflect.String {
+ if mt.Key.Kind() == reflect.String && mt.Key != rt.JsonNumberType {
return &mapStrKeyDecoder{
mapType: mt,
assign: rt.GetMapStrAssign(vt),
@@ -399,7 +400,7 @@ func tryCompileKeyUnmarshaler(vt reflect.Type) decKey {
return decodeKeyTextUnmarshaler
}
- /* not support map key with `json.Unmarshaler` */
+ /* NOTE: encoding/json not support map key with `json.Unmarshaler` */
return nil
}
@@ -413,8 +414,18 @@ func (c *compiler) compileMapKey(vt reflect.Type) decKey {
return decodeKeyU8
case reflect.Uint16:
return decodeKeyU16
+ // NOTE: actually, encoding/json can't use float as map key
+ case reflect.Float32:
+ return decodeFloat32Key
+ case reflect.Float64:
+ return decodeFloat64Key
+ case reflect.String:
+ if rt.UnpackType(vt.Key()) == rt.JsonNumberType {
+ return decodeJsonNumberKey
+ }
+ fallthrough
default:
- panic(&json.UnmarshalTypeError{Type: vt})
+ return nil
}
}
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/errors.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/errors.go
index db0af547b..daa75c59c 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/errors.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/errors.go
@@ -70,4 +70,10 @@
Msg: msg,
}
}
+
+ func error_unsuppoted(typ *rt.GoType) error {
+ return &json.UnsupportedTypeError{
+ Type: typ.Pack(),
+ }
+}
\ No newline at end of file
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/functor.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/functor.go
index 2a0523d5e..48a8953c1 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/functor.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/functor.go
@@ -279,3 +279,16 @@ func (d *recuriveDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) er
}
return dec.FromDom(vp, node, ctx)
}
+
+type unsupportedTypeDecoder struct {
+ typ *rt.GoType
+}
+
+
+func (d *unsupportedTypeDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
+ if node.IsNull() {
+ return nil
+ }
+ return error_unsuppoted(d.typ)
+}
+
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/interface.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/interface.go
index 0c063d55f..0285f0f8f 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/interface.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/interface.go
@@ -13,32 +13,44 @@ type efaceDecoder struct {
}
func (d *efaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
- if node.IsNull() {
- *(*interface{})(vp) = interface{}(nil)
- return nil
- }
-
- eface := *(*rt.GoEface)(vp)
-
- // not pointer type, or nil pointer, or *interface{}
- if eface.Value == nil || eface.Type.Kind() != reflect.Ptr || rt.PtrElem(eface.Type) == anyType {
+ /* check the defined pointer type for issue 379 */
+ eface := (*rt.GoEface)(vp)
+
+ /*
+ not pointer type, or nil pointer, or self-pointed interface{}, such as
+ ```go
+ var v interface{}
+ v = &v
+ return v
+ ``` see `issue758_test.go`.
+ */
+ if eface.Value == nil || eface.Type.Kind() != reflect.Ptr || eface.Value == vp {
ret, err := node.AsEface(ctx)
if err != nil {
return err
}
-
*(*interface{})(vp) = ret
return nil
}
+ if node.IsNull() {
+ if eface.Type.Indirect() || (!eface.Type.Indirect() && eface.Type.Pack().Elem().Kind() != reflect.Ptr) {
+ *(*interface{})(vp) = nil
+ return nil
+ }
+ }
+
etp := rt.PtrElem(eface.Type)
vp = eface.Value
- /* check the defined pointer type for issue 379 */
if eface.Type.IsNamed() {
+ // check named pointer type, avoid call its `Unmarshaler`
newp := vp
etp = eface.Type
vp = unsafe.Pointer(&newp)
+ } else if !eface.Type.Indirect() {
+ // check direct value
+ etp = rt.UnpackType(eface.Type.Pack().Elem())
}
dec, err := findOrCompile(etp)
@@ -65,19 +77,10 @@ func (d *ifaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error
}
vt := iface.Itab.Vt
-
- // not pointer type, or nil pointer, or *interface{}
- if vp == nil || vt.Kind() != reflect.Ptr || rt.PtrElem(vt) == anyType {
- ret, err := node.AsEface(ctx)
- if err != nil {
- return err
- }
-
- *(*interface{})(vp) = ret
- return nil
+ if vt.Kind() != reflect.Ptr || iface.Value == nil {
+ return error_type(d.typ)
}
-
etp := rt.PtrElem(vt)
vp = iface.Value
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/map.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/map.go
index 1a2bda8f3..958ebc4b0 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/map.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/map.go
@@ -292,9 +292,9 @@ func (d *mapU64KeyDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) e
/** Decoder for generic cases */
-type decKey func(dec *mapDecoder, raw string, ctx *context) (interface{}, error)
+type decKey func(dec *mapDecoder, raw string) (interface{}, error)
-func decodeKeyU8(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
+func decodeKeyU8(dec *mapDecoder, raw string) (interface{}, error) {
key, err := Unquote(raw)
if err != nil {
return nil, err
@@ -309,7 +309,7 @@ func decodeKeyU8(dec *mapDecoder, raw string, ctx *context) (interface{}, error)
return uint8(ret), nil
}
-func decodeKeyU16(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
+func decodeKeyU16(dec *mapDecoder, raw string) (interface{}, error) {
key, err := Unquote(raw)
if err != nil {
return nil, err
@@ -324,7 +324,7 @@ func decodeKeyU16(dec *mapDecoder, raw string, ctx *context) (interface{}, error
return uint16(ret), nil
}
-func decodeKeyI8(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
+func decodeKeyI8(dec *mapDecoder, raw string) (interface{}, error) {
key, err := Unquote(raw)
if err != nil {
return nil, err
@@ -339,7 +339,7 @@ func decodeKeyI8(dec *mapDecoder, raw string, ctx *context) (interface{}, error)
return int8(ret), nil
}
-func decodeKeyI16(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
+func decodeKeyI16(dec *mapDecoder, raw string) (interface{}, error) {
key, err := Unquote(raw)
if err != nil {
return nil, err
@@ -354,26 +354,53 @@ func decodeKeyI16(dec *mapDecoder, raw string, ctx *context) (interface{}, error
return int16(ret), nil
}
-func decodeKeyJSONUnmarshaler(dec *mapDecoder, raw string, _ *context) (interface{}, error) {
+func decodeKeyTextUnmarshaler(dec *mapDecoder, raw string) (interface{}, error) {
+ key, err := Unquote(raw)
+ if err != nil {
+ return nil, err
+ }
ret := reflect.New(dec.mapType.Key.Pack()).Interface()
- err := ret.(json.Unmarshaler).UnmarshalJSON([]byte(raw))
+ err = ret.(encoding.TextUnmarshaler).UnmarshalText(rt.Str2Mem(key))
if err != nil {
return nil, err
}
return ret, nil
}
-func decodeKeyTextUnmarshaler(dec *mapDecoder, raw string, ctx *context) (interface{}, error) {
+func decodeFloat32Key(dec *mapDecoder, raw string) (interface{}, error) {
key, err := Unquote(raw)
if err != nil {
return nil, err
}
- ret := reflect.New(dec.mapType.Key.Pack()).Interface()
- err = ret.(encoding.TextUnmarshaler).UnmarshalText([]byte(key))
+ ret, err := ParseF64(key)
if err != nil {
return nil, err
}
- return ret, nil
+ if ret > math.MaxFloat32 || ret < -math.MaxFloat32 {
+ return nil, error_value(key, dec.mapType.Key.Pack())
+ }
+ return float32(ret), nil
+}
+
+func decodeFloat64Key(dec *mapDecoder, raw string) (interface{}, error) {
+ key, err := Unquote(raw)
+ if err != nil {
+ return nil, err
+ }
+ return ParseF64(key)
+}
+
+func decodeJsonNumberKey(dec *mapDecoder, raw string) (interface{}, error) {
+ // skip the quote
+ raw = raw[1:len(raw)-1]
+ end, ok := SkipNumberFast(raw, 0)
+
+ // check trailing chars
+ if !ok || end != len(raw) {
+ return nil, error_value(raw, rt.JsonNumberType.Pack())
+ }
+
+ return json.Number(raw[0:end]), nil
}
type mapDecoder struct {
@@ -389,8 +416,8 @@ func (d *mapDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
}
obj, ok := node.AsObj()
- if !ok {
- return error_mismatch(node, ctx, d.mapType.Pack())
+ if !ok || d.keyDec == nil {
+ return error_mismatch(node, ctx, d.mapType.Pack())
}
// allocate map
@@ -404,7 +431,8 @@ func (d *mapDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
for i := 0; i < obj.Len(); i++ {
keyn := NewNode(next)
raw := keyn.AsRaw(ctx)
- key, err := d.keyDec(d, raw, ctx)
+
+ key, err := d.keyDec(d, raw)
if err != nil {
if gerr == nil {
gerr = error_mismatch(keyn, ctx, d.mapType.Pack())
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/native.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/native.go
index 5dadec0b7..60f407d2e 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/native.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/native.go
@@ -74,6 +74,7 @@ type nodeBuf struct {
depth uint64
nstart uintptr
nend uintptr
+ iskey bool
stat jsonStat
}
@@ -196,14 +197,14 @@ func (p *Parser) parse() ErrorCode {
// check OoB here
offset := p.nbuf.ncur - p.nbuf.nstart
- curLen := offset / unsafe.Sizeof(node{})
- if curLen != uintptr(len(p.nodes)) {
+ curLen := int(offset / unsafe.Sizeof(node{}))
+ if curLen != len(p.nodes) {
panic(fmt.Sprintf("current len: %d, real len: %d cap: %d", curLen, len(p.nodes), cap(p.nodes)))
}
// node buf is not enough, continue parse
// the maxCap is always meet all valid JSON
- maxCap := calMaxNodeCap(len(p.Json))
+ maxCap := curLen + calMaxNodeCap(len(p.Json) - int(p.cur - p.start))
slice := rt.GoSlice{
Ptr: rt.Mallocgc(uintptr(maxCap) * nodeType.Size, nodeType, false),
Len: maxCap,
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/node.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/node.go
index b23901e38..774b6eef7 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/node.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/node.go
@@ -301,6 +301,17 @@ func (self Node) AsI64(ctx *Context) (int64, bool) {
}
}
+func (self Node) AsByte(ctx *Context) (uint8, bool) {
+ typ := self.Type()
+ if typ == KUint && self.U64() <= math.MaxUint8 {
+ return uint8(self.U64()), true
+ } else if typ == KSint && self.I64() == 0 {
+ return 0, true
+ } else {
+ return 0, false
+ }
+}
+
/********* Parse Node String into Value ***************/
func (val Node) ParseI64(ctx *Context) (int64, bool) {
@@ -457,20 +468,6 @@ func (val Node) AsStrRef(ctx *Context) (string, bool) {
}
}
-func (val Node) AsBytesRef(ctx *Context) ([]byte, bool) {
- switch val.Type() {
- case KStringEscaped:
- node := ptrCast(val.cptr)
- offset := val.Position()
- len := int(node.val)
- return ctx.Parser.JsonBytes()[offset : offset + len], true
- case KStringCommon:
- return rt.Str2Mem(val.StringRef(ctx)), true
- default:
- return nil, false
- }
-}
-
func (val Node) AsStringText(ctx *Context) ([]byte, bool) {
if !val.IsStr() {
return nil, false
@@ -551,7 +548,7 @@ func (val Node) AsRaw(ctx *Context) string {
node := ptrCast(val.cptr)
len := int(node.val)
offset := val.Position()
- // add start abd end quote
+ // add start and end quote
ref := rt.Str2Mem(ctx.Parser.Json)[offset-1 : offset+len+1]
return rt.Mem2Str(ref)
case KRawNumber: fallthrough
@@ -867,15 +864,38 @@ func (node *Node) AsSliceString(ctx *Context, vp unsafe.Pointer) error {
return gerr
}
-func (node *Node) AsSliceBytes(ctx *Context) ([]byte, error) {
- b, ok := node.AsBytesRef(ctx)
- if !ok {
- return nil, newUnmatched(node.Position(), rt.BytesType)
+func (val *Node) AsSliceBytes(ctx *Context) ([]byte, error) {
+ var origin []byte
+ switch val.Type() {
+ case KStringEscaped:
+ node := ptrCast(val.cptr)
+ offset := val.Position()
+ len := int(node.val)
+ origin = ctx.Parser.JsonBytes()[offset : offset + len]
+ case KStringCommon:
+ origin = rt.Str2Mem(val.StringRef(ctx))
+ case KArray:
+ arr := val.Array()
+ size := arr.Len()
+ a := make([]byte, size)
+ elem := NewNode(arr.Children())
+ var gerr error
+ var ok bool
+ for i := 0; i < size; i++ {
+ a[i], ok = elem.AsByte(ctx)
+ if !ok && gerr == nil {
+ gerr = newUnmatched(val.Position(), rt.BytesType)
+ }
+ elem = NewNode(PtrOffset(elem.cptr, 1))
+ }
+ return a, gerr
+ default:
+ return nil, newUnmatched(val.Position(), rt.BytesType)
}
-
- b64, err := rt.DecodeBase64(b)
+
+ b64, err := rt.DecodeBase64(origin)
if err != nil {
- return nil, newUnmatched(node.Position(), rt.BytesType)
+ return nil, newUnmatched(val.Position(), rt.BytesType)
}
return b64, nil
}
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/slice.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/slice.go
index a94e422b3..da7b12fc5 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/slice.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/slice.go
@@ -80,9 +80,13 @@ func (d *arrayDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error
}
/* zero rest of array */
- ptr := unsafe.Pointer(uintptr(vp) + uintptr(i)*d.elemType.Size)
+ addr := uintptr(vp) + uintptr(i)*d.elemType.Size
n := uintptr(d.len-i) * d.elemType.Size
- rt.ClearMemory(d.elemType, ptr, n)
+
+ /* the boundary pointer may points to another unknown object, so we need to avoid using it */
+ if n != 0 {
+ rt.ClearMemory(d.elemType, unsafe.Pointer(addr), n)
+ }
return gerr
}
@@ -95,7 +99,18 @@ func (d *sliceEfaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context)
return nil
}
- return node.AsSliceEface(ctx, vp)
+ /* if slice is empty, just call `AsSliceEface` */
+ if ((*rt.GoSlice)(vp)).Len == 0 {
+ return node.AsSliceEface(ctx, vp)
+ }
+
+ decoder := sliceDecoder{
+ elemType: rt.AnyType,
+ elemDec: &efaceDecoder{},
+ typ: rt.SliceEfaceType.Pack(),
+ }
+
+ return decoder.FromDom(vp, node, ctx)
}
type sliceI32Decoder struct {
@@ -168,12 +183,8 @@ func (d *sliceBytesDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context)
}
s, err := node.AsSliceBytes(ctx)
- if err != nil {
- return err
- }
-
*(*[]byte)(vp) = s
- return nil
+ return err
}
type sliceBytesUnmarshalerDecoder struct {
diff --git a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go
index bce2758f1..8b148eadf 100644
--- a/vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go
+++ b/vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go
@@ -4,6 +4,7 @@ import (
"reflect"
"unsafe"
+ "github.com/bytedance/sonic/internal/decoder/consts"
caching "github.com/bytedance/sonic/internal/optcaching"
"github.com/bytedance/sonic/internal/resolver"
)
@@ -38,7 +39,7 @@ func (d *structDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) erro
next = val.Next()
// find field idx
- idx := d.fieldMap.Get(key)
+ idx := d.fieldMap.Get(key, ctx.Options()&uint64(consts.OptionCaseSensitive) != 0)
if idx == -1 {
if Options(ctx.Options())&OptionDisableUnknown != 0 {
return error_field(key)