summaryrefslogtreecommitdiff
path: root/vendor/github.com/goccy/go-json/internal/decoder
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/goccy/go-json/internal/decoder')
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go37
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/array.go169
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/bool.go78
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/bytes.go114
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/compile.go510
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go28
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/compile_race.go36
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/context.go254
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/float.go158
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/func.go141
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/int.go242
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/interface.go458
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/map.go186
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/number.go112
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/option.go15
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/ptr.go87
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/slice.go301
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/stream.go554
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/string.go371
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/struct.go819
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/type.go29
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/uint.go190
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go91
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go280
-rw-r--r--vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go68
25 files changed, 5328 insertions, 0 deletions
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go b/vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go
new file mode 100644
index 000000000..030cb7a97
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go
@@ -0,0 +1,37 @@
+package decoder
+
+import (
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type anonymousFieldDecoder struct {
+ structType *runtime.Type
+ offset uintptr
+ dec Decoder
+}
+
+func newAnonymousFieldDecoder(structType *runtime.Type, offset uintptr, dec Decoder) *anonymousFieldDecoder {
+ return &anonymousFieldDecoder{
+ structType: structType,
+ offset: offset,
+ dec: dec,
+ }
+}
+
+func (d *anonymousFieldDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ if *(*unsafe.Pointer)(p) == nil {
+ *(*unsafe.Pointer)(p) = unsafe_New(d.structType)
+ }
+ p = *(*unsafe.Pointer)(p)
+ return d.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+d.offset))
+}
+
+func (d *anonymousFieldDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ if *(*unsafe.Pointer)(p) == nil {
+ *(*unsafe.Pointer)(p) = unsafe_New(d.structType)
+ }
+ p = *(*unsafe.Pointer)(p)
+ return d.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/array.go b/vendor/github.com/goccy/go-json/internal/decoder/array.go
new file mode 100644
index 000000000..21f1fd585
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/array.go
@@ -0,0 +1,169 @@
+package decoder
+
+import (
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type arrayDecoder struct {
+ elemType *runtime.Type
+ size uintptr
+ valueDecoder Decoder
+ alen int
+ structName string
+ fieldName string
+ zeroValue unsafe.Pointer
+}
+
+func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
+ zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
+ return &arrayDecoder{
+ valueDecoder: dec,
+ elemType: elemType,
+ size: elemType.Size(),
+ alen: alen,
+ structName: structName,
+ fieldName: fieldName,
+ zeroValue: zeroValue,
+ }
+}
+
+func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+
+ for {
+ switch s.char() {
+ case ' ', '\n', '\t', '\r':
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ return nil
+ case '[':
+ idx := 0
+ s.cursor++
+ if s.skipWhiteSpace() == ']' {
+ for idx < d.alen {
+ *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
+ idx++
+ }
+ s.cursor++
+ return nil
+ }
+ for {
+ if idx < d.alen {
+ if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
+ return err
+ }
+ } else {
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ }
+ idx++
+ switch s.skipWhiteSpace() {
+ case ']':
+ for idx < d.alen {
+ *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
+ idx++
+ }
+ s.cursor++
+ return nil
+ case ',':
+ s.cursor++
+ continue
+ case nul:
+ if s.read() {
+ s.cursor++
+ continue
+ }
+ goto ERROR
+ default:
+ goto ERROR
+ }
+ }
+ case nul:
+ if s.read() {
+ continue
+ }
+ goto ERROR
+ default:
+ goto ERROR
+ }
+ s.cursor++
+ }
+ERROR:
+ return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
+}
+
+func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+
+ for {
+ switch buf[cursor] {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ continue
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ return cursor, nil
+ case '[':
+ idx := 0
+ cursor++
+ cursor = skipWhiteSpace(buf, cursor)
+ if buf[cursor] == ']' {
+ for idx < d.alen {
+ *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
+ idx++
+ }
+ cursor++
+ return cursor, nil
+ }
+ for {
+ if idx < d.alen {
+ c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ } else {
+ c, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ }
+ idx++
+ cursor = skipWhiteSpace(buf, cursor)
+ switch buf[cursor] {
+ case ']':
+ for idx < d.alen {
+ *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
+ idx++
+ }
+ cursor++
+ return cursor, nil
+ case ',':
+ cursor++
+ continue
+ default:
+ return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
+ }
+ }
+ default:
+ return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
+ }
+ }
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/bool.go b/vendor/github.com/goccy/go-json/internal/decoder/bool.go
new file mode 100644
index 000000000..455042a53
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/bool.go
@@ -0,0 +1,78 @@
+package decoder
+
+import (
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+)
+
+type boolDecoder struct {
+ structName string
+ fieldName string
+}
+
+func newBoolDecoder(structName, fieldName string) *boolDecoder {
+ return &boolDecoder{structName: structName, fieldName: fieldName}
+}
+
+func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ c := s.skipWhiteSpace()
+ for {
+ switch c {
+ case 't':
+ if err := trueBytes(s); err != nil {
+ return err
+ }
+ **(**bool)(unsafe.Pointer(&p)) = true
+ return nil
+ case 'f':
+ if err := falseBytes(s); err != nil {
+ return err
+ }
+ **(**bool)(unsafe.Pointer(&p)) = false
+ return nil
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ return nil
+ case nul:
+ if s.read() {
+ c = s.char()
+ continue
+ }
+ goto ERROR
+ }
+ break
+ }
+ERROR:
+ return errors.ErrUnexpectedEndOfJSON("bool", s.totalOffset())
+}
+
+func (d *boolDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ cursor = skipWhiteSpace(buf, cursor)
+ switch buf[cursor] {
+ case 't':
+ if err := validateTrue(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ **(**bool)(unsafe.Pointer(&p)) = true
+ return cursor, nil
+ case 'f':
+ if err := validateFalse(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 5
+ **(**bool)(unsafe.Pointer(&p)) = false
+ return cursor, nil
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ return cursor, nil
+ }
+ return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/bytes.go b/vendor/github.com/goccy/go-json/internal/decoder/bytes.go
new file mode 100644
index 000000000..01a37fef4
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/bytes.go
@@ -0,0 +1,114 @@
+package decoder
+
+import (
+ "encoding/base64"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type bytesDecoder struct {
+ typ *runtime.Type
+ sliceDecoder Decoder
+ stringDecoder *stringDecoder
+ structName string
+ fieldName string
+}
+
+func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder {
+ var unmarshalDecoder Decoder
+ switch {
+ case runtime.PtrTo(typ).Implements(unmarshalJSONType):
+ unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
+ case runtime.PtrTo(typ).Implements(unmarshalTextType):
+ unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
+ }
+ if unmarshalDecoder == nil {
+ return nil
+ }
+ return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
+}
+
+func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder {
+ return &bytesDecoder{
+ typ: typ,
+ sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName),
+ stringDecoder: newStringDecoder(structName, fieldName),
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *bytesDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ bytes, err := d.decodeStreamBinary(s, depth, p)
+ if err != nil {
+ return err
+ }
+ if bytes == nil {
+ s.reset()
+ return nil
+ }
+ decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
+ buf := make([]byte, decodedLen)
+ n, err := base64.StdEncoding.Decode(buf, bytes)
+ if err != nil {
+ return err
+ }
+ *(*[]byte)(p) = buf[:n]
+ s.reset()
+ return nil
+}
+
+func (d *bytesDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ bytes, c, err := d.decodeBinary(ctx, cursor, depth, p)
+ if err != nil {
+ return 0, err
+ }
+ if bytes == nil {
+ return c, nil
+ }
+ cursor = c
+ decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
+ b := make([]byte, decodedLen)
+ n, err := base64.StdEncoding.Decode(b, bytes)
+ if err != nil {
+ return 0, err
+ }
+ *(*[]byte)(p) = b[:n]
+ return cursor, nil
+}
+
+func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
+ c := s.skipWhiteSpace()
+ if c == '[' {
+ if d.sliceDecoder == nil {
+ return nil, &errors.UnmarshalTypeError{
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ }
+ err := d.sliceDecoder.DecodeStream(s, depth, p)
+ return nil, err
+ }
+ return d.stringDecoder.decodeStreamByte(s)
+}
+
+func (d *bytesDecoder) decodeBinary(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
+ buf := ctx.Buf
+ cursor = skipWhiteSpace(buf, cursor)
+ if buf[cursor] == '[' {
+ if d.sliceDecoder == nil {
+ return nil, 0, &errors.UnmarshalTypeError{
+ Type: runtime.RType2Type(d.typ),
+ Offset: cursor,
+ }
+ }
+ c, err := d.sliceDecoder.Decode(ctx, cursor, depth, p)
+ if err != nil {
+ return nil, 0, err
+ }
+ return nil, c, nil
+ }
+ return d.stringDecoder.decodeByte(buf, cursor)
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile.go b/vendor/github.com/goccy/go-json/internal/decoder/compile.go
new file mode 100644
index 000000000..08dd044e6
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/compile.go
@@ -0,0 +1,510 @@
+package decoder
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strings"
+ "sync/atomic"
+ "unicode"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+var (
+ jsonNumberType = reflect.TypeOf(json.Number(""))
+ typeAddr *runtime.TypeAddr
+ cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
+ cachedDecoder []Decoder
+)
+
+func init() {
+ typeAddr = runtime.AnalyzeTypeAddr()
+ if typeAddr == nil {
+ typeAddr = &runtime.TypeAddr{}
+ }
+ cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift)
+}
+
+func loadDecoderMap() map[uintptr]Decoder {
+ p := atomic.LoadPointer(&cachedDecoderMap)
+ return *(*map[uintptr]Decoder)(unsafe.Pointer(&p))
+}
+
+func storeDecoder(typ uintptr, dec Decoder, m map[uintptr]Decoder) {
+ newDecoderMap := make(map[uintptr]Decoder, len(m)+1)
+ newDecoderMap[typ] = dec
+
+ for k, v := range m {
+ newDecoderMap[k] = v
+ }
+
+ atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap)))
+}
+
+func compileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (Decoder, error) {
+ decoderMap := loadDecoderMap()
+ if dec, exists := decoderMap[typeptr]; exists {
+ return dec, nil
+ }
+
+ dec, err := compileHead(typ, map[uintptr]Decoder{})
+ if err != nil {
+ return nil, err
+ }
+ storeDecoder(typeptr, dec, decoderMap)
+ return dec, nil
+}
+
+func compileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ switch {
+ case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
+ return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil
+ case runtime.PtrTo(typ).Implements(unmarshalTextType):
+ return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil
+ }
+ return compile(typ.Elem(), "", "", structTypeToDecoder)
+}
+
+func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ switch {
+ case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
+ return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil
+ case runtime.PtrTo(typ).Implements(unmarshalTextType):
+ return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
+ }
+
+ switch typ.Kind() {
+ case reflect.Ptr:
+ return compilePtr(typ, structName, fieldName, structTypeToDecoder)
+ case reflect.Struct:
+ return compileStruct(typ, structName, fieldName, structTypeToDecoder)
+ case reflect.Slice:
+ elem := typ.Elem()
+ if elem.Kind() == reflect.Uint8 {
+ return compileBytes(elem, structName, fieldName)
+ }
+ return compileSlice(typ, structName, fieldName, structTypeToDecoder)
+ case reflect.Array:
+ return compileArray(typ, structName, fieldName, structTypeToDecoder)
+ case reflect.Map:
+ return compileMap(typ, structName, fieldName, structTypeToDecoder)
+ case reflect.Interface:
+ return compileInterface(typ, structName, fieldName)
+ case reflect.Uintptr:
+ return compileUint(typ, structName, fieldName)
+ case reflect.Int:
+ return compileInt(typ, structName, fieldName)
+ case reflect.Int8:
+ return compileInt8(typ, structName, fieldName)
+ case reflect.Int16:
+ return compileInt16(typ, structName, fieldName)
+ case reflect.Int32:
+ return compileInt32(typ, structName, fieldName)
+ case reflect.Int64:
+ return compileInt64(typ, structName, fieldName)
+ case reflect.Uint:
+ return compileUint(typ, structName, fieldName)
+ case reflect.Uint8:
+ return compileUint8(typ, structName, fieldName)
+ case reflect.Uint16:
+ return compileUint16(typ, structName, fieldName)
+ case reflect.Uint32:
+ return compileUint32(typ, structName, fieldName)
+ case reflect.Uint64:
+ return compileUint64(typ, structName, fieldName)
+ case reflect.String:
+ return compileString(typ, structName, fieldName)
+ case reflect.Bool:
+ return compileBool(structName, fieldName)
+ case reflect.Float32:
+ return compileFloat32(structName, fieldName)
+ case reflect.Float64:
+ return compileFloat64(structName, fieldName)
+ case reflect.Func:
+ return compileFunc(typ, structName, fieldName)
+ }
+ return nil, &errors.UnmarshalTypeError{
+ Value: "object",
+ Type: runtime.RType2Type(typ),
+ Offset: 0,
+ Struct: structName,
+ Field: fieldName,
+ }
+}
+
+func isStringTagSupportedType(typ *runtime.Type) bool {
+ switch {
+ case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
+ return false
+ case runtime.PtrTo(typ).Implements(unmarshalTextType):
+ return false
+ }
+ switch typ.Kind() {
+ case reflect.Map:
+ return false
+ case reflect.Slice:
+ return false
+ case reflect.Array:
+ return false
+ case reflect.Struct:
+ return false
+ case reflect.Interface:
+ return false
+ }
+ return true
+}
+
+func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ if runtime.PtrTo(typ).Implements(unmarshalTextType) {
+ return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
+ }
+ dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
+ if err != nil {
+ return nil, err
+ }
+ for {
+ switch t := dec.(type) {
+ case *stringDecoder, *interfaceDecoder:
+ return dec, nil
+ case *boolDecoder, *intDecoder, *uintDecoder, *numberDecoder:
+ return newWrappedStringDecoder(typ, dec, structName, fieldName), nil
+ case *ptrDecoder:
+ dec = t.dec
+ default:
+ goto ERROR
+ }
+ }
+ERROR:
+ return nil, &errors.UnmarshalTypeError{
+ Value: "object",
+ Type: runtime.RType2Type(typ),
+ Offset: 0,
+ Struct: structName,
+ Field: fieldName,
+ }
+}
+
+func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ dec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
+ if err != nil {
+ return nil, err
+ }
+ return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil
+}
+
+func compileInt(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
+ *(*int)(p) = int(v)
+ }), nil
+}
+
+func compileInt8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
+ *(*int8)(p) = int8(v)
+ }), nil
+}
+
+func compileInt16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
+ *(*int16)(p) = int16(v)
+ }), nil
+}
+
+func compileInt32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
+ *(*int32)(p) = int32(v)
+ }), nil
+}
+
+func compileInt64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
+ *(*int64)(p) = v
+ }), nil
+}
+
+func compileUint(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
+ *(*uint)(p) = uint(v)
+ }), nil
+}
+
+func compileUint8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
+ *(*uint8)(p) = uint8(v)
+ }), nil
+}
+
+func compileUint16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
+ *(*uint16)(p) = uint16(v)
+ }), nil
+}
+
+func compileUint32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
+ *(*uint32)(p) = uint32(v)
+ }), nil
+}
+
+func compileUint64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
+ *(*uint64)(p) = v
+ }), nil
+}
+
+func compileFloat32(structName, fieldName string) (Decoder, error) {
+ return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
+ *(*float32)(p) = float32(v)
+ }), nil
+}
+
+func compileFloat64(structName, fieldName string) (Decoder, error) {
+ return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
+ *(*float64)(p) = v
+ }), nil
+}
+
+func compileString(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ if typ == runtime.Type2RType(jsonNumberType) {
+ return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
+ *(*json.Number)(p) = v
+ }), nil
+ }
+ return newStringDecoder(structName, fieldName), nil
+}
+
+func compileBool(structName, fieldName string) (Decoder, error) {
+ return newBoolDecoder(structName, fieldName), nil
+}
+
+func compileBytes(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newBytesDecoder(typ, structName, fieldName), nil
+}
+
+func compileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ elem := typ.Elem()
+ decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
+ if err != nil {
+ return nil, err
+ }
+ return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
+}
+
+func compileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ elem := typ.Elem()
+ decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
+ if err != nil {
+ return nil, err
+ }
+ return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
+}
+
+func compileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ keyDec, err := compileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
+ if err != nil {
+ return nil, err
+ }
+ valueDec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
+ if err != nil {
+ return nil, err
+ }
+ return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil
+}
+
+func compileInterface(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
+ return newInterfaceDecoder(typ, structName, fieldName), nil
+}
+
+func compileFunc(typ *runtime.Type, strutName, fieldName string) (Decoder, error) {
+ return newFuncDecoder(typ, strutName, fieldName), nil
+}
+
+func removeConflictFields(fieldMap map[string]*structFieldSet, conflictedMap map[string]struct{}, dec *structDecoder, field reflect.StructField) {
+ for k, v := range dec.fieldMap {
+ if _, exists := conflictedMap[k]; exists {
+ // already conflicted key
+ continue
+ }
+ set, exists := fieldMap[k]
+ if !exists {
+ fieldSet := &structFieldSet{
+ dec: v.dec,
+ offset: field.Offset + v.offset,
+ isTaggedKey: v.isTaggedKey,
+ key: k,
+ keyLen: int64(len(k)),
+ }
+ fieldMap[k] = fieldSet
+ lower := strings.ToLower(k)
+ if _, exists := fieldMap[lower]; !exists {
+ fieldMap[lower] = fieldSet
+ }
+ continue
+ }
+ if set.isTaggedKey {
+ if v.isTaggedKey {
+ // conflict tag key
+ delete(fieldMap, k)
+ delete(fieldMap, strings.ToLower(k))
+ conflictedMap[k] = struct{}{}
+ conflictedMap[strings.ToLower(k)] = struct{}{}
+ }
+ } else {
+ if v.isTaggedKey {
+ fieldSet := &structFieldSet{
+ dec: v.dec,
+ offset: field.Offset + v.offset,
+ isTaggedKey: v.isTaggedKey,
+ key: k,
+ keyLen: int64(len(k)),
+ }
+ fieldMap[k] = fieldSet
+ lower := strings.ToLower(k)
+ if _, exists := fieldMap[lower]; !exists {
+ fieldMap[lower] = fieldSet
+ }
+ } else {
+ // conflict tag key
+ delete(fieldMap, k)
+ delete(fieldMap, strings.ToLower(k))
+ conflictedMap[k] = struct{}{}
+ conflictedMap[strings.ToLower(k)] = struct{}{}
+ }
+ }
+ }
+}
+
+func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
+ fieldNum := typ.NumField()
+ conflictedMap := map[string]struct{}{}
+ fieldMap := map[string]*structFieldSet{}
+ typeptr := uintptr(unsafe.Pointer(typ))
+ if dec, exists := structTypeToDecoder[typeptr]; exists {
+ return dec, nil
+ }
+ structDec := newStructDecoder(structName, fieldName, fieldMap)
+ structTypeToDecoder[typeptr] = structDec
+ structName = typ.Name()
+ for i := 0; i < fieldNum; i++ {
+ field := typ.Field(i)
+ if runtime.IsIgnoredStructField(field) {
+ continue
+ }
+ isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
+ tag := runtime.StructTagFromField(field)
+ dec, err := compile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder)
+ if err != nil {
+ return nil, err
+ }
+ if field.Anonymous && !tag.IsTaggedKey {
+ if stDec, ok := dec.(*structDecoder); ok {
+ if runtime.Type2RType(field.Type) == typ {
+ // recursive definition
+ continue
+ }
+ removeConflictFields(fieldMap, conflictedMap, stDec, field)
+ } else if pdec, ok := dec.(*ptrDecoder); ok {
+ contentDec := pdec.contentDecoder()
+ if pdec.typ == typ {
+ // recursive definition
+ continue
+ }
+ var fieldSetErr error
+ if isUnexportedField {
+ fieldSetErr = fmt.Errorf(
+ "json: cannot set embedded pointer to unexported struct: %v",
+ field.Type.Elem(),
+ )
+ }
+ if dec, ok := contentDec.(*structDecoder); ok {
+ for k, v := range dec.fieldMap {
+ if _, exists := conflictedMap[k]; exists {
+ // already conflicted key
+ continue
+ }
+ set, exists := fieldMap[k]
+ if !exists {
+ fieldSet := &structFieldSet{
+ dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
+ offset: field.Offset,
+ isTaggedKey: v.isTaggedKey,
+ key: k,
+ keyLen: int64(len(k)),
+ err: fieldSetErr,
+ }
+ fieldMap[k] = fieldSet
+ lower := strings.ToLower(k)
+ if _, exists := fieldMap[lower]; !exists {
+ fieldMap[lower] = fieldSet
+ }
+ continue
+ }
+ if set.isTaggedKey {
+ if v.isTaggedKey {
+ // conflict tag key
+ delete(fieldMap, k)
+ delete(fieldMap, strings.ToLower(k))
+ conflictedMap[k] = struct{}{}
+ conflictedMap[strings.ToLower(k)] = struct{}{}
+ }
+ } else {
+ if v.isTaggedKey {
+ fieldSet := &structFieldSet{
+ dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
+ offset: field.Offset,
+ isTaggedKey: v.isTaggedKey,
+ key: k,
+ keyLen: int64(len(k)),
+ err: fieldSetErr,
+ }
+ fieldMap[k] = fieldSet
+ lower := strings.ToLower(k)
+ if _, exists := fieldMap[lower]; !exists {
+ fieldMap[lower] = fieldSet
+ }
+ } else {
+ // conflict tag key
+ delete(fieldMap, k)
+ delete(fieldMap, strings.ToLower(k))
+ conflictedMap[k] = struct{}{}
+ conflictedMap[strings.ToLower(k)] = struct{}{}
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
+ dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name)
+ }
+ var key string
+ if tag.Key != "" {
+ key = tag.Key
+ } else {
+ key = field.Name
+ }
+ fieldSet := &structFieldSet{
+ dec: dec,
+ offset: field.Offset,
+ isTaggedKey: tag.IsTaggedKey,
+ key: key,
+ keyLen: int64(len(key)),
+ }
+ fieldMap[key] = fieldSet
+ lower := strings.ToLower(key)
+ if _, exists := fieldMap[lower]; !exists {
+ fieldMap[lower] = fieldSet
+ }
+ }
+ }
+ delete(structTypeToDecoder, typeptr)
+ structDec.tryOptimize()
+ return structDec, nil
+}
+
+func implementsUnmarshalJSONType(typ *runtime.Type) bool {
+ return typ.Implements(unmarshalJSONType) || typ.Implements(unmarshalJSONContextType)
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go b/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go
new file mode 100644
index 000000000..592f63737
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go
@@ -0,0 +1,28 @@
+// +build !race
+
+package decoder
+
+import (
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
+ typeptr := uintptr(unsafe.Pointer(typ))
+ if typeptr > typeAddr.MaxTypeAddr {
+ return compileToGetDecoderSlowPath(typeptr, typ)
+ }
+
+ index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
+ if dec := cachedDecoder[index]; dec != nil {
+ return dec, nil
+ }
+
+ dec, err := compileHead(typ, map[uintptr]Decoder{})
+ if err != nil {
+ return nil, err
+ }
+ cachedDecoder[index] = dec
+ return dec, nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go b/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go
new file mode 100644
index 000000000..b691bc947
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go
@@ -0,0 +1,36 @@
+// +build race
+
+package decoder
+
+import (
+ "sync"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+var decMu sync.RWMutex
+
+func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
+ typeptr := uintptr(unsafe.Pointer(typ))
+ if typeptr > typeAddr.MaxTypeAddr {
+ return compileToGetDecoderSlowPath(typeptr, typ)
+ }
+
+ index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
+ decMu.RLock()
+ if dec := cachedDecoder[index]; dec != nil {
+ decMu.RUnlock()
+ return dec, nil
+ }
+ decMu.RUnlock()
+
+ dec, err := compileHead(typ, map[uintptr]Decoder{})
+ if err != nil {
+ return nil, err
+ }
+ decMu.Lock()
+ cachedDecoder[index] = dec
+ decMu.Unlock()
+ return dec, nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/context.go b/vendor/github.com/goccy/go-json/internal/decoder/context.go
new file mode 100644
index 000000000..cb2ffdafd
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/context.go
@@ -0,0 +1,254 @@
+package decoder
+
+import (
+ "sync"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+)
+
+type RuntimeContext struct {
+ Buf []byte
+ Option *Option
+}
+
+var (
+ runtimeContextPool = sync.Pool{
+ New: func() interface{} {
+ return &RuntimeContext{
+ Option: &Option{},
+ }
+ },
+ }
+)
+
+func TakeRuntimeContext() *RuntimeContext {
+ return runtimeContextPool.Get().(*RuntimeContext)
+}
+
+func ReleaseRuntimeContext(ctx *RuntimeContext) {
+ runtimeContextPool.Put(ctx)
+}
+
+var (
+ isWhiteSpace = [256]bool{}
+)
+
+func init() {
+ isWhiteSpace[' '] = true
+ isWhiteSpace['\n'] = true
+ isWhiteSpace['\t'] = true
+ isWhiteSpace['\r'] = true
+}
+
+func char(ptr unsafe.Pointer, offset int64) byte {
+ return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset)))
+}
+
+func skipWhiteSpace(buf []byte, cursor int64) int64 {
+ for isWhiteSpace[buf[cursor]] {
+ cursor++
+ }
+ return cursor
+}
+
+func skipObject(buf []byte, cursor, depth int64) (int64, error) {
+ braceCount := 1
+ for {
+ switch buf[cursor] {
+ case '{':
+ braceCount++
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+ case '}':
+ depth--
+ braceCount--
+ if braceCount == 0 {
+ return cursor + 1, nil
+ }
+ case '[':
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+ case ']':
+ depth--
+ case '"':
+ for {
+ cursor++
+ switch buf[cursor] {
+ case '\\':
+ cursor++
+ if buf[cursor] == nul {
+ return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ case '"':
+ goto SWITCH_OUT
+ case nul:
+ return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ }
+ case nul:
+ return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
+ }
+ SWITCH_OUT:
+ cursor++
+ }
+}
+
+func skipArray(buf []byte, cursor, depth int64) (int64, error) {
+ bracketCount := 1
+ for {
+ switch buf[cursor] {
+ case '[':
+ bracketCount++
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+ case ']':
+ bracketCount--
+ depth--
+ if bracketCount == 0 {
+ return cursor + 1, nil
+ }
+ case '{':
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+ case '}':
+ depth--
+ case '"':
+ for {
+ cursor++
+ switch buf[cursor] {
+ case '\\':
+ cursor++
+ if buf[cursor] == nul {
+ return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ case '"':
+ goto SWITCH_OUT
+ case nul:
+ return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ }
+ case nul:
+ return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
+ }
+ SWITCH_OUT:
+ cursor++
+ }
+}
+
+func skipValue(buf []byte, cursor, depth int64) (int64, error) {
+ for {
+ switch buf[cursor] {
+ case ' ', '\t', '\n', '\r':
+ cursor++
+ continue
+ case '{':
+ return skipObject(buf, cursor+1, depth+1)
+ case '[':
+ return skipArray(buf, cursor+1, depth+1)
+ case '"':
+ for {
+ cursor++
+ switch buf[cursor] {
+ case '\\':
+ cursor++
+ if buf[cursor] == nul {
+ return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ case '"':
+ return cursor + 1, nil
+ case nul:
+ return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ for {
+ cursor++
+ if floatTable[buf[cursor]] {
+ continue
+ }
+ break
+ }
+ return cursor, nil
+ case 't':
+ if err := validateTrue(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ return cursor, nil
+ case 'f':
+ if err := validateFalse(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 5
+ return cursor, nil
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ return cursor, nil
+ default:
+ return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
+ }
+ }
+}
+
+func validateTrue(buf []byte, cursor int64) error {
+ if cursor+3 >= int64(len(buf)) {
+ return errors.ErrUnexpectedEndOfJSON("true", cursor)
+ }
+ if buf[cursor+1] != 'r' {
+ return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor)
+ }
+ if buf[cursor+2] != 'u' {
+ return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
+ }
+ if buf[cursor+3] != 'e' {
+ return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
+ }
+ return nil
+}
+
+func validateFalse(buf []byte, cursor int64) error {
+ if cursor+4 >= int64(len(buf)) {
+ return errors.ErrUnexpectedEndOfJSON("false", cursor)
+ }
+ if buf[cursor+1] != 'a' {
+ return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor)
+ }
+ if buf[cursor+2] != 'l' {
+ return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
+ }
+ if buf[cursor+3] != 's' {
+ return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor)
+ }
+ if buf[cursor+4] != 'e' {
+ return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
+ }
+ return nil
+}
+
+func validateNull(buf []byte, cursor int64) error {
+ if cursor+3 >= int64(len(buf)) {
+ return errors.ErrUnexpectedEndOfJSON("null", cursor)
+ }
+ if buf[cursor+1] != 'u' {
+ return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor)
+ }
+ if buf[cursor+2] != 'l' {
+ return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
+ }
+ if buf[cursor+3] != 'l' {
+ return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
+ }
+ return nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/float.go b/vendor/github.com/goccy/go-json/internal/decoder/float.go
new file mode 100644
index 000000000..dfb7168da
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/float.go
@@ -0,0 +1,158 @@
+package decoder
+
+import (
+ "strconv"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+)
+
+type floatDecoder struct {
+ op func(unsafe.Pointer, float64)
+ structName string
+ fieldName string
+}
+
+func newFloatDecoder(structName, fieldName string, op func(unsafe.Pointer, float64)) *floatDecoder {
+ return &floatDecoder{op: op, structName: structName, fieldName: fieldName}
+}
+
+var (
+ floatTable = [256]bool{
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ '.': true,
+ 'e': true,
+ 'E': true,
+ '+': true,
+ '-': true,
+ }
+
+ validEndNumberChar = [256]bool{
+ nul: true,
+ ' ': true,
+ '\t': true,
+ '\r': true,
+ '\n': true,
+ ',': true,
+ ':': true,
+ '}': true,
+ ']': true,
+ }
+)
+
+func floatBytes(s *Stream) []byte {
+ start := s.cursor
+ for {
+ s.cursor++
+ if floatTable[s.char()] {
+ continue
+ } else if s.char() == nul {
+ if s.read() {
+ s.cursor-- // for retry current character
+ continue
+ }
+ }
+ break
+ }
+ return s.buf[start:s.cursor]
+}
+
+func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
+ for {
+ switch s.char() {
+ case ' ', '\n', '\t', '\r':
+ s.cursor++
+ continue
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return floatBytes(s), nil
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case nul:
+ if s.read() {
+ continue
+ }
+ goto ERROR
+ default:
+ goto ERROR
+ }
+ }
+ERROR:
+ return nil, errors.ErrUnexpectedEndOfJSON("float", s.totalOffset())
+}
+
+func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
+ for {
+ switch buf[cursor] {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ continue
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ start := cursor
+ cursor++
+ for floatTable[buf[cursor]] {
+ cursor++
+ }
+ num := buf[start:cursor]
+ return num, cursor, nil
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return nil, 0, err
+ }
+ cursor += 4
+ return nil, cursor, nil
+ default:
+ return nil, 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
+ }
+ }
+}
+
+func (d *floatDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ bytes, err := d.decodeStreamByte(s)
+ if err != nil {
+ return err
+ }
+ if bytes == nil {
+ return nil
+ }
+ str := *(*string)(unsafe.Pointer(&bytes))
+ f64, err := strconv.ParseFloat(str, 64)
+ if err != nil {
+ return errors.ErrSyntax(err.Error(), s.totalOffset())
+ }
+ d.op(p, f64)
+ return nil
+}
+
+func (d *floatDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ bytes, c, err := d.decodeByte(buf, cursor)
+ if err != nil {
+ return 0, err
+ }
+ if bytes == nil {
+ return c, nil
+ }
+ cursor = c
+ if !validEndNumberChar[buf[cursor]] {
+ return 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
+ }
+ s := *(*string)(unsafe.Pointer(&bytes))
+ f64, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return 0, errors.ErrSyntax(err.Error(), cursor)
+ }
+ d.op(p, f64)
+ return cursor, nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/func.go b/vendor/github.com/goccy/go-json/internal/decoder/func.go
new file mode 100644
index 000000000..ee3563711
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/func.go
@@ -0,0 +1,141 @@
+package decoder
+
+import (
+ "bytes"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type funcDecoder struct {
+ typ *runtime.Type
+ structName string
+ fieldName string
+}
+
+func newFuncDecoder(typ *runtime.Type, structName, fieldName string) *funcDecoder {
+ fnDecoder := &funcDecoder{typ, structName, fieldName}
+ return fnDecoder
+}
+
+func (d *funcDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ s.skipWhiteSpace()
+ start := s.cursor
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ src := s.buf[start:s.cursor]
+ if len(src) > 0 {
+ switch src[0] {
+ case '"':
+ return &errors.UnmarshalTypeError{
+ Value: "string",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ case '[':
+ return &errors.UnmarshalTypeError{
+ Value: "array",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ case '{':
+ return &errors.UnmarshalTypeError{
+ Value: "object",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return &errors.UnmarshalTypeError{
+ Value: "number",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ *(*unsafe.Pointer)(p) = nil
+ return nil
+ case 't':
+ if err := trueBytes(s); err == nil {
+ return &errors.UnmarshalTypeError{
+ Value: "boolean",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ }
+ case 'f':
+ if err := falseBytes(s); err == nil {
+ return &errors.UnmarshalTypeError{
+ Value: "boolean",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ }
+ }
+ }
+ return errors.ErrInvalidBeginningOfValue(s.buf[s.cursor], s.totalOffset())
+}
+
+func (d *funcDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ cursor = skipWhiteSpace(buf, cursor)
+ start := cursor
+ end, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ src := buf[start:end]
+ if len(src) > 0 {
+ switch src[0] {
+ case '"':
+ return 0, &errors.UnmarshalTypeError{
+ Value: "string",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ case '[':
+ return 0, &errors.UnmarshalTypeError{
+ Value: "array",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ case '{':
+ return 0, &errors.UnmarshalTypeError{
+ Value: "object",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return 0, &errors.UnmarshalTypeError{
+ Value: "number",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ case 'n':
+ if bytes.Equal(src, nullbytes) {
+ *(*unsafe.Pointer)(p) = nil
+ return end, nil
+ }
+ case 't':
+ if err := validateTrue(buf, start); err == nil {
+ return 0, &errors.UnmarshalTypeError{
+ Value: "boolean",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ }
+ case 'f':
+ if err := validateFalse(buf, start); err == nil {
+ return 0, &errors.UnmarshalTypeError{
+ Value: "boolean",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ }
+ }
+ }
+ return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/int.go b/vendor/github.com/goccy/go-json/internal/decoder/int.go
new file mode 100644
index 000000000..7edfb0411
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/int.go
@@ -0,0 +1,242 @@
+package decoder
+
+import (
+ "fmt"
+ "reflect"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type intDecoder struct {
+ typ *runtime.Type
+ kind reflect.Kind
+ op func(unsafe.Pointer, int64)
+ structName string
+ fieldName string
+}
+
+func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
+ return &intDecoder{
+ typ: typ,
+ kind: typ.Kind(),
+ op: op,
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
+ return &errors.UnmarshalTypeError{
+ Value: fmt.Sprintf("number %s", string(buf)),
+ Type: runtime.RType2Type(d.typ),
+ Struct: d.structName,
+ Field: d.fieldName,
+ Offset: offset,
+ }
+}
+
+var (
+ pow10i64 = [...]int64{
+ 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18,
+ }
+ pow10i64Len = len(pow10i64)
+)
+
+func (d *intDecoder) parseInt(b []byte) (int64, error) {
+ isNegative := false
+ if b[0] == '-' {
+ b = b[1:]
+ isNegative = true
+ }
+ maxDigit := len(b)
+ if maxDigit > pow10i64Len {
+ return 0, fmt.Errorf("invalid length of number")
+ }
+ sum := int64(0)
+ for i := 0; i < maxDigit; i++ {
+ c := int64(b[i]) - 48
+ digitValue := pow10i64[maxDigit-i-1]
+ sum += c * digitValue
+ }
+ if isNegative {
+ return -1 * sum, nil
+ }
+ return sum, nil
+}
+
+var (
+ numTable = [256]bool{
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ }
+)
+
+var (
+ numZeroBuf = []byte{'0'}
+)
+
+func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
+ for {
+ switch s.char() {
+ case ' ', '\n', '\t', '\r':
+ s.cursor++
+ continue
+ case '-':
+ start := s.cursor
+ for {
+ s.cursor++
+ if numTable[s.char()] {
+ continue
+ } else if s.char() == nul {
+ if s.read() {
+ s.cursor-- // for retry current character
+ continue
+ }
+ }
+ break
+ }
+ num := s.buf[start:s.cursor]
+ if len(num) < 2 {
+ goto ERROR
+ }
+ return num, nil
+ case '0':
+ s.cursor++
+ return numZeroBuf, nil
+ case '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ start := s.cursor
+ for {
+ s.cursor++
+ if numTable[s.char()] {
+ continue
+ } else if s.char() == nul {
+ if s.read() {
+ s.cursor-- // for retry current character
+ continue
+ }
+ }
+ break
+ }
+ num := s.buf[start:s.cursor]
+ return num, nil
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case nul:
+ if s.read() {
+ continue
+ }
+ goto ERROR
+ default:
+ return nil, d.typeError([]byte{s.char()}, s.totalOffset())
+ }
+ }
+ERROR:
+ return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset())
+}
+
+func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
+ b := (*sliceHeader)(unsafe.Pointer(&buf)).data
+ for {
+ switch char(b, cursor) {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ continue
+ case '0':
+ cursor++
+ return numZeroBuf, cursor, nil
+ case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ start := cursor
+ cursor++
+ for numTable[char(b, cursor)] {
+ cursor++
+ }
+ num := buf[start:cursor]
+ return num, cursor, nil
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return nil, 0, err
+ }
+ cursor += 4
+ return nil, cursor, nil
+ default:
+ return nil, 0, d.typeError([]byte{char(b, cursor)}, cursor)
+ }
+ }
+}
+
+func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ bytes, err := d.decodeStreamByte(s)
+ if err != nil {
+ return err
+ }
+ if bytes == nil {
+ return nil
+ }
+ i64, err := d.parseInt(bytes)
+ if err != nil {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ switch d.kind {
+ case reflect.Int8:
+ if i64 <= -1*(1<<7) || (1<<7) <= i64 {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ case reflect.Int16:
+ if i64 <= -1*(1<<15) || (1<<15) <= i64 {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ case reflect.Int32:
+ if i64 <= -1*(1<<31) || (1<<31) <= i64 {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ }
+ d.op(p, i64)
+ s.reset()
+ return nil
+}
+
+func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ bytes, c, err := d.decodeByte(ctx.Buf, cursor)
+ if err != nil {
+ return 0, err
+ }
+ if bytes == nil {
+ return c, nil
+ }
+ cursor = c
+
+ i64, err := d.parseInt(bytes)
+ if err != nil {
+ return 0, d.typeError(bytes, cursor)
+ }
+ switch d.kind {
+ case reflect.Int8:
+ if i64 <= -1*(1<<7) || (1<<7) <= i64 {
+ return 0, d.typeError(bytes, cursor)
+ }
+ case reflect.Int16:
+ if i64 <= -1*(1<<15) || (1<<15) <= i64 {
+ return 0, d.typeError(bytes, cursor)
+ }
+ case reflect.Int32:
+ if i64 <= -1*(1<<31) || (1<<31) <= i64 {
+ return 0, d.typeError(bytes, cursor)
+ }
+ }
+ d.op(p, i64)
+ return cursor, nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/interface.go b/vendor/github.com/goccy/go-json/internal/decoder/interface.go
new file mode 100644
index 000000000..4dbb4be4a
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/interface.go
@@ -0,0 +1,458 @@
+package decoder
+
+import (
+ "bytes"
+ "encoding"
+ "encoding/json"
+ "reflect"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type interfaceDecoder struct {
+ typ *runtime.Type
+ structName string
+ fieldName string
+ sliceDecoder *sliceDecoder
+ mapDecoder *mapDecoder
+ floatDecoder *floatDecoder
+ numberDecoder *numberDecoder
+ stringDecoder *stringDecoder
+}
+
+func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
+ ifaceDecoder := &interfaceDecoder{
+ typ: emptyInterfaceType,
+ structName: structName,
+ fieldName: fieldName,
+ floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
+ *(*interface{})(p) = v
+ }),
+ numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
+ *(*interface{})(p) = v
+ }),
+ stringDecoder: newStringDecoder(structName, fieldName),
+ }
+ ifaceDecoder.sliceDecoder = newSliceDecoder(
+ ifaceDecoder,
+ emptyInterfaceType,
+ emptyInterfaceType.Size(),
+ structName, fieldName,
+ )
+ ifaceDecoder.mapDecoder = newMapDecoder(
+ interfaceMapType,
+ stringType,
+ ifaceDecoder.stringDecoder,
+ interfaceMapType.Elem(),
+ ifaceDecoder,
+ structName,
+ fieldName,
+ )
+ return ifaceDecoder
+}
+
+func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
+ emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
+ stringDecoder := newStringDecoder(structName, fieldName)
+ return &interfaceDecoder{
+ typ: typ,
+ structName: structName,
+ fieldName: fieldName,
+ sliceDecoder: newSliceDecoder(
+ emptyIfaceDecoder,
+ emptyInterfaceType,
+ emptyInterfaceType.Size(),
+ structName, fieldName,
+ ),
+ mapDecoder: newMapDecoder(
+ interfaceMapType,
+ stringType,
+ stringDecoder,
+ interfaceMapType.Elem(),
+ emptyIfaceDecoder,
+ structName,
+ fieldName,
+ ),
+ floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
+ *(*interface{})(p) = v
+ }),
+ numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
+ *(*interface{})(p) = v
+ }),
+ stringDecoder: stringDecoder,
+ }
+}
+
+func (d *interfaceDecoder) numDecoder(s *Stream) Decoder {
+ if s.UseNumber {
+ return d.numberDecoder
+ }
+ return d.floatDecoder
+}
+
+var (
+ emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
+ interfaceMapType = runtime.Type2RType(
+ reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
+ )
+ stringType = runtime.Type2RType(
+ reflect.TypeOf(""),
+ )
+)
+
+func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
+ start := s.cursor
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ src := s.buf[start:s.cursor]
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ if err := unmarshaler.UnmarshalJSON(dst); err != nil {
+ return err
+ }
+ return nil
+}
+
+func decodeStreamUnmarshalerContext(s *Stream, depth int64, unmarshaler unmarshalerContext) error {
+ start := s.cursor
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ src := s.buf[start:s.cursor]
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ if err := unmarshaler.UnmarshalJSON(s.Option.Context, dst); err != nil {
+ return err
+ }
+ return nil
+}
+
+func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) {
+ cursor = skipWhiteSpace(buf, cursor)
+ start := cursor
+ end, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ src := buf[start:end]
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ if err := unmarshaler.UnmarshalJSON(dst); err != nil {
+ return 0, err
+ }
+ return end, nil
+}
+
+func decodeUnmarshalerContext(ctx *RuntimeContext, buf []byte, cursor, depth int64, unmarshaler unmarshalerContext) (int64, error) {
+ cursor = skipWhiteSpace(buf, cursor)
+ start := cursor
+ end, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ src := buf[start:end]
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ if err := unmarshaler.UnmarshalJSON(ctx.Option.Context, dst); err != nil {
+ return 0, err
+ }
+ return end, nil
+}
+
+func decodeStreamTextUnmarshaler(s *Stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error {
+ start := s.cursor
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ src := s.buf[start:s.cursor]
+ if bytes.Equal(src, nullbytes) {
+ *(*unsafe.Pointer)(p) = nil
+ return nil
+ }
+
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ if err := unmarshaler.UnmarshalText(dst); err != nil {
+ return err
+ }
+ return nil
+}
+
+func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) (int64, error) {
+ cursor = skipWhiteSpace(buf, cursor)
+ start := cursor
+ end, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ src := buf[start:end]
+ if bytes.Equal(src, nullbytes) {
+ *(*unsafe.Pointer)(p) = nil
+ return end, nil
+ }
+ if s, ok := unquoteBytes(src); ok {
+ src = s
+ }
+ if err := unmarshaler.UnmarshalText(src); err != nil {
+ return 0, err
+ }
+ return end, nil
+}
+
+func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error {
+ c := s.skipWhiteSpace()
+ for {
+ switch c {
+ case '{':
+ var v map[string]interface{}
+ ptr := unsafe.Pointer(&v)
+ if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil {
+ return err
+ }
+ *(*interface{})(p) = v
+ return nil
+ case '[':
+ var v []interface{}
+ ptr := unsafe.Pointer(&v)
+ if err := d.sliceDecoder.DecodeStream(s, depth, ptr); err != nil {
+ return err
+ }
+ *(*interface{})(p) = v
+ return nil
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return d.numDecoder(s).DecodeStream(s, depth, p)
+ case '"':
+ s.cursor++
+ start := s.cursor
+ for {
+ switch s.char() {
+ case '\\':
+ if _, err := decodeEscapeString(s, nil); err != nil {
+ return err
+ }
+ case '"':
+ literal := s.buf[start:s.cursor]
+ s.cursor++
+ *(*interface{})(p) = string(literal)
+ return nil
+ case nul:
+ if s.read() {
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ }
+ s.cursor++
+ }
+ case 't':
+ if err := trueBytes(s); err != nil {
+ return err
+ }
+ **(**interface{})(unsafe.Pointer(&p)) = true
+ return nil
+ case 'f':
+ if err := falseBytes(s); err != nil {
+ return err
+ }
+ **(**interface{})(unsafe.Pointer(&p)) = false
+ return nil
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ *(*interface{})(p) = nil
+ return nil
+ case nul:
+ if s.read() {
+ c = s.char()
+ continue
+ }
+ }
+ break
+ }
+ return errors.ErrInvalidBeginningOfValue(c, s.totalOffset())
+}
+
+type emptyInterface struct {
+ typ *runtime.Type
+ ptr unsafe.Pointer
+}
+
+func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
+ typ: d.typ,
+ ptr: p,
+ }))
+ rv := reflect.ValueOf(runtimeInterfaceValue)
+ if rv.NumMethod() > 0 && rv.CanInterface() {
+ if u, ok := rv.Interface().(unmarshalerContext); ok {
+ return decodeStreamUnmarshalerContext(s, depth, u)
+ }
+ if u, ok := rv.Interface().(json.Unmarshaler); ok {
+ return decodeStreamUnmarshaler(s, depth, u)
+ }
+ if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
+ return decodeStreamTextUnmarshaler(s, depth, u, p)
+ }
+ if s.skipWhiteSpace() == 'n' {
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ *(*interface{})(p) = nil
+ return nil
+ }
+ return d.errUnmarshalType(rv.Type(), s.totalOffset())
+ }
+ iface := rv.Interface()
+ ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
+ typ := ifaceHeader.typ
+ if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
+ // concrete type is empty interface
+ return d.decodeStreamEmptyInterface(s, depth, p)
+ }
+ if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
+ return d.decodeStreamEmptyInterface(s, depth, p)
+ }
+ if s.skipWhiteSpace() == 'n' {
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ *(*interface{})(p) = nil
+ return nil
+ }
+ decoder, err := CompileToGetDecoder(typ)
+ if err != nil {
+ return err
+ }
+ return decoder.DecodeStream(s, depth, ifaceHeader.ptr)
+}
+
+func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
+ return &errors.UnmarshalTypeError{
+ Value: typ.String(),
+ Type: typ,
+ Offset: offset,
+ Struct: d.structName,
+ Field: d.fieldName,
+ }
+}
+
+func (d *interfaceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
+ typ: d.typ,
+ ptr: p,
+ }))
+ rv := reflect.ValueOf(runtimeInterfaceValue)
+ if rv.NumMethod() > 0 && rv.CanInterface() {
+ if u, ok := rv.Interface().(unmarshalerContext); ok {
+ return decodeUnmarshalerContext(ctx, buf, cursor, depth, u)
+ }
+ if u, ok := rv.Interface().(json.Unmarshaler); ok {
+ return decodeUnmarshaler(buf, cursor, depth, u)
+ }
+ if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
+ return decodeTextUnmarshaler(buf, cursor, depth, u, p)
+ }
+ cursor = skipWhiteSpace(buf, cursor)
+ if buf[cursor] == 'n' {
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ **(**interface{})(unsafe.Pointer(&p)) = nil
+ return cursor, nil
+ }
+ return 0, d.errUnmarshalType(rv.Type(), cursor)
+ }
+
+ iface := rv.Interface()
+ ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
+ typ := ifaceHeader.typ
+ if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
+ // concrete type is empty interface
+ return d.decodeEmptyInterface(ctx, cursor, depth, p)
+ }
+ if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
+ return d.decodeEmptyInterface(ctx, cursor, depth, p)
+ }
+ cursor = skipWhiteSpace(buf, cursor)
+ if buf[cursor] == 'n' {
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ **(**interface{})(unsafe.Pointer(&p)) = nil
+ return cursor, nil
+ }
+ decoder, err := CompileToGetDecoder(typ)
+ if err != nil {
+ return 0, err
+ }
+ return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr)
+}
+
+func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ cursor = skipWhiteSpace(buf, cursor)
+ switch buf[cursor] {
+ case '{':
+ var v map[string]interface{}
+ ptr := unsafe.Pointer(&v)
+ cursor, err := d.mapDecoder.Decode(ctx, cursor, depth, ptr)
+ if err != nil {
+ return 0, err
+ }
+ **(**interface{})(unsafe.Pointer(&p)) = v
+ return cursor, nil
+ case '[':
+ var v []interface{}
+ ptr := unsafe.Pointer(&v)
+ cursor, err := d.sliceDecoder.Decode(ctx, cursor, depth, ptr)
+ if err != nil {
+ return 0, err
+ }
+ **(**interface{})(unsafe.Pointer(&p)) = v
+ return cursor, nil
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return d.floatDecoder.Decode(ctx, cursor, depth, p)
+ case '"':
+ var v string
+ ptr := unsafe.Pointer(&v)
+ cursor, err := d.stringDecoder.Decode(ctx, cursor, depth, ptr)
+ if err != nil {
+ return 0, err
+ }
+ **(**interface{})(unsafe.Pointer(&p)) = v
+ return cursor, nil
+ case 't':
+ if err := validateTrue(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ **(**interface{})(unsafe.Pointer(&p)) = true
+ return cursor, nil
+ case 'f':
+ if err := validateFalse(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 5
+ **(**interface{})(unsafe.Pointer(&p)) = false
+ return cursor, nil
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ **(**interface{})(unsafe.Pointer(&p)) = nil
+ return cursor, nil
+ }
+ return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/map.go b/vendor/github.com/goccy/go-json/internal/decoder/map.go
new file mode 100644
index 000000000..bb18ef995
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/map.go
@@ -0,0 +1,186 @@
+package decoder
+
+import (
+ "reflect"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type mapDecoder struct {
+ mapType *runtime.Type
+ keyType *runtime.Type
+ valueType *runtime.Type
+ canUseAssignFaststrType bool
+ keyDecoder Decoder
+ valueDecoder Decoder
+ structName string
+ fieldName string
+}
+
+func newMapDecoder(mapType *runtime.Type, keyType *runtime.Type, keyDec Decoder, valueType *runtime.Type, valueDec Decoder, structName, fieldName string) *mapDecoder {
+ return &mapDecoder{
+ mapType: mapType,
+ keyDecoder: keyDec,
+ keyType: keyType,
+ canUseAssignFaststrType: canUseAssignFaststrType(keyType, valueType),
+ valueType: valueType,
+ valueDecoder: valueDec,
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+const (
+ mapMaxElemSize = 128
+)
+
+// See detail: https://github.com/goccy/go-json/pull/283
+func canUseAssignFaststrType(key *runtime.Type, value *runtime.Type) bool {
+ indirectElem := value.Size() > mapMaxElemSize
+ if indirectElem {
+ return false
+ }
+ return key.Kind() == reflect.String
+}
+
+//go:linkname makemap reflect.makemap
+func makemap(*runtime.Type, int) unsafe.Pointer
+
+//nolint:golint
+//go:linkname mapassign_faststr runtime.mapassign_faststr
+//go:noescape
+func mapassign_faststr(t *runtime.Type, m unsafe.Pointer, s string) unsafe.Pointer
+
+//go:linkname mapassign reflect.mapassign
+//go:noescape
+func mapassign(t *runtime.Type, m unsafe.Pointer, k, v unsafe.Pointer)
+
+func (d *mapDecoder) mapassign(t *runtime.Type, m, k, v unsafe.Pointer) {
+ if d.canUseAssignFaststrType {
+ mapV := mapassign_faststr(t, m, *(*string)(k))
+ typedmemmove(d.valueType, mapV, v)
+ } else {
+ mapassign(t, m, k, v)
+ }
+}
+
+func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+
+ switch s.skipWhiteSpace() {
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ **(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil
+ return nil
+ case '{':
+ default:
+ return errors.ErrExpected("{ character for map value", s.totalOffset())
+ }
+ mapValue := *(*unsafe.Pointer)(p)
+ if mapValue == nil {
+ mapValue = makemap(d.mapType, 0)
+ }
+ if s.buf[s.cursor+1] == '}' {
+ *(*unsafe.Pointer)(p) = mapValue
+ s.cursor += 2
+ return nil
+ }
+ for {
+ s.cursor++
+ k := unsafe_New(d.keyType)
+ if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil {
+ return err
+ }
+ s.skipWhiteSpace()
+ if !s.equalChar(':') {
+ return errors.ErrExpected("colon after object key", s.totalOffset())
+ }
+ s.cursor++
+ v := unsafe_New(d.valueType)
+ if err := d.valueDecoder.DecodeStream(s, depth, v); err != nil {
+ return err
+ }
+ d.mapassign(d.mapType, mapValue, k, v)
+ s.skipWhiteSpace()
+ if s.equalChar('}') {
+ **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
+ s.cursor++
+ return nil
+ }
+ if !s.equalChar(',') {
+ return errors.ErrExpected("comma after object value", s.totalOffset())
+ }
+ }
+}
+
+func (d *mapDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+
+ cursor = skipWhiteSpace(buf, cursor)
+ buflen := int64(len(buf))
+ if buflen < 2 {
+ return 0, errors.ErrExpected("{} for map", cursor)
+ }
+ switch buf[cursor] {
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ **(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil
+ return cursor, nil
+ case '{':
+ default:
+ return 0, errors.ErrExpected("{ character for map value", cursor)
+ }
+ cursor++
+ cursor = skipWhiteSpace(buf, cursor)
+ mapValue := *(*unsafe.Pointer)(p)
+ if mapValue == nil {
+ mapValue = makemap(d.mapType, 0)
+ }
+ if buf[cursor] == '}' {
+ **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
+ cursor++
+ return cursor, nil
+ }
+ for {
+ k := unsafe_New(d.keyType)
+ keyCursor, err := d.keyDecoder.Decode(ctx, cursor, depth, k)
+ if err != nil {
+ return 0, err
+ }
+ cursor = skipWhiteSpace(buf, keyCursor)
+ if buf[cursor] != ':' {
+ return 0, errors.ErrExpected("colon after object key", cursor)
+ }
+ cursor++
+ v := unsafe_New(d.valueType)
+ valueCursor, err := d.valueDecoder.Decode(ctx, cursor, depth, v)
+ if err != nil {
+ return 0, err
+ }
+ d.mapassign(d.mapType, mapValue, k, v)
+ cursor = skipWhiteSpace(buf, valueCursor)
+ if buf[cursor] == '}' {
+ **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
+ cursor++
+ return cursor, nil
+ }
+ if buf[cursor] != ',' {
+ return 0, errors.ErrExpected("comma after object value", cursor)
+ }
+ cursor++
+ }
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/number.go b/vendor/github.com/goccy/go-json/internal/decoder/number.go
new file mode 100644
index 000000000..bf63773e3
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/number.go
@@ -0,0 +1,112 @@
+package decoder
+
+import (
+ "encoding/json"
+ "strconv"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+)
+
+type numberDecoder struct {
+ stringDecoder *stringDecoder
+ op func(unsafe.Pointer, json.Number)
+ structName string
+ fieldName string
+}
+
+func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder {
+ return &numberDecoder{
+ stringDecoder: newStringDecoder(structName, fieldName),
+ op: op,
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ bytes, err := d.decodeStreamByte(s)
+ if err != nil {
+ return err
+ }
+ if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
+ return errors.ErrSyntax(err.Error(), s.totalOffset())
+ }
+ d.op(p, json.Number(string(bytes)))
+ s.reset()
+ return nil
+}
+
+func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ bytes, c, err := d.decodeByte(ctx.Buf, cursor)
+ if err != nil {
+ return 0, err
+ }
+ if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
+ return 0, errors.ErrSyntax(err.Error(), c)
+ }
+ cursor = c
+ s := *(*string)(unsafe.Pointer(&bytes))
+ d.op(p, json.Number(s))
+ return cursor, nil
+}
+
+func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
+ start := s.cursor
+ for {
+ switch s.char() {
+ case ' ', '\n', '\t', '\r':
+ s.cursor++
+ continue
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return floatBytes(s), nil
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case '"':
+ return d.stringDecoder.decodeStreamByte(s)
+ case nul:
+ if s.read() {
+ continue
+ }
+ goto ERROR
+ default:
+ goto ERROR
+ }
+ }
+ERROR:
+ if s.cursor == start {
+ return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
+ }
+ return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset())
+}
+
+func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
+ for {
+ switch buf[cursor] {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ continue
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ start := cursor
+ cursor++
+ for floatTable[buf[cursor]] {
+ cursor++
+ }
+ num := buf[start:cursor]
+ return num, cursor, nil
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return nil, 0, err
+ }
+ cursor += 4
+ return nil, cursor, nil
+ case '"':
+ return d.stringDecoder.decodeByte(buf, cursor)
+ default:
+ return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor)
+ }
+ }
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/option.go b/vendor/github.com/goccy/go-json/internal/decoder/option.go
new file mode 100644
index 000000000..e41f876b0
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/option.go
@@ -0,0 +1,15 @@
+package decoder
+
+import "context"
+
+type OptionFlags uint8
+
+const (
+ FirstWinOption OptionFlags = 1 << iota
+ ContextOption
+)
+
+type Option struct {
+ Flags OptionFlags
+ Context context.Context
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/ptr.go b/vendor/github.com/goccy/go-json/internal/decoder/ptr.go
new file mode 100644
index 000000000..2c83b9c44
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/ptr.go
@@ -0,0 +1,87 @@
+package decoder
+
+import (
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type ptrDecoder struct {
+ dec Decoder
+ typ *runtime.Type
+ structName string
+ fieldName string
+}
+
+func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder {
+ return &ptrDecoder{
+ dec: dec,
+ typ: typ,
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *ptrDecoder) contentDecoder() Decoder {
+ dec, ok := d.dec.(*ptrDecoder)
+ if !ok {
+ return d.dec
+ }
+ return dec.contentDecoder()
+}
+
+//nolint:golint
+//go:linkname unsafe_New reflect.unsafe_New
+func unsafe_New(*runtime.Type) unsafe.Pointer
+
+func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ if s.skipWhiteSpace() == nul {
+ s.read()
+ }
+ if s.char() == 'n' {
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ *(*unsafe.Pointer)(p) = nil
+ return nil
+ }
+ var newptr unsafe.Pointer
+ if *(*unsafe.Pointer)(p) == nil {
+ newptr = unsafe_New(d.typ)
+ *(*unsafe.Pointer)(p) = newptr
+ } else {
+ newptr = *(*unsafe.Pointer)(p)
+ }
+ if err := d.dec.DecodeStream(s, depth, newptr); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ cursor = skipWhiteSpace(buf, cursor)
+ if buf[cursor] == 'n' {
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ if p != nil {
+ *(*unsafe.Pointer)(p) = nil
+ }
+ cursor += 4
+ return cursor, nil
+ }
+ var newptr unsafe.Pointer
+ if *(*unsafe.Pointer)(p) == nil {
+ newptr = unsafe_New(d.typ)
+ *(*unsafe.Pointer)(p) = newptr
+ } else {
+ newptr = *(*unsafe.Pointer)(p)
+ }
+ c, err := d.dec.Decode(ctx, cursor, depth, newptr)
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ return cursor, nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/slice.go b/vendor/github.com/goccy/go-json/internal/decoder/slice.go
new file mode 100644
index 000000000..85b6e1119
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/slice.go
@@ -0,0 +1,301 @@
+package decoder
+
+import (
+ "reflect"
+ "sync"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+var (
+ sliceType = runtime.Type2RType(
+ reflect.TypeOf((*sliceHeader)(nil)).Elem(),
+ )
+ nilSlice = unsafe.Pointer(&sliceHeader{})
+)
+
+type sliceDecoder struct {
+ elemType *runtime.Type
+ isElemPointerType bool
+ valueDecoder Decoder
+ size uintptr
+ arrayPool sync.Pool
+ structName string
+ fieldName string
+}
+
+// If use reflect.SliceHeader, data type is uintptr.
+// In this case, Go compiler cannot trace reference created by newArray().
+// So, define using unsafe.Pointer as data type
+type sliceHeader struct {
+ data unsafe.Pointer
+ len int
+ cap int
+}
+
+const (
+ defaultSliceCapacity = 2
+)
+
+func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder {
+ return &sliceDecoder{
+ valueDecoder: dec,
+ elemType: elemType,
+ isElemPointerType: elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map,
+ size: size,
+ arrayPool: sync.Pool{
+ New: func() interface{} {
+ return &sliceHeader{
+ data: newArray(elemType, defaultSliceCapacity),
+ len: 0,
+ cap: defaultSliceCapacity,
+ }
+ },
+ },
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *sliceDecoder) newSlice(src *sliceHeader) *sliceHeader {
+ slice := d.arrayPool.Get().(*sliceHeader)
+ if src.len > 0 {
+ // copy original elem
+ if slice.cap < src.cap {
+ data := newArray(d.elemType, src.cap)
+ slice = &sliceHeader{data: data, len: src.len, cap: src.cap}
+ } else {
+ slice.len = src.len
+ }
+ copySlice(d.elemType, *slice, *src)
+ } else {
+ slice.len = 0
+ }
+ return slice
+}
+
+func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
+ d.arrayPool.Put(p)
+}
+
+//go:linkname copySlice reflect.typedslicecopy
+func copySlice(elemType *runtime.Type, dst, src sliceHeader) int
+
+//go:linkname newArray reflect.unsafe_NewArray
+func newArray(*runtime.Type, int) unsafe.Pointer
+
+//go:linkname typedmemmove reflect.typedmemmove
+func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer)
+
+func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError {
+ return &errors.UnmarshalTypeError{
+ Value: "number",
+ Type: reflect.SliceOf(runtime.RType2Type(d.elemType)),
+ Struct: d.structName,
+ Field: d.fieldName,
+ Offset: offset,
+ }
+}
+
+func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+
+ for {
+ switch s.char() {
+ case ' ', '\n', '\t', '\r':
+ s.cursor++
+ continue
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ typedmemmove(sliceType, p, nilSlice)
+ return nil
+ case '[':
+ s.cursor++
+ if s.skipWhiteSpace() == ']' {
+ dst := (*sliceHeader)(p)
+ if dst.data == nil {
+ dst.data = newArray(d.elemType, 0)
+ } else {
+ dst.len = 0
+ }
+ s.cursor++
+ return nil
+ }
+ idx := 0
+ slice := d.newSlice((*sliceHeader)(p))
+ srcLen := slice.len
+ capacity := slice.cap
+ data := slice.data
+ for {
+ if capacity <= idx {
+ src := sliceHeader{data: data, len: idx, cap: capacity}
+ capacity *= 2
+ data = newArray(d.elemType, capacity)
+ dst := sliceHeader{data: data, len: idx, cap: capacity}
+ copySlice(d.elemType, dst, src)
+ }
+ ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
+
+ // if srcLen is greater than idx, keep the original reference
+ if srcLen <= idx {
+ if d.isElemPointerType {
+ **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
+ } else {
+ // assign new element to the slice
+ typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
+ }
+ }
+
+ if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil {
+ return err
+ }
+ s.skipWhiteSpace()
+ RETRY:
+ switch s.char() {
+ case ']':
+ slice.cap = capacity
+ slice.len = idx + 1
+ slice.data = data
+ dst := (*sliceHeader)(p)
+ dst.len = idx + 1
+ if dst.len > dst.cap {
+ dst.data = newArray(d.elemType, dst.len)
+ dst.cap = dst.len
+ }
+ copySlice(d.elemType, *dst, *slice)
+ d.releaseSlice(slice)
+ s.cursor++
+ return nil
+ case ',':
+ idx++
+ case nul:
+ if s.read() {
+ goto RETRY
+ }
+ slice.cap = capacity
+ slice.data = data
+ d.releaseSlice(slice)
+ goto ERROR
+ default:
+ slice.cap = capacity
+ slice.data = data
+ d.releaseSlice(slice)
+ goto ERROR
+ }
+ s.cursor++
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return d.errNumber(s.totalOffset())
+ case nul:
+ if s.read() {
+ continue
+ }
+ goto ERROR
+ default:
+ goto ERROR
+ }
+ }
+ERROR:
+ return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset())
+}
+
+func (d *sliceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+
+ for {
+ switch buf[cursor] {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ continue
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ typedmemmove(sliceType, p, nilSlice)
+ return cursor, nil
+ case '[':
+ cursor++
+ cursor = skipWhiteSpace(buf, cursor)
+ if buf[cursor] == ']' {
+ dst := (*sliceHeader)(p)
+ if dst.data == nil {
+ dst.data = newArray(d.elemType, 0)
+ } else {
+ dst.len = 0
+ }
+ cursor++
+ return cursor, nil
+ }
+ idx := 0
+ slice := d.newSlice((*sliceHeader)(p))
+ srcLen := slice.len
+ capacity := slice.cap
+ data := slice.data
+ for {
+ if capacity <= idx {
+ src := sliceHeader{data: data, len: idx, cap: capacity}
+ capacity *= 2
+ data = newArray(d.elemType, capacity)
+ dst := sliceHeader{data: data, len: idx, cap: capacity}
+ copySlice(d.elemType, dst, src)
+ }
+ ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
+ // if srcLen is greater than idx, keep the original reference
+ if srcLen <= idx {
+ if d.isElemPointerType {
+ **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
+ } else {
+ // assign new element to the slice
+ typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
+ }
+ }
+ c, err := d.valueDecoder.Decode(ctx, cursor, depth, ep)
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ cursor = skipWhiteSpace(buf, cursor)
+ switch buf[cursor] {
+ case ']':
+ slice.cap = capacity
+ slice.len = idx + 1
+ slice.data = data
+ dst := (*sliceHeader)(p)
+ dst.len = idx + 1
+ if dst.len > dst.cap {
+ dst.data = newArray(d.elemType, dst.len)
+ dst.cap = dst.len
+ }
+ copySlice(d.elemType, *dst, *slice)
+ d.releaseSlice(slice)
+ cursor++
+ return cursor, nil
+ case ',':
+ idx++
+ default:
+ slice.cap = capacity
+ slice.data = data
+ d.releaseSlice(slice)
+ return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
+ }
+ cursor++
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return 0, d.errNumber(cursor)
+ default:
+ return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
+ }
+ }
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/stream.go b/vendor/github.com/goccy/go-json/internal/decoder/stream.go
new file mode 100644
index 000000000..c27468348
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/stream.go
@@ -0,0 +1,554 @@
+package decoder
+
+import (
+ "bytes"
+ "encoding/json"
+ "io"
+ "strconv"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+)
+
+const (
+ initBufSize = 512
+)
+
+type Stream struct {
+ buf []byte
+ bufSize int64
+ length int64
+ r io.Reader
+ offset int64
+ cursor int64
+ filledBuffer bool
+ allRead bool
+ UseNumber bool
+ DisallowUnknownFields bool
+ Option *Option
+}
+
+func NewStream(r io.Reader) *Stream {
+ return &Stream{
+ r: r,
+ bufSize: initBufSize,
+ buf: make([]byte, initBufSize),
+ Option: &Option{},
+ }
+}
+
+func (s *Stream) TotalOffset() int64 {
+ return s.totalOffset()
+}
+
+func (s *Stream) Buffered() io.Reader {
+ buflen := int64(len(s.buf))
+ for i := s.cursor; i < buflen; i++ {
+ if s.buf[i] == nul {
+ return bytes.NewReader(s.buf[s.cursor:i])
+ }
+ }
+ return bytes.NewReader(s.buf[s.cursor:])
+}
+
+func (s *Stream) PrepareForDecode() error {
+ for {
+ switch s.char() {
+ case ' ', '\t', '\r', '\n':
+ s.cursor++
+ continue
+ case ',', ':':
+ s.cursor++
+ return nil
+ case nul:
+ if s.read() {
+ continue
+ }
+ return io.EOF
+ }
+ break
+ }
+ return nil
+}
+
+func (s *Stream) totalOffset() int64 {
+ return s.offset + s.cursor
+}
+
+func (s *Stream) char() byte {
+ return s.buf[s.cursor]
+}
+
+func (s *Stream) equalChar(c byte) bool {
+ cur := s.buf[s.cursor]
+ if cur == nul {
+ s.read()
+ cur = s.buf[s.cursor]
+ }
+ return cur == c
+}
+
+func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) {
+ return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
+}
+
+func (s *Stream) bufptr() unsafe.Pointer {
+ return (*sliceHeader)(unsafe.Pointer(&s.buf)).data
+}
+
+func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
+ s.cursor-- // for retry ( because caller progress cursor position in each loop )
+ return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
+}
+
+func (s *Stream) Reset() {
+ s.reset()
+ s.bufSize = initBufSize
+}
+
+func (s *Stream) More() bool {
+ for {
+ switch s.char() {
+ case ' ', '\n', '\r', '\t':
+ s.cursor++
+ continue
+ case '}', ']':
+ return false
+ case nul:
+ if s.read() {
+ continue
+ }
+ return false
+ }
+ break
+ }
+ return true
+}
+
+func (s *Stream) Token() (interface{}, error) {
+ for {
+ c := s.char()
+ switch c {
+ case ' ', '\n', '\r', '\t':
+ s.cursor++
+ case '{', '[', ']', '}':
+ s.cursor++
+ return json.Delim(c), nil
+ case ',', ':':
+ s.cursor++
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ bytes := floatBytes(s)
+ s := *(*string)(unsafe.Pointer(&bytes))
+ f64, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return nil, err
+ }
+ return f64, nil
+ case '"':
+ bytes, err := stringBytes(s)
+ if err != nil {
+ return nil, err
+ }
+ return string(bytes), nil
+ case 't':
+ if err := trueBytes(s); err != nil {
+ return nil, err
+ }
+ return true, nil
+ case 'f':
+ if err := falseBytes(s); err != nil {
+ return nil, err
+ }
+ return false, nil
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case nul:
+ if s.read() {
+ continue
+ }
+ goto END
+ default:
+ return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset())
+ }
+ }
+END:
+ return nil, io.EOF
+}
+
+func (s *Stream) reset() {
+ s.offset += s.cursor
+ s.buf = s.buf[s.cursor:]
+ s.length -= s.cursor
+ s.cursor = 0
+}
+
+func (s *Stream) readBuf() []byte {
+ if s.filledBuffer {
+ s.bufSize *= 2
+ remainBuf := s.buf
+ s.buf = make([]byte, s.bufSize)
+ copy(s.buf, remainBuf)
+ }
+ remainLen := s.length - s.cursor
+ remainNotNulCharNum := int64(0)
+ for i := int64(0); i < remainLen; i++ {
+ if s.buf[s.cursor+i] == nul {
+ break
+ }
+ remainNotNulCharNum++
+ }
+ s.length = s.cursor + remainNotNulCharNum
+ return s.buf[s.cursor+remainNotNulCharNum:]
+}
+
+func (s *Stream) read() bool {
+ if s.allRead {
+ return false
+ }
+ buf := s.readBuf()
+ last := len(buf) - 1
+ buf[last] = nul
+ n, err := s.r.Read(buf[:last])
+ s.length += int64(n)
+ if n == last {
+ s.filledBuffer = true
+ } else {
+ s.filledBuffer = false
+ }
+ if err == io.EOF {
+ s.allRead = true
+ } else if err != nil {
+ return false
+ }
+ return true
+}
+
+func (s *Stream) skipWhiteSpace() byte {
+ p := s.bufptr()
+LOOP:
+ c := char(p, s.cursor)
+ switch c {
+ case ' ', '\n', '\t', '\r':
+ s.cursor++
+ goto LOOP
+ case nul:
+ if s.read() {
+ p = s.bufptr()
+ goto LOOP
+ }
+ }
+ return c
+}
+
+func (s *Stream) skipObject(depth int64) error {
+ braceCount := 1
+ _, cursor, p := s.stat()
+ for {
+ switch char(p, cursor) {
+ case '{':
+ braceCount++
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+ case '}':
+ braceCount--
+ depth--
+ if braceCount == 0 {
+ s.cursor = cursor + 1
+ return nil
+ }
+ case '[':
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+ case ']':
+ depth--
+ case '"':
+ for {
+ cursor++
+ switch char(p, cursor) {
+ case '\\':
+ cursor++
+ if char(p, cursor) == nul {
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.statForRetry()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ case '"':
+ goto SWITCH_OUT
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.statForRetry()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ }
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("object of object", cursor)
+ }
+ SWITCH_OUT:
+ cursor++
+ }
+}
+
+func (s *Stream) skipArray(depth int64) error {
+ bracketCount := 1
+ _, cursor, p := s.stat()
+ for {
+ switch char(p, cursor) {
+ case '[':
+ bracketCount++
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+ case ']':
+ bracketCount--
+ depth--
+ if bracketCount == 0 {
+ s.cursor = cursor + 1
+ return nil
+ }
+ case '{':
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+ case '}':
+ depth--
+ case '"':
+ for {
+ cursor++
+ switch char(p, cursor) {
+ case '\\':
+ cursor++
+ if char(p, cursor) == nul {
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.statForRetry()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ case '"':
+ goto SWITCH_OUT
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.statForRetry()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
+ }
+ }
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("array of object", cursor)
+ }
+ SWITCH_OUT:
+ cursor++
+ }
+}
+
+func (s *Stream) skipValue(depth int64) error {
+ _, cursor, p := s.stat()
+ for {
+ switch char(p, cursor) {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ continue
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset())
+ case '{':
+ s.cursor = cursor + 1
+ return s.skipObject(depth + 1)
+ case '[':
+ s.cursor = cursor + 1
+ return s.skipArray(depth + 1)
+ case '"':
+ for {
+ cursor++
+ switch char(p, cursor) {
+ case '\\':
+ cursor++
+ if char(p, cursor) == nul {
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.statForRetry()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
+ }
+ case '"':
+ s.cursor = cursor + 1
+ return nil
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.statForRetry()
+ continue
+ }
+ return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
+ }
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ for {
+ cursor++
+ c := char(p, cursor)
+ if floatTable[c] {
+ continue
+ } else if c == nul {
+ if s.read() {
+ s.cursor-- // for retry current character
+ _, cursor, p = s.stat()
+ continue
+ }
+ }
+ s.cursor = cursor
+ return nil
+ }
+ case 't':
+ s.cursor = cursor
+ if err := trueBytes(s); err != nil {
+ return err
+ }
+ return nil
+ case 'f':
+ s.cursor = cursor
+ if err := falseBytes(s); err != nil {
+ return err
+ }
+ return nil
+ case 'n':
+ s.cursor = cursor
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ return nil
+ }
+ cursor++
+ }
+}
+
+func nullBytes(s *Stream) error {
+ // current cursor's character is 'n'
+ s.cursor++
+ if s.char() != 'u' {
+ if err := retryReadNull(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ if s.char() != 'l' {
+ if err := retryReadNull(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ if s.char() != 'l' {
+ if err := retryReadNull(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ return nil
+}
+
+func retryReadNull(s *Stream) error {
+ if s.char() == nul && s.read() {
+ return nil
+ }
+ return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset())
+}
+
+func trueBytes(s *Stream) error {
+ // current cursor's character is 't'
+ s.cursor++
+ if s.char() != 'r' {
+ if err := retryReadTrue(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ if s.char() != 'u' {
+ if err := retryReadTrue(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ if s.char() != 'e' {
+ if err := retryReadTrue(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ return nil
+}
+
+func retryReadTrue(s *Stream) error {
+ if s.char() == nul && s.read() {
+ return nil
+ }
+ return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
+}
+
+func falseBytes(s *Stream) error {
+ // current cursor's character is 'f'
+ s.cursor++
+ if s.char() != 'a' {
+ if err := retryReadFalse(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ if s.char() != 'l' {
+ if err := retryReadFalse(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ if s.char() != 's' {
+ if err := retryReadFalse(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ if s.char() != 'e' {
+ if err := retryReadFalse(s); err != nil {
+ return err
+ }
+ }
+ s.cursor++
+ return nil
+}
+
+func retryReadFalse(s *Stream) error {
+ if s.char() == nul && s.read() {
+ return nil
+ }
+ return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/string.go b/vendor/github.com/goccy/go-json/internal/decoder/string.go
new file mode 100644
index 000000000..65b100488
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/string.go
@@ -0,0 +1,371 @@
+package decoder
+
+import (
+ "reflect"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+)
+
+type stringDecoder struct {
+ structName string
+ fieldName string
+}
+
+func newStringDecoder(structName, fieldName string) *stringDecoder {
+ return &stringDecoder{
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError {
+ return &errors.UnmarshalTypeError{
+ Value: typeName,
+ Type: reflect.TypeOf(""),
+ Offset: offset,
+ Struct: d.structName,
+ Field: d.fieldName,
+ }
+}
+
+func (d *stringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ bytes, err := d.decodeStreamByte(s)
+ if err != nil {
+ return err
+ }
+ if bytes == nil {
+ return nil
+ }
+ **(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes))
+ s.reset()
+ return nil
+}
+
+func (d *stringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ bytes, c, err := d.decodeByte(ctx.Buf, cursor)
+ if err != nil {
+ return 0, err
+ }
+ if bytes == nil {
+ return c, nil
+ }
+ cursor = c
+ **(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes))
+ return cursor, nil
+}
+
+var (
+ hexToInt = [256]int{
+ '0': 0,
+ '1': 1,
+ '2': 2,
+ '3': 3,
+ '4': 4,
+ '5': 5,
+ '6': 6,
+ '7': 7,
+ '8': 8,
+ '9': 9,
+ 'A': 10,
+ 'B': 11,
+ 'C': 12,
+ 'D': 13,
+ 'E': 14,
+ 'F': 15,
+ 'a': 10,
+ 'b': 11,
+ 'c': 12,
+ 'd': 13,
+ 'e': 14,
+ 'f': 15,
+ }
+)
+
+func unicodeToRune(code []byte) rune {
+ var r rune
+ for i := 0; i < len(code); i++ {
+ r = r*16 + rune(hexToInt[code[i]])
+ }
+ return r
+}
+
+func decodeUnicodeRune(s *Stream, p unsafe.Pointer) (rune, int64, unsafe.Pointer, error) {
+ const defaultOffset = 5
+ const surrogateOffset = 11
+
+ if s.cursor+defaultOffset >= s.length {
+ if !s.read() {
+ return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
+ }
+ p = s.bufptr()
+ }
+
+ r := unicodeToRune(s.buf[s.cursor+1 : s.cursor+defaultOffset])
+ if utf16.IsSurrogate(r) {
+ if s.cursor+surrogateOffset >= s.length {
+ s.read()
+ p = s.bufptr()
+ }
+ if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' {
+ return unicode.ReplacementChar, defaultOffset, p, nil
+ }
+ r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset])
+ if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
+ return r, surrogateOffset, p, nil
+ }
+ }
+ return r, defaultOffset, p, nil
+}
+
+func decodeUnicode(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) {
+ const backSlashAndULen = 2 // length of \u
+
+ r, offset, pp, err := decodeUnicodeRune(s, p)
+ if err != nil {
+ return nil, err
+ }
+ unicode := []byte(string(r))
+ unicodeLen := int64(len(unicode))
+ s.buf = append(append(s.buf[:s.cursor-1], unicode...), s.buf[s.cursor+offset:]...)
+ unicodeOrgLen := offset - 1
+ s.length = s.length - (backSlashAndULen + (unicodeOrgLen - unicodeLen))
+ s.cursor = s.cursor - backSlashAndULen + unicodeLen
+ return pp, nil
+}
+
+func decodeEscapeString(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) {
+ s.cursor++
+RETRY:
+ switch s.buf[s.cursor] {
+ case '"':
+ s.buf[s.cursor] = '"'
+ case '\\':
+ s.buf[s.cursor] = '\\'
+ case '/':
+ s.buf[s.cursor] = '/'
+ case 'b':
+ s.buf[s.cursor] = '\b'
+ case 'f':
+ s.buf[s.cursor] = '\f'
+ case 'n':
+ s.buf[s.cursor] = '\n'
+ case 'r':
+ s.buf[s.cursor] = '\r'
+ case 't':
+ s.buf[s.cursor] = '\t'
+ case 'u':
+ return decodeUnicode(s, p)
+ case nul:
+ if !s.read() {
+ return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
+ }
+ goto RETRY
+ default:
+ return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ }
+ s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...)
+ s.length--
+ s.cursor--
+ p = s.bufptr()
+ return p, nil
+}
+
+var (
+ runeErrBytes = []byte(string(utf8.RuneError))
+ runeErrBytesLen = int64(len(runeErrBytes))
+)
+
+func stringBytes(s *Stream) ([]byte, error) {
+ _, cursor, p := s.stat()
+ cursor++ // skip double quote char
+ start := cursor
+ for {
+ switch char(p, cursor) {
+ case '\\':
+ s.cursor = cursor
+ pp, err := decodeEscapeString(s, p)
+ if err != nil {
+ return nil, err
+ }
+ p = pp
+ cursor = s.cursor
+ case '"':
+ literal := s.buf[start:cursor]
+ cursor++
+ s.cursor = cursor
+ return literal, nil
+ case
+ // 0x00 is nul, 0x5c is '\\', 0x22 is '"' .
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 0x00-0x0F
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // 0x10-0x1F
+ 0x20, 0x21 /*0x22,*/, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // 0x20-0x2F
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, // 0x30-0x3F
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, // 0x40-0x4F
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B /*0x5C,*/, 0x5D, 0x5E, 0x5F, // 0x50-0x5F
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, // 0x60-0x6F
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F: // 0x70-0x7F
+ // character is ASCII. skip to next char
+ case
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, // 0x80-0x8F
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, // 0x90-0x9F
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, // 0xA0-0xAF
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, // 0xB0-0xBF
+ 0xC0, 0xC1, // 0xC0-0xC1
+ 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF: // 0xF5-0xFE
+ // character is invalid
+ s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...)
+ _, _, p = s.stat()
+ cursor += runeErrBytesLen
+ s.length += runeErrBytesLen
+ continue
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ goto ERROR
+ case 0xEF:
+ // RuneError is {0xEF, 0xBF, 0xBD}
+ if s.buf[cursor+1] == 0xBF && s.buf[cursor+2] == 0xBD {
+ // found RuneError: skip
+ cursor += 2
+ break
+ }
+ fallthrough
+ default:
+ // multi bytes character
+ if !utf8.FullRune(s.buf[cursor : len(s.buf)-1]) {
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ goto ERROR
+ }
+ r, size := utf8.DecodeRune(s.buf[cursor:])
+ if r == utf8.RuneError {
+ s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...)
+ cursor += runeErrBytesLen
+ s.length += runeErrBytesLen
+ _, _, p = s.stat()
+ } else {
+ cursor += int64(size)
+ }
+ continue
+ }
+ cursor++
+ }
+ERROR:
+ return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+}
+
+func (d *stringDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
+ for {
+ switch s.char() {
+ case ' ', '\n', '\t', '\r':
+ s.cursor++
+ continue
+ case '[':
+ return nil, d.errUnmarshalType("array", s.totalOffset())
+ case '{':
+ return nil, d.errUnmarshalType("object", s.totalOffset())
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return nil, d.errUnmarshalType("number", s.totalOffset())
+ case '"':
+ return stringBytes(s)
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case nul:
+ if s.read() {
+ continue
+ }
+ }
+ break
+ }
+ return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
+}
+
+func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
+ for {
+ switch buf[cursor] {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ case '[':
+ return nil, 0, d.errUnmarshalType("array", cursor)
+ case '{':
+ return nil, 0, d.errUnmarshalType("object", cursor)
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return nil, 0, d.errUnmarshalType("number", cursor)
+ case '"':
+ cursor++
+ start := cursor
+ b := (*sliceHeader)(unsafe.Pointer(&buf)).data
+ for {
+ switch char(b, cursor) {
+ case '\\':
+ cursor++
+ switch char(b, cursor) {
+ case '"':
+ buf[cursor] = '"'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case '\\':
+ buf[cursor] = '\\'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case '/':
+ buf[cursor] = '/'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case 'b':
+ buf[cursor] = '\b'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case 'f':
+ buf[cursor] = '\f'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case 'n':
+ buf[cursor] = '\n'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case 'r':
+ buf[cursor] = '\r'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case 't':
+ buf[cursor] = '\t'
+ buf = append(buf[:cursor-1], buf[cursor:]...)
+ case 'u':
+ buflen := int64(len(buf))
+ if cursor+5 >= buflen {
+ return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
+ }
+ code := unicodeToRune(buf[cursor+1 : cursor+5])
+ unicode := []byte(string(code))
+ buf = append(append(buf[:cursor-1], unicode...), buf[cursor+5:]...)
+ default:
+ return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
+ }
+ continue
+ case '"':
+ literal := buf[start:cursor]
+ cursor++
+ return literal, cursor, nil
+ case nul:
+ return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor)
+ }
+ cursor++
+ }
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return nil, 0, err
+ }
+ cursor += 4
+ return nil, cursor, nil
+ default:
+ return nil, 0, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
+ }
+ }
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/struct.go b/vendor/github.com/goccy/go-json/internal/decoder/struct.go
new file mode 100644
index 000000000..2c6468045
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/struct.go
@@ -0,0 +1,819 @@
+package decoder
+
+import (
+ "fmt"
+ "math"
+ "math/bits"
+ "sort"
+ "strings"
+ "unicode"
+ "unicode/utf16"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+)
+
+type structFieldSet struct {
+ dec Decoder
+ offset uintptr
+ isTaggedKey bool
+ fieldIdx int
+ key string
+ keyLen int64
+ err error
+}
+
+type structDecoder struct {
+ fieldMap map[string]*structFieldSet
+ fieldUniqueNameNum int
+ stringDecoder *stringDecoder
+ structName string
+ fieldName string
+ isTriedOptimize bool
+ keyBitmapUint8 [][256]uint8
+ keyBitmapUint16 [][256]uint16
+ sortedFieldSets []*structFieldSet
+ keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
+ keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error)
+}
+
+var (
+ largeToSmallTable [256]byte
+)
+
+func init() {
+ for i := 0; i < 256; i++ {
+ c := i
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ largeToSmallTable[i] = byte(c)
+ }
+}
+
+func newStructDecoder(structName, fieldName string, fieldMap map[string]*structFieldSet) *structDecoder {
+ return &structDecoder{
+ fieldMap: fieldMap,
+ stringDecoder: newStringDecoder(structName, fieldName),
+ structName: structName,
+ fieldName: fieldName,
+ keyDecoder: decodeKey,
+ keyStreamDecoder: decodeKeyStream,
+ }
+}
+
+const (
+ allowOptimizeMaxKeyLen = 64
+ allowOptimizeMaxFieldLen = 16
+)
+
+func (d *structDecoder) tryOptimize() {
+ fieldUniqueNameMap := map[string]int{}
+ fieldIdx := -1
+ for k, v := range d.fieldMap {
+ lower := strings.ToLower(k)
+ idx, exists := fieldUniqueNameMap[lower]
+ if exists {
+ v.fieldIdx = idx
+ } else {
+ fieldIdx++
+ v.fieldIdx = fieldIdx
+ }
+ fieldUniqueNameMap[lower] = fieldIdx
+ }
+ d.fieldUniqueNameNum = len(fieldUniqueNameMap)
+
+ if d.isTriedOptimize {
+ return
+ }
+ fieldMap := map[string]*structFieldSet{}
+ conflicted := map[string]struct{}{}
+ for k, v := range d.fieldMap {
+ key := strings.ToLower(k)
+ if key != k {
+ // already exists same key (e.g. Hello and HELLO has same lower case key
+ if _, exists := conflicted[key]; exists {
+ d.isTriedOptimize = true
+ return
+ }
+ conflicted[key] = struct{}{}
+ }
+ if field, exists := fieldMap[key]; exists {
+ if field != v {
+ d.isTriedOptimize = true
+ return
+ }
+ }
+ fieldMap[key] = v
+ }
+
+ if len(fieldMap) > allowOptimizeMaxFieldLen {
+ d.isTriedOptimize = true
+ return
+ }
+
+ var maxKeyLen int
+ sortedKeys := []string{}
+ for key := range fieldMap {
+ keyLen := len(key)
+ if keyLen > allowOptimizeMaxKeyLen {
+ d.isTriedOptimize = true
+ return
+ }
+ if maxKeyLen < keyLen {
+ maxKeyLen = keyLen
+ }
+ sortedKeys = append(sortedKeys, key)
+ }
+ sort.Strings(sortedKeys)
+
+ // By allocating one extra capacity than `maxKeyLen`,
+ // it is possible to avoid the process of comparing the index of the key with the length of the bitmap each time.
+ bitmapLen := maxKeyLen + 1
+ if len(sortedKeys) <= 8 {
+ keyBitmap := make([][256]uint8, bitmapLen)
+ for i, key := range sortedKeys {
+ for j := 0; j < len(key); j++ {
+ c := key[j]
+ keyBitmap[j][c] |= (1 << uint(i))
+ }
+ d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
+ }
+ d.keyBitmapUint8 = keyBitmap
+ d.keyDecoder = decodeKeyByBitmapUint8
+ d.keyStreamDecoder = decodeKeyByBitmapUint8Stream
+ } else {
+ keyBitmap := make([][256]uint16, bitmapLen)
+ for i, key := range sortedKeys {
+ for j := 0; j < len(key); j++ {
+ c := key[j]
+ keyBitmap[j][c] |= (1 << uint(i))
+ }
+ d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
+ }
+ d.keyBitmapUint16 = keyBitmap
+ d.keyDecoder = decodeKeyByBitmapUint16
+ d.keyStreamDecoder = decodeKeyByBitmapUint16Stream
+ }
+}
+
+// decode from '\uXXXX'
+func decodeKeyCharByUnicodeRune(buf []byte, cursor int64) ([]byte, int64) {
+ const defaultOffset = 4
+ const surrogateOffset = 6
+
+ r := unicodeToRune(buf[cursor : cursor+defaultOffset])
+ if utf16.IsSurrogate(r) {
+ cursor += defaultOffset
+ if cursor+surrogateOffset >= int64(len(buf)) || buf[cursor] != '\\' || buf[cursor+1] != 'u' {
+ return []byte(string(unicode.ReplacementChar)), cursor + defaultOffset - 1
+ }
+ cursor += 2
+ r2 := unicodeToRune(buf[cursor : cursor+defaultOffset])
+ if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
+ return []byte(string(r)), cursor + defaultOffset - 1
+ }
+ }
+ return []byte(string(r)), cursor + defaultOffset - 1
+}
+
+func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64) {
+ c := buf[cursor]
+ cursor++
+ switch c {
+ case '"':
+ return []byte{'"'}, cursor
+ case '\\':
+ return []byte{'\\'}, cursor
+ case '/':
+ return []byte{'/'}, cursor
+ case 'b':
+ return []byte{'\b'}, cursor
+ case 'f':
+ return []byte{'\f'}, cursor
+ case 'n':
+ return []byte{'\n'}, cursor
+ case 'r':
+ return []byte{'\r'}, cursor
+ case 't':
+ return []byte{'\t'}, cursor
+ case 'u':
+ return decodeKeyCharByUnicodeRune(buf, cursor)
+ }
+ return nil, cursor
+}
+
+func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
+ var (
+ curBit uint8 = math.MaxUint8
+ )
+ b := (*sliceHeader)(unsafe.Pointer(&buf)).data
+ for {
+ switch char(b, cursor) {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ case '"':
+ cursor++
+ c := char(b, cursor)
+ switch c {
+ case '"':
+ cursor++
+ return cursor, nil, nil
+ case nul:
+ return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
+ }
+ keyIdx := 0
+ bitmap := d.keyBitmapUint8
+ start := cursor
+ for {
+ c := char(b, cursor)
+ switch c {
+ case '"':
+ fieldSetIndex := bits.TrailingZeros8(curBit)
+ field := d.sortedFieldSets[fieldSetIndex]
+ keyLen := cursor - start
+ cursor++
+ if keyLen < field.keyLen {
+ // early match
+ return cursor, nil, nil
+ }
+ return cursor, field, nil
+ case nul:
+ return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
+ case '\\':
+ cursor++
+ chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
+ for _, c := range chars {
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ return decodeKeyNotFound(b, cursor)
+ }
+ keyIdx++
+ }
+ cursor = nextCursor
+ default:
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ return decodeKeyNotFound(b, cursor)
+ }
+ keyIdx++
+ }
+ cursor++
+ }
+ default:
+ return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
+ }
+ }
+}
+
+func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
+ var (
+ curBit uint16 = math.MaxUint16
+ )
+ b := (*sliceHeader)(unsafe.Pointer(&buf)).data
+ for {
+ switch char(b, cursor) {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ case '"':
+ cursor++
+ c := char(b, cursor)
+ switch c {
+ case '"':
+ cursor++
+ return cursor, nil, nil
+ case nul:
+ return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
+ }
+ keyIdx := 0
+ bitmap := d.keyBitmapUint16
+ start := cursor
+ for {
+ c := char(b, cursor)
+ switch c {
+ case '"':
+ fieldSetIndex := bits.TrailingZeros16(curBit)
+ field := d.sortedFieldSets[fieldSetIndex]
+ keyLen := cursor - start
+ cursor++
+ if keyLen < field.keyLen {
+ // early match
+ return cursor, nil, nil
+ }
+ return cursor, field, nil
+ case nul:
+ return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
+ case '\\':
+ cursor++
+ chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
+ for _, c := range chars {
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ return decodeKeyNotFound(b, cursor)
+ }
+ keyIdx++
+ }
+ cursor = nextCursor
+ default:
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ return decodeKeyNotFound(b, cursor)
+ }
+ keyIdx++
+ }
+ cursor++
+ }
+ default:
+ return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
+ }
+ }
+}
+
+func decodeKeyNotFound(b unsafe.Pointer, cursor int64) (int64, *structFieldSet, error) {
+ for {
+ cursor++
+ switch char(b, cursor) {
+ case '"':
+ cursor++
+ return cursor, nil, nil
+ case '\\':
+ cursor++
+ if char(b, cursor) == nul {
+ return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
+ }
+ case nul:
+ return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
+ }
+ }
+}
+
+func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
+ key, c, err := d.stringDecoder.decodeByte(buf, cursor)
+ if err != nil {
+ return 0, nil, err
+ }
+ cursor = c
+ k := *(*string)(unsafe.Pointer(&key))
+ field, exists := d.fieldMap[k]
+ if !exists {
+ return cursor, nil, nil
+ }
+ return cursor, field, nil
+}
+
+func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
+ var (
+ curBit uint8 = math.MaxUint8
+ )
+ _, cursor, p := s.stat()
+ for {
+ switch char(p, cursor) {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
+ case '"':
+ cursor++
+ FIRST_CHAR:
+ start := cursor
+ switch char(p, cursor) {
+ case '"':
+ cursor++
+ s.cursor = cursor
+ return nil, "", nil
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ goto FIRST_CHAR
+ }
+ return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ }
+ keyIdx := 0
+ bitmap := d.keyBitmapUint8
+ for {
+ c := char(p, cursor)
+ switch c {
+ case '"':
+ fieldSetIndex := bits.TrailingZeros8(curBit)
+ field := d.sortedFieldSets[fieldSetIndex]
+ keyLen := cursor - start
+ cursor++
+ s.cursor = cursor
+ if keyLen < field.keyLen {
+ // early match
+ return nil, field.key, nil
+ }
+ return field, field.key, nil
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ case '\\':
+ s.cursor = cursor + 1 // skip '\' char
+ chars, err := decodeKeyCharByEscapeCharStream(s)
+ if err != nil {
+ return nil, "", err
+ }
+ cursor = s.cursor
+ for _, c := range chars {
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ s.cursor = cursor
+ return decodeKeyNotFoundStream(s, start)
+ }
+ keyIdx++
+ }
+ default:
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ s.cursor = cursor
+ return decodeKeyNotFoundStream(s, start)
+ }
+ keyIdx++
+ }
+ cursor++
+ }
+ default:
+ return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
+ }
+ }
+}
+
+func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
+ var (
+ curBit uint16 = math.MaxUint16
+ )
+ _, cursor, p := s.stat()
+ for {
+ switch char(p, cursor) {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
+ case '"':
+ cursor++
+ FIRST_CHAR:
+ start := cursor
+ switch char(p, cursor) {
+ case '"':
+ cursor++
+ s.cursor = cursor
+ return nil, "", nil
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ goto FIRST_CHAR
+ }
+ return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ }
+ keyIdx := 0
+ bitmap := d.keyBitmapUint16
+ for {
+ c := char(p, cursor)
+ switch c {
+ case '"':
+ fieldSetIndex := bits.TrailingZeros16(curBit)
+ field := d.sortedFieldSets[fieldSetIndex]
+ keyLen := cursor - start
+ cursor++
+ s.cursor = cursor
+ if keyLen < field.keyLen {
+ // early match
+ return nil, field.key, nil
+ }
+ return field, field.key, nil
+ case nul:
+ s.cursor = cursor
+ if s.read() {
+ _, cursor, p = s.stat()
+ continue
+ }
+ return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ case '\\':
+ s.cursor = cursor + 1 // skip '\' char
+ chars, err := decodeKeyCharByEscapeCharStream(s)
+ if err != nil {
+ return nil, "", err
+ }
+ cursor = s.cursor
+ for _, c := range chars {
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ s.cursor = cursor
+ return decodeKeyNotFoundStream(s, start)
+ }
+ keyIdx++
+ }
+ default:
+ curBit &= bitmap[keyIdx][largeToSmallTable[c]]
+ if curBit == 0 {
+ s.cursor = cursor
+ return decodeKeyNotFoundStream(s, start)
+ }
+ keyIdx++
+ }
+ cursor++
+ }
+ default:
+ return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
+ }
+ }
+}
+
+// decode from '\uXXXX'
+func decodeKeyCharByUnicodeRuneStream(s *Stream) ([]byte, error) {
+ const defaultOffset = 4
+ const surrogateOffset = 6
+
+ if s.cursor+defaultOffset >= s.length {
+ if !s.read() {
+ return nil, errors.ErrInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset())
+ }
+ }
+
+ r := unicodeToRune(s.buf[s.cursor : s.cursor+defaultOffset])
+ if utf16.IsSurrogate(r) {
+ s.cursor += defaultOffset
+ if s.cursor+surrogateOffset >= s.length {
+ s.read()
+ }
+ if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor] != '\\' || s.buf[s.cursor+1] != 'u' {
+ s.cursor += defaultOffset - 1
+ return []byte(string(unicode.ReplacementChar)), nil
+ }
+ r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset])
+ if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
+ s.cursor += defaultOffset - 1
+ return []byte(string(r)), nil
+ }
+ }
+ s.cursor += defaultOffset - 1
+ return []byte(string(r)), nil
+}
+
+func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) {
+ c := s.buf[s.cursor]
+ s.cursor++
+RETRY:
+ switch c {
+ case '"':
+ return []byte{'"'}, nil
+ case '\\':
+ return []byte{'\\'}, nil
+ case '/':
+ return []byte{'/'}, nil
+ case 'b':
+ return []byte{'\b'}, nil
+ case 'f':
+ return []byte{'\f'}, nil
+ case 'n':
+ return []byte{'\n'}, nil
+ case 'r':
+ return []byte{'\r'}, nil
+ case 't':
+ return []byte{'\t'}, nil
+ case 'u':
+ return decodeKeyCharByUnicodeRuneStream(s)
+ case nul:
+ if !s.read() {
+ return nil, errors.ErrInvalidCharacter(s.char(), "escaped char", s.totalOffset())
+ }
+ goto RETRY
+ default:
+ return nil, errors.ErrUnexpectedEndOfJSON("struct field", s.totalOffset())
+ }
+}
+
+func decodeKeyNotFoundStream(s *Stream, start int64) (*structFieldSet, string, error) {
+ buf, cursor, p := s.stat()
+ for {
+ cursor++
+ switch char(p, cursor) {
+ case '"':
+ b := buf[start:cursor]
+ key := *(*string)(unsafe.Pointer(&b))
+ cursor++
+ s.cursor = cursor
+ return nil, key, nil
+ case '\\':
+ cursor++
+ if char(p, cursor) == nul {
+ s.cursor = cursor
+ if !s.read() {
+ return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ }
+ buf, cursor, p = s.statForRetry()
+ }
+ case nul:
+ s.cursor = cursor
+ if !s.read() {
+ return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
+ }
+ buf, cursor, p = s.statForRetry()
+ }
+ }
+}
+
+func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
+ key, err := d.stringDecoder.decodeStreamByte(s)
+ if err != nil {
+ return nil, "", err
+ }
+ k := *(*string)(unsafe.Pointer(&key))
+ return d.fieldMap[k], k, nil
+}
+
+func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return errors.ErrExceededMaxDepth(s.char(), s.cursor)
+ }
+
+ c := s.skipWhiteSpace()
+ switch c {
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return err
+ }
+ return nil
+ default:
+ if s.char() != '{' {
+ return errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
+ }
+ }
+ s.cursor++
+ if s.skipWhiteSpace() == '}' {
+ s.cursor++
+ return nil
+ }
+ var (
+ seenFields map[int]struct{}
+ seenFieldNum int
+ )
+ firstWin := (s.Option.Flags & FirstWinOption) != 0
+ if firstWin {
+ seenFields = make(map[int]struct{}, d.fieldUniqueNameNum)
+ }
+ for {
+ s.reset()
+ field, key, err := d.keyStreamDecoder(d, s)
+ if err != nil {
+ return err
+ }
+ if s.skipWhiteSpace() != ':' {
+ return errors.ErrExpected("colon after object key", s.totalOffset())
+ }
+ s.cursor++
+ if field != nil {
+ if field.err != nil {
+ return field.err
+ }
+ if firstWin {
+ if _, exists := seenFields[field.fieldIdx]; exists {
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ } else {
+ if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
+ return err
+ }
+ seenFieldNum++
+ if d.fieldUniqueNameNum <= seenFieldNum {
+ return s.skipObject(depth)
+ }
+ seenFields[field.fieldIdx] = struct{}{}
+ }
+ } else {
+ if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
+ return err
+ }
+ }
+ } else if s.DisallowUnknownFields {
+ return fmt.Errorf("json: unknown field %q", key)
+ } else {
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ }
+ c := s.skipWhiteSpace()
+ if c == '}' {
+ s.cursor++
+ return nil
+ }
+ if c != ',' {
+ return errors.ErrExpected("comma after object element", s.totalOffset())
+ }
+ s.cursor++
+ }
+}
+
+func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ depth++
+ if depth > maxDecodeNestingDepth {
+ return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
+ }
+ buflen := int64(len(buf))
+ cursor = skipWhiteSpace(buf, cursor)
+ b := (*sliceHeader)(unsafe.Pointer(&buf)).data
+ switch char(b, cursor) {
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return 0, err
+ }
+ cursor += 4
+ return cursor, nil
+ case '{':
+ default:
+ return 0, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
+ }
+ cursor++
+ cursor = skipWhiteSpace(buf, cursor)
+ if buf[cursor] == '}' {
+ cursor++
+ return cursor, nil
+ }
+ var (
+ seenFields map[int]struct{}
+ seenFieldNum int
+ )
+ firstWin := (ctx.Option.Flags & FirstWinOption) != 0
+ if firstWin {
+ seenFields = make(map[int]struct{}, d.fieldUniqueNameNum)
+ }
+ for {
+ c, field, err := d.keyDecoder(d, buf, cursor)
+ if err != nil {
+ return 0, err
+ }
+ cursor = skipWhiteSpace(buf, c)
+ if char(b, cursor) != ':' {
+ return 0, errors.ErrExpected("colon after object key", cursor)
+ }
+ cursor++
+ if cursor >= buflen {
+ return 0, errors.ErrExpected("object value after colon", cursor)
+ }
+ if field != nil {
+ if field.err != nil {
+ return 0, field.err
+ }
+ if firstWin {
+ if _, exists := seenFields[field.fieldIdx]; exists {
+ c, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ } else {
+ c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ seenFieldNum++
+ if d.fieldUniqueNameNum <= seenFieldNum {
+ return skipObject(buf, cursor, depth)
+ }
+ seenFields[field.fieldIdx] = struct{}{}
+ }
+ } else {
+ c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ }
+ } else {
+ c, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ cursor = c
+ }
+ cursor = skipWhiteSpace(buf, cursor)
+ if char(b, cursor) == '}' {
+ cursor++
+ return cursor, nil
+ }
+ if char(b, cursor) != ',' {
+ return 0, errors.ErrExpected("comma after object element", cursor)
+ }
+ cursor++
+ }
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/type.go b/vendor/github.com/goccy/go-json/internal/decoder/type.go
new file mode 100644
index 000000000..70e9907c8
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/type.go
@@ -0,0 +1,29 @@
+package decoder
+
+import (
+ "context"
+ "encoding"
+ "encoding/json"
+ "reflect"
+ "unsafe"
+)
+
+type Decoder interface {
+ Decode(*RuntimeContext, int64, int64, unsafe.Pointer) (int64, error)
+ DecodeStream(*Stream, int64, unsafe.Pointer) error
+}
+
+const (
+ nul = '\000'
+ maxDecodeNestingDepth = 10000
+)
+
+type unmarshalerContext interface {
+ UnmarshalJSON(context.Context, []byte) error
+}
+
+var (
+ unmarshalJSONType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
+ unmarshalJSONContextType = reflect.TypeOf((*unmarshalerContext)(nil)).Elem()
+ unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+)
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/uint.go b/vendor/github.com/goccy/go-json/internal/decoder/uint.go
new file mode 100644
index 000000000..a62c51492
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/uint.go
@@ -0,0 +1,190 @@
+package decoder
+
+import (
+ "fmt"
+ "reflect"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type uintDecoder struct {
+ typ *runtime.Type
+ kind reflect.Kind
+ op func(unsafe.Pointer, uint64)
+ structName string
+ fieldName string
+}
+
+func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
+ return &uintDecoder{
+ typ: typ,
+ kind: typ.Kind(),
+ op: op,
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
+ return &errors.UnmarshalTypeError{
+ Value: fmt.Sprintf("number %s", string(buf)),
+ Type: runtime.RType2Type(d.typ),
+ Offset: offset,
+ }
+}
+
+var (
+ pow10u64 = [...]uint64{
+ 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ }
+ pow10u64Len = len(pow10u64)
+)
+
+func (d *uintDecoder) parseUint(b []byte) (uint64, error) {
+ maxDigit := len(b)
+ if maxDigit > pow10u64Len {
+ return 0, fmt.Errorf("invalid length of number")
+ }
+ sum := uint64(0)
+ for i := 0; i < maxDigit; i++ {
+ c := uint64(b[i]) - 48
+ digitValue := pow10u64[maxDigit-i-1]
+ sum += c * digitValue
+ }
+ return sum, nil
+}
+
+func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
+ for {
+ switch s.char() {
+ case ' ', '\n', '\t', '\r':
+ s.cursor++
+ continue
+ case '0':
+ s.cursor++
+ return numZeroBuf, nil
+ case '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ start := s.cursor
+ for {
+ s.cursor++
+ if numTable[s.char()] {
+ continue
+ } else if s.char() == nul {
+ if s.read() {
+ s.cursor-- // for retry current character
+ continue
+ }
+ }
+ break
+ }
+ num := s.buf[start:s.cursor]
+ return num, nil
+ case 'n':
+ if err := nullBytes(s); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case nul:
+ if s.read() {
+ continue
+ }
+ default:
+ return nil, d.typeError([]byte{s.char()}, s.totalOffset())
+ }
+ break
+ }
+ return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
+}
+
+func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
+ for {
+ switch buf[cursor] {
+ case ' ', '\n', '\t', '\r':
+ cursor++
+ continue
+ case '0':
+ cursor++
+ return numZeroBuf, cursor, nil
+ case '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ start := cursor
+ cursor++
+ for numTable[buf[cursor]] {
+ cursor++
+ }
+ num := buf[start:cursor]
+ return num, cursor, nil
+ case 'n':
+ if err := validateNull(buf, cursor); err != nil {
+ return nil, 0, err
+ }
+ cursor += 4
+ return nil, cursor, nil
+ default:
+ return nil, 0, d.typeError([]byte{buf[cursor]}, cursor)
+ }
+ }
+}
+
+func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ bytes, err := d.decodeStreamByte(s)
+ if err != nil {
+ return err
+ }
+ if bytes == nil {
+ return nil
+ }
+ u64, err := d.parseUint(bytes)
+ if err != nil {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ switch d.kind {
+ case reflect.Uint8:
+ if (1 << 8) <= u64 {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ case reflect.Uint16:
+ if (1 << 16) <= u64 {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ case reflect.Uint32:
+ if (1 << 32) <= u64 {
+ return d.typeError(bytes, s.totalOffset())
+ }
+ }
+ d.op(p, u64)
+ return nil
+}
+
+func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ bytes, c, err := d.decodeByte(ctx.Buf, cursor)
+ if err != nil {
+ return 0, err
+ }
+ if bytes == nil {
+ return c, nil
+ }
+ cursor = c
+ u64, err := d.parseUint(bytes)
+ if err != nil {
+ return 0, d.typeError(bytes, cursor)
+ }
+ switch d.kind {
+ case reflect.Uint8:
+ if (1 << 8) <= u64 {
+ return 0, d.typeError(bytes, cursor)
+ }
+ case reflect.Uint16:
+ if (1 << 16) <= u64 {
+ return 0, d.typeError(bytes, cursor)
+ }
+ case reflect.Uint32:
+ if (1 << 32) <= u64 {
+ return 0, d.typeError(bytes, cursor)
+ }
+ }
+ d.op(p, u64)
+ return cursor, nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
new file mode 100644
index 000000000..d90f39cc5
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
@@ -0,0 +1,91 @@
+package decoder
+
+import (
+ "encoding/json"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type unmarshalJSONDecoder struct {
+ typ *runtime.Type
+ structName string
+ fieldName string
+}
+
+func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
+ return &unmarshalJSONDecoder{
+ typ: typ,
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
+ switch e := err.(type) {
+ case *errors.UnmarshalTypeError:
+ e.Struct = d.structName
+ e.Field = d.fieldName
+ case *errors.SyntaxError:
+ e.Offset = cursor
+ }
+}
+
+func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ s.skipWhiteSpace()
+ start := s.cursor
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ src := s.buf[start:s.cursor]
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ v := *(*interface{})(unsafe.Pointer(&emptyInterface{
+ typ: d.typ,
+ ptr: p,
+ }))
+ if (s.Option.Flags & ContextOption) != 0 {
+ if err := v.(unmarshalerContext).UnmarshalJSON(s.Option.Context, dst); err != nil {
+ d.annotateError(s.cursor, err)
+ return err
+ }
+ } else {
+ if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
+ d.annotateError(s.cursor, err)
+ return err
+ }
+ }
+ return nil
+}
+
+func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ cursor = skipWhiteSpace(buf, cursor)
+ start := cursor
+ end, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ src := buf[start:end]
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ v := *(*interface{})(unsafe.Pointer(&emptyInterface{
+ typ: d.typ,
+ ptr: p,
+ }))
+ if (ctx.Option.Flags & ContextOption) != 0 {
+ if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil {
+ d.annotateError(cursor, err)
+ return 0, err
+ }
+ } else {
+ if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
+ d.annotateError(cursor, err)
+ return 0, err
+ }
+ }
+ return end, nil
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go
new file mode 100644
index 000000000..1ef287782
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go
@@ -0,0 +1,280 @@
+package decoder
+
+import (
+ "bytes"
+ "encoding"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/errors"
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type unmarshalTextDecoder struct {
+ typ *runtime.Type
+ structName string
+ fieldName string
+}
+
+func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder {
+ return &unmarshalTextDecoder{
+ typ: typ,
+ structName: structName,
+ fieldName: fieldName,
+ }
+}
+
+func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) {
+ switch e := err.(type) {
+ case *errors.UnmarshalTypeError:
+ e.Struct = d.structName
+ e.Field = d.fieldName
+ case *errors.SyntaxError:
+ e.Offset = cursor
+ }
+}
+
+var (
+ nullbytes = []byte(`null`)
+)
+
+func (d *unmarshalTextDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ s.skipWhiteSpace()
+ start := s.cursor
+ if err := s.skipValue(depth); err != nil {
+ return err
+ }
+ src := s.buf[start:s.cursor]
+ if len(src) > 0 {
+ switch src[0] {
+ case '[':
+ return &errors.UnmarshalTypeError{
+ Value: "array",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ case '{':
+ return &errors.UnmarshalTypeError{
+ Value: "object",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return &errors.UnmarshalTypeError{
+ Value: "number",
+ Type: runtime.RType2Type(d.typ),
+ Offset: s.totalOffset(),
+ }
+ case 'n':
+ if bytes.Equal(src, nullbytes) {
+ *(*unsafe.Pointer)(p) = nil
+ return nil
+ }
+ }
+ }
+ dst := make([]byte, len(src))
+ copy(dst, src)
+
+ if b, ok := unquoteBytes(dst); ok {
+ dst = b
+ }
+ v := *(*interface{})(unsafe.Pointer(&emptyInterface{
+ typ: d.typ,
+ ptr: p,
+ }))
+ if err := v.(encoding.TextUnmarshaler).UnmarshalText(dst); err != nil {
+ d.annotateError(s.cursor, err)
+ return err
+ }
+ return nil
+}
+
+func (d *unmarshalTextDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ buf := ctx.Buf
+ cursor = skipWhiteSpace(buf, cursor)
+ start := cursor
+ end, err := skipValue(buf, cursor, depth)
+ if err != nil {
+ return 0, err
+ }
+ src := buf[start:end]
+ if len(src) > 0 {
+ switch src[0] {
+ case '[':
+ return 0, &errors.UnmarshalTypeError{
+ Value: "array",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ case '{':
+ return 0, &errors.UnmarshalTypeError{
+ Value: "object",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return 0, &errors.UnmarshalTypeError{
+ Value: "number",
+ Type: runtime.RType2Type(d.typ),
+ Offset: start,
+ }
+ case 'n':
+ if bytes.Equal(src, nullbytes) {
+ *(*unsafe.Pointer)(p) = nil
+ return end, nil
+ }
+ }
+ }
+
+ if s, ok := unquoteBytes(src); ok {
+ src = s
+ }
+ v := *(*interface{})(unsafe.Pointer(&emptyInterface{
+ typ: d.typ,
+ ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
+ }))
+ if err := v.(encoding.TextUnmarshaler).UnmarshalText(src); err != nil {
+ d.annotateError(cursor, err)
+ return 0, err
+ }
+ return end, nil
+}
+
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+ length := len(s)
+ if length < 2 || s[0] != '"' || s[length-1] != '"' {
+ return
+ }
+ s = s[1 : length-1]
+ length -= 2
+
+ // Check for unusual characters. If there are none,
+ // then no unquoting is needed, so return a slice of the
+ // original bytes.
+ r := 0
+ for r < length {
+ c := s[r]
+ if c == '\\' || c == '"' || c < ' ' {
+ break
+ }
+ if c < utf8.RuneSelf {
+ r++
+ continue
+ }
+ rr, size := utf8.DecodeRune(s[r:])
+ if rr == utf8.RuneError && size == 1 {
+ break
+ }
+ r += size
+ }
+ if r == length {
+ return s, true
+ }
+
+ b := make([]byte, length+2*utf8.UTFMax)
+ w := copy(b, s[0:r])
+ for r < length {
+ // Out of room? Can only happen if s is full of
+ // malformed UTF-8 and we're replacing each
+ // byte with RuneError.
+ if w >= len(b)-2*utf8.UTFMax {
+ nb := make([]byte, (len(b)+utf8.UTFMax)*2)
+ copy(nb, b[0:w])
+ b = nb
+ }
+ switch c := s[r]; {
+ case c == '\\':
+ r++
+ if r >= length {
+ return
+ }
+ switch s[r] {
+ default:
+ return
+ case '"', '\\', '/', '\'':
+ b[w] = s[r]
+ r++
+ w++
+ case 'b':
+ b[w] = '\b'
+ r++
+ w++
+ case 'f':
+ b[w] = '\f'
+ r++
+ w++
+ case 'n':
+ b[w] = '\n'
+ r++
+ w++
+ case 'r':
+ b[w] = '\r'
+ r++
+ w++
+ case 't':
+ b[w] = '\t'
+ r++
+ w++
+ case 'u':
+ r--
+ rr := getu4(s[r:])
+ if rr < 0 {
+ return
+ }
+ r += 6
+ if utf16.IsSurrogate(rr) {
+ rr1 := getu4(s[r:])
+ if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+ // A valid pair; consume.
+ r += 6
+ w += utf8.EncodeRune(b[w:], dec)
+ break
+ }
+ // Invalid surrogate; fall back to replacement rune.
+ rr = unicode.ReplacementChar
+ }
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+
+ // Quote, control characters are invalid.
+ case c == '"', c < ' ':
+ return
+
+ // ASCII
+ case c < utf8.RuneSelf:
+ b[w] = c
+ r++
+ w++
+
+ // Coerce to well-formed UTF-8.
+ default:
+ rr, size := utf8.DecodeRune(s[r:])
+ r += size
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+ }
+ return b[0:w], true
+}
+
+func getu4(s []byte) rune {
+ if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
+ return -1
+ }
+ var r rune
+ for _, c := range s[2:6] {
+ switch {
+ case '0' <= c && c <= '9':
+ c = c - '0'
+ case 'a' <= c && c <= 'f':
+ c = c - 'a' + 10
+ case 'A' <= c && c <= 'F':
+ c = c - 'A' + 10
+ default:
+ return -1
+ }
+ r = r*16 + rune(c)
+ }
+ return r
+}
diff --git a/vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go b/vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go
new file mode 100644
index 000000000..66227ae02
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go
@@ -0,0 +1,68 @@
+package decoder
+
+import (
+ "reflect"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+type wrappedStringDecoder struct {
+ typ *runtime.Type
+ dec Decoder
+ stringDecoder *stringDecoder
+ structName string
+ fieldName string
+ isPtrType bool
+}
+
+func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) *wrappedStringDecoder {
+ return &wrappedStringDecoder{
+ typ: typ,
+ dec: dec,
+ stringDecoder: newStringDecoder(structName, fieldName),
+ structName: structName,
+ fieldName: fieldName,
+ isPtrType: typ.Kind() == reflect.Ptr,
+ }
+}
+
+func (d *wrappedStringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
+ bytes, err := d.stringDecoder.decodeStreamByte(s)
+ if err != nil {
+ return err
+ }
+ if bytes == nil {
+ if d.isPtrType {
+ *(*unsafe.Pointer)(p) = nil
+ }
+ return nil
+ }
+ b := make([]byte, len(bytes)+1)
+ copy(b, bytes)
+ if _, err := d.dec.Decode(&RuntimeContext{Buf: b}, 0, depth, p); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (d *wrappedStringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
+ bytes, c, err := d.stringDecoder.decodeByte(ctx.Buf, cursor)
+ if err != nil {
+ return 0, err
+ }
+ if bytes == nil {
+ if d.isPtrType {
+ *(*unsafe.Pointer)(p) = nil
+ }
+ return c, nil
+ }
+ bytes = append(bytes, nul)
+ oldBuf := ctx.Buf
+ ctx.Buf = bytes
+ if _, err := d.dec.Decode(ctx, 0, depth, p); err != nil {
+ return 0, err
+ }
+ ctx.Buf = oldBuf
+ return c, nil
+}