mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 17:32:25 -05:00
migrate go version to 1.17 (#203)
* migrate go version to 1.17 * update contributing
This commit is contained in:
parent
e681aac589
commit
f2e5bedea6
282 changed files with 11863 additions and 12600 deletions
3
vendor/github.com/goccy/go-json/.codecov.yml
generated
vendored
3
vendor/github.com/goccy/go-json/.codecov.yml
generated
vendored
|
|
@ -28,4 +28,5 @@ comment:
|
|||
require_changes: no
|
||||
|
||||
ignore:
|
||||
- internal/encoder/vm_debug
|
||||
- internal/encoder/vm_color
|
||||
- internal/encoder/vm_color_indent
|
||||
|
|
|
|||
115
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
115
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
|
|
@ -1,3 +1,118 @@
|
|||
# v0.7.8 - 2021/09/01
|
||||
|
||||
* Fix mapassign_faststr for indirect struct type ( #283 )
|
||||
* Fix encoding of not empty interface type ( #284 )
|
||||
* Fix encoding of empty struct interface type ( #286 )
|
||||
|
||||
# v0.7.7 - 2021/08/25
|
||||
|
||||
* Fix invalid utf8 on stream decoder ( #279 )
|
||||
* Fix buffer length bug on string stream decoder ( #280 )
|
||||
|
||||
Thank you @orisano !!
|
||||
|
||||
# v0.7.6 - 2021/08/13
|
||||
|
||||
* Fix nil slice assignment ( #276 )
|
||||
* Improve error message ( #277 )
|
||||
|
||||
# v0.7.5 - 2021/08/12
|
||||
|
||||
* Fix encoding of embedded struct with tags ( #265 )
|
||||
* Fix encoding of embedded struct that isn't first field ( #272 )
|
||||
* Fix decoding of binary type with escaped char ( #273 )
|
||||
|
||||
# v0.7.4 - 2021/07/06
|
||||
|
||||
* Fix encoding of indirect layout structure ( #264 )
|
||||
|
||||
# v0.7.3 - 2021/06/29
|
||||
|
||||
* Fix encoding of pointer type in empty interface ( #262 )
|
||||
|
||||
# v0.7.2 - 2021/06/26
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Add decoder for func type to fix decoding of nil function value ( #257 )
|
||||
* Fix stream decoding of []byte type ( #258 )
|
||||
|
||||
### Performance
|
||||
|
||||
* Improve decoding performance of map[string]interface{} type ( use `mapassign_faststr` ) ( #256 )
|
||||
* Improve encoding performance of empty interface type ( remove recursive calling of `vm.Run` ) ( #259 )
|
||||
|
||||
### Benchmark
|
||||
|
||||
* Add bytedance/sonic as benchmark target ( #254 )
|
||||
|
||||
# v0.7.1 - 2021/06/18
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix error when unmarshal empty array ( #253 )
|
||||
|
||||
# v0.7.0 - 2021/06/12
|
||||
|
||||
### Support context for MarshalJSON and UnmarshalJSON ( #248 )
|
||||
|
||||
* json.MarshalContext(context.Context, interface{}, ...json.EncodeOption) ([]byte, error)
|
||||
* json.NewEncoder(io.Writer).EncodeContext(context.Context, interface{}, ...json.EncodeOption) error
|
||||
* json.UnmarshalContext(context.Context, []byte, interface{}, ...json.DecodeOption) error
|
||||
* json.NewDecoder(io.Reader).DecodeContext(context.Context, interface{}) error
|
||||
|
||||
```go
|
||||
type MarshalerContext interface {
|
||||
MarshalJSON(context.Context) ([]byte, error)
|
||||
}
|
||||
|
||||
type UnmarshalerContext interface {
|
||||
UnmarshalJSON(context.Context, []byte) error
|
||||
}
|
||||
```
|
||||
|
||||
### Add DecodeFieldPriorityFirstWin option ( #242 )
|
||||
|
||||
In the default behavior, go-json, like encoding/json, will reflect the result of the last evaluation when a field with the same name exists. I've added new options to allow you to change this behavior. `json.DecodeFieldPriorityFirstWin` option reflects the result of the first evaluation if a field with the same name exists. This behavior has a performance advantage as it allows the subsequent strings to be skipped if all fields have been evaluated.
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix indent number contains recursive type ( #249 )
|
||||
* Fix encoding of using empty interface as map key ( #244 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoding fields containing escaped characters ( #237 )
|
||||
|
||||
### Refactor
|
||||
|
||||
* Move some tests to subdirectory ( #243 )
|
||||
* Refactor package layout for decoder ( #238 )
|
||||
|
||||
# v0.6.1 - 2021/06/02
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix value of totalLength for encoding ( #236 )
|
||||
|
||||
# v0.6.0 - 2021/06/01
|
||||
|
||||
### Support Colorize option for encoding (#233)
|
||||
|
||||
```go
|
||||
b, err := json.MarshalWithOption(v, json.Colorize(json.DefaultColorScheme))
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
fmt.Println(string(b)) // print colored json
|
||||
```
|
||||
|
||||
### Refactor
|
||||
|
||||
* Fix opcode layout - Adjust memory layout of the opcode to 128 bytes in a 64-bit environment ( #230 )
|
||||
* Refactor encode option ( #231 )
|
||||
* Refactor escape string ( #232 )
|
||||
|
||||
# v0.5.1 - 2021/5/20
|
||||
|
||||
### Optimization
|
||||
|
|
|
|||
4
vendor/github.com/goccy/go-json/Makefile
generated
vendored
4
vendor/github.com/goccy/go-json/Makefile
generated
vendored
|
|
@ -1,7 +1,7 @@
|
|||
PKG := github.com/goccy/go-json
|
||||
|
||||
BIN_DIR := $(CURDIR)/bin
|
||||
PKGS := $(shell go list ./... | grep -v internal/cmd)
|
||||
PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test)
|
||||
COVER_PKGS := $(foreach pkg,$(PKGS),$(subst $(PKG),.,$(pkg)))
|
||||
|
||||
COMMA := ,
|
||||
|
|
@ -14,7 +14,7 @@ $(BIN_DIR):
|
|||
|
||||
.PHONY: cover
|
||||
cover:
|
||||
go test -coverpkg=$(COVERPKG_OPT) -coverprofile=cover.out .
|
||||
go test -coverpkg=$(COVERPKG_OPT) -coverprofile=cover.out ./...
|
||||
|
||||
.PHONY: cover-html
|
||||
cover-html: cover
|
||||
|
|
|
|||
40
vendor/github.com/goccy/go-json/README.md
generated
vendored
40
vendor/github.com/goccy/go-json/README.md
generated
vendored
|
|
@ -13,23 +13,26 @@ Fast JSON encoder/decoder compatible with encoding/json for Go
|
|||
```
|
||||
* version ( expected release date )
|
||||
|
||||
* v0.5.0
|
||||
|
|
||||
| refactor all sources for maintainability and improve performance
|
||||
|
|
||||
v
|
||||
* v0.6.0 ( 2021/05 Mid )
|
||||
* v0.7.0
|
||||
|
|
||||
| while maintaining compatibility with encoding/json, we will add convenient APIs
|
||||
|
|
||||
v
|
||||
* v1.0.0 ( 2021/06 Mid )
|
||||
* v1.0.0
|
||||
```
|
||||
|
||||
We are accepting requests for features that will be implemented between v0.6.0 and v.1.0.0.
|
||||
We are accepting requests for features that will be implemented between v0.7.0 and v.1.0.0.
|
||||
If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues).
|
||||
For example, I'm thinking of supporting `context.Context` of `json.Marshaler` and decoding using JSON Path.
|
||||
|
||||
# Features
|
||||
|
||||
- Drop-in replacement of `encoding/json`
|
||||
- Fast ( See [Benchmark section](https://github.com/goccy/go-json#benchmarks) )
|
||||
- Flexible customization with options
|
||||
- Coloring the encoded string
|
||||
- Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON`
|
||||
|
||||
# Installation
|
||||
|
||||
```
|
||||
|
|
@ -53,13 +56,26 @@ Replace import statement from `encoding/json` to `github.com/goccy/go-json`
|
|||
| [json-iterator/go](https://github.com/json-iterator/go) | yes | yes | partial |
|
||||
| [easyjson](https://github.com/mailru/easyjson) | yes | yes | no |
|
||||
| [gojay](https://github.com/francoispqt/gojay) | yes | yes | no |
|
||||
| [segmentio/encoding/json](https://github.com/segmentio/encoding/tree/master/json) | yes | yes | yes |
|
||||
| [segmentio/encoding/json](https://github.com/segmentio/encoding/tree/master/json) | yes | yes | partial |
|
||||
| [jettison](https://github.com/wI2L/jettison) | yes | no | no |
|
||||
| [simdjson-go](https://github.com/minio/simdjson-go) | no | yes | no |
|
||||
| goccy/go-json | yes | yes | yes |
|
||||
|
||||
- `json-iterator/go` isn't compatible with `encoding/json` in many ways, but it hasn't been supported for a long time.
|
||||
- `json-iterator/go` isn't compatible with `encoding/json` in many ways (e.g. https://github.com/json-iterator/go/issues/229 ), but it hasn't been supported for a long time.
|
||||
- `segmentio/encoding/json` is well supported for encoders, but some are not supported for decoder APIs such as `Token` ( streaming decode )
|
||||
|
||||
## Other libraries
|
||||
|
||||
- [jingo](https://github.com/bet365/jingo)
|
||||
|
||||
I tried the benchmark but it didn't work.
|
||||
Also, it seems to panic when it receives an unexpected value because there is no error handling...
|
||||
|
||||
- [ffjson](https://github.com/pquerna/ffjson)
|
||||
|
||||
Benchmarking gave very slow results.
|
||||
It seems that it is assumed that the user will use the buffer pool properly.
|
||||
Also, development seems to have already stopped
|
||||
|
||||
# Benchmarks
|
||||
|
||||
|
|
@ -176,7 +192,7 @@ For this reason, to date `reflect.Type` is the same as `*reflect.rtype`.
|
|||
|
||||
Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`.
|
||||
|
||||
The technique for working with `*reflect.rtype` directly from `go-json` is implemented at https://github.com/goccy/go-json/blob/master/rtype.go.
|
||||
The technique for working with `*reflect.rtype` directly from `go-json` is implemented at [rtype.go](https://github.com/goccy/go-json/blob/master/internal/runtime/rtype.go)
|
||||
|
||||
Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect )
|
||||
|
||||
|
|
@ -337,7 +353,7 @@ However, if there is too much type information, it will use a lot of memory, so
|
|||
|
||||
If this approach is not available, it will fall back to the `atomic` based process described above.
|
||||
|
||||
If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/codec.go#L24-L76 )
|
||||
If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/internal/runtime/type.go#L36-L100)
|
||||
|
||||
## Decoder
|
||||
|
||||
|
|
|
|||
104
vendor/github.com/goccy/go-json/codec.go
generated
vendored
104
vendor/github.com/goccy/go-json/codec.go
generated
vendored
|
|
@ -1,104 +0,0 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
maxAcceptableTypeAddrRange = 1024 * 1024 * 2 // 2 Mib
|
||||
)
|
||||
|
||||
var (
|
||||
cachedDecoder []decoder
|
||||
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
|
||||
baseTypeAddr uintptr
|
||||
maxTypeAddr uintptr
|
||||
typeAddrShift uintptr
|
||||
)
|
||||
|
||||
//go:linkname typelinks reflect.typelinks
|
||||
func typelinks() ([]unsafe.Pointer, [][]int32)
|
||||
|
||||
//go:linkname rtypeOff reflect.rtypeOff
|
||||
func rtypeOff(unsafe.Pointer, int32) unsafe.Pointer
|
||||
|
||||
func setupCodec() error {
|
||||
sections, offsets := typelinks()
|
||||
if len(sections) != 1 {
|
||||
return fmt.Errorf("failed to get sections")
|
||||
}
|
||||
if len(offsets) != 1 {
|
||||
return fmt.Errorf("failed to get offsets")
|
||||
}
|
||||
section := sections[0]
|
||||
offset := offsets[0]
|
||||
var (
|
||||
min uintptr = uintptr(^uint(0))
|
||||
max uintptr = 0
|
||||
isAligned64 = true
|
||||
isAligned32 = true
|
||||
)
|
||||
for i := 0; i < len(offset); i++ {
|
||||
typ := (*rtype)(rtypeOff(section, offset[i]))
|
||||
addr := uintptr(unsafe.Pointer(typ))
|
||||
if min > addr {
|
||||
min = addr
|
||||
}
|
||||
if max < addr {
|
||||
max = addr
|
||||
}
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
addr = uintptr(unsafe.Pointer(typ.Elem()))
|
||||
if min > addr {
|
||||
min = addr
|
||||
}
|
||||
if max < addr {
|
||||
max = addr
|
||||
}
|
||||
}
|
||||
|
||||
// check every address is aligned from the base address
|
||||
isAligned64 = isAligned64 && (addr-min)&63 == 0
|
||||
isAligned32 = isAligned32 && (addr-min)&31 == 0
|
||||
}
|
||||
addrRange := max - min
|
||||
if addrRange == 0 {
|
||||
return fmt.Errorf("failed to get address range of types")
|
||||
}
|
||||
if isAligned64 {
|
||||
typeAddrShift = 6
|
||||
} else if isAligned32 {
|
||||
typeAddrShift = 5
|
||||
}
|
||||
cacheSize := addrRange >> typeAddrShift
|
||||
if cacheSize > maxAcceptableTypeAddrRange {
|
||||
return fmt.Errorf("too big address range %d", addrRange)
|
||||
}
|
||||
cachedDecoder = make([]decoder, cacheSize)
|
||||
baseTypeAddr = min
|
||||
maxTypeAddr = max
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
_ = setupCodec()
|
||||
}
|
||||
|
||||
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)))
|
||||
}
|
||||
68
vendor/github.com/goccy/go-json/color.go
generated
vendored
Normal file
68
vendor/github.com/goccy/go-json/color.go
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goccy/go-json/internal/encoder"
|
||||
)
|
||||
|
||||
type (
|
||||
ColorFormat = encoder.ColorFormat
|
||||
ColorScheme = encoder.ColorScheme
|
||||
)
|
||||
|
||||
const escape = "\x1b"
|
||||
|
||||
type colorAttr int
|
||||
|
||||
//nolint:deadcode,varcheck
|
||||
const (
|
||||
fgBlackColor colorAttr = iota + 30
|
||||
fgRedColor
|
||||
fgGreenColor
|
||||
fgYellowColor
|
||||
fgBlueColor
|
||||
fgMagentaColor
|
||||
fgCyanColor
|
||||
fgWhiteColor
|
||||
)
|
||||
|
||||
//nolint:deadcode,varcheck
|
||||
const (
|
||||
fgHiBlackColor colorAttr = iota + 90
|
||||
fgHiRedColor
|
||||
fgHiGreenColor
|
||||
fgHiYellowColor
|
||||
fgHiBlueColor
|
||||
fgHiMagentaColor
|
||||
fgHiCyanColor
|
||||
fgHiWhiteColor
|
||||
)
|
||||
|
||||
func createColorFormat(attr colorAttr) ColorFormat {
|
||||
return ColorFormat{
|
||||
Header: wrapColor(attr),
|
||||
Footer: resetColor(),
|
||||
}
|
||||
}
|
||||
|
||||
func wrapColor(attr colorAttr) string {
|
||||
return fmt.Sprintf("%s[%dm", escape, attr)
|
||||
}
|
||||
|
||||
func resetColor() string {
|
||||
return wrapColor(colorAttr(0))
|
||||
}
|
||||
|
||||
var (
|
||||
DefaultColorScheme = &ColorScheme{
|
||||
Int: createColorFormat(fgHiMagentaColor),
|
||||
Uint: createColorFormat(fgHiMagentaColor),
|
||||
Float: createColorFormat(fgHiMagentaColor),
|
||||
Bool: createColorFormat(fgHiYellowColor),
|
||||
String: createColorFormat(fgHiGreenColor),
|
||||
Binary: createColorFormat(fgHiRedColor),
|
||||
ObjectKey: createColorFormat(fgHiCyanColor),
|
||||
Null: createColorFormat(fgBlueColor),
|
||||
}
|
||||
)
|
||||
219
vendor/github.com/goccy/go-json/decode.go
generated
vendored
219
vendor/github.com/goccy/go-json/decode.go
generated
vendored
|
|
@ -1,34 +1,31 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type decoder interface {
|
||||
decode([]byte, int64, int64, unsafe.Pointer) (int64, error)
|
||||
decodeStream(*stream, int64, unsafe.Pointer) error
|
||||
}
|
||||
"github.com/goccy/go-json/internal/decoder"
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type Decoder struct {
|
||||
s *stream
|
||||
s *decoder.Stream
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalJSONType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
||||
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
const (
|
||||
nul = '\000'
|
||||
maxDecodeNestingDepth = 10000
|
||||
nul = '\000'
|
||||
)
|
||||
|
||||
func unmarshal(data []byte, v interface{}) error {
|
||||
type emptyInterface struct {
|
||||
typ *runtime.Type
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func unmarshal(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||
copy(src, data)
|
||||
|
||||
|
|
@ -37,18 +34,26 @@ func unmarshal(data []byte, v interface{}) error {
|
|||
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
||||
return err
|
||||
}
|
||||
dec, err := decodeCompileToGetDecoder(header.typ)
|
||||
dec, err := decoder.CompileToGetDecoder(header.typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cursor, err := dec.decode(src, 0, 0, header.ptr)
|
||||
ctx := decoder.TakeRuntimeContext()
|
||||
ctx.Buf = src
|
||||
ctx.Option.Flags = 0
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(ctx.Option)
|
||||
}
|
||||
cursor, err := dec.Decode(ctx, 0, 0, header.ptr)
|
||||
if err != nil {
|
||||
decoder.ReleaseRuntimeContext(ctx)
|
||||
return err
|
||||
}
|
||||
decoder.ReleaseRuntimeContext(ctx)
|
||||
return validateEndBuf(src, cursor)
|
||||
}
|
||||
|
||||
func unmarshalNoEscape(data []byte, v interface{}) error {
|
||||
func unmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||
copy(src, data)
|
||||
|
||||
|
|
@ -57,14 +62,53 @@ func unmarshalNoEscape(data []byte, v interface{}) error {
|
|||
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
||||
return err
|
||||
}
|
||||
dec, err := decodeCompileToGetDecoder(header.typ)
|
||||
dec, err := decoder.CompileToGetDecoder(header.typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cursor, err := dec.decode(src, 0, 0, noescape(header.ptr))
|
||||
rctx := decoder.TakeRuntimeContext()
|
||||
rctx.Buf = src
|
||||
rctx.Option.Flags = 0
|
||||
rctx.Option.Flags |= decoder.ContextOption
|
||||
rctx.Option.Context = ctx
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(rctx.Option)
|
||||
}
|
||||
cursor, err := dec.Decode(rctx, 0, 0, header.ptr)
|
||||
if err != nil {
|
||||
decoder.ReleaseRuntimeContext(rctx)
|
||||
return err
|
||||
}
|
||||
decoder.ReleaseRuntimeContext(rctx)
|
||||
return validateEndBuf(src, cursor)
|
||||
}
|
||||
|
||||
func unmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||
copy(src, data)
|
||||
|
||||
header := (*emptyInterface)(unsafe.Pointer(&v))
|
||||
|
||||
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
||||
return err
|
||||
}
|
||||
dec, err := decoder.CompileToGetDecoder(header.typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := decoder.TakeRuntimeContext()
|
||||
ctx.Buf = src
|
||||
ctx.Option.Flags = 0
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(ctx.Option)
|
||||
}
|
||||
cursor, err := dec.Decode(ctx, 0, 0, noescape(header.ptr))
|
||||
if err != nil {
|
||||
decoder.ReleaseRuntimeContext(ctx)
|
||||
return err
|
||||
}
|
||||
decoder.ReleaseRuntimeContext(ctx)
|
||||
return validateEndBuf(src, cursor)
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +121,7 @@ func validateEndBuf(src []byte, cursor int64) error {
|
|||
case nul:
|
||||
return nil
|
||||
}
|
||||
return errSyntax(
|
||||
return errors.ErrSyntax(
|
||||
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
|
||||
cursor+1,
|
||||
)
|
||||
|
|
@ -91,9 +135,9 @@ func noescape(p unsafe.Pointer) unsafe.Pointer {
|
|||
return unsafe.Pointer(x ^ 0)
|
||||
}
|
||||
|
||||
func validateType(typ *rtype, p uintptr) error {
|
||||
func validateType(typ *runtime.Type, p uintptr) error {
|
||||
if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
|
||||
return &InvalidUnmarshalError{Type: rtype2type(typ)}
|
||||
return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -103,7 +147,7 @@ func validateType(typ *rtype, p uintptr) error {
|
|||
// The decoder introduces its own buffering and may
|
||||
// read data from r beyond the JSON values requested.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
s := newStream(r)
|
||||
s := decoder.NewStream(r)
|
||||
return &Decoder{
|
||||
s: s,
|
||||
}
|
||||
|
|
@ -112,28 +156,7 @@ func NewDecoder(r io.Reader) *Decoder {
|
|||
// Buffered returns a reader of the data remaining in the Decoder's
|
||||
// buffer. The reader is valid until the next call to Decode.
|
||||
func (d *Decoder) Buffered() io.Reader {
|
||||
return d.s.buffered()
|
||||
}
|
||||
|
||||
func (d *Decoder) prepareForDecode() error {
|
||||
s := d.s
|
||||
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
|
||||
return d.s.Buffered()
|
||||
}
|
||||
|
||||
// Decode reads the next JSON-encoded value from its
|
||||
|
|
@ -142,120 +165,68 @@ func (d *Decoder) prepareForDecode() error {
|
|||
// See the documentation for Unmarshal for details about
|
||||
// the conversion of JSON into a Go value.
|
||||
func (d *Decoder) Decode(v interface{}) error {
|
||||
return d.DecodeWithOption(v)
|
||||
}
|
||||
|
||||
// DecodeContext reads the next JSON-encoded value from its
|
||||
// input and stores it in the value pointed to by v with context.Context.
|
||||
func (d *Decoder) DecodeContext(ctx context.Context, v interface{}) error {
|
||||
d.s.Option.Flags |= decoder.ContextOption
|
||||
d.s.Option.Context = ctx
|
||||
return d.DecodeWithOption(v)
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeWithOption(v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||
header := (*emptyInterface)(unsafe.Pointer(&v))
|
||||
typ := header.typ
|
||||
ptr := uintptr(header.ptr)
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
||||
|
||||
if err := validateType(copiedType, ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dec, err := decodeCompileToGetDecoder(typ)
|
||||
dec, err := decoder.CompileToGetDecoder(typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.prepareForDecode(); err != nil {
|
||||
if err := d.s.PrepareForDecode(); err != nil {
|
||||
return err
|
||||
}
|
||||
s := d.s
|
||||
if err := dec.decodeStream(s, 0, header.ptr); err != nil {
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(s.Option)
|
||||
}
|
||||
if err := dec.DecodeStream(s, 0, header.ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
s.reset()
|
||||
s.bufSize = initBufSize
|
||||
s.Reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) More() bool {
|
||||
s := d.s
|
||||
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
|
||||
return d.s.More()
|
||||
}
|
||||
|
||||
func (d *Decoder) Token() (Token, error) {
|
||||
s := d.s
|
||||
for {
|
||||
c := s.char()
|
||||
switch c {
|
||||
case ' ', '\n', '\r', '\t':
|
||||
s.cursor++
|
||||
case '{', '[', ']', '}':
|
||||
s.cursor++
|
||||
return 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, errInvalidCharacter(s.char(), "token", s.totalOffset())
|
||||
}
|
||||
}
|
||||
END:
|
||||
return nil, io.EOF
|
||||
return d.s.Token()
|
||||
}
|
||||
|
||||
// DisallowUnknownFields causes the Decoder to return an error when the destination
|
||||
// is a struct and the input contains object keys which do not match any
|
||||
// non-ignored, exported fields in the destination.
|
||||
func (d *Decoder) DisallowUnknownFields() {
|
||||
d.s.disallowUnknownFields = true
|
||||
d.s.DisallowUnknownFields = true
|
||||
}
|
||||
|
||||
func (d *Decoder) InputOffset() int64 {
|
||||
return d.s.totalOffset()
|
||||
return d.s.TotalOffset()
|
||||
}
|
||||
|
||||
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
||||
// Number instead of as a float64.
|
||||
func (d *Decoder) UseNumber() {
|
||||
d.s.useNumber = true
|
||||
d.s.UseNumber = true
|
||||
}
|
||||
|
|
|
|||
35
vendor/github.com/goccy/go-json/decode_anonymous_field.go
generated
vendored
35
vendor/github.com/goccy/go-json/decode_anonymous_field.go
generated
vendored
|
|
@ -1,35 +0,0 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type anonymousFieldDecoder struct {
|
||||
structType *rtype
|
||||
offset uintptr
|
||||
dec decoder
|
||||
}
|
||||
|
||||
func newAnonymousFieldDecoder(structType *rtype, 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(buf []byte, 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(buf, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
|
||||
}
|
||||
172
vendor/github.com/goccy/go-json/decode_bytes.go
generated
vendored
172
vendor/github.com/goccy/go-json/decode_bytes.go
generated
vendored
|
|
@ -1,172 +0,0 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type bytesDecoder struct {
|
||||
typ *rtype
|
||||
sliceDecoder decoder
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func byteUnmarshalerSliceDecoder(typ *rtype, structName string, fieldName string) decoder {
|
||||
var unmarshalDecoder decoder
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
unmarshalDecoder = newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName)
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
unmarshalDecoder = newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName)
|
||||
}
|
||||
if unmarshalDecoder == nil {
|
||||
return nil
|
||||
}
|
||||
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
|
||||
}
|
||||
|
||||
func newBytesDecoder(typ *rtype, structName string, fieldName string) *bytesDecoder {
|
||||
return &bytesDecoder{
|
||||
typ: typ,
|
||||
sliceDecoder: byteUnmarshalerSliceDecoder(typ, 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)
|
||||
if _, err := base64.StdEncoding.Decode(buf, bytes); err != nil {
|
||||
return err
|
||||
}
|
||||
*(*[]byte)(p) = buf
|
||||
s.reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *bytesDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
bytes, c, err := d.decodeBinary(buf, 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 binaryBytes(s *stream) ([]byte, error) {
|
||||
s.cursor++
|
||||
start := s.cursor
|
||||
for {
|
||||
switch s.char() {
|
||||
case '"':
|
||||
literal := s.buf[start:s.cursor]
|
||||
s.cursor++
|
||||
return literal, nil
|
||||
case nul:
|
||||
if s.read() {
|
||||
continue
|
||||
}
|
||||
goto ERROR
|
||||
}
|
||||
s.cursor++
|
||||
}
|
||||
ERROR:
|
||||
return nil, errUnexpectedEndOfJSON("[]byte", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Pointer) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
s.cursor++
|
||||
continue
|
||||
case '"':
|
||||
return binaryBytes(s)
|
||||
case 'n':
|
||||
if err := nullBytes(s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
case '[':
|
||||
if d.sliceDecoder == nil {
|
||||
return nil, &UnmarshalTypeError{
|
||||
Type: rtype2type(d.typ),
|
||||
Offset: s.totalOffset(),
|
||||
}
|
||||
}
|
||||
if err := d.sliceDecoder.decodeStream(s, depth, p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
case nul:
|
||||
if s.read() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil, errNotAtBeginningOfValue(s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
|
||||
for {
|
||||
switch buf[cursor] {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
cursor++
|
||||
case '"':
|
||||
cursor++
|
||||
start := cursor
|
||||
for {
|
||||
switch buf[cursor] {
|
||||
case '"':
|
||||
literal := buf[start:cursor]
|
||||
cursor++
|
||||
return literal, cursor, nil
|
||||
case nul:
|
||||
return nil, 0, errUnexpectedEndOfJSON("[]byte", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
case '[':
|
||||
if d.sliceDecoder == nil {
|
||||
return nil, 0, &UnmarshalTypeError{
|
||||
Type: rtype2type(d.typ),
|
||||
Offset: cursor,
|
||||
}
|
||||
}
|
||||
c, err := d.sliceDecoder.decode(buf, cursor, depth, p)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return nil, c, nil
|
||||
case 'n':
|
||||
if err := validateNull(buf, cursor); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
cursor += 4
|
||||
return nil, cursor, nil
|
||||
default:
|
||||
return nil, 0, errNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
24
vendor/github.com/goccy/go-json/decode_compile_norace.go
generated
vendored
24
vendor/github.com/goccy/go-json/decode_compile_norace.go
generated
vendored
|
|
@ -1,24 +0,0 @@
|
|||
// +build !race
|
||||
|
||||
package json
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
if typeptr > maxTypeAddr {
|
||||
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
|
||||
}
|
||||
|
||||
index := (typeptr - baseTypeAddr) >> typeAddrShift
|
||||
if dec := cachedDecoder[index]; dec != nil {
|
||||
return dec, nil
|
||||
}
|
||||
|
||||
dec, err := decodeCompileHead(typ, map[uintptr]decoder{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cachedDecoder[index] = dec
|
||||
return dec, nil
|
||||
}
|
||||
154
vendor/github.com/goccy/go-json/decode_map.go
generated
vendored
154
vendor/github.com/goccy/go-json/decode_map.go
generated
vendored
|
|
@ -1,154 +0,0 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type mapDecoder struct {
|
||||
mapType *rtype
|
||||
keyType *rtype
|
||||
valueType *rtype
|
||||
keyDecoder decoder
|
||||
valueDecoder decoder
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newMapDecoder(mapType *rtype, keyType *rtype, keyDec decoder, valueType *rtype, valueDec decoder, structName, fieldName string) *mapDecoder {
|
||||
return &mapDecoder{
|
||||
mapType: mapType,
|
||||
keyDecoder: keyDec,
|
||||
keyType: keyType,
|
||||
valueType: valueType,
|
||||
valueDecoder: valueDec,
|
||||
structName: structName,
|
||||
fieldName: fieldName,
|
||||
}
|
||||
}
|
||||
|
||||
//go:linkname makemap reflect.makemap
|
||||
func makemap(*rtype, int) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign reflect.mapassign
|
||||
//go:noescape
|
||||
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
|
||||
|
||||
func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
s.skipWhiteSpace()
|
||||
switch s.char() {
|
||||
case 'n':
|
||||
if err := nullBytes(s); err != nil {
|
||||
return err
|
||||
}
|
||||
**(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil
|
||||
return nil
|
||||
case '{':
|
||||
default:
|
||||
return errExpected("{ character for map value", s.totalOffset())
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
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 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
|
||||
}
|
||||
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 errExpected("comma after object value", s.totalOffset())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
buflen := int64(len(buf))
|
||||
if buflen < 2 {
|
||||
return 0, 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, 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(buf, cursor, depth, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cursor = skipWhiteSpace(buf, keyCursor)
|
||||
if buf[cursor] != ':' {
|
||||
return 0, errExpected("colon after object key", cursor)
|
||||
}
|
||||
cursor++
|
||||
v := unsafe_New(d.valueType)
|
||||
valueCursor, err := d.valueDecoder.decode(buf, cursor, depth, v)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
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, errExpected("comma after object value", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
}
|
||||
623
vendor/github.com/goccy/go-json/decode_struct.go
generated
vendored
623
vendor/github.com/goccy/go-json/decode_struct.go
generated
vendored
|
|
@ -1,623 +0,0 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/bits"
|
||||
"sort"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type structFieldSet struct {
|
||||
dec decoder
|
||||
offset uintptr
|
||||
isTaggedKey bool
|
||||
key string
|
||||
keyLen int64
|
||||
err error
|
||||
}
|
||||
|
||||
type structDecoder struct {
|
||||
fieldMap map[string]*structFieldSet
|
||||
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() {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
|
||||
var (
|
||||
field *structFieldSet
|
||||
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, field, nil
|
||||
case nul:
|
||||
return 0, nil, 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, errUnexpectedEndOfJSON("string", cursor)
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
for {
|
||||
cursor++
|
||||
switch char(b, cursor) {
|
||||
case '"':
|
||||
cursor++
|
||||
return cursor, field, nil
|
||||
case '\\':
|
||||
cursor++
|
||||
if char(b, cursor) == nul {
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
keyIdx++
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
default:
|
||||
return cursor, nil, errNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
|
||||
var (
|
||||
field *structFieldSet
|
||||
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, field, nil
|
||||
case nul:
|
||||
return 0, nil, 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, errUnexpectedEndOfJSON("string", cursor)
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
for {
|
||||
cursor++
|
||||
switch char(b, cursor) {
|
||||
case '"':
|
||||
cursor++
|
||||
return cursor, field, nil
|
||||
case '\\':
|
||||
cursor++
|
||||
if char(b, cursor) == nul {
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
keyIdx++
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
default:
|
||||
return cursor, nil, errNotAtBeginningOfValue(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 (
|
||||
field *structFieldSet
|
||||
curBit uint8 = math.MaxUint8
|
||||
)
|
||||
buf, cursor, p := s.stat()
|
||||
for {
|
||||
switch char(p, cursor) {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
cursor++
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if s.read() {
|
||||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
||||
case '"':
|
||||
cursor++
|
||||
FIRST_CHAR:
|
||||
start := cursor
|
||||
switch char(p, cursor) {
|
||||
case '"':
|
||||
cursor++
|
||||
s.cursor = cursor
|
||||
return field, "", nil
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if s.read() {
|
||||
buf, cursor, p = s.stat()
|
||||
goto FIRST_CHAR
|
||||
}
|
||||
return nil, "", 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() {
|
||||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
for {
|
||||
cursor++
|
||||
switch char(p, cursor) {
|
||||
case '"':
|
||||
b := buf[start:cursor]
|
||||
key := *(*string)(unsafe.Pointer(&b))
|
||||
cursor++
|
||||
s.cursor = cursor
|
||||
return field, key, nil
|
||||
case '\\':
|
||||
cursor++
|
||||
if char(p, cursor) == nul {
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
}
|
||||
}
|
||||
keyIdx++
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
default:
|
||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
|
||||
var (
|
||||
field *structFieldSet
|
||||
curBit uint16 = math.MaxUint16
|
||||
)
|
||||
buf, cursor, p := s.stat()
|
||||
for {
|
||||
switch char(p, cursor) {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
cursor++
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if s.read() {
|
||||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
||||
case '"':
|
||||
cursor++
|
||||
FIRST_CHAR:
|
||||
start := cursor
|
||||
switch char(p, cursor) {
|
||||
case '"':
|
||||
cursor++
|
||||
s.cursor = cursor
|
||||
return field, "", nil
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if s.read() {
|
||||
buf, cursor, p = s.stat()
|
||||
goto FIRST_CHAR
|
||||
}
|
||||
return nil, "", 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() {
|
||||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
for {
|
||||
cursor++
|
||||
switch char(p, cursor) {
|
||||
case '"':
|
||||
b := buf[start:cursor]
|
||||
key := *(*string)(unsafe.Pointer(&b))
|
||||
cursor++
|
||||
s.cursor = cursor
|
||||
return field, key, nil
|
||||
case '\\':
|
||||
cursor++
|
||||
if char(p, cursor) == nul {
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
}
|
||||
}
|
||||
keyIdx++
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
default:
|
||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 errExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
s.skipWhiteSpace()
|
||||
switch s.char() {
|
||||
case 'n':
|
||||
if err := nullBytes(s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case nul:
|
||||
s.read()
|
||||
default:
|
||||
if s.char() != '{' {
|
||||
return errNotAtBeginningOfValue(s.totalOffset())
|
||||
}
|
||||
}
|
||||
s.cursor++
|
||||
s.skipWhiteSpace()
|
||||
if s.char() == '}' {
|
||||
s.cursor++
|
||||
return nil
|
||||
}
|
||||
for {
|
||||
s.reset()
|
||||
field, key, err := d.keyStreamDecoder(d, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
if s.char() != ':' {
|
||||
return errExpected("colon after object key", s.totalOffset())
|
||||
}
|
||||
s.cursor++
|
||||
if s.char() == nul {
|
||||
if !s.read() {
|
||||
return errExpected("object value after colon", s.totalOffset())
|
||||
}
|
||||
}
|
||||
if field != nil {
|
||||
if field.err != nil {
|
||||
return field.err
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
c := s.char()
|
||||
if c == '}' {
|
||||
s.cursor++
|
||||
return nil
|
||||
}
|
||||
if c != ',' {
|
||||
return errExpected("comma after object element", s.totalOffset())
|
||||
}
|
||||
s.cursor++
|
||||
}
|
||||
}
|
||||
|
||||
func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, 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, errNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
cursor++
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
if buf[cursor] == '}' {
|
||||
cursor++
|
||||
return cursor, nil
|
||||
}
|
||||
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, errExpected("colon after object key", cursor)
|
||||
}
|
||||
cursor++
|
||||
if cursor >= buflen {
|
||||
return 0, errExpected("object value after colon", cursor)
|
||||
}
|
||||
if field != nil {
|
||||
if field.err != nil {
|
||||
return 0, field.err
|
||||
}
|
||||
c, err := field.dec.decode(buf, 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, errExpected("comma after object element", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
}
|
||||
72
vendor/github.com/goccy/go-json/decode_unmarshal_json.go
generated
vendored
72
vendor/github.com/goccy/go-json/decode_unmarshal_json.go
generated
vendored
|
|
@ -1,72 +0,0 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type unmarshalJSONDecoder struct {
|
||||
typ *rtype
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newUnmarshalJSONDecoder(typ *rtype, 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 *UnmarshalTypeError:
|
||||
e.Struct = d.structName
|
||||
e.Field = d.fieldName
|
||||
case *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 err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||
d.annotateError(s.cursor, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *unmarshalJSONDecoder) decode(buf []byte, cursor, depth int64, 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]
|
||||
dst := make([]byte, len(src))
|
||||
copy(dst, src)
|
||||
|
||||
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
|
||||
typ: d.typ,
|
||||
ptr: p,
|
||||
}))
|
||||
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||
d.annotateError(cursor, err)
|
||||
return 0, err
|
||||
}
|
||||
return end, nil
|
||||
}
|
||||
159
vendor/github.com/goccy/go-json/encode.go
generated
vendored
159
vendor/github.com/goccy/go-json/encode.go
generated
vendored
|
|
@ -1,13 +1,14 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/encoder"
|
||||
"github.com/goccy/go-json/internal/encoder/vm"
|
||||
"github.com/goccy/go-json/internal/encoder/vm_escaped"
|
||||
"github.com/goccy/go-json/internal/encoder/vm_escaped_indent"
|
||||
"github.com/goccy/go-json/internal/encoder/vm_color"
|
||||
"github.com/goccy/go-json/internal/encoder/vm_color_indent"
|
||||
"github.com/goccy/go-json/internal/encoder/vm_indent"
|
||||
)
|
||||
|
||||
|
|
@ -20,15 +21,6 @@ type Encoder struct {
|
|||
indentStr string
|
||||
}
|
||||
|
||||
type EncodeOption int
|
||||
|
||||
const (
|
||||
EncodeOptionHTMLEscape EncodeOption = 1 << iota
|
||||
EncodeOptionIndent
|
||||
EncodeOptionUnorderedMap
|
||||
EncodeOptionDebug
|
||||
)
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w, enabledHTMLEscape: true}
|
||||
|
|
@ -44,6 +36,7 @@ func (e *Encoder) Encode(v interface{}) error {
|
|||
// EncodeWithOption call Encode with EncodeOption.
|
||||
func (e *Encoder) EncodeWithOption(v interface{}, optFuncs ...EncodeOptionFunc) error {
|
||||
ctx := encoder.TakeRuntimeContext()
|
||||
ctx.Option.Flag = 0
|
||||
|
||||
err := e.encodeWithOption(ctx, v, optFuncs...)
|
||||
|
||||
|
|
@ -51,22 +44,34 @@ func (e *Encoder) EncodeWithOption(v interface{}, optFuncs ...EncodeOptionFunc)
|
|||
return err
|
||||
}
|
||||
|
||||
// EncodeContext call Encode with context.Context and EncodeOption.
|
||||
func (e *Encoder) EncodeContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) error {
|
||||
rctx := encoder.TakeRuntimeContext()
|
||||
rctx.Option.Flag = 0
|
||||
rctx.Option.Flag |= encoder.ContextOption
|
||||
rctx.Option.Context = ctx
|
||||
|
||||
err := e.encodeWithOption(rctx, v, optFuncs...)
|
||||
|
||||
encoder.ReleaseRuntimeContext(rctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, optFuncs ...EncodeOptionFunc) error {
|
||||
var opt EncodeOption
|
||||
if e.enabledHTMLEscape {
|
||||
opt |= EncodeOptionHTMLEscape
|
||||
ctx.Option.Flag |= encoder.HTMLEscapeOption
|
||||
}
|
||||
for _, optFunc := range optFuncs {
|
||||
opt = optFunc(opt)
|
||||
optFunc(ctx.Option)
|
||||
}
|
||||
var (
|
||||
buf []byte
|
||||
err error
|
||||
)
|
||||
if e.enabledIndent {
|
||||
buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr, opt)
|
||||
buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr)
|
||||
} else {
|
||||
buf, err = encode(ctx, v, opt)
|
||||
buf, err = encode(ctx, v)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -103,10 +108,43 @@ func (e *Encoder) SetIndent(prefix, indent string) {
|
|||
e.enabledIndent = true
|
||||
}
|
||||
|
||||
func marshal(v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||
rctx := encoder.TakeRuntimeContext()
|
||||
rctx.Option.Flag = 0
|
||||
rctx.Option.Flag = encoder.HTMLEscapeOption | encoder.ContextOption
|
||||
rctx.Option.Context = ctx
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(rctx.Option)
|
||||
}
|
||||
|
||||
buf, err := encode(rctx, v)
|
||||
if err != nil {
|
||||
encoder.ReleaseRuntimeContext(rctx)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// this line exists to escape call of `runtime.makeslicecopy` .
|
||||
// if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`,
|
||||
// dst buffer size and src buffer size are differrent.
|
||||
// in this case, compiler uses `runtime.makeslicecopy`, but it is slow.
|
||||
buf = buf[:len(buf)-1]
|
||||
copied := make([]byte, len(buf))
|
||||
copy(copied, buf)
|
||||
|
||||
encoder.ReleaseRuntimeContext(rctx)
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
func marshal(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||
ctx := encoder.TakeRuntimeContext()
|
||||
|
||||
buf, err := encode(ctx, v, opt|EncodeOptionHTMLEscape)
|
||||
ctx.Option.Flag = 0
|
||||
ctx.Option.Flag |= encoder.HTMLEscapeOption
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(ctx.Option)
|
||||
}
|
||||
|
||||
buf, err := encode(ctx, v)
|
||||
if err != nil {
|
||||
encoder.ReleaseRuntimeContext(ctx)
|
||||
return nil, err
|
||||
|
|
@ -124,10 +162,13 @@ func marshal(v interface{}, opt EncodeOption) ([]byte, error) {
|
|||
return copied, nil
|
||||
}
|
||||
|
||||
func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
func marshalNoEscape(v interface{}) ([]byte, error) {
|
||||
ctx := encoder.TakeRuntimeContext()
|
||||
|
||||
buf, err := encodeNoEscape(ctx, v, opt|EncodeOptionHTMLEscape)
|
||||
ctx.Option.Flag = 0
|
||||
ctx.Option.Flag |= encoder.HTMLEscapeOption
|
||||
|
||||
buf, err := encodeNoEscape(ctx, v)
|
||||
if err != nil {
|
||||
encoder.ReleaseRuntimeContext(ctx)
|
||||
return nil, err
|
||||
|
|
@ -145,10 +186,16 @@ func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) {
|
|||
return copied, nil
|
||||
}
|
||||
|
||||
func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) {
|
||||
func marshalIndent(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||
ctx := encoder.TakeRuntimeContext()
|
||||
|
||||
buf, err := encodeIndent(ctx, v, prefix, indent, opt|EncodeOptionHTMLEscape)
|
||||
ctx.Option.Flag = 0
|
||||
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.IndentOption)
|
||||
for _, optFunc := range optFuncs {
|
||||
optFunc(ctx.Option)
|
||||
}
|
||||
|
||||
buf, err := encodeIndent(ctx, v, prefix, indent)
|
||||
if err != nil {
|
||||
encoder.ReleaseRuntimeContext(ctx)
|
||||
return nil, err
|
||||
|
|
@ -162,11 +209,11 @@ func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]by
|
|||
return copied, nil
|
||||
}
|
||||
|
||||
func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
func encode(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) {
|
||||
b := ctx.Buf[:0]
|
||||
if v == nil {
|
||||
b = encoder.AppendNull(b)
|
||||
b = encoder.AppendComma(b)
|
||||
b = encoder.AppendNull(ctx, b)
|
||||
b = encoder.AppendComma(ctx, b)
|
||||
return b, nil
|
||||
}
|
||||
header := (*emptyInterface)(unsafe.Pointer(&v))
|
||||
|
|
@ -182,7 +229,7 @@ func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byt
|
|||
ctx.Init(p, codeSet.CodeLength)
|
||||
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
|
||||
|
||||
buf, err := encodeRunCode(ctx, b, codeSet, opt)
|
||||
buf, err := encodeRunCode(ctx, b, codeSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -190,11 +237,11 @@ func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byt
|
|||
return buf, nil
|
||||
}
|
||||
|
||||
func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
||||
func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) {
|
||||
b := ctx.Buf[:0]
|
||||
if v == nil {
|
||||
b = encoder.AppendNull(b)
|
||||
b = encoder.AppendComma(b)
|
||||
b = encoder.AppendNull(ctx, b)
|
||||
b = encoder.AppendComma(ctx, b)
|
||||
return b, nil
|
||||
}
|
||||
header := (*emptyInterface)(unsafe.Pointer(&v))
|
||||
|
|
@ -208,7 +255,7 @@ func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption
|
|||
|
||||
p := uintptr(header.ptr)
|
||||
ctx.Init(p, codeSet.CodeLength)
|
||||
buf, err := encodeRunCode(ctx, b, codeSet, opt)
|
||||
buf, err := encodeRunCode(ctx, b, codeSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -217,11 +264,11 @@ func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption
|
|||
return buf, nil
|
||||
}
|
||||
|
||||
func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) {
|
||||
func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent string) ([]byte, error) {
|
||||
b := ctx.Buf[:0]
|
||||
if v == nil {
|
||||
b = encoder.AppendNull(b)
|
||||
b = encoder.AppendCommaIndent(b)
|
||||
b = encoder.AppendNull(ctx, b)
|
||||
b = encoder.AppendCommaIndent(ctx, b)
|
||||
return b, nil
|
||||
}
|
||||
header := (*emptyInterface)(unsafe.Pointer(&v))
|
||||
|
|
@ -235,7 +282,7 @@ func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent str
|
|||
|
||||
p := uintptr(header.ptr)
|
||||
ctx.Init(p, codeSet.CodeLength)
|
||||
buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent, opt)
|
||||
buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent)
|
||||
|
||||
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
|
||||
|
||||
|
|
@ -247,38 +294,30 @@ func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent str
|
|||
return buf, nil
|
||||
}
|
||||
|
||||
func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt EncodeOption) ([]byte, error) {
|
||||
if (opt & EncodeOptionDebug) != 0 {
|
||||
return encodeDebugRunCode(ctx, b, codeSet, opt)
|
||||
func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||
if (ctx.Option.Flag & encoder.DebugOption) != 0 {
|
||||
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
|
||||
return vm_color.DebugRun(ctx, b, codeSet)
|
||||
}
|
||||
return vm.DebugRun(ctx, b, codeSet)
|
||||
}
|
||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
||||
return vm_escaped.Run(ctx, b, codeSet, encoder.Option(opt))
|
||||
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
|
||||
return vm_color.Run(ctx, b, codeSet)
|
||||
}
|
||||
return vm.Run(ctx, b, codeSet, encoder.Option(opt))
|
||||
return vm.Run(ctx, b, codeSet)
|
||||
}
|
||||
|
||||
func encodeDebugRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt EncodeOption) ([]byte, error) {
|
||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
||||
return vm_escaped.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
||||
}
|
||||
return vm.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
||||
}
|
||||
|
||||
func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string, opt EncodeOption) ([]byte, error) {
|
||||
func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string) ([]byte, error) {
|
||||
ctx.Prefix = []byte(prefix)
|
||||
ctx.IndentStr = []byte(indent)
|
||||
if (opt & EncodeOptionDebug) != 0 {
|
||||
return encodeDebugRunIndentCode(ctx, b, codeSet, opt)
|
||||
if (ctx.Option.Flag & encoder.DebugOption) != 0 {
|
||||
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
|
||||
return vm_color_indent.DebugRun(ctx, b, codeSet)
|
||||
}
|
||||
return vm_indent.DebugRun(ctx, b, codeSet)
|
||||
}
|
||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
||||
return vm_escaped_indent.Run(ctx, b, codeSet, encoder.Option(opt))
|
||||
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
|
||||
return vm_color_indent.Run(ctx, b, codeSet)
|
||||
}
|
||||
return vm_indent.Run(ctx, b, codeSet, encoder.Option(opt))
|
||||
}
|
||||
|
||||
func encodeDebugRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt EncodeOption) ([]byte, error) {
|
||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
||||
return vm_escaped_indent.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
||||
}
|
||||
return vm_indent.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
||||
return vm_indent.Run(ctx, b, codeSet)
|
||||
}
|
||||
|
|
|
|||
10
vendor/github.com/goccy/go-json/error.go
generated
vendored
10
vendor/github.com/goccy/go-json/error.go
generated
vendored
|
|
@ -37,13 +37,3 @@ type UnmarshalTypeError = errors.UnmarshalTypeError
|
|||
type UnsupportedTypeError = errors.UnsupportedTypeError
|
||||
|
||||
type UnsupportedValueError = errors.UnsupportedValueError
|
||||
|
||||
var (
|
||||
errExceededMaxDepth = errors.ErrExceededMaxDepth
|
||||
errNotAtBeginningOfValue = errors.ErrNotAtBeginningOfValue
|
||||
errUnexpectedEndOfJSON = errors.ErrUnexpectedEndOfJSON
|
||||
errExpected = errors.ErrExpected
|
||||
errInvalidCharacter = errors.ErrInvalidCharacter
|
||||
errSyntax = errors.ErrSyntax
|
||||
errMarshaler = errors.ErrMarshaler
|
||||
)
|
||||
|
|
|
|||
3
vendor/github.com/goccy/go-json/go.mod
generated
vendored
3
vendor/github.com/goccy/go-json/go.mod
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
module github.com/goccy/go-json
|
||||
|
||||
go 1.12
|
||||
0
vendor/github.com/goccy/go-json/go.sum
generated
vendored
0
vendor/github.com/goccy/go-json/go.sum
generated
vendored
37
vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go
generated
vendored
Normal file
37
vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go
generated
vendored
Normal file
|
|
@ -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))
|
||||
}
|
||||
|
|
@ -1,20 +1,23 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type arrayDecoder struct {
|
||||
elemType *rtype
|
||||
elemType *runtime.Type
|
||||
size uintptr
|
||||
valueDecoder decoder
|
||||
valueDecoder Decoder
|
||||
alen int
|
||||
structName string
|
||||
fieldName string
|
||||
zeroValue unsafe.Pointer
|
||||
}
|
||||
|
||||
func newArrayDecoder(dec decoder, elemType *rtype, alen int, structName, fieldName string) *arrayDecoder {
|
||||
func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
|
||||
zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
|
||||
return &arrayDecoder{
|
||||
valueDecoder: dec,
|
||||
|
|
@ -27,10 +30,10 @@ func newArrayDecoder(dec decoder, elemType *rtype, alen int, structName, fieldNa
|
|||
}
|
||||
}
|
||||
|
||||
func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
@ -43,10 +46,18 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
return nil
|
||||
case '[':
|
||||
idx := 0
|
||||
for {
|
||||
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 {
|
||||
if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
|
@ -55,8 +66,7 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
}
|
||||
}
|
||||
idx++
|
||||
s.skipWhiteSpace()
|
||||
switch s.char() {
|
||||
switch s.skipWhiteSpace() {
|
||||
case ']':
|
||||
for idx < d.alen {
|
||||
*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
|
||||
|
|
@ -65,9 +75,11 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
s.cursor++
|
||||
return nil
|
||||
case ',':
|
||||
s.cursor++
|
||||
continue
|
||||
case nul:
|
||||
if s.read() {
|
||||
s.cursor++
|
||||
continue
|
||||
}
|
||||
goto ERROR
|
||||
|
|
@ -86,13 +98,14 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
s.cursor++
|
||||
}
|
||||
ERROR:
|
||||
return errUnexpectedEndOfJSON("array", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
buf := ctx.Buf
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
@ -108,10 +121,19 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
return cursor, nil
|
||||
case '[':
|
||||
idx := 0
|
||||
for {
|
||||
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(buf, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
|
||||
c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -134,13 +156,14 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
cursor++
|
||||
return cursor, nil
|
||||
case ',':
|
||||
cursor++
|
||||
continue
|
||||
default:
|
||||
return 0, errInvalidCharacter(buf[cursor], "array", cursor)
|
||||
return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return 0, errUnexpectedEndOfJSON("array", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type boolDecoder struct {
|
||||
|
|
@ -13,10 +15,10 @@ func newBoolDecoder(structName, fieldName string) *boolDecoder {
|
|||
return &boolDecoder{structName: structName, fieldName: fieldName}
|
||||
}
|
||||
|
||||
func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
s.skipWhiteSpace()
|
||||
func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
c := s.skipWhiteSpace()
|
||||
for {
|
||||
switch s.char() {
|
||||
switch c {
|
||||
case 't':
|
||||
if err := trueBytes(s); err != nil {
|
||||
return err
|
||||
|
|
@ -36,6 +38,7 @@ func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
|
|||
return nil
|
||||
case nul:
|
||||
if s.read() {
|
||||
c = s.char()
|
||||
continue
|
||||
}
|
||||
goto ERROR
|
||||
|
|
@ -43,10 +46,11 @@ func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
|
|||
break
|
||||
}
|
||||
ERROR:
|
||||
return errUnexpectedEndOfJSON("bool", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("bool", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
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':
|
||||
|
|
@ -70,5 +74,5 @@ func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
cursor += 4
|
||||
return cursor, nil
|
||||
}
|
||||
return 0, errUnexpectedEndOfJSON("bool", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
|
||||
}
|
||||
114
vendor/github.com/goccy/go-json/internal/decoder/bytes.go
generated
vendored
Normal file
114
vendor/github.com/goccy/go-json/internal/decoder/bytes.go
generated
vendored
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -1,27 +1,56 @@
|
|||
package json
|
||||
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(""))
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
typeAddr *runtime.TypeAddr
|
||||
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
|
||||
cachedDecoder []Decoder
|
||||
)
|
||||
|
||||
func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, error) {
|
||||
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 := decodeCompileHead(typ, map[uintptr]decoder{})
|
||||
dec, err := compileHead(typ, map[uintptr]Decoder{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -29,84 +58,88 @@ func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, er
|
|||
return dec, nil
|
||||
}
|
||||
|
||||
func decodeCompileHead(typ *rtype, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func compileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil
|
||||
case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
|
||||
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil
|
||||
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||
return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil
|
||||
}
|
||||
return decodeCompile(typ.Elem(), "", "", structTypeToDecoder)
|
||||
return compile(typ.Elem(), "", "", structTypeToDecoder)
|
||||
}
|
||||
|
||||
func decodeCompile(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||
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 decodeCompilePtr(typ, structName, fieldName, structTypeToDecoder)
|
||||
return compilePtr(typ, structName, fieldName, structTypeToDecoder)
|
||||
case reflect.Struct:
|
||||
return decodeCompileStruct(typ, structName, fieldName, structTypeToDecoder)
|
||||
return compileStruct(typ, structName, fieldName, structTypeToDecoder)
|
||||
case reflect.Slice:
|
||||
elem := typ.Elem()
|
||||
if elem.Kind() == reflect.Uint8 {
|
||||
return decodeCompileBytes(elem, structName, fieldName)
|
||||
return compileBytes(elem, structName, fieldName)
|
||||
}
|
||||
return decodeCompileSlice(typ, structName, fieldName, structTypeToDecoder)
|
||||
return compileSlice(typ, structName, fieldName, structTypeToDecoder)
|
||||
case reflect.Array:
|
||||
return decodeCompileArray(typ, structName, fieldName, structTypeToDecoder)
|
||||
return compileArray(typ, structName, fieldName, structTypeToDecoder)
|
||||
case reflect.Map:
|
||||
return decodeCompileMap(typ, structName, fieldName, structTypeToDecoder)
|
||||
return compileMap(typ, structName, fieldName, structTypeToDecoder)
|
||||
case reflect.Interface:
|
||||
return decodeCompileInterface(typ, structName, fieldName)
|
||||
return compileInterface(typ, structName, fieldName)
|
||||
case reflect.Uintptr:
|
||||
return decodeCompileUint(typ, structName, fieldName)
|
||||
return compileUint(typ, structName, fieldName)
|
||||
case reflect.Int:
|
||||
return decodeCompileInt(typ, structName, fieldName)
|
||||
return compileInt(typ, structName, fieldName)
|
||||
case reflect.Int8:
|
||||
return decodeCompileInt8(typ, structName, fieldName)
|
||||
return compileInt8(typ, structName, fieldName)
|
||||
case reflect.Int16:
|
||||
return decodeCompileInt16(typ, structName, fieldName)
|
||||
return compileInt16(typ, structName, fieldName)
|
||||
case reflect.Int32:
|
||||
return decodeCompileInt32(typ, structName, fieldName)
|
||||
return compileInt32(typ, structName, fieldName)
|
||||
case reflect.Int64:
|
||||
return decodeCompileInt64(typ, structName, fieldName)
|
||||
return compileInt64(typ, structName, fieldName)
|
||||
case reflect.Uint:
|
||||
return decodeCompileUint(typ, structName, fieldName)
|
||||
return compileUint(typ, structName, fieldName)
|
||||
case reflect.Uint8:
|
||||
return decodeCompileUint8(typ, structName, fieldName)
|
||||
return compileUint8(typ, structName, fieldName)
|
||||
case reflect.Uint16:
|
||||
return decodeCompileUint16(typ, structName, fieldName)
|
||||
return compileUint16(typ, structName, fieldName)
|
||||
case reflect.Uint32:
|
||||
return decodeCompileUint32(typ, structName, fieldName)
|
||||
return compileUint32(typ, structName, fieldName)
|
||||
case reflect.Uint64:
|
||||
return decodeCompileUint64(typ, structName, fieldName)
|
||||
return compileUint64(typ, structName, fieldName)
|
||||
case reflect.String:
|
||||
return decodeCompileString(typ, structName, fieldName)
|
||||
return compileString(typ, structName, fieldName)
|
||||
case reflect.Bool:
|
||||
return decodeCompileBool(structName, fieldName)
|
||||
return compileBool(structName, fieldName)
|
||||
case reflect.Float32:
|
||||
return decodeCompileFloat32(structName, fieldName)
|
||||
return compileFloat32(structName, fieldName)
|
||||
case reflect.Float64:
|
||||
return decodeCompileFloat64(structName, fieldName)
|
||||
return compileFloat64(structName, fieldName)
|
||||
case reflect.Func:
|
||||
return compileFunc(typ, structName, fieldName)
|
||||
}
|
||||
return nil, &UnmarshalTypeError{
|
||||
return nil, &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(typ),
|
||||
Type: runtime.RType2Type(typ),
|
||||
Offset: 0,
|
||||
Struct: structName,
|
||||
Field: fieldName,
|
||||
}
|
||||
}
|
||||
|
||||
func isStringTagSupportedType(typ *rtype) bool {
|
||||
func isStringTagSupportedType(typ *runtime.Type) bool {
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
|
||||
return false
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||
return false
|
||||
}
|
||||
switch typ.Kind() {
|
||||
|
|
@ -124,11 +157,11 @@ func isStringTagSupportedType(typ *rtype) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
if rtype_ptrTo(typ).Implements(unmarshalTextType) {
|
||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||
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 := decodeCompile(typ, structName, fieldName, structTypeToDecoder)
|
||||
dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -145,145 +178,151 @@ func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToD
|
|||
}
|
||||
}
|
||||
ERROR:
|
||||
return nil, &UnmarshalTypeError{
|
||||
return nil, &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(typ),
|
||||
Type: runtime.RType2Type(typ),
|
||||
Offset: 0,
|
||||
Struct: structName,
|
||||
Field: fieldName,
|
||||
}
|
||||
}
|
||||
|
||||
func decodeCompilePtr(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
dec, err := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder)
|
||||
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 decodeCompileInt(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileInt8(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileInt16(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileInt32(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileInt64(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileUint(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileUint8(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileUint16(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileUint32(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileUint64(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
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 decodeCompileFloat32(structName, fieldName string) (decoder, error) {
|
||||
func compileFloat32(structName, fieldName string) (Decoder, error) {
|
||||
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||
*(*float32)(p) = float32(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileFloat64(structName, fieldName string) (decoder, error) {
|
||||
func compileFloat64(structName, fieldName string) (Decoder, error) {
|
||||
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||
*(*float64)(p) = v
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileString(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
if typ == type2rtype(jsonNumberType) {
|
||||
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
|
||||
*(*Number)(p) = v
|
||||
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 decodeCompileBool(structName, fieldName string) (decoder, error) {
|
||||
func compileBool(structName, fieldName string) (Decoder, error) {
|
||||
return newBoolDecoder(structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileBytes(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func compileBytes(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||
return newBytesDecoder(typ, structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileSlice(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func compileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||
elem := typ.Elem()
|
||||
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
|
||||
decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileArray(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func compileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||
elem := typ.Elem()
|
||||
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
|
||||
decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileMap(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
keyDec, err := decodeCompileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
|
||||
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 := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder)
|
||||
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 decodeCompileInterface(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func compileInterface(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||
return newInterfaceDecoder(typ, structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeRemoveConflictFields(fieldMap map[string]*structFieldSet, conflictedMap map[string]struct{}, dec *structDecoder, field reflect.StructField) {
|
||||
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
|
||||
|
|
@ -338,7 +377,7 @@ func decodeRemoveConflictFields(fieldMap map[string]*structFieldSet, conflictedM
|
|||
}
|
||||
}
|
||||
|
||||
func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
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{}
|
||||
|
|
@ -356,17 +395,17 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
|
|||
}
|
||||
isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
|
||||
tag := runtime.StructTagFromField(field)
|
||||
dec, err := decodeCompile(type2rtype(field.Type), structName, field.Name, structTypeToDecoder)
|
||||
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 type2rtype(field.Type) == typ {
|
||||
if runtime.Type2RType(field.Type) == typ {
|
||||
// recursive definition
|
||||
continue
|
||||
}
|
||||
decodeRemoveConflictFields(fieldMap, conflictedMap, stDec, field)
|
||||
removeConflictFields(fieldMap, conflictedMap, stDec, field)
|
||||
} else if pdec, ok := dec.(*ptrDecoder); ok {
|
||||
contentDec := pdec.contentDecoder()
|
||||
if pdec.typ == typ {
|
||||
|
|
@ -438,8 +477,8 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if tag.IsString && isStringTagSupportedType(type2rtype(field.Type)) {
|
||||
dec = newWrappedStringDecoder(type2rtype(field.Type), dec, structName, field.Name)
|
||||
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
|
||||
dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name)
|
||||
}
|
||||
var key string
|
||||
if tag.Key != "" {
|
||||
|
|
@ -465,3 +504,7 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
|
|||
structDec.tryOptimize()
|
||||
return structDec, nil
|
||||
}
|
||||
|
||||
func implementsUnmarshalJSONType(typ *runtime.Type) bool {
|
||||
return typ.Implements(unmarshalJSONType) || typ.Implements(unmarshalJSONContextType)
|
||||
}
|
||||
28
vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go
generated
vendored
Normal file
28
vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -1,21 +1,23 @@
|
|||
// +build race
|
||||
|
||||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
var decMu sync.RWMutex
|
||||
|
||||
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
||||
func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
if typeptr > maxTypeAddr {
|
||||
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
|
||||
if typeptr > typeAddr.MaxTypeAddr {
|
||||
return compileToGetDecoderSlowPath(typeptr, typ)
|
||||
}
|
||||
|
||||
index := (typeptr - baseTypeAddr) >> typeAddrShift
|
||||
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
||||
decMu.RLock()
|
||||
if dec := cachedDecoder[index]; dec != nil {
|
||||
decMu.RUnlock()
|
||||
|
|
@ -23,7 +25,7 @@ func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
|||
}
|
||||
decMu.RUnlock()
|
||||
|
||||
dec, err := decodeCompileHead(typ, map[uintptr]decoder{})
|
||||
dec, err := compileHead(typ, map[uintptr]Decoder{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -1,9 +1,35 @@
|
|||
package json
|
||||
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{}
|
||||
)
|
||||
|
|
@ -34,7 +60,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
|||
braceCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case '}':
|
||||
depth--
|
||||
|
|
@ -45,7 +71,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '[':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case ']':
|
||||
depth--
|
||||
|
|
@ -56,16 +82,16 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '\\':
|
||||
cursor++
|
||||
if buf[cursor] == nul {
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("object of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
|
|
@ -80,7 +106,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
|||
bracketCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case ']':
|
||||
bracketCount--
|
||||
|
|
@ -91,7 +117,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '{':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case '}':
|
||||
depth--
|
||||
|
|
@ -102,16 +128,16 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '\\':
|
||||
cursor++
|
||||
if buf[cursor] == nul {
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("array of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
|
|
@ -135,12 +161,12 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '\\':
|
||||
cursor++
|
||||
if buf[cursor] == nul {
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
return cursor + 1, nil
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
|
|
@ -171,58 +197,58 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
|
|||
cursor += 4
|
||||
return cursor, nil
|
||||
default:
|
||||
return cursor, errUnexpectedEndOfJSON("null", cursor)
|
||||
return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func validateTrue(buf []byte, cursor int64) error {
|
||||
if cursor+3 >= int64(len(buf)) {
|
||||
return errUnexpectedEndOfJSON("true", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("true", cursor)
|
||||
}
|
||||
if buf[cursor+1] != 'r' {
|
||||
return errInvalidCharacter(buf[cursor+1], "true", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor)
|
||||
}
|
||||
if buf[cursor+2] != 'u' {
|
||||
return errInvalidCharacter(buf[cursor+2], "true", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
|
||||
}
|
||||
if buf[cursor+3] != 'e' {
|
||||
return errInvalidCharacter(buf[cursor+3], "true", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateFalse(buf []byte, cursor int64) error {
|
||||
if cursor+4 >= int64(len(buf)) {
|
||||
return errUnexpectedEndOfJSON("false", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("false", cursor)
|
||||
}
|
||||
if buf[cursor+1] != 'a' {
|
||||
return errInvalidCharacter(buf[cursor+1], "false", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor)
|
||||
}
|
||||
if buf[cursor+2] != 'l' {
|
||||
return errInvalidCharacter(buf[cursor+2], "false", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
|
||||
}
|
||||
if buf[cursor+3] != 's' {
|
||||
return errInvalidCharacter(buf[cursor+3], "false", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor)
|
||||
}
|
||||
if buf[cursor+4] != 'e' {
|
||||
return errInvalidCharacter(buf[cursor+4], "false", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateNull(buf []byte, cursor int64) error {
|
||||
if cursor+3 >= int64(len(buf)) {
|
||||
return errUnexpectedEndOfJSON("null", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("null", cursor)
|
||||
}
|
||||
if buf[cursor+1] != 'u' {
|
||||
return errInvalidCharacter(buf[cursor+1], "null", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor)
|
||||
}
|
||||
if buf[cursor+2] != 'l' {
|
||||
return errInvalidCharacter(buf[cursor+2], "null", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
|
||||
}
|
||||
if buf[cursor+3] != 'l' {
|
||||
return errInvalidCharacter(buf[cursor+3], "null", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type floatDecoder struct {
|
||||
|
|
@ -47,7 +49,7 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func floatBytes(s *stream) []byte {
|
||||
func floatBytes(s *Stream) []byte {
|
||||
start := s.cursor
|
||||
for {
|
||||
s.cursor++
|
||||
|
|
@ -64,7 +66,7 @@ func floatBytes(s *stream) []byte {
|
|||
return s.buf[start:s.cursor]
|
||||
}
|
||||
|
||||
func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
|
@ -87,7 +89,7 @@ func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
}
|
||||
}
|
||||
ERROR:
|
||||
return nil, errUnexpectedEndOfJSON("float", s.totalOffset())
|
||||
return nil, errors.ErrUnexpectedEndOfJSON("float", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||
|
|
@ -111,12 +113,12 @@ func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, erro
|
|||
cursor += 4
|
||||
return nil, cursor, nil
|
||||
default:
|
||||
return nil, 0, errUnexpectedEndOfJSON("float", cursor)
|
||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *floatDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
bytes, err := d.decodeStreamByte(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -127,13 +129,14 @@ func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
str := *(*string)(unsafe.Pointer(&bytes))
|
||||
f64, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil {
|
||||
return errSyntax(err.Error(), s.totalOffset())
|
||||
return errors.ErrSyntax(err.Error(), s.totalOffset())
|
||||
}
|
||||
d.op(p, f64)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *floatDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
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
|
||||
|
|
@ -143,12 +146,12 @@ func (d *floatDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
}
|
||||
cursor = c
|
||||
if !validEndNumberChar[buf[cursor]] {
|
||||
return 0, errUnexpectedEndOfJSON("float", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
|
||||
}
|
||||
s := *(*string)(unsafe.Pointer(&bytes))
|
||||
f64, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return 0, errSyntax(err.Error(), cursor)
|
||||
return 0, errors.ErrSyntax(err.Error(), cursor)
|
||||
}
|
||||
d.op(p, f64)
|
||||
return cursor, nil
|
||||
141
vendor/github.com/goccy/go-json/internal/decoder/func.go
generated
vendored
Normal file
141
vendor/github.com/goccy/go-json/internal/decoder/func.go
generated
vendored
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -1,20 +1,23 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type intDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
kind reflect.Kind
|
||||
op func(unsafe.Pointer, int64)
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newIntDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
|
||||
func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
|
||||
return &intDecoder{
|
||||
typ: typ,
|
||||
kind: typ.Kind(),
|
||||
|
|
@ -24,10 +27,10 @@ func newIntDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Poin
|
|||
}
|
||||
}
|
||||
|
||||
func (d *intDecoder) typeError(buf []byte, offset int64) *UnmarshalTypeError {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: fmt.Sprintf("number %s", string(buf)),
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Struct: d.structName,
|
||||
Field: d.fieldName,
|
||||
Offset: offset,
|
||||
|
|
@ -79,7 +82,11 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
var (
|
||||
numZeroBuf = []byte{'0'}
|
||||
)
|
||||
|
||||
func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
|
@ -106,7 +113,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
return num, nil
|
||||
case '0':
|
||||
s.cursor++
|
||||
return []byte{'0'}, nil
|
||||
return numZeroBuf, nil
|
||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
start := s.cursor
|
||||
for {
|
||||
|
|
@ -138,7 +145,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
}
|
||||
}
|
||||
ERROR:
|
||||
return nil, errUnexpectedEndOfJSON("number(integer)", s.totalOffset())
|
||||
return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||
|
|
@ -150,7 +157,7 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
|
|||
continue
|
||||
case '0':
|
||||
cursor++
|
||||
return []byte{'0'}, cursor, nil
|
||||
return numZeroBuf, cursor, nil
|
||||
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
start := cursor
|
||||
cursor++
|
||||
|
|
@ -171,7 +178,7 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
|
|||
}
|
||||
}
|
||||
|
||||
func (d *intDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
bytes, err := d.decodeStreamByte(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -202,8 +209,8 @@ func (d *intDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *intDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
bytes, c, err := d.decodeByte(buf, cursor)
|
||||
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
|
||||
}
|
||||
|
|
@ -1,14 +1,18 @@
|
|||
package json
|
||||
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 *rtype
|
||||
typ *runtime.Type
|
||||
structName string
|
||||
fieldName string
|
||||
sliceDecoder *sliceDecoder
|
||||
|
|
@ -26,7 +30,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
|
|||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||
*(*interface{})(p) = v
|
||||
}),
|
||||
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
|
||||
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
||||
*(*interface{})(p) = v
|
||||
}),
|
||||
stringDecoder: newStringDecoder(structName, fieldName),
|
||||
|
|
@ -49,7 +53,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
|
|||
return ifaceDecoder
|
||||
}
|
||||
|
||||
func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder {
|
||||
func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
|
||||
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
|
||||
stringDecoder := newStringDecoder(structName, fieldName)
|
||||
return &interfaceDecoder{
|
||||
|
|
@ -74,31 +78,31 @@ func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDec
|
|||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||
*(*interface{})(p) = v
|
||||
}),
|
||||
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
|
||||
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 {
|
||||
func (d *interfaceDecoder) numDecoder(s *Stream) Decoder {
|
||||
if s.UseNumber {
|
||||
return d.numberDecoder
|
||||
}
|
||||
return d.floatDecoder
|
||||
}
|
||||
|
||||
var (
|
||||
emptyInterfaceType = type2rtype(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||
interfaceMapType = type2rtype(
|
||||
emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||
interfaceMapType = runtime.Type2RType(
|
||||
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
|
||||
)
|
||||
stringType = type2rtype(
|
||||
stringType = runtime.Type2RType(
|
||||
reflect.TypeOf(""),
|
||||
)
|
||||
)
|
||||
|
||||
func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) error {
|
||||
func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
|
||||
start := s.cursor
|
||||
if err := s.skipValue(depth); err != nil {
|
||||
return err
|
||||
|
|
@ -113,7 +117,22 @@ func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) er
|
|||
return nil
|
||||
}
|
||||
|
||||
func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler) (int64, error) {
|
||||
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)
|
||||
|
|
@ -130,7 +149,24 @@ func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler)
|
|||
return end, nil
|
||||
}
|
||||
|
||||
func decodeStreamTextUnmarshaler(s *stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error {
|
||||
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
|
||||
|
|
@ -171,14 +207,14 @@ func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding
|
|||
return end, nil
|
||||
}
|
||||
|
||||
func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
s.skipWhiteSpace()
|
||||
func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
c := s.skipWhiteSpace()
|
||||
for {
|
||||
switch s.char() {
|
||||
switch c {
|
||||
case '{':
|
||||
var v map[string]interface{}
|
||||
ptr := unsafe.Pointer(&v)
|
||||
if err := d.mapDecoder.decodeStream(s, depth, ptr); err != nil {
|
||||
if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
*(*interface{})(p) = v
|
||||
|
|
@ -186,20 +222,20 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
|||
case '[':
|
||||
var v []interface{}
|
||||
ptr := unsafe.Pointer(&v)
|
||||
if err := d.sliceDecoder.decodeStream(s, depth, ptr); err != nil {
|
||||
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)
|
||||
return d.numDecoder(s).DecodeStream(s, depth, p)
|
||||
case '"':
|
||||
s.cursor++
|
||||
start := s.cursor
|
||||
for {
|
||||
switch s.char() {
|
||||
case '\\':
|
||||
if err := decodeEscapeString(s); err != nil {
|
||||
if _, err := decodeEscapeString(s, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
case '"':
|
||||
|
|
@ -211,7 +247,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
|||
if s.read() {
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
s.cursor++
|
||||
}
|
||||
|
|
@ -235,29 +271,37 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
|||
return nil
|
||||
case nul:
|
||||
if s.read() {
|
||||
c = s.char()
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
return errNotAtBeginningOfValue(s.totalOffset())
|
||||
return errors.ErrInvalidBeginningOfValue(c, s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
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().(Unmarshaler); ok {
|
||||
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)
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
if s.char() == 'n' {
|
||||
if s.skipWhiteSpace() == 'n' {
|
||||
if err := nullBytes(s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -276,23 +320,22 @@ func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer
|
|||
if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
|
||||
return d.decodeStreamEmptyInterface(s, depth, p)
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
if s.char() == 'n' {
|
||||
if s.skipWhiteSpace() == 'n' {
|
||||
if err := nullBytes(s); err != nil {
|
||||
return err
|
||||
}
|
||||
*(*interface{})(p) = nil
|
||||
return nil
|
||||
}
|
||||
decoder, err := decodeCompileToGetDecoder(typ)
|
||||
decoder, err := CompileToGetDecoder(typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return decoder.decodeStream(s, depth, ifaceHeader.ptr)
|
||||
return decoder.DecodeStream(s, depth, ifaceHeader.ptr)
|
||||
}
|
||||
|
||||
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *UnmarshalTypeError {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: typ.String(),
|
||||
Type: typ,
|
||||
Offset: offset,
|
||||
|
|
@ -301,14 +344,18 @@ func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *Unm
|
|||
}
|
||||
}
|
||||
|
||||
func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
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().(Unmarshaler); ok {
|
||||
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 {
|
||||
|
|
@ -331,10 +378,10 @@ func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Poin
|
|||
typ := ifaceHeader.typ
|
||||
if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
|
||||
// concrete type is empty interface
|
||||
return d.decodeEmptyInterface(buf, cursor, depth, p)
|
||||
return d.decodeEmptyInterface(ctx, cursor, depth, p)
|
||||
}
|
||||
if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
|
||||
return d.decodeEmptyInterface(buf, cursor, depth, p)
|
||||
return d.decodeEmptyInterface(ctx, cursor, depth, p)
|
||||
}
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
if buf[cursor] == 'n' {
|
||||
|
|
@ -345,20 +392,21 @@ func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Poin
|
|||
**(**interface{})(unsafe.Pointer(&p)) = nil
|
||||
return cursor, nil
|
||||
}
|
||||
decoder, err := decodeCompileToGetDecoder(typ)
|
||||
decoder, err := CompileToGetDecoder(typ)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return decoder.decode(buf, cursor, depth, ifaceHeader.ptr)
|
||||
return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr)
|
||||
}
|
||||
|
||||
func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
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(buf, cursor, depth, ptr)
|
||||
cursor, err := d.mapDecoder.Decode(ctx, cursor, depth, ptr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -367,18 +415,18 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
|||
case '[':
|
||||
var v []interface{}
|
||||
ptr := unsafe.Pointer(&v)
|
||||
cursor, err := d.sliceDecoder.decode(buf, cursor, depth, ptr)
|
||||
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(buf, cursor, depth, p)
|
||||
return d.floatDecoder.Decode(ctx, cursor, depth, p)
|
||||
case '"':
|
||||
var v string
|
||||
ptr := unsafe.Pointer(&v)
|
||||
cursor, err := d.stringDecoder.decode(buf, cursor, depth, ptr)
|
||||
cursor, err := d.stringDecoder.Decode(ctx, cursor, depth, ptr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -406,5 +454,5 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
|||
**(**interface{})(unsafe.Pointer(&p)) = nil
|
||||
return cursor, nil
|
||||
}
|
||||
return cursor, errNotAtBeginningOfValue(cursor)
|
||||
return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
|
||||
}
|
||||
186
vendor/github.com/goccy/go-json/internal/decoder/map.go
generated
vendored
Normal file
186
vendor/github.com/goccy/go-json/internal/decoder/map.go
generated
vendored
Normal file
|
|
@ -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++
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,21 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type numberDecoder struct {
|
||||
stringDecoder *stringDecoder
|
||||
op func(unsafe.Pointer, Number)
|
||||
op func(unsafe.Pointer, json.Number)
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, Number)) *numberDecoder {
|
||||
func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder {
|
||||
return &numberDecoder{
|
||||
stringDecoder: newStringDecoder(structName, fieldName),
|
||||
op: op,
|
||||
|
|
@ -21,34 +24,35 @@ func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, Numb
|
|||
}
|
||||
}
|
||||
|
||||
func (d *numberDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
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 errSyntax(err.Error(), s.totalOffset())
|
||||
return errors.ErrSyntax(err.Error(), s.totalOffset())
|
||||
}
|
||||
d.op(p, Number(string(bytes)))
|
||||
d.op(p, json.Number(string(bytes)))
|
||||
s.reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *numberDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
bytes, c, err := d.decodeByte(buf, cursor)
|
||||
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, errSyntax(err.Error(), c)
|
||||
return 0, errors.ErrSyntax(err.Error(), c)
|
||||
}
|
||||
cursor = c
|
||||
s := *(*string)(unsafe.Pointer(&bytes))
|
||||
d.op(p, Number(s))
|
||||
d.op(p, json.Number(s))
|
||||
return cursor, nil
|
||||
}
|
||||
|
||||
func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
start := s.cursor
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
|
@ -73,7 +77,10 @@ func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
}
|
||||
}
|
||||
ERROR:
|
||||
return nil, errUnexpectedEndOfJSON("json.Number", s.totalOffset())
|
||||
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) {
|
||||
|
|
@ -99,7 +106,7 @@ func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||
case '"':
|
||||
return d.stringDecoder.decodeByte(buf, cursor)
|
||||
default:
|
||||
return nil, 0, errUnexpectedEndOfJSON("json.Number", cursor)
|
||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
15
vendor/github.com/goccy/go-json/internal/decoder/option.go
generated
vendored
Normal file
15
vendor/github.com/goccy/go-json/internal/decoder/option.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type ptrDecoder struct {
|
||||
dec decoder
|
||||
typ *rtype
|
||||
dec Decoder
|
||||
typ *runtime.Type
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newPtrDecoder(dec decoder, typ *rtype, structName, fieldName string) *ptrDecoder {
|
||||
func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder {
|
||||
return &ptrDecoder{
|
||||
dec: dec,
|
||||
typ: typ,
|
||||
|
|
@ -20,7 +22,7 @@ func newPtrDecoder(dec decoder, typ *rtype, structName, fieldName string) *ptrDe
|
|||
}
|
||||
}
|
||||
|
||||
func (d *ptrDecoder) contentDecoder() decoder {
|
||||
func (d *ptrDecoder) contentDecoder() Decoder {
|
||||
dec, ok := d.dec.(*ptrDecoder)
|
||||
if !ok {
|
||||
return d.dec
|
||||
|
|
@ -30,11 +32,10 @@ func (d *ptrDecoder) contentDecoder() decoder {
|
|||
|
||||
//nolint:golint
|
||||
//go:linkname unsafe_New reflect.unsafe_New
|
||||
func unsafe_New(*rtype) unsafe.Pointer
|
||||
func unsafe_New(*runtime.Type) unsafe.Pointer
|
||||
|
||||
func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
s.skipWhiteSpace()
|
||||
if s.char() == nul {
|
||||
func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
if s.skipWhiteSpace() == nul {
|
||||
s.read()
|
||||
}
|
||||
if s.char() == 'n' {
|
||||
|
|
@ -51,13 +52,14 @@ func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
|||
} else {
|
||||
newptr = *(*unsafe.Pointer)(p)
|
||||
}
|
||||
if err := d.dec.decodeStream(s, depth, newptr); err != nil {
|
||||
if err := d.dec.DecodeStream(s, depth, newptr); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
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 {
|
||||
|
|
@ -76,7 +78,7 @@ func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
|||
} else {
|
||||
newptr = *(*unsafe.Pointer)(p)
|
||||
}
|
||||
c, err := d.dec.decode(buf, cursor, depth, newptr)
|
||||
c, err := d.dec.Decode(ctx, cursor, depth, newptr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -1,15 +1,25 @@
|
|||
package json
|
||||
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 *rtype
|
||||
elemType *runtime.Type
|
||||
isElemPointerType bool
|
||||
valueDecoder decoder
|
||||
valueDecoder Decoder
|
||||
size uintptr
|
||||
arrayPool sync.Pool
|
||||
structName string
|
||||
|
|
@ -29,7 +39,7 @@ const (
|
|||
defaultSliceCapacity = 2
|
||||
)
|
||||
|
||||
func newSliceDecoder(dec decoder, elemType *rtype, size uintptr, structName, fieldName string) *sliceDecoder {
|
||||
func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder {
|
||||
return &sliceDecoder{
|
||||
valueDecoder: dec,
|
||||
elemType: elemType,
|
||||
|
|
@ -71,28 +81,28 @@ func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
|
|||
}
|
||||
|
||||
//go:linkname copySlice reflect.typedslicecopy
|
||||
func copySlice(elemType *rtype, dst, src sliceHeader) int
|
||||
func copySlice(elemType *runtime.Type, dst, src sliceHeader) int
|
||||
|
||||
//go:linkname newArray reflect.unsafe_NewArray
|
||||
func newArray(*rtype, int) unsafe.Pointer
|
||||
func newArray(*runtime.Type, int) unsafe.Pointer
|
||||
|
||||
//go:linkname typedmemmove reflect.typedmemmove
|
||||
func typedmemmove(t *rtype, dst, src unsafe.Pointer)
|
||||
func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer)
|
||||
|
||||
func (d *sliceDecoder) errNumber(offset int64) *UnmarshalTypeError {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "number",
|
||||
Type: reflect.SliceOf(rtype2type(d.elemType)),
|
||||
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 {
|
||||
func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
@ -104,12 +114,11 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
if err := nullBytes(s); err != nil {
|
||||
return err
|
||||
}
|
||||
*(*unsafe.Pointer)(p) = nil
|
||||
typedmemmove(sliceType, p, nilSlice)
|
||||
return nil
|
||||
case '[':
|
||||
s.cursor++
|
||||
s.skipWhiteSpace()
|
||||
if s.char() == ']' {
|
||||
if s.skipWhiteSpace() == ']' {
|
||||
dst := (*sliceHeader)(p)
|
||||
if dst.data == nil {
|
||||
dst.data = newArray(d.elemType, 0)
|
||||
|
|
@ -144,7 +153,7 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
}
|
||||
}
|
||||
|
||||
if err := d.valueDecoder.decodeStream(s, depth, ep); err != nil {
|
||||
if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil {
|
||||
return err
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
|
|
@ -194,13 +203,14 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
}
|
||||
}
|
||||
ERROR:
|
||||
return errUnexpectedEndOfJSON("slice", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
func (d *sliceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
buf := ctx.Buf
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
@ -213,7 +223,7 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
return 0, err
|
||||
}
|
||||
cursor += 4
|
||||
*(*unsafe.Pointer)(p) = nil
|
||||
typedmemmove(sliceType, p, nilSlice)
|
||||
return cursor, nil
|
||||
case '[':
|
||||
cursor++
|
||||
|
|
@ -251,7 +261,7 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
|
||||
}
|
||||
}
|
||||
c, err := d.valueDecoder.decode(buf, cursor, depth, ep)
|
||||
c, err := d.valueDecoder.Decode(ctx, cursor, depth, ep)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -278,14 +288,14 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
slice.cap = capacity
|
||||
slice.data = data
|
||||
d.releaseSlice(slice)
|
||||
return 0, errInvalidCharacter(buf[cursor], "slice", cursor)
|
||||
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, errUnexpectedEndOfJSON("slice", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,20 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
initBufSize = 512
|
||||
)
|
||||
|
||||
type stream struct {
|
||||
type Stream struct {
|
||||
buf []byte
|
||||
bufSize int64
|
||||
length int64
|
||||
|
|
@ -19,19 +23,25 @@ type stream struct {
|
|||
cursor int64
|
||||
filledBuffer bool
|
||||
allRead bool
|
||||
useNumber bool
|
||||
disallowUnknownFields bool
|
||||
UseNumber bool
|
||||
DisallowUnknownFields bool
|
||||
Option *Option
|
||||
}
|
||||
|
||||
func newStream(r io.Reader) *stream {
|
||||
return &stream{
|
||||
func NewStream(r io.Reader) *Stream {
|
||||
return &Stream{
|
||||
r: r,
|
||||
bufSize: initBufSize,
|
||||
buf: []byte{nul},
|
||||
buf: make([]byte, initBufSize),
|
||||
Option: &Option{},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) buffered() io.Reader {
|
||||
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 {
|
||||
|
|
@ -41,15 +51,35 @@ func (s *stream) buffered() io.Reader {
|
|||
return bytes.NewReader(s.buf[s.cursor:])
|
||||
}
|
||||
|
||||
func (s *stream) totalOffset() int64 {
|
||||
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 {
|
||||
func (s *Stream) char() byte {
|
||||
return s.buf[s.cursor]
|
||||
}
|
||||
|
||||
func (s *stream) equalChar(c byte) bool {
|
||||
func (s *Stream) equalChar(c byte) bool {
|
||||
cur := s.buf[s.cursor]
|
||||
if cur == nul {
|
||||
s.read()
|
||||
|
|
@ -58,23 +88,104 @@ func (s *stream) equalChar(c byte) bool {
|
|||
return cur == c
|
||||
}
|
||||
|
||||
func (s *stream) stat() ([]byte, int64, unsafe.Pointer) {
|
||||
func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) {
|
||||
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
|
||||
}
|
||||
|
||||
func (s *stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
|
||||
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() {
|
||||
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 {
|
||||
func (s *Stream) readBuf() []byte {
|
||||
if s.filledBuffer {
|
||||
s.bufSize *= 2
|
||||
remainBuf := s.buf
|
||||
|
|
@ -89,10 +200,11 @@ func (s *stream) readBuf() []byte {
|
|||
}
|
||||
remainNotNulCharNum++
|
||||
}
|
||||
s.length = s.cursor + remainNotNulCharNum
|
||||
return s.buf[s.cursor+remainNotNulCharNum:]
|
||||
}
|
||||
|
||||
func (s *stream) read() bool {
|
||||
func (s *Stream) read() bool {
|
||||
if s.allRead {
|
||||
return false
|
||||
}
|
||||
|
|
@ -100,7 +212,7 @@ func (s *stream) read() bool {
|
|||
last := len(buf) - 1
|
||||
buf[last] = nul
|
||||
n, err := s.r.Read(buf[:last])
|
||||
s.length = s.cursor + int64(n)
|
||||
s.length += int64(n)
|
||||
if n == last {
|
||||
s.filledBuffer = true
|
||||
} else {
|
||||
|
|
@ -114,20 +226,24 @@ func (s *stream) read() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *stream) skipWhiteSpace() {
|
||||
func (s *Stream) skipWhiteSpace() byte {
|
||||
p := s.bufptr()
|
||||
LOOP:
|
||||
switch s.char() {
|
||||
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 {
|
||||
func (s *Stream) skipObject(depth int64) error {
|
||||
braceCount := 1
|
||||
_, cursor, p := s.stat()
|
||||
for {
|
||||
|
|
@ -136,7 +252,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
braceCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case '}':
|
||||
braceCount--
|
||||
|
|
@ -148,7 +264,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
case '[':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case ']':
|
||||
depth--
|
||||
|
|
@ -164,7 +280,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
|
|
@ -174,7 +290,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
|
|
@ -183,14 +299,14 @@ func (s *stream) skipObject(depth int64) error {
|
|||
_, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("object of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("object of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) skipArray(depth int64) error {
|
||||
func (s *Stream) skipArray(depth int64) error {
|
||||
bracketCount := 1
|
||||
_, cursor, p := s.stat()
|
||||
for {
|
||||
|
|
@ -199,7 +315,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
bracketCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case ']':
|
||||
bracketCount--
|
||||
|
|
@ -211,7 +327,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
case '{':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case '}':
|
||||
depth--
|
||||
|
|
@ -227,7 +343,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
|
|
@ -237,7 +353,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
|
|
@ -246,14 +362,14 @@ func (s *stream) skipArray(depth int64) error {
|
|||
_, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("array of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("array of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) skipValue(depth int64) error {
|
||||
func (s *Stream) skipValue(depth int64) error {
|
||||
_, cursor, p := s.stat()
|
||||
for {
|
||||
switch char(p, cursor) {
|
||||
|
|
@ -266,7 +382,7 @@ func (s *stream) skipValue(depth int64) error {
|
|||
_, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("value of object", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset())
|
||||
case '{':
|
||||
s.cursor = cursor + 1
|
||||
return s.skipObject(depth + 1)
|
||||
|
|
@ -285,7 +401,7 @@ func (s *stream) skipValue(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||
}
|
||||
case '"':
|
||||
s.cursor = cursor + 1
|
||||
|
|
@ -296,7 +412,7 @@ func (s *stream) skipValue(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||
}
|
||||
}
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
|
|
@ -338,7 +454,7 @@ func (s *stream) skipValue(depth int64) error {
|
|||
}
|
||||
}
|
||||
|
||||
func nullBytes(s *stream) error {
|
||||
func nullBytes(s *Stream) error {
|
||||
// current cursor's character is 'n'
|
||||
s.cursor++
|
||||
if s.char() != 'u' {
|
||||
|
|
@ -362,14 +478,14 @@ func nullBytes(s *stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func retryReadNull(s *stream) error {
|
||||
func retryReadNull(s *Stream) error {
|
||||
if s.char() == nul && s.read() {
|
||||
return nil
|
||||
}
|
||||
return errInvalidCharacter(s.char(), "null", s.totalOffset())
|
||||
return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset())
|
||||
}
|
||||
|
||||
func trueBytes(s *stream) error {
|
||||
func trueBytes(s *Stream) error {
|
||||
// current cursor's character is 't'
|
||||
s.cursor++
|
||||
if s.char() != 'r' {
|
||||
|
|
@ -393,14 +509,14 @@ func trueBytes(s *stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func retryReadTrue(s *stream) error {
|
||||
func retryReadTrue(s *Stream) error {
|
||||
if s.char() == nul && s.read() {
|
||||
return nil
|
||||
}
|
||||
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
|
||||
return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
|
||||
}
|
||||
|
||||
func falseBytes(s *stream) error {
|
||||
func falseBytes(s *Stream) error {
|
||||
// current cursor's character is 'f'
|
||||
s.cursor++
|
||||
if s.char() != 'a' {
|
||||
|
|
@ -430,9 +546,9 @@ func falseBytes(s *stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func retryReadFalse(s *stream) error {
|
||||
func retryReadFalse(s *Stream) error {
|
||||
if s.char() == nul && s.read() {
|
||||
return nil
|
||||
}
|
||||
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
|
||||
return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
|
@ -6,6 +6,8 @@ import (
|
|||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type stringDecoder struct {
|
||||
|
|
@ -20,8 +22,8 @@ func newStringDecoder(structName, fieldName string) *stringDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *UnmarshalTypeError {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: typeName,
|
||||
Type: reflect.TypeOf(""),
|
||||
Offset: offset,
|
||||
|
|
@ -30,7 +32,7 @@ func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *Unmarsh
|
|||
}
|
||||
}
|
||||
|
||||
func (d *stringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *stringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
bytes, err := d.decodeStreamByte(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -43,8 +45,8 @@ func (d *stringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *stringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
bytes, c, err := d.decodeByte(buf, cursor)
|
||||
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
|
||||
}
|
||||
|
|
@ -91,38 +93,40 @@ func unicodeToRune(code []byte) rune {
|
|||
return r
|
||||
}
|
||||
|
||||
func decodeUnicodeRune(s *stream) (rune, int64, error) {
|
||||
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, errInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||
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, nil
|
||||
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, nil
|
||||
return r, surrogateOffset, p, nil
|
||||
}
|
||||
}
|
||||
return r, defaultOffset, nil
|
||||
return r, defaultOffset, p, nil
|
||||
}
|
||||
|
||||
func decodeUnicode(s *stream) error {
|
||||
func decodeUnicode(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) {
|
||||
const backSlashAndULen = 2 // length of \u
|
||||
|
||||
r, offset, err := decodeUnicodeRune(s)
|
||||
r, offset, pp, err := decodeUnicodeRune(s, p)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
unicode := []byte(string(r))
|
||||
unicodeLen := int64(len(unicode))
|
||||
|
|
@ -130,10 +134,10 @@ func decodeUnicode(s *stream) error {
|
|||
unicodeOrgLen := offset - 1
|
||||
s.length = s.length - (backSlashAndULen + (unicodeOrgLen - unicodeLen))
|
||||
s.cursor = s.cursor - backSlashAndULen + unicodeLen
|
||||
return nil
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
func decodeEscapeString(s *stream) error {
|
||||
func decodeEscapeString(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) {
|
||||
s.cursor++
|
||||
RETRY:
|
||||
switch s.buf[s.cursor] {
|
||||
|
|
@ -154,19 +158,20 @@ RETRY:
|
|||
case 't':
|
||||
s.buf[s.cursor] = '\t'
|
||||
case 'u':
|
||||
return decodeUnicode(s)
|
||||
return decodeUnicode(s, p)
|
||||
case nul:
|
||||
if !s.read() {
|
||||
return errInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||
return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||
}
|
||||
goto RETRY
|
||||
default:
|
||||
return errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...)
|
||||
s.length--
|
||||
s.cursor--
|
||||
return nil
|
||||
p = s.bufptr()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -174,7 +179,7 @@ var (
|
|||
runeErrBytesLen = int64(len(runeErrBytes))
|
||||
)
|
||||
|
||||
func stringBytes(s *stream) ([]byte, error) {
|
||||
func stringBytes(s *Stream) ([]byte, error) {
|
||||
_, cursor, p := s.stat()
|
||||
cursor++ // skip double quote char
|
||||
start := cursor
|
||||
|
|
@ -182,9 +187,11 @@ func stringBytes(s *stream) ([]byte, error) {
|
|||
switch char(p, cursor) {
|
||||
case '\\':
|
||||
s.cursor = cursor
|
||||
if err := decodeEscapeString(s); err != nil {
|
||||
pp, err := decodeEscapeString(s, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p = pp
|
||||
cursor = s.cursor
|
||||
case '"':
|
||||
literal := s.buf[start:cursor]
|
||||
|
|
@ -232,23 +239,32 @@ func stringBytes(s *stream) ([]byte, error) {
|
|||
fallthrough
|
||||
default:
|
||||
// multi bytes character
|
||||
r, _ := utf8.DecodeRune(s.buf[cursor:])
|
||||
b := []byte(string(r))
|
||||
if r == utf8.RuneError {
|
||||
s.buf = append(append(append([]byte{}, s.buf[:cursor]...), b...), s.buf[cursor+1:]...)
|
||||
_, _, p = s.stat()
|
||||
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)
|
||||
}
|
||||
cursor += int64(len(b))
|
||||
s.length += int64(len(b))
|
||||
continue
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
ERROR:
|
||||
return nil, errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *stringDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
|
@ -274,7 +290,7 @@ func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
return nil, errNotAtBeginningOfValue(s.totalOffset())
|
||||
return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||
|
|
@ -324,13 +340,13 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||
case 'u':
|
||||
buflen := int64(len(buf))
|
||||
if cursor+5 >= buflen {
|
||||
return nil, 0, errUnexpectedEndOfJSON("escaped string", cursor)
|
||||
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, errUnexpectedEndOfJSON("escaped string", cursor)
|
||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
||||
}
|
||||
continue
|
||||
case '"':
|
||||
|
|
@ -338,7 +354,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||
cursor++
|
||||
return literal, cursor, nil
|
||||
case nul:
|
||||
return nil, 0, errUnexpectedEndOfJSON("string", cursor)
|
||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
|
|
@ -349,7 +365,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||
cursor += 4
|
||||
return nil, cursor, nil
|
||||
default:
|
||||
return nil, 0, errNotAtBeginningOfValue(cursor)
|
||||
return nil, 0, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
819
vendor/github.com/goccy/go-json/internal/decoder/struct.go
generated
vendored
Normal file
819
vendor/github.com/goccy/go-json/internal/decoder/struct.go
generated
vendored
Normal file
|
|
@ -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++
|
||||
}
|
||||
}
|
||||
29
vendor/github.com/goccy/go-json/internal/decoder/type.go
generated
vendored
Normal file
29
vendor/github.com/goccy/go-json/internal/decoder/type.go
generated
vendored
Normal file
|
|
@ -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()
|
||||
)
|
||||
|
|
@ -1,20 +1,23 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type uintDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
kind reflect.Kind
|
||||
op func(unsafe.Pointer, uint64)
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newUintDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
|
||||
func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
|
||||
return &uintDecoder{
|
||||
typ: typ,
|
||||
kind: typ.Kind(),
|
||||
|
|
@ -24,10 +27,10 @@ func newUintDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Poi
|
|||
}
|
||||
}
|
||||
|
||||
func (d *uintDecoder) typeError(buf []byte, offset int64) *UnmarshalTypeError {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: fmt.Sprintf("number %s", string(buf)),
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: offset,
|
||||
}
|
||||
}
|
||||
|
|
@ -54,7 +57,7 @@ func (d *uintDecoder) parseUint(b []byte) (uint64, error) {
|
|||
return sum, nil
|
||||
}
|
||||
|
||||
func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
|
@ -62,7 +65,7 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
continue
|
||||
case '0':
|
||||
s.cursor++
|
||||
return []byte{'0'}, nil
|
||||
return numZeroBuf, nil
|
||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
start := s.cursor
|
||||
for {
|
||||
|
|
@ -93,7 +96,7 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
return nil, errUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
|
||||
return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
|
||||
}
|
||||
|
||||
func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||
|
|
@ -104,7 +107,7 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
|
|||
continue
|
||||
case '0':
|
||||
cursor++
|
||||
return []byte{'0'}, cursor, nil
|
||||
return numZeroBuf, cursor, nil
|
||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
start := cursor
|
||||
cursor++
|
||||
|
|
@ -125,7 +128,7 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
|
|||
}
|
||||
}
|
||||
|
||||
func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
bytes, err := d.decodeStreamByte(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -155,8 +158,8 @@ func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *uintDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
bytes, c, err := d.decodeByte(buf, cursor)
|
||||
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
|
||||
}
|
||||
91
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
generated
vendored
Normal file
91
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
@ -7,15 +7,18 @@ import (
|
|||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type unmarshalTextDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarshalTextDecoder {
|
||||
func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder {
|
||||
return &unmarshalTextDecoder{
|
||||
typ: typ,
|
||||
structName: structName,
|
||||
|
|
@ -25,10 +28,10 @@ func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarsha
|
|||
|
||||
func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) {
|
||||
switch e := err.(type) {
|
||||
case *UnmarshalTypeError:
|
||||
case *errors.UnmarshalTypeError:
|
||||
e.Struct = d.structName
|
||||
e.Field = d.fieldName
|
||||
case *SyntaxError:
|
||||
case *errors.SyntaxError:
|
||||
e.Offset = cursor
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +40,7 @@ var (
|
|||
nullbytes = []byte(`null`)
|
||||
)
|
||||
|
||||
func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *unmarshalTextDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
s.skipWhiteSpace()
|
||||
start := s.cursor
|
||||
if err := s.skipValue(depth); err != nil {
|
||||
|
|
@ -47,21 +50,21 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
|||
if len(src) > 0 {
|
||||
switch src[0] {
|
||||
case '[':
|
||||
return &UnmarshalTypeError{
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "array",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: s.totalOffset(),
|
||||
}
|
||||
case '{':
|
||||
return &UnmarshalTypeError{
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: s.totalOffset(),
|
||||
}
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return &UnmarshalTypeError{
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "number",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: s.totalOffset(),
|
||||
}
|
||||
case 'n':
|
||||
|
|
@ -88,7 +91,8 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *unmarshalTextDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
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)
|
||||
|
|
@ -99,21 +103,21 @@ func (d *unmarshalTextDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
|
|||
if len(src) > 0 {
|
||||
switch src[0] {
|
||||
case '[':
|
||||
return 0, &UnmarshalTypeError{
|
||||
return 0, &errors.UnmarshalTypeError{
|
||||
Value: "array",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: start,
|
||||
}
|
||||
case '{':
|
||||
return 0, &UnmarshalTypeError{
|
||||
return 0, &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: start,
|
||||
}
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return 0, &UnmarshalTypeError{
|
||||
return 0, &errors.UnmarshalTypeError{
|
||||
Value: "number",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: start,
|
||||
}
|
||||
case 'n':
|
||||
|
|
@ -1,20 +1,22 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type wrappedStringDecoder struct {
|
||||
typ *rtype
|
||||
dec decoder
|
||||
typ *runtime.Type
|
||||
dec Decoder
|
||||
stringDecoder *stringDecoder
|
||||
structName string
|
||||
fieldName string
|
||||
isPtrType bool
|
||||
}
|
||||
|
||||
func newWrappedStringDecoder(typ *rtype, dec decoder, structName, fieldName string) *wrappedStringDecoder {
|
||||
func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) *wrappedStringDecoder {
|
||||
return &wrappedStringDecoder{
|
||||
typ: typ,
|
||||
dec: dec,
|
||||
|
|
@ -25,7 +27,7 @@ func newWrappedStringDecoder(typ *rtype, dec decoder, structName, fieldName stri
|
|||
}
|
||||
}
|
||||
|
||||
func (d *wrappedStringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *wrappedStringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
bytes, err := d.stringDecoder.decodeStreamByte(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -38,14 +40,14 @@ func (d *wrappedStringDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
|||
}
|
||||
b := make([]byte, len(bytes)+1)
|
||||
copy(b, bytes)
|
||||
if _, err := d.dec.decode(b, 0, depth, p); err != nil {
|
||||
if _, err := d.dec.Decode(&RuntimeContext{Buf: b}, 0, depth, p); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *wrappedStringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||
bytes, c, err := d.stringDecoder.decodeByte(buf, cursor)
|
||||
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
|
||||
}
|
||||
|
|
@ -56,8 +58,11 @@ func (d *wrappedStringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
|
|||
return c, nil
|
||||
}
|
||||
bytes = append(bytes, nul)
|
||||
if _, err := d.dec.decode(bytes, 0, depth, p); err != nil {
|
||||
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
|
||||
}
|
||||
276
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
276
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package encoder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
|
@ -13,13 +14,18 @@ import (
|
|||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type marshalerContext interface {
|
||||
MarshalJSON(context.Context) ([]byte, error)
|
||||
}
|
||||
|
||||
var (
|
||||
marshalJSONType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
cachedOpcodeSets []*OpcodeSet
|
||||
cachedOpcodeMap unsafe.Pointer // map[uintptr]*OpcodeSet
|
||||
typeAddr *runtime.TypeAddr
|
||||
marshalJSONType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
marshalJSONContextType = reflect.TypeOf((*marshalerContext)(nil)).Elem()
|
||||
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
cachedOpcodeSets []*OpcodeSet
|
||||
cachedOpcodeMap unsafe.Pointer // map[uintptr]*OpcodeSet
|
||||
typeAddr *runtime.TypeAddr
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -55,19 +61,36 @@ func compileToGetCodeSetSlowPath(typeptr uintptr) (*OpcodeSet, error) {
|
|||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
||||
|
||||
code, err := compileHead(&compileContext{
|
||||
noescapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code = copyOpcode(code)
|
||||
codeLength := code.TotalLength()
|
||||
escapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
escapeKey: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
||||
codeLength := noescapeKeyCode.TotalLength()
|
||||
codeSet := &OpcodeSet{
|
||||
Type: copiedType,
|
||||
Code: code,
|
||||
CodeLength: codeLength,
|
||||
Type: copiedType,
|
||||
NoescapeKeyCode: noescapeKeyCode,
|
||||
EscapeKeyCode: escapeKeyCode,
|
||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
||||
CodeLength: codeLength,
|
||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
||||
}
|
||||
storeOpcodeSet(typeptr, codeSet, opcodeMap)
|
||||
return codeSet, nil
|
||||
|
|
@ -100,7 +123,7 @@ func compileHead(ctx *compileContext) (*Opcode, error) {
|
|||
elem := typ.Elem()
|
||||
if elem.Kind() == reflect.Uint8 {
|
||||
p := runtime.PtrTo(elem)
|
||||
if !p.Implements(marshalJSONType) && !p.Implements(marshalTextType) {
|
||||
if !implementsMarshalJSONType(p) && !p.Implements(marshalTextType) {
|
||||
if isPtr {
|
||||
return compileBytesPtr(ctx)
|
||||
}
|
||||
|
|
@ -246,6 +269,7 @@ func linkRecursiveCode(c *Opcode) {
|
|||
continue
|
||||
}
|
||||
code.Jmp.Code = copyOpcode(code.Jmp.Code)
|
||||
|
||||
c := code.Jmp.Code
|
||||
c.End.Next = newEndOp(&compileContext{})
|
||||
c.Op = c.Op.PtrHeadToHead()
|
||||
|
|
@ -258,8 +282,8 @@ func linkRecursiveCode(c *Opcode) {
|
|||
lastCode.Length = lastCode.Idx + 2*uintptrSize
|
||||
|
||||
// extend length to alloc slot for elemIdx + length
|
||||
totalLength := uintptr(code.TotalLength() + 2)
|
||||
nextTotalLength := uintptr(c.TotalLength() + 2)
|
||||
totalLength := uintptr(code.TotalLength() + 3)
|
||||
nextTotalLength := uintptr(c.TotalLength() + 3)
|
||||
|
||||
c.End.Next.Op = OpRecursiveEnd
|
||||
|
||||
|
|
@ -268,6 +292,7 @@ func linkRecursiveCode(c *Opcode) {
|
|||
code.Jmp.Linked = true
|
||||
|
||||
linkRecursiveCode(code.Jmp.Code)
|
||||
|
||||
code = code.Next
|
||||
continue
|
||||
}
|
||||
|
|
@ -328,14 +353,14 @@ func optimizeStructEnd(c *Opcode) {
|
|||
}
|
||||
|
||||
func implementsMarshalJSON(typ *runtime.Type) bool {
|
||||
if !typ.Implements(marshalJSONType) {
|
||||
if !implementsMarshalJSONType(typ) {
|
||||
return false
|
||||
}
|
||||
if typ.Kind() != reflect.Ptr {
|
||||
return true
|
||||
}
|
||||
// type kind is reflect.Ptr
|
||||
if !typ.Elem().Implements(marshalJSONType) {
|
||||
if !implementsMarshalJSONType(typ.Elem()) {
|
||||
return true
|
||||
}
|
||||
// needs to dereference
|
||||
|
|
@ -372,7 +397,7 @@ func compile(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
elem := typ.Elem()
|
||||
if elem.Kind() == reflect.Uint8 {
|
||||
p := runtime.PtrTo(elem)
|
||||
if !p.Implements(marshalJSONType) && !p.Implements(marshalTextType) {
|
||||
if !implementsMarshalJSONType(p) && !p.Implements(marshalTextType) {
|
||||
return compileBytes(ctx)
|
||||
}
|
||||
}
|
||||
|
|
@ -474,8 +499,6 @@ func compileKey(ctx *compileContext) (*Opcode, error) {
|
|||
switch typ.Kind() {
|
||||
case reflect.Ptr:
|
||||
return compilePtr(ctx)
|
||||
case reflect.Interface:
|
||||
return compileInterface(ctx)
|
||||
case reflect.String:
|
||||
return compileString(ctx)
|
||||
case reflect.Int:
|
||||
|
|
@ -517,10 +540,17 @@ func compilePtr(ctx *compileContext) (*Opcode, error) {
|
|||
func compileMarshalJSON(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpMarshalJSON)
|
||||
typ := ctx.typ
|
||||
if !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType) {
|
||||
code.AddrForMarshaler = true
|
||||
if isPtrMarshalJSONType(typ) {
|
||||
code.Flags |= AddrForMarshalerFlags
|
||||
}
|
||||
if typ.Implements(marshalJSONContextType) || runtime.PtrTo(typ).Implements(marshalJSONContextType) {
|
||||
code.Flags |= MarshalerContextFlags
|
||||
}
|
||||
if isNilableType(typ) {
|
||||
code.Flags |= IsNilableTypeFlags
|
||||
} else {
|
||||
code.Flags &= ^IsNilableTypeFlags
|
||||
}
|
||||
code.IsNilableType = isNilableType(typ)
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -529,9 +559,13 @@ func compileMarshalText(ctx *compileContext) (*Opcode, error) {
|
|||
code := newOpCode(ctx, OpMarshalText)
|
||||
typ := ctx.typ
|
||||
if !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) {
|
||||
code.AddrForMarshaler = true
|
||||
code.Flags |= AddrForMarshalerFlags
|
||||
}
|
||||
if isNilableType(typ) {
|
||||
code.Flags |= IsNilableTypeFlags
|
||||
} else {
|
||||
code.Flags &= ^IsNilableTypeFlags
|
||||
}
|
||||
code.IsNilableType = isNilableType(typ)
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -540,7 +574,7 @@ const intSize = 32 << (^uint(0) >> 63)
|
|||
|
||||
func compileInt(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -556,7 +590,7 @@ func compileIntPtr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt8(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -572,7 +606,7 @@ func compileInt8Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt16(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -588,7 +622,7 @@ func compileInt16Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt32(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -604,7 +638,7 @@ func compileInt32Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt64(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -620,7 +654,7 @@ func compileInt64Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -636,7 +670,7 @@ func compileUintPtr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint8(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -652,7 +686,7 @@ func compileUint8Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint16(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -668,7 +702,7 @@ func compileUint16Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint32(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -684,7 +718,7 @@ func compileUint32Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint64(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -700,70 +734,70 @@ func compileUint64Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileIntString(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt8String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt16String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt32String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt64String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUintString(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint8String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint16String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint32String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint64String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
|
@ -879,7 +913,7 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code.Indirect = true
|
||||
code.Flags |= IndirectFlags
|
||||
|
||||
// header => opcode => elem => end
|
||||
// ^ |
|
||||
|
|
@ -891,7 +925,6 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
|
|||
end := newOpCode(ctx, OpSliceEnd)
|
||||
ctx.incIndex()
|
||||
|
||||
header.Elem = elemCode
|
||||
header.End = end
|
||||
header.Next = code
|
||||
code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode))
|
||||
|
|
@ -903,7 +936,7 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
|
|||
func compileListElem(ctx *compileContext) (*Opcode, error) {
|
||||
typ := ctx.typ
|
||||
switch {
|
||||
case !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType):
|
||||
case isPtrMarshalJSONType(typ):
|
||||
return compileMarshalJSON(ctx)
|
||||
case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType):
|
||||
return compileMarshalText(ctx)
|
||||
|
|
@ -934,7 +967,7 @@ func compileArray(ctx *compileContext) (*Opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code.Indirect = true
|
||||
code.Flags |= IndirectFlags
|
||||
// header => opcode => elem => end
|
||||
// ^ |
|
||||
// |________|
|
||||
|
|
@ -945,7 +978,6 @@ func compileArray(ctx *compileContext) (*Opcode, error) {
|
|||
end := newOpCode(ctx, OpArrayEnd)
|
||||
ctx.incIndex()
|
||||
|
||||
header.Elem = elemCode
|
||||
header.End = end
|
||||
header.Next = code
|
||||
code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode))
|
||||
|
|
@ -976,16 +1008,13 @@ func compileMap(ctx *compileContext) (*Opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valueCode.Indirect = true
|
||||
valueCode.Flags |= IndirectFlags
|
||||
|
||||
key := newMapKeyCode(ctx, header)
|
||||
ctx.incIndex()
|
||||
|
||||
ctx = ctx.decIndent()
|
||||
|
||||
header.MapKey = key
|
||||
header.MapValue = value
|
||||
|
||||
end := newMapEndCode(ctx, header)
|
||||
ctx.incIndex()
|
||||
|
||||
|
|
@ -1052,8 +1081,7 @@ func compiledCode(ctx *compileContext) *Opcode {
|
|||
func structHeader(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode {
|
||||
op := optimizeStructHeader(valueCode, tag)
|
||||
fieldCode.Op = op
|
||||
fieldCode.Mask = valueCode.Mask
|
||||
fieldCode.RshiftNum = valueCode.RshiftNum
|
||||
fieldCode.NumBitSize = valueCode.NumBitSize
|
||||
fieldCode.PtrNum = valueCode.PtrNum
|
||||
if op.IsMultipleOpHead() {
|
||||
return valueCode.BeforeLastCode()
|
||||
|
|
@ -1065,9 +1093,8 @@ func structHeader(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag
|
|||
func structField(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode {
|
||||
op := optimizeStructField(valueCode, tag)
|
||||
fieldCode.Op = op
|
||||
fieldCode.NumBitSize = valueCode.NumBitSize
|
||||
fieldCode.PtrNum = valueCode.PtrNum
|
||||
fieldCode.Mask = valueCode.Mask
|
||||
fieldCode.RshiftNum = valueCode.RshiftNum
|
||||
if op.IsMultipleOpField() {
|
||||
return valueCode.BeforeLastCode()
|
||||
}
|
||||
|
|
@ -1082,7 +1109,7 @@ func isNotExistsField(head *Opcode) bool {
|
|||
if head.Op != OpStructHead {
|
||||
return false
|
||||
}
|
||||
if !head.AnonymousHead {
|
||||
if (head.Flags & AnonymousHeadFlags) == 0 {
|
||||
return false
|
||||
}
|
||||
if head.Next == nil {
|
||||
|
|
@ -1117,7 +1144,7 @@ func optimizeAnonymousFields(head *Opcode) {
|
|||
if isNotExistsField(code.Next) {
|
||||
code.Next = code.NextField
|
||||
diff := code.Next.DisplayIdx - code.DisplayIdx
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
code.Next.decOpcodeIndex()
|
||||
}
|
||||
linkPrevToNextField(code, removedFields)
|
||||
|
|
@ -1147,20 +1174,20 @@ func anonymousStructFieldPairMap(tags runtime.StructTags, named string, valueCod
|
|||
isHeadOp := strings.Contains(f.Op.String(), "Head")
|
||||
if existsKey && f.Next != nil && strings.Contains(f.Next.Op.String(), "Recursive") {
|
||||
// through
|
||||
} else if isHeadOp && !f.AnonymousHead {
|
||||
} else if isHeadOp && (f.Flags&AnonymousHeadFlags) == 0 {
|
||||
if existsKey {
|
||||
// TODO: need to remove this head
|
||||
f.Op = OpStructHead
|
||||
f.AnonymousKey = true
|
||||
f.AnonymousHead = true
|
||||
f.Flags |= AnonymousKeyFlags
|
||||
f.Flags |= AnonymousHeadFlags
|
||||
} else if named == "" {
|
||||
f.AnonymousHead = true
|
||||
f.Flags |= AnonymousHeadFlags
|
||||
}
|
||||
} else if named == "" && f.Op == OpStructEnd {
|
||||
f.Op = OpStructAnonymousEnd
|
||||
} else if existsKey {
|
||||
diff := f.NextField.DisplayIdx - f.DisplayIdx
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
f.NextField.decOpcodeIndex()
|
||||
}
|
||||
linkPrevToNextField(f, removedFields)
|
||||
|
|
@ -1179,7 +1206,7 @@ func anonymousStructFieldPairMap(tags runtime.StructTags, named string, valueCod
|
|||
anonymousFields[key] = append(anonymousFields[key], structFieldPair{
|
||||
prevField: prevAnonymousField,
|
||||
curField: f,
|
||||
isTaggedKey: f.IsTaggedKey,
|
||||
isTaggedKey: (f.Flags & IsTaggedKeyFlags) != 0,
|
||||
})
|
||||
if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField {
|
||||
for k, v := range anonymousFieldPairRecursively(named, f.Next) {
|
||||
|
|
@ -1200,12 +1227,12 @@ func anonymousFieldPairRecursively(named string, valueCode *Opcode) map[string][
|
|||
f := valueCode
|
||||
var prevAnonymousField *Opcode
|
||||
for {
|
||||
if f.DisplayKey != "" && f.AnonymousHead {
|
||||
if f.DisplayKey != "" && (f.Flags&AnonymousHeadFlags) != 0 {
|
||||
key := fmt.Sprintf("%s.%s", named, f.DisplayKey)
|
||||
anonymousFields[key] = append(anonymousFields[key], structFieldPair{
|
||||
prevField: prevAnonymousField,
|
||||
curField: f,
|
||||
isTaggedKey: f.IsTaggedKey,
|
||||
isTaggedKey: (f.Flags & IsTaggedKeyFlags) != 0,
|
||||
})
|
||||
if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField {
|
||||
for k, v := range anonymousFieldPairRecursively(named, f.Next) {
|
||||
|
|
@ -1238,11 +1265,11 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
|
|||
if fieldPair.prevField == nil {
|
||||
// head operation
|
||||
fieldPair.curField.Op = OpStructHead
|
||||
fieldPair.curField.AnonymousHead = true
|
||||
fieldPair.curField.AnonymousKey = true
|
||||
fieldPair.curField.Flags |= AnonymousHeadFlags
|
||||
fieldPair.curField.Flags |= AnonymousKeyFlags
|
||||
} else {
|
||||
diff := fieldPair.curField.NextField.DisplayIdx - fieldPair.curField.DisplayIdx
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
fieldPair.curField.NextField.decOpcodeIndex()
|
||||
}
|
||||
removedFields[fieldPair.curField] = struct{}{}
|
||||
|
|
@ -1258,12 +1285,12 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
|
|||
if fieldPair.prevField == nil {
|
||||
// head operation
|
||||
fieldPair.curField.Op = OpStructHead
|
||||
fieldPair.curField.AnonymousHead = true
|
||||
fieldPair.curField.AnonymousKey = true
|
||||
fieldPair.curField.Flags |= AnonymousHeadFlags
|
||||
fieldPair.curField.Flags |= AnonymousKeyFlags
|
||||
} else {
|
||||
diff := fieldPair.curField.NextField.DisplayIdx - fieldPair.curField.DisplayIdx
|
||||
removedFields[fieldPair.curField] = struct{}{}
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
fieldPair.curField.NextField.decOpcodeIndex()
|
||||
}
|
||||
linkPrevToNextField(fieldPair.curField, removedFields)
|
||||
|
|
@ -1273,7 +1300,7 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
|
|||
}
|
||||
} else {
|
||||
for _, fieldPair := range taggedPairs {
|
||||
fieldPair.curField.IsTaggedKey = false
|
||||
fieldPair.curField.Flags &= ^IsTaggedKeyFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1390,7 +1417,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
valueCode = code
|
||||
}
|
||||
|
||||
if field.Anonymous {
|
||||
if field.Anonymous && !tag.IsTaggedKey {
|
||||
tagKey := ""
|
||||
if tag.IsTaggedKey {
|
||||
tagKey = tag.Key
|
||||
|
|
@ -1398,50 +1425,76 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
for k, v := range anonymousStructFieldPairMap(tags, tagKey, valueCode) {
|
||||
anonymousFields[k] = append(anonymousFields[k], v...)
|
||||
}
|
||||
|
||||
valueCode.decIndent()
|
||||
|
||||
// fix issue144
|
||||
if !(isPtr && strings.Contains(valueCode.Op.String(), "Marshal")) {
|
||||
valueCode.Indirect = indirect
|
||||
if indirect {
|
||||
valueCode.Flags |= IndirectFlags
|
||||
} else {
|
||||
valueCode.Flags &= ^IndirectFlags
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if indirect {
|
||||
// if parent is indirect type, set child indirect property to true
|
||||
valueCode.Indirect = indirect
|
||||
valueCode.Flags |= IndirectFlags
|
||||
} else {
|
||||
// if parent is not indirect type and child have only one field, set child indirect property to false
|
||||
if i == 0 && valueCode.NextField != nil && valueCode.NextField.Op == OpStructEnd {
|
||||
valueCode.Indirect = indirect
|
||||
// if parent is not indirect type, set child indirect property to false.
|
||||
// but if parent's indirect is false and isPtr is true, then indirect must be true.
|
||||
// Do this only if indirectConversion is enabled at the end of compileStruct.
|
||||
if i == 0 {
|
||||
valueCode.Flags &= ^IndirectFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
key := fmt.Sprintf(`"%s":`, tag.Key)
|
||||
escapedKey := fmt.Sprintf(`%s:`, string(AppendEscapedString([]byte{}, tag.Key)))
|
||||
var flags OpFlags
|
||||
if indirect {
|
||||
flags |= IndirectFlags
|
||||
}
|
||||
if field.Anonymous {
|
||||
flags |= AnonymousKeyFlags
|
||||
}
|
||||
if tag.IsTaggedKey {
|
||||
flags |= IsTaggedKeyFlags
|
||||
}
|
||||
if nilcheck {
|
||||
flags |= NilCheckFlags
|
||||
}
|
||||
if addrForMarshaler {
|
||||
flags |= AddrForMarshalerFlags
|
||||
}
|
||||
if strings.Contains(valueCode.Op.String(), "Ptr") || valueCode.Op == OpInterface {
|
||||
flags |= IsNextOpPtrTypeFlags
|
||||
}
|
||||
if isNilableType {
|
||||
flags |= IsNilableTypeFlags
|
||||
}
|
||||
var key string
|
||||
if ctx.escapeKey {
|
||||
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
|
||||
key = fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, tag.Key)))
|
||||
} else {
|
||||
key = fmt.Sprintf(`"%s":`, tag.Key)
|
||||
}
|
||||
fieldCode := &Opcode{
|
||||
Type: valueCode.Type,
|
||||
DisplayIdx: fieldOpcodeIndex,
|
||||
Idx: opcodeOffset(fieldPtrIndex),
|
||||
Next: valueCode,
|
||||
Indent: ctx.indent,
|
||||
AnonymousKey: field.Anonymous,
|
||||
Key: []byte(key),
|
||||
EscapedKey: []byte(escapedKey),
|
||||
IsTaggedKey: tag.IsTaggedKey,
|
||||
DisplayKey: tag.Key,
|
||||
Offset: field.Offset,
|
||||
Indirect: indirect,
|
||||
Nilcheck: nilcheck,
|
||||
AddrForMarshaler: addrForMarshaler,
|
||||
IsNextOpPtrType: strings.Contains(valueCode.Op.String(), "Ptr") || valueCode.Op == OpInterface,
|
||||
IsNilableType: isNilableType,
|
||||
Idx: opcodeOffset(fieldPtrIndex),
|
||||
Next: valueCode,
|
||||
Flags: flags,
|
||||
Key: key,
|
||||
Offset: uint32(field.Offset),
|
||||
Type: valueCode.Type,
|
||||
DisplayIdx: fieldOpcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
DisplayKey: tag.Key,
|
||||
}
|
||||
if fieldIdx == 0 {
|
||||
fieldCode.HeadIdx = fieldCode.Idx
|
||||
code = structHeader(ctx, fieldCode, valueCode, tag)
|
||||
head = fieldCode
|
||||
prevField = fieldCode
|
||||
} else {
|
||||
fieldCode.HeadIdx = head.HeadIdx
|
||||
fieldCode.Idx = head.Idx
|
||||
code.Next = fieldCode
|
||||
code = structField(ctx, fieldCode, valueCode, tag)
|
||||
prevField.NextField = fieldCode
|
||||
|
|
@ -1455,7 +1508,6 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
Op: OpStructEnd,
|
||||
Type: nil,
|
||||
Indent: ctx.indent,
|
||||
Next: newEndOp(ctx),
|
||||
}
|
||||
|
||||
ctx = ctx.decIndent()
|
||||
|
|
@ -1464,12 +1516,11 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
if head == nil {
|
||||
head = &Opcode{
|
||||
Op: OpStructHead,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
NextField: structEndCode,
|
||||
Type: typ,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
HeadIdx: opcodeOffset(ctx.ptrIndex),
|
||||
Indent: ctx.indent,
|
||||
NextField: structEndCode,
|
||||
}
|
||||
structEndCode.PrevField = head
|
||||
ctx.incIndex()
|
||||
|
|
@ -1479,6 +1530,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
structEndCode.DisplayIdx = ctx.opcodeIndex
|
||||
structEndCode.Idx = opcodeOffset(ctx.ptrIndex)
|
||||
ctx.incIndex()
|
||||
structEndCode.Next = newEndOp(ctx)
|
||||
|
||||
if prevField != nil && prevField.NextField == nil {
|
||||
prevField.NextField = structEndCode
|
||||
|
|
@ -1494,15 +1546,23 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
|
||||
delete(ctx.structTypeToCompiledCode, typeptr)
|
||||
|
||||
if !disableIndirectConversion && !head.Indirect && isPtr {
|
||||
head.Indirect = true
|
||||
if !disableIndirectConversion && (head.Flags&IndirectFlags == 0) && isPtr {
|
||||
headCode := head
|
||||
for strings.Contains(headCode.Op.String(), "Head") {
|
||||
headCode.Flags |= IndirectFlags
|
||||
headCode = headCode.Next
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func implementsMarshalJSONType(typ *runtime.Type) bool {
|
||||
return typ.Implements(marshalJSONType) || typ.Implements(marshalJSONContextType)
|
||||
}
|
||||
|
||||
func isPtrMarshalJSONType(typ *runtime.Type) bool {
|
||||
return !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType)
|
||||
return !implementsMarshalJSONType(typ) && implementsMarshalJSONType(runtime.PtrTo(typ))
|
||||
}
|
||||
|
||||
func isPtrMarshalTextType(typ *runtime.Type) bool {
|
||||
|
|
|
|||
29
vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go
generated
vendored
29
vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go
generated
vendored
|
|
@ -20,19 +20,36 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
|||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
||||
|
||||
code, err := compileHead(&compileContext{
|
||||
noescapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code = copyOpcode(code)
|
||||
codeLength := code.TotalLength()
|
||||
escapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
escapeKey: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
||||
codeLength := noescapeKeyCode.TotalLength()
|
||||
codeSet := &OpcodeSet{
|
||||
Type: copiedType,
|
||||
Code: code,
|
||||
CodeLength: codeLength,
|
||||
Type: copiedType,
|
||||
NoescapeKeyCode: noescapeKeyCode,
|
||||
EscapeKeyCode: escapeKeyCode,
|
||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
||||
CodeLength: codeLength,
|
||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
||||
}
|
||||
cachedOpcodeSets[index] = codeSet
|
||||
return codeSet, nil
|
||||
|
|
|
|||
30
vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go
generated
vendored
30
vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go
generated
vendored
|
|
@ -26,19 +26,37 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
|||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
||||
|
||||
code, err := compileHead(&compileContext{
|
||||
noescapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code = copyOpcode(code)
|
||||
codeLength := code.TotalLength()
|
||||
escapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
escapeKey: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
||||
codeLength := noescapeKeyCode.TotalLength()
|
||||
codeSet := &OpcodeSet{
|
||||
Type: copiedType,
|
||||
Code: code,
|
||||
CodeLength: codeLength,
|
||||
Type: copiedType,
|
||||
NoescapeKeyCode: noescapeKeyCode,
|
||||
EscapeKeyCode: escapeKeyCode,
|
||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
||||
CodeLength: codeLength,
|
||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
||||
}
|
||||
setsMu.Lock()
|
||||
cachedOpcodeSets[index] = codeSet
|
||||
|
|
|
|||
12
vendor/github.com/goccy/go-json/internal/encoder/context.go
generated
vendored
12
vendor/github.com/goccy/go-json/internal/encoder/context.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package encoder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
|
|
@ -9,9 +10,10 @@ import (
|
|||
|
||||
type compileContext struct {
|
||||
typ *runtime.Type
|
||||
opcodeIndex int
|
||||
opcodeIndex uint32
|
||||
ptrIndex int
|
||||
indent int
|
||||
indent uint32
|
||||
escapeKey bool
|
||||
structTypeToCompiledCode map[uintptr]*CompiledCode
|
||||
|
||||
parent *compileContext
|
||||
|
|
@ -23,6 +25,7 @@ func (c *compileContext) context() *compileContext {
|
|||
opcodeIndex: c.opcodeIndex,
|
||||
ptrIndex: c.ptrIndex,
|
||||
indent: c.indent,
|
||||
escapeKey: c.escapeKey,
|
||||
structTypeToCompiledCode: c.structTypeToCompiledCode,
|
||||
parent: c,
|
||||
}
|
||||
|
|
@ -95,20 +98,23 @@ var (
|
|||
Buf: make([]byte, 0, bufSize),
|
||||
Ptrs: make([]uintptr, 128),
|
||||
KeepRefs: make([]unsafe.Pointer, 0, 8),
|
||||
Option: &Option{},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type RuntimeContext struct {
|
||||
Context context.Context
|
||||
Buf []byte
|
||||
MarshalBuf []byte
|
||||
Ptrs []uintptr
|
||||
KeepRefs []unsafe.Pointer
|
||||
SeenPtr []uintptr
|
||||
BaseIndent int
|
||||
BaseIndent uint32
|
||||
Prefix []byte
|
||||
IndentStr []byte
|
||||
Option *Option
|
||||
}
|
||||
|
||||
func (c *RuntimeContext) Init(p uintptr, codelen int) {
|
||||
|
|
|
|||
134
vendor/github.com/goccy/go-json/internal/encoder/encoder.go
generated
vendored
134
vendor/github.com/goccy/go-json/internal/encoder/encoder.go
generated
vendored
|
|
@ -17,14 +17,6 @@ import (
|
|||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type Option int
|
||||
|
||||
const (
|
||||
HTMLEscapeOption Option = 1 << iota
|
||||
IndentOption
|
||||
UnorderedMapOption
|
||||
)
|
||||
|
||||
func (t OpType) IsMultipleOpHead() bool {
|
||||
switch t {
|
||||
case OpStructHead:
|
||||
|
|
@ -102,9 +94,13 @@ func (t OpType) IsMultipleOpField() bool {
|
|||
}
|
||||
|
||||
type OpcodeSet struct {
|
||||
Type *runtime.Type
|
||||
Code *Opcode
|
||||
CodeLength int
|
||||
Type *runtime.Type
|
||||
NoescapeKeyCode *Opcode
|
||||
EscapeKeyCode *Opcode
|
||||
InterfaceNoescapeKeyCode *Opcode
|
||||
InterfaceEscapeKeyCode *Opcode
|
||||
CodeLength int
|
||||
EndCode *Opcode
|
||||
}
|
||||
|
||||
type CompiledCode struct {
|
||||
|
|
@ -276,7 +272,7 @@ func MapIterNext(it unsafe.Pointer)
|
|||
//go:noescape
|
||||
func MapLen(m unsafe.Pointer) int
|
||||
|
||||
func AppendByteSlice(b []byte, src []byte) []byte {
|
||||
func AppendByteSlice(_ *RuntimeContext, b []byte, src []byte) []byte {
|
||||
if src == nil {
|
||||
return append(b, `null`...)
|
||||
}
|
||||
|
|
@ -294,7 +290,7 @@ func AppendByteSlice(b []byte, src []byte) []byte {
|
|||
return append(append(b, buf...), '"')
|
||||
}
|
||||
|
||||
func AppendFloat32(b []byte, v float32) []byte {
|
||||
func AppendFloat32(_ *RuntimeContext, b []byte, v float32) []byte {
|
||||
f64 := float64(v)
|
||||
abs := math.Abs(f64)
|
||||
fmt := byte('f')
|
||||
|
|
@ -308,7 +304,7 @@ func AppendFloat32(b []byte, v float32) []byte {
|
|||
return strconv.AppendFloat(b, f64, fmt, -1, 32)
|
||||
}
|
||||
|
||||
func AppendFloat64(b []byte, v float64) []byte {
|
||||
func AppendFloat64(_ *RuntimeContext, b []byte, v float64) []byte {
|
||||
abs := math.Abs(v)
|
||||
fmt := byte('f')
|
||||
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
|
||||
|
|
@ -320,7 +316,7 @@ func AppendFloat64(b []byte, v float64) []byte {
|
|||
return strconv.AppendFloat(b, v, fmt, -1, 64)
|
||||
}
|
||||
|
||||
func AppendBool(b []byte, v bool) []byte {
|
||||
func AppendBool(_ *RuntimeContext, b []byte, v bool) []byte {
|
||||
if v {
|
||||
return append(b, "true"...)
|
||||
}
|
||||
|
|
@ -347,7 +343,7 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func AppendNumber(b []byte, n json.Number) ([]byte, error) {
|
||||
func AppendNumber(_ *RuntimeContext, b []byte, n json.Number) ([]byte, error) {
|
||||
if len(n) == 0 {
|
||||
return append(b, '0'), nil
|
||||
}
|
||||
|
|
@ -360,9 +356,9 @@ func AppendNumber(b []byte, n json.Number) ([]byte, error) {
|
|||
return b, nil
|
||||
}
|
||||
|
||||
func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
|
||||
func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
rv := reflect.ValueOf(v) // convert by dynamic interface type
|
||||
if code.AddrForMarshaler {
|
||||
if (code.Flags & AddrForMarshalerFlags) != 0 {
|
||||
if rv.CanAddr() {
|
||||
rv = rv.Addr()
|
||||
} else {
|
||||
|
|
@ -372,17 +368,31 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{
|
|||
}
|
||||
}
|
||||
v = rv.Interface()
|
||||
marshaler, ok := v.(json.Marshaler)
|
||||
if !ok {
|
||||
return AppendNull(b), nil
|
||||
}
|
||||
bb, err := marshaler.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
var bb []byte
|
||||
if (code.Flags & MarshalerContextFlags) != 0 {
|
||||
marshaler, ok := v.(marshalerContext)
|
||||
if !ok {
|
||||
return AppendNull(ctx, b), nil
|
||||
}
|
||||
b, err := marshaler.MarshalJSON(ctx.Option.Context)
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
}
|
||||
bb = b
|
||||
} else {
|
||||
marshaler, ok := v.(json.Marshaler)
|
||||
if !ok {
|
||||
return AppendNull(ctx, b), nil
|
||||
}
|
||||
b, err := marshaler.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
}
|
||||
bb = b
|
||||
}
|
||||
marshalBuf := ctx.MarshalBuf[:0]
|
||||
marshalBuf = append(append(marshalBuf, bb...), nul)
|
||||
compactedBuf, err := compact(b, marshalBuf, escape)
|
||||
compactedBuf, err := compact(b, marshalBuf, (ctx.Option.Flag&HTMLEscapeOption) != 0)
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
}
|
||||
|
|
@ -390,9 +400,9 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{
|
|||
return compactedBuf, nil
|
||||
}
|
||||
|
||||
func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
|
||||
func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
rv := reflect.ValueOf(v) // convert by dynamic interface type
|
||||
if code.AddrForMarshaler {
|
||||
if (code.Flags & AddrForMarshalerFlags) != 0 {
|
||||
if rv.CanAddr() {
|
||||
rv = rv.Addr()
|
||||
} else {
|
||||
|
|
@ -402,22 +412,36 @@ func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v inte
|
|||
}
|
||||
}
|
||||
v = rv.Interface()
|
||||
marshaler, ok := v.(json.Marshaler)
|
||||
if !ok {
|
||||
return AppendNull(b), nil
|
||||
}
|
||||
bb, err := marshaler.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
var bb []byte
|
||||
if (code.Flags & MarshalerContextFlags) != 0 {
|
||||
marshaler, ok := v.(marshalerContext)
|
||||
if !ok {
|
||||
return AppendNull(ctx, b), nil
|
||||
}
|
||||
b, err := marshaler.MarshalJSON(ctx.Option.Context)
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
}
|
||||
bb = b
|
||||
} else {
|
||||
marshaler, ok := v.(json.Marshaler)
|
||||
if !ok {
|
||||
return AppendNull(ctx, b), nil
|
||||
}
|
||||
b, err := marshaler.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
}
|
||||
bb = b
|
||||
}
|
||||
marshalBuf := ctx.MarshalBuf[:0]
|
||||
marshalBuf = append(append(marshalBuf, bb...), nul)
|
||||
indentedBuf, err := doIndent(
|
||||
b,
|
||||
marshalBuf,
|
||||
string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), ctx.BaseIndent+code.Indent),
|
||||
string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), int(ctx.BaseIndent+code.Indent)),
|
||||
string(ctx.IndentStr),
|
||||
escape,
|
||||
(ctx.Option.Flag&HTMLEscapeOption) != 0,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
|
|
@ -426,9 +450,9 @@ func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v inte
|
|||
return indentedBuf, nil
|
||||
}
|
||||
|
||||
func AppendMarshalText(code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
|
||||
func AppendMarshalText(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
rv := reflect.ValueOf(v) // convert by dynamic interface type
|
||||
if code.AddrForMarshaler {
|
||||
if (code.Flags & AddrForMarshalerFlags) != 0 {
|
||||
if rv.CanAddr() {
|
||||
rv = rv.Addr()
|
||||
} else {
|
||||
|
|
@ -440,21 +464,18 @@ func AppendMarshalText(code *Opcode, b []byte, v interface{}, escape bool) ([]by
|
|||
v = rv.Interface()
|
||||
marshaler, ok := v.(encoding.TextMarshaler)
|
||||
if !ok {
|
||||
return AppendNull(b), nil
|
||||
return AppendNull(ctx, b), nil
|
||||
}
|
||||
bytes, err := marshaler.MarshalText()
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
}
|
||||
if escape {
|
||||
return AppendEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||
}
|
||||
return AppendString(b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||
return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||
}
|
||||
|
||||
func AppendMarshalTextIndent(code *Opcode, b []byte, v interface{}, escape bool) ([]byte, error) {
|
||||
func AppendMarshalTextIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
rv := reflect.ValueOf(v) // convert by dynamic interface type
|
||||
if code.AddrForMarshaler {
|
||||
if (code.Flags & AddrForMarshalerFlags) != 0 {
|
||||
if rv.CanAddr() {
|
||||
rv = rv.Addr()
|
||||
} else {
|
||||
|
|
@ -466,31 +487,28 @@ func AppendMarshalTextIndent(code *Opcode, b []byte, v interface{}, escape bool)
|
|||
v = rv.Interface()
|
||||
marshaler, ok := v.(encoding.TextMarshaler)
|
||||
if !ok {
|
||||
return AppendNull(b), nil
|
||||
return AppendNull(ctx, b), nil
|
||||
}
|
||||
bytes, err := marshaler.MarshalText()
|
||||
if err != nil {
|
||||
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||
}
|
||||
if escape {
|
||||
return AppendEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||
}
|
||||
return AppendString(b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||
return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||
}
|
||||
|
||||
func AppendNull(b []byte) []byte {
|
||||
func AppendNull(_ *RuntimeContext, b []byte) []byte {
|
||||
return append(b, "null"...)
|
||||
}
|
||||
|
||||
func AppendComma(b []byte) []byte {
|
||||
func AppendComma(_ *RuntimeContext, b []byte) []byte {
|
||||
return append(b, ',')
|
||||
}
|
||||
|
||||
func AppendCommaIndent(b []byte) []byte {
|
||||
func AppendCommaIndent(_ *RuntimeContext, b []byte) []byte {
|
||||
return append(b, ',', '\n')
|
||||
}
|
||||
|
||||
func AppendStructEnd(b []byte) []byte {
|
||||
func AppendStructEnd(_ *RuntimeContext, b []byte) []byte {
|
||||
return append(b, '}', ',')
|
||||
}
|
||||
|
||||
|
|
@ -498,16 +516,16 @@ func AppendStructEndIndent(ctx *RuntimeContext, code *Opcode, b []byte) []byte {
|
|||
b = append(b, '\n')
|
||||
b = append(b, ctx.Prefix...)
|
||||
indentNum := ctx.BaseIndent + code.Indent - 1
|
||||
for i := 0; i < indentNum; i++ {
|
||||
for i := uint32(0); i < indentNum; i++ {
|
||||
b = append(b, ctx.IndentStr...)
|
||||
}
|
||||
return append(b, '}', ',', '\n')
|
||||
}
|
||||
|
||||
func AppendIndent(ctx *RuntimeContext, b []byte, indent int) []byte {
|
||||
func AppendIndent(ctx *RuntimeContext, b []byte, indent uint32) []byte {
|
||||
b = append(b, ctx.Prefix...)
|
||||
indentNum := ctx.BaseIndent + indent
|
||||
for i := 0; i < indentNum; i++ {
|
||||
for i := uint32(0); i < indentNum; i++ {
|
||||
b = append(b, ctx.IndentStr...)
|
||||
}
|
||||
return b
|
||||
|
|
|
|||
18
vendor/github.com/goccy/go-json/internal/encoder/int.go
generated
vendored
18
vendor/github.com/goccy/go-json/internal/encoder/int.go
generated
vendored
|
|
@ -49,9 +49,14 @@ var intBELookup = [100]uint16{
|
|||
|
||||
var intLookup = [2]*[100]uint16{&intLELookup, &intBELookup}
|
||||
|
||||
func AppendInt(out []byte, u64 uint64, code *Opcode) []byte {
|
||||
n := u64 & code.Mask
|
||||
negative := (u64>>code.RshiftNum)&1 == 1
|
||||
func numMask(numBitSize uint8) uint64 {
|
||||
return 1<<numBitSize - 1
|
||||
}
|
||||
|
||||
func AppendInt(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte {
|
||||
mask := numMask(code.NumBitSize)
|
||||
n := u64 & mask
|
||||
negative := (u64>>(code.NumBitSize-1))&1 == 1
|
||||
if !negative {
|
||||
if n < 10 {
|
||||
return append(out, byte(n+'0'))
|
||||
|
|
@ -60,7 +65,7 @@ func AppendInt(out []byte, u64 uint64, code *Opcode) []byte {
|
|||
return append(out, byte(u), byte(u>>8))
|
||||
}
|
||||
} else {
|
||||
n = -n & code.Mask
|
||||
n = -n & mask
|
||||
}
|
||||
|
||||
lookup := intLookup[endianness]
|
||||
|
|
@ -91,8 +96,9 @@ func AppendInt(out []byte, u64 uint64, code *Opcode) []byte {
|
|||
return append(out, b[i:]...)
|
||||
}
|
||||
|
||||
func AppendUint(out []byte, u64 uint64, code *Opcode) []byte {
|
||||
n := u64 & code.Mask
|
||||
func AppendUint(_ *RuntimeContext, out []byte, u64 uint64, code *Opcode) []byte {
|
||||
mask := numMask(code.NumBitSize)
|
||||
n := u64 & mask
|
||||
if n < 10 {
|
||||
return append(out, byte(n+'0'))
|
||||
} else if n < 100 {
|
||||
|
|
|
|||
289
vendor/github.com/goccy/go-json/internal/encoder/opcode.go
generated
vendored
289
vendor/github.com/goccy/go-json/internal/encoder/opcode.go
generated
vendored
|
|
@ -2,7 +2,6 @@ package encoder
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
|
|
@ -11,61 +10,61 @@ import (
|
|||
|
||||
const uintptrSize = 4 << (^uintptr(0) >> 63)
|
||||
|
||||
type OpFlags uint16
|
||||
|
||||
const (
|
||||
AnonymousHeadFlags OpFlags = 1 << 0
|
||||
AnonymousKeyFlags OpFlags = 1 << 1
|
||||
IndirectFlags OpFlags = 1 << 2
|
||||
IsTaggedKeyFlags OpFlags = 1 << 3
|
||||
NilCheckFlags OpFlags = 1 << 4
|
||||
AddrForMarshalerFlags OpFlags = 1 << 5
|
||||
IsNextOpPtrTypeFlags OpFlags = 1 << 6
|
||||
IsNilableTypeFlags OpFlags = 1 << 7
|
||||
MarshalerContextFlags OpFlags = 1 << 8
|
||||
NonEmptyInterfaceFlags OpFlags = 1 << 9
|
||||
)
|
||||
|
||||
type Opcode struct {
|
||||
Op OpType // operation type
|
||||
Type *runtime.Type // go type
|
||||
DisplayIdx int // opcode index
|
||||
Key []byte // struct field key
|
||||
EscapedKey []byte // struct field key ( HTML escaped )
|
||||
PtrNum int // pointer number: e.g. double pointer is 2.
|
||||
DisplayKey string // key text to display
|
||||
IsTaggedKey bool // whether tagged key
|
||||
AnonymousKey bool // whether anonymous key
|
||||
AnonymousHead bool // whether anonymous head or not
|
||||
Indirect bool // whether indirect or not
|
||||
Nilcheck bool // whether needs to nilcheck or not
|
||||
AddrForMarshaler bool // whether needs to addr for marshaler or not
|
||||
IsNextOpPtrType bool // whether next operation is ptr type or not
|
||||
IsNilableType bool // whether type is nilable or not
|
||||
RshiftNum uint8 // use to take bit for judging whether negative integer or not
|
||||
Mask uint64 // mask for number
|
||||
Indent int // indent number
|
||||
Op OpType // operation type
|
||||
Idx uint32 // offset to access ptr
|
||||
Next *Opcode // next opcode
|
||||
End *Opcode // array/slice/struct/map end
|
||||
NextField *Opcode // next struct field
|
||||
Key string // struct field key
|
||||
Offset uint32 // offset size from struct header
|
||||
PtrNum uint8 // pointer number: e.g. double pointer is 2.
|
||||
NumBitSize uint8
|
||||
Flags OpFlags
|
||||
|
||||
Idx uintptr // offset to access ptr
|
||||
HeadIdx uintptr // offset to access slice/struct head
|
||||
ElemIdx uintptr // offset to access array/slice/map elem
|
||||
Length uintptr // offset to access slice/map length or array length
|
||||
MapIter uintptr // offset to access map iterator
|
||||
MapPos uintptr // offset to access position list for sorted map
|
||||
Offset uintptr // offset size from struct header
|
||||
Size uintptr // array/slice elem size
|
||||
|
||||
MapKey *Opcode // map key
|
||||
MapValue *Opcode // map value
|
||||
Elem *Opcode // array/slice elem
|
||||
End *Opcode // array/slice/struct/map end
|
||||
PrevField *Opcode // prev struct field
|
||||
NextField *Opcode // next struct field
|
||||
Next *Opcode // next opcode
|
||||
Jmp *CompiledCode // for recursive call
|
||||
Type *runtime.Type // go type
|
||||
PrevField *Opcode // prev struct field
|
||||
Jmp *CompiledCode // for recursive call
|
||||
ElemIdx uint32 // offset to access array/slice/map elem
|
||||
Length uint32 // offset to access slice/map length or array length
|
||||
MapIter uint32 // offset to access map iterator
|
||||
MapPos uint32 // offset to access position list for sorted map
|
||||
Indent uint32 // indent number
|
||||
Size uint32 // array/slice elem size
|
||||
DisplayIdx uint32 // opcode index
|
||||
DisplayKey string // key text to display
|
||||
}
|
||||
|
||||
func rshitNum(bitSize uint8) uint8 {
|
||||
return bitSize - 1
|
||||
}
|
||||
|
||||
func (c *Opcode) setMaskAndRshiftNum(bitSize uint8) {
|
||||
switch bitSize {
|
||||
case 8:
|
||||
c.Mask = math.MaxUint8
|
||||
case 16:
|
||||
c.Mask = math.MaxUint16
|
||||
case 32:
|
||||
c.Mask = math.MaxUint32
|
||||
case 64:
|
||||
c.Mask = math.MaxUint64
|
||||
func (c *Opcode) MaxIdx() uint32 {
|
||||
max := uint32(0)
|
||||
for _, value := range []uint32{
|
||||
c.Idx,
|
||||
c.ElemIdx,
|
||||
c.Length,
|
||||
c.MapIter,
|
||||
c.MapPos,
|
||||
c.Size,
|
||||
} {
|
||||
if max < value {
|
||||
max = value
|
||||
}
|
||||
}
|
||||
c.RshiftNum = rshitNum(bitSize)
|
||||
return max
|
||||
}
|
||||
|
||||
func (c *Opcode) ToHeaderType(isString bool) OpType {
|
||||
|
|
@ -278,8 +277,8 @@ func newOpCode(ctx *compileContext, op OpType) *Opcode {
|
|||
return newOpCodeWithNext(ctx, op, newEndOp(ctx))
|
||||
}
|
||||
|
||||
func opcodeOffset(idx int) uintptr {
|
||||
return uintptr(idx) * uintptrSize
|
||||
func opcodeOffset(idx int) uint32 {
|
||||
return uint32(idx) * uintptrSize
|
||||
}
|
||||
|
||||
func copyOpcode(code *Opcode) *Opcode {
|
||||
|
|
@ -287,14 +286,53 @@ func copyOpcode(code *Opcode) *Opcode {
|
|||
return code.copy(codeMap)
|
||||
}
|
||||
|
||||
func setTotalLengthToInterfaceOp(code *Opcode) {
|
||||
c := code
|
||||
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
|
||||
if c.Op == OpInterface {
|
||||
c.Length = uint32(code.TotalLength())
|
||||
}
|
||||
switch c.Op.CodeType() {
|
||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
||||
c = c.End
|
||||
default:
|
||||
c = c.Next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ToEndCode(code *Opcode) *Opcode {
|
||||
c := code
|
||||
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
|
||||
switch c.Op.CodeType() {
|
||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
||||
c = c.End
|
||||
default:
|
||||
c = c.Next
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func copyToInterfaceOpcode(code *Opcode) *Opcode {
|
||||
copied := copyOpcode(code)
|
||||
c := copied
|
||||
c = ToEndCode(c)
|
||||
c.Idx += uintptrSize
|
||||
c.ElemIdx = c.Idx + uintptrSize
|
||||
c.Length = c.Idx + 2*uintptrSize
|
||||
c.Op = OpInterfaceEnd
|
||||
return copied
|
||||
}
|
||||
|
||||
func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: op,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Next: next,
|
||||
Type: ctx.typ,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Next: next,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -311,37 +349,24 @@ func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
|
|||
return code
|
||||
}
|
||||
copied := &Opcode{
|
||||
Op: c.Op,
|
||||
Type: c.Type,
|
||||
DisplayIdx: c.DisplayIdx,
|
||||
Key: c.Key,
|
||||
EscapedKey: c.EscapedKey,
|
||||
DisplayKey: c.DisplayKey,
|
||||
PtrNum: c.PtrNum,
|
||||
Mask: c.Mask,
|
||||
RshiftNum: c.RshiftNum,
|
||||
IsTaggedKey: c.IsTaggedKey,
|
||||
AnonymousKey: c.AnonymousKey,
|
||||
AnonymousHead: c.AnonymousHead,
|
||||
Indirect: c.Indirect,
|
||||
Nilcheck: c.Nilcheck,
|
||||
AddrForMarshaler: c.AddrForMarshaler,
|
||||
IsNextOpPtrType: c.IsNextOpPtrType,
|
||||
IsNilableType: c.IsNilableType,
|
||||
Indent: c.Indent,
|
||||
Idx: c.Idx,
|
||||
HeadIdx: c.HeadIdx,
|
||||
ElemIdx: c.ElemIdx,
|
||||
Length: c.Length,
|
||||
MapIter: c.MapIter,
|
||||
MapPos: c.MapPos,
|
||||
Offset: c.Offset,
|
||||
Size: c.Size,
|
||||
Op: c.Op,
|
||||
Key: c.Key,
|
||||
PtrNum: c.PtrNum,
|
||||
NumBitSize: c.NumBitSize,
|
||||
Flags: c.Flags,
|
||||
Idx: c.Idx,
|
||||
Offset: c.Offset,
|
||||
Type: c.Type,
|
||||
DisplayIdx: c.DisplayIdx,
|
||||
DisplayKey: c.DisplayKey,
|
||||
ElemIdx: c.ElemIdx,
|
||||
Length: c.Length,
|
||||
MapIter: c.MapIter,
|
||||
MapPos: c.MapPos,
|
||||
Size: c.Size,
|
||||
Indent: c.Indent,
|
||||
}
|
||||
codeMap[addr] = copied
|
||||
copied.MapKey = c.MapKey.copy(codeMap)
|
||||
copied.MapValue = c.MapValue.copy(codeMap)
|
||||
copied.Elem = c.Elem.copy(codeMap)
|
||||
copied.End = c.End.copy(codeMap)
|
||||
copied.PrevField = c.PrevField.copy(codeMap)
|
||||
copied.NextField = c.NextField.copy(codeMap)
|
||||
|
|
@ -369,8 +394,12 @@ func (c *Opcode) BeforeLastCode() *Opcode {
|
|||
|
||||
func (c *Opcode) TotalLength() int {
|
||||
var idx int
|
||||
for code := c; code.Op != OpEnd; {
|
||||
idx = int(code.Idx / uintptrSize)
|
||||
code := c
|
||||
for code.Op != OpEnd && code.Op != OpInterfaceEnd {
|
||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||
if idx < maxIdx {
|
||||
idx = maxIdx
|
||||
}
|
||||
if code.Op == OpRecursiveEnd {
|
||||
break
|
||||
}
|
||||
|
|
@ -381,15 +410,18 @@ func (c *Opcode) TotalLength() int {
|
|||
code = code.Next
|
||||
}
|
||||
}
|
||||
return idx + 2 // opEnd + 1
|
||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||
if idx < maxIdx {
|
||||
idx = maxIdx
|
||||
}
|
||||
return idx + 1
|
||||
}
|
||||
|
||||
func (c *Opcode) decOpcodeIndex() {
|
||||
for code := c; code.Op != OpEnd; {
|
||||
code.DisplayIdx--
|
||||
code.Idx -= uintptrSize
|
||||
if code.HeadIdx > 0 {
|
||||
code.HeadIdx -= uintptrSize
|
||||
if code.Idx > 0 {
|
||||
code.Idx -= uintptrSize
|
||||
}
|
||||
if code.ElemIdx > 0 {
|
||||
code.ElemIdx -= uintptrSize
|
||||
|
|
@ -422,19 +454,18 @@ func (c *Opcode) decIndent() {
|
|||
}
|
||||
|
||||
func (c *Opcode) dumpHead(code *Opcode) string {
|
||||
var length uintptr
|
||||
var length uint32
|
||||
if code.Op.CodeType() == CodeArrayHead {
|
||||
length = code.Length
|
||||
} else {
|
||||
length = code.Length / uintptrSize
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d])`,
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
code.HeadIdx/uintptrSize,
|
||||
code.ElemIdx/uintptrSize,
|
||||
length,
|
||||
)
|
||||
|
|
@ -442,12 +473,11 @@ func (c *Opcode) dumpHead(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) dumpMapHead(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
code.HeadIdx/uintptrSize,
|
||||
code.ElemIdx/uintptrSize,
|
||||
code.Length/uintptrSize,
|
||||
code.MapIter/uintptrSize,
|
||||
|
|
@ -458,7 +488,7 @@ func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
|||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
code.MapPos/uintptrSize,
|
||||
|
|
@ -467,19 +497,18 @@ func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
|||
}
|
||||
|
||||
func (c *Opcode) dumpElem(code *Opcode) string {
|
||||
var length uintptr
|
||||
var length uint32
|
||||
if code.Op.CodeType() == CodeArrayElem {
|
||||
length = code.Length
|
||||
} else {
|
||||
length = code.Length / uintptrSize
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][headIdx:%d][elemIdx:%d][length:%d][size:%d])`,
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
code.HeadIdx/uintptrSize,
|
||||
code.ElemIdx/uintptrSize,
|
||||
length,
|
||||
code.Size,
|
||||
|
|
@ -488,14 +517,13 @@ func (c *Opcode) dumpElem(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) dumpField(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][key:%s][offset:%d][headIdx:%d])`,
|
||||
`[%d]%s%s ([idx:%d][key:%s][offset:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
code.DisplayKey,
|
||||
code.Offset,
|
||||
code.HeadIdx/uintptrSize,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -503,7 +531,7 @@ func (c *Opcode) dumpKey(code *Opcode) string {
|
|||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
code.ElemIdx/uintptrSize,
|
||||
|
|
@ -516,7 +544,7 @@ func (c *Opcode) dumpValue(code *Opcode) string {
|
|||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][mapIter:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
code.MapIter/uintptrSize,
|
||||
|
|
@ -525,7 +553,7 @@ func (c *Opcode) dumpValue(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) Dump() string {
|
||||
codes := []string{}
|
||||
for code := c; code.Op != OpEnd; {
|
||||
for code := c; code.Op != OpEnd && code.Op != OpInterfaceEnd; {
|
||||
switch code.Op.CodeType() {
|
||||
case CodeSliceHead:
|
||||
codes = append(codes, c.dumpHead(code))
|
||||
|
|
@ -555,7 +583,7 @@ func (c *Opcode) Dump() string {
|
|||
codes = append(codes, fmt.Sprintf(
|
||||
"[%d]%s%s ([idx:%d])",
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", code.Indent),
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
))
|
||||
|
|
@ -610,9 +638,8 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
|||
length := opcodeOffset(ctx.ptrIndex)
|
||||
return &Opcode{
|
||||
Op: OpSlice,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: idx,
|
||||
HeadIdx: idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: elemIdx,
|
||||
Length: length,
|
||||
Indent: ctx.indent,
|
||||
|
|
@ -622,13 +649,12 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
|||
func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpSliceElem,
|
||||
Idx: head.Idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
HeadIdx: head.Idx,
|
||||
ElemIdx: head.ElemIdx,
|
||||
Length: head.Length,
|
||||
Indent: ctx.indent,
|
||||
Size: size,
|
||||
Size: uint32(size),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -638,25 +664,23 @@ func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
|
|||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||
return &Opcode{
|
||||
Op: OpArray,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: idx,
|
||||
HeadIdx: idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: elemIdx,
|
||||
Indent: ctx.indent,
|
||||
Length: uintptr(alen),
|
||||
Length: uint32(alen),
|
||||
}
|
||||
}
|
||||
|
||||
func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpArrayElem,
|
||||
Idx: head.Idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
ElemIdx: head.ElemIdx,
|
||||
HeadIdx: head.HeadIdx,
|
||||
Length: uintptr(length),
|
||||
Length: uint32(length),
|
||||
Indent: ctx.indent,
|
||||
Size: size,
|
||||
Size: uint32(size),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -670,9 +694,9 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
|
|||
mapIter := opcodeOffset(ctx.ptrIndex)
|
||||
return &Opcode{
|
||||
Op: OpMap,
|
||||
Idx: idx,
|
||||
Type: ctx.typ,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: idx,
|
||||
ElemIdx: elemIdx,
|
||||
Length: length,
|
||||
MapIter: mapIter,
|
||||
|
|
@ -683,8 +707,8 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
|
|||
func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpMapKey,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: head.ElemIdx,
|
||||
Length: head.Length,
|
||||
MapIter: head.MapIter,
|
||||
|
|
@ -695,8 +719,8 @@ func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
|
|||
func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpMapValue,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: head.ElemIdx,
|
||||
Length: head.Length,
|
||||
MapIter: head.MapIter,
|
||||
|
|
@ -710,34 +734,39 @@ func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
|
|||
idx := opcodeOffset(ctx.ptrIndex)
|
||||
return &Opcode{
|
||||
Op: OpMapEnd,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: idx,
|
||||
Next: newEndOp(ctx),
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Length: head.Length,
|
||||
MapPos: mapPos,
|
||||
Indent: ctx.indent,
|
||||
Next: newEndOp(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func newInterfaceCode(ctx *compileContext) *Opcode {
|
||||
var flag OpFlags
|
||||
if ctx.typ.NumMethod() > 0 {
|
||||
flag |= NonEmptyInterfaceFlags
|
||||
}
|
||||
return &Opcode{
|
||||
Op: OpInterface,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Next: newEndOp(ctx),
|
||||
Type: ctx.typ,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Indent: ctx.indent,
|
||||
Next: newEndOp(ctx),
|
||||
Flags: flag,
|
||||
}
|
||||
}
|
||||
|
||||
func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpRecursive,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Next: newEndOp(ctx),
|
||||
Type: ctx.typ,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Indent: ctx.indent,
|
||||
Next: newEndOp(ctx),
|
||||
Jmp: jmp,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
41
vendor/github.com/goccy/go-json/internal/encoder/option.go
generated
vendored
Normal file
41
vendor/github.com/goccy/go-json/internal/encoder/option.go
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package encoder
|
||||
|
||||
import "context"
|
||||
|
||||
type OptionFlag uint8
|
||||
|
||||
const (
|
||||
HTMLEscapeOption OptionFlag = 1 << iota
|
||||
IndentOption
|
||||
UnorderedMapOption
|
||||
DebugOption
|
||||
ColorizeOption
|
||||
ContextOption
|
||||
)
|
||||
|
||||
type Option struct {
|
||||
Flag OptionFlag
|
||||
ColorScheme *ColorScheme
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
type EncodeFormat struct {
|
||||
Header string
|
||||
Footer string
|
||||
}
|
||||
|
||||
type EncodeFormatScheme struct {
|
||||
Int EncodeFormat
|
||||
Uint EncodeFormat
|
||||
Float EncodeFormat
|
||||
Bool EncodeFormat
|
||||
String EncodeFormat
|
||||
Binary EncodeFormat
|
||||
ObjectKey EncodeFormat
|
||||
Null EncodeFormat
|
||||
}
|
||||
|
||||
type (
|
||||
ColorScheme = EncodeFormatScheme
|
||||
ColorFormat = EncodeFormat
|
||||
)
|
||||
782
vendor/github.com/goccy/go-json/internal/encoder/optype.go
generated
vendored
782
vendor/github.com/goccy/go-json/internal/encoder/optype.go
generated
vendored
|
|
@ -22,7 +22,7 @@ const (
|
|||
CodeStructEnd CodeType = 11
|
||||
)
|
||||
|
||||
var opTypeStrings = [400]string{
|
||||
var opTypeStrings = [401]string{
|
||||
"End",
|
||||
"Interface",
|
||||
"Ptr",
|
||||
|
|
@ -36,6 +36,7 @@ var opTypeStrings = [400]string{
|
|||
"Recursive",
|
||||
"RecursivePtr",
|
||||
"RecursiveEnd",
|
||||
"InterfaceEnd",
|
||||
"StructAnonymousEnd",
|
||||
"Int",
|
||||
"Uint",
|
||||
|
|
@ -425,7 +426,7 @@ var opTypeStrings = [400]string{
|
|||
"StructEndOmitEmpty",
|
||||
}
|
||||
|
||||
type OpType int
|
||||
type OpType uint16
|
||||
|
||||
const (
|
||||
OpEnd OpType = 0
|
||||
|
|
@ -441,397 +442,398 @@ const (
|
|||
OpRecursive OpType = 10
|
||||
OpRecursivePtr OpType = 11
|
||||
OpRecursiveEnd OpType = 12
|
||||
OpStructAnonymousEnd OpType = 13
|
||||
OpInt OpType = 14
|
||||
OpUint OpType = 15
|
||||
OpFloat32 OpType = 16
|
||||
OpFloat64 OpType = 17
|
||||
OpBool OpType = 18
|
||||
OpString OpType = 19
|
||||
OpBytes OpType = 20
|
||||
OpNumber OpType = 21
|
||||
OpArray OpType = 22
|
||||
OpMap OpType = 23
|
||||
OpSlice OpType = 24
|
||||
OpStruct OpType = 25
|
||||
OpMarshalJSON OpType = 26
|
||||
OpMarshalText OpType = 27
|
||||
OpIntString OpType = 28
|
||||
OpUintString OpType = 29
|
||||
OpFloat32String OpType = 30
|
||||
OpFloat64String OpType = 31
|
||||
OpBoolString OpType = 32
|
||||
OpStringString OpType = 33
|
||||
OpNumberString OpType = 34
|
||||
OpIntPtr OpType = 35
|
||||
OpUintPtr OpType = 36
|
||||
OpFloat32Ptr OpType = 37
|
||||
OpFloat64Ptr OpType = 38
|
||||
OpBoolPtr OpType = 39
|
||||
OpStringPtr OpType = 40
|
||||
OpBytesPtr OpType = 41
|
||||
OpNumberPtr OpType = 42
|
||||
OpArrayPtr OpType = 43
|
||||
OpMapPtr OpType = 44
|
||||
OpSlicePtr OpType = 45
|
||||
OpMarshalJSONPtr OpType = 46
|
||||
OpMarshalTextPtr OpType = 47
|
||||
OpInterfacePtr OpType = 48
|
||||
OpIntPtrString OpType = 49
|
||||
OpUintPtrString OpType = 50
|
||||
OpFloat32PtrString OpType = 51
|
||||
OpFloat64PtrString OpType = 52
|
||||
OpBoolPtrString OpType = 53
|
||||
OpStringPtrString OpType = 54
|
||||
OpNumberPtrString OpType = 55
|
||||
OpStructHeadInt OpType = 56
|
||||
OpStructHeadOmitEmptyInt OpType = 57
|
||||
OpStructPtrHeadInt OpType = 58
|
||||
OpStructPtrHeadOmitEmptyInt OpType = 59
|
||||
OpStructHeadUint OpType = 60
|
||||
OpStructHeadOmitEmptyUint OpType = 61
|
||||
OpStructPtrHeadUint OpType = 62
|
||||
OpStructPtrHeadOmitEmptyUint OpType = 63
|
||||
OpStructHeadFloat32 OpType = 64
|
||||
OpStructHeadOmitEmptyFloat32 OpType = 65
|
||||
OpStructPtrHeadFloat32 OpType = 66
|
||||
OpStructPtrHeadOmitEmptyFloat32 OpType = 67
|
||||
OpStructHeadFloat64 OpType = 68
|
||||
OpStructHeadOmitEmptyFloat64 OpType = 69
|
||||
OpStructPtrHeadFloat64 OpType = 70
|
||||
OpStructPtrHeadOmitEmptyFloat64 OpType = 71
|
||||
OpStructHeadBool OpType = 72
|
||||
OpStructHeadOmitEmptyBool OpType = 73
|
||||
OpStructPtrHeadBool OpType = 74
|
||||
OpStructPtrHeadOmitEmptyBool OpType = 75
|
||||
OpStructHeadString OpType = 76
|
||||
OpStructHeadOmitEmptyString OpType = 77
|
||||
OpStructPtrHeadString OpType = 78
|
||||
OpStructPtrHeadOmitEmptyString OpType = 79
|
||||
OpStructHeadBytes OpType = 80
|
||||
OpStructHeadOmitEmptyBytes OpType = 81
|
||||
OpStructPtrHeadBytes OpType = 82
|
||||
OpStructPtrHeadOmitEmptyBytes OpType = 83
|
||||
OpStructHeadNumber OpType = 84
|
||||
OpStructHeadOmitEmptyNumber OpType = 85
|
||||
OpStructPtrHeadNumber OpType = 86
|
||||
OpStructPtrHeadOmitEmptyNumber OpType = 87
|
||||
OpStructHeadArray OpType = 88
|
||||
OpStructHeadOmitEmptyArray OpType = 89
|
||||
OpStructPtrHeadArray OpType = 90
|
||||
OpStructPtrHeadOmitEmptyArray OpType = 91
|
||||
OpStructHeadMap OpType = 92
|
||||
OpStructHeadOmitEmptyMap OpType = 93
|
||||
OpStructPtrHeadMap OpType = 94
|
||||
OpStructPtrHeadOmitEmptyMap OpType = 95
|
||||
OpStructHeadSlice OpType = 96
|
||||
OpStructHeadOmitEmptySlice OpType = 97
|
||||
OpStructPtrHeadSlice OpType = 98
|
||||
OpStructPtrHeadOmitEmptySlice OpType = 99
|
||||
OpStructHeadStruct OpType = 100
|
||||
OpStructHeadOmitEmptyStruct OpType = 101
|
||||
OpStructPtrHeadStruct OpType = 102
|
||||
OpStructPtrHeadOmitEmptyStruct OpType = 103
|
||||
OpStructHeadMarshalJSON OpType = 104
|
||||
OpStructHeadOmitEmptyMarshalJSON OpType = 105
|
||||
OpStructPtrHeadMarshalJSON OpType = 106
|
||||
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 107
|
||||
OpStructHeadMarshalText OpType = 108
|
||||
OpStructHeadOmitEmptyMarshalText OpType = 109
|
||||
OpStructPtrHeadMarshalText OpType = 110
|
||||
OpStructPtrHeadOmitEmptyMarshalText OpType = 111
|
||||
OpStructHeadIntString OpType = 112
|
||||
OpStructHeadOmitEmptyIntString OpType = 113
|
||||
OpStructPtrHeadIntString OpType = 114
|
||||
OpStructPtrHeadOmitEmptyIntString OpType = 115
|
||||
OpStructHeadUintString OpType = 116
|
||||
OpStructHeadOmitEmptyUintString OpType = 117
|
||||
OpStructPtrHeadUintString OpType = 118
|
||||
OpStructPtrHeadOmitEmptyUintString OpType = 119
|
||||
OpStructHeadFloat32String OpType = 120
|
||||
OpStructHeadOmitEmptyFloat32String OpType = 121
|
||||
OpStructPtrHeadFloat32String OpType = 122
|
||||
OpStructPtrHeadOmitEmptyFloat32String OpType = 123
|
||||
OpStructHeadFloat64String OpType = 124
|
||||
OpStructHeadOmitEmptyFloat64String OpType = 125
|
||||
OpStructPtrHeadFloat64String OpType = 126
|
||||
OpStructPtrHeadOmitEmptyFloat64String OpType = 127
|
||||
OpStructHeadBoolString OpType = 128
|
||||
OpStructHeadOmitEmptyBoolString OpType = 129
|
||||
OpStructPtrHeadBoolString OpType = 130
|
||||
OpStructPtrHeadOmitEmptyBoolString OpType = 131
|
||||
OpStructHeadStringString OpType = 132
|
||||
OpStructHeadOmitEmptyStringString OpType = 133
|
||||
OpStructPtrHeadStringString OpType = 134
|
||||
OpStructPtrHeadOmitEmptyStringString OpType = 135
|
||||
OpStructHeadNumberString OpType = 136
|
||||
OpStructHeadOmitEmptyNumberString OpType = 137
|
||||
OpStructPtrHeadNumberString OpType = 138
|
||||
OpStructPtrHeadOmitEmptyNumberString OpType = 139
|
||||
OpStructHeadIntPtr OpType = 140
|
||||
OpStructHeadOmitEmptyIntPtr OpType = 141
|
||||
OpStructPtrHeadIntPtr OpType = 142
|
||||
OpStructPtrHeadOmitEmptyIntPtr OpType = 143
|
||||
OpStructHeadUintPtr OpType = 144
|
||||
OpStructHeadOmitEmptyUintPtr OpType = 145
|
||||
OpStructPtrHeadUintPtr OpType = 146
|
||||
OpStructPtrHeadOmitEmptyUintPtr OpType = 147
|
||||
OpStructHeadFloat32Ptr OpType = 148
|
||||
OpStructHeadOmitEmptyFloat32Ptr OpType = 149
|
||||
OpStructPtrHeadFloat32Ptr OpType = 150
|
||||
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 151
|
||||
OpStructHeadFloat64Ptr OpType = 152
|
||||
OpStructHeadOmitEmptyFloat64Ptr OpType = 153
|
||||
OpStructPtrHeadFloat64Ptr OpType = 154
|
||||
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 155
|
||||
OpStructHeadBoolPtr OpType = 156
|
||||
OpStructHeadOmitEmptyBoolPtr OpType = 157
|
||||
OpStructPtrHeadBoolPtr OpType = 158
|
||||
OpStructPtrHeadOmitEmptyBoolPtr OpType = 159
|
||||
OpStructHeadStringPtr OpType = 160
|
||||
OpStructHeadOmitEmptyStringPtr OpType = 161
|
||||
OpStructPtrHeadStringPtr OpType = 162
|
||||
OpStructPtrHeadOmitEmptyStringPtr OpType = 163
|
||||
OpStructHeadBytesPtr OpType = 164
|
||||
OpStructHeadOmitEmptyBytesPtr OpType = 165
|
||||
OpStructPtrHeadBytesPtr OpType = 166
|
||||
OpStructPtrHeadOmitEmptyBytesPtr OpType = 167
|
||||
OpStructHeadNumberPtr OpType = 168
|
||||
OpStructHeadOmitEmptyNumberPtr OpType = 169
|
||||
OpStructPtrHeadNumberPtr OpType = 170
|
||||
OpStructPtrHeadOmitEmptyNumberPtr OpType = 171
|
||||
OpStructHeadArrayPtr OpType = 172
|
||||
OpStructHeadOmitEmptyArrayPtr OpType = 173
|
||||
OpStructPtrHeadArrayPtr OpType = 174
|
||||
OpStructPtrHeadOmitEmptyArrayPtr OpType = 175
|
||||
OpStructHeadMapPtr OpType = 176
|
||||
OpStructHeadOmitEmptyMapPtr OpType = 177
|
||||
OpStructPtrHeadMapPtr OpType = 178
|
||||
OpStructPtrHeadOmitEmptyMapPtr OpType = 179
|
||||
OpStructHeadSlicePtr OpType = 180
|
||||
OpStructHeadOmitEmptySlicePtr OpType = 181
|
||||
OpStructPtrHeadSlicePtr OpType = 182
|
||||
OpStructPtrHeadOmitEmptySlicePtr OpType = 183
|
||||
OpStructHeadMarshalJSONPtr OpType = 184
|
||||
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 185
|
||||
OpStructPtrHeadMarshalJSONPtr OpType = 186
|
||||
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 187
|
||||
OpStructHeadMarshalTextPtr OpType = 188
|
||||
OpStructHeadOmitEmptyMarshalTextPtr OpType = 189
|
||||
OpStructPtrHeadMarshalTextPtr OpType = 190
|
||||
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 191
|
||||
OpStructHeadInterfacePtr OpType = 192
|
||||
OpStructHeadOmitEmptyInterfacePtr OpType = 193
|
||||
OpStructPtrHeadInterfacePtr OpType = 194
|
||||
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 195
|
||||
OpStructHeadIntPtrString OpType = 196
|
||||
OpStructHeadOmitEmptyIntPtrString OpType = 197
|
||||
OpStructPtrHeadIntPtrString OpType = 198
|
||||
OpStructPtrHeadOmitEmptyIntPtrString OpType = 199
|
||||
OpStructHeadUintPtrString OpType = 200
|
||||
OpStructHeadOmitEmptyUintPtrString OpType = 201
|
||||
OpStructPtrHeadUintPtrString OpType = 202
|
||||
OpStructPtrHeadOmitEmptyUintPtrString OpType = 203
|
||||
OpStructHeadFloat32PtrString OpType = 204
|
||||
OpStructHeadOmitEmptyFloat32PtrString OpType = 205
|
||||
OpStructPtrHeadFloat32PtrString OpType = 206
|
||||
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 207
|
||||
OpStructHeadFloat64PtrString OpType = 208
|
||||
OpStructHeadOmitEmptyFloat64PtrString OpType = 209
|
||||
OpStructPtrHeadFloat64PtrString OpType = 210
|
||||
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 211
|
||||
OpStructHeadBoolPtrString OpType = 212
|
||||
OpStructHeadOmitEmptyBoolPtrString OpType = 213
|
||||
OpStructPtrHeadBoolPtrString OpType = 214
|
||||
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 215
|
||||
OpStructHeadStringPtrString OpType = 216
|
||||
OpStructHeadOmitEmptyStringPtrString OpType = 217
|
||||
OpStructPtrHeadStringPtrString OpType = 218
|
||||
OpStructPtrHeadOmitEmptyStringPtrString OpType = 219
|
||||
OpStructHeadNumberPtrString OpType = 220
|
||||
OpStructHeadOmitEmptyNumberPtrString OpType = 221
|
||||
OpStructPtrHeadNumberPtrString OpType = 222
|
||||
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 223
|
||||
OpStructHead OpType = 224
|
||||
OpStructHeadOmitEmpty OpType = 225
|
||||
OpStructPtrHead OpType = 226
|
||||
OpStructPtrHeadOmitEmpty OpType = 227
|
||||
OpStructFieldInt OpType = 228
|
||||
OpStructFieldOmitEmptyInt OpType = 229
|
||||
OpStructEndInt OpType = 230
|
||||
OpStructEndOmitEmptyInt OpType = 231
|
||||
OpStructFieldUint OpType = 232
|
||||
OpStructFieldOmitEmptyUint OpType = 233
|
||||
OpStructEndUint OpType = 234
|
||||
OpStructEndOmitEmptyUint OpType = 235
|
||||
OpStructFieldFloat32 OpType = 236
|
||||
OpStructFieldOmitEmptyFloat32 OpType = 237
|
||||
OpStructEndFloat32 OpType = 238
|
||||
OpStructEndOmitEmptyFloat32 OpType = 239
|
||||
OpStructFieldFloat64 OpType = 240
|
||||
OpStructFieldOmitEmptyFloat64 OpType = 241
|
||||
OpStructEndFloat64 OpType = 242
|
||||
OpStructEndOmitEmptyFloat64 OpType = 243
|
||||
OpStructFieldBool OpType = 244
|
||||
OpStructFieldOmitEmptyBool OpType = 245
|
||||
OpStructEndBool OpType = 246
|
||||
OpStructEndOmitEmptyBool OpType = 247
|
||||
OpStructFieldString OpType = 248
|
||||
OpStructFieldOmitEmptyString OpType = 249
|
||||
OpStructEndString OpType = 250
|
||||
OpStructEndOmitEmptyString OpType = 251
|
||||
OpStructFieldBytes OpType = 252
|
||||
OpStructFieldOmitEmptyBytes OpType = 253
|
||||
OpStructEndBytes OpType = 254
|
||||
OpStructEndOmitEmptyBytes OpType = 255
|
||||
OpStructFieldNumber OpType = 256
|
||||
OpStructFieldOmitEmptyNumber OpType = 257
|
||||
OpStructEndNumber OpType = 258
|
||||
OpStructEndOmitEmptyNumber OpType = 259
|
||||
OpStructFieldArray OpType = 260
|
||||
OpStructFieldOmitEmptyArray OpType = 261
|
||||
OpStructEndArray OpType = 262
|
||||
OpStructEndOmitEmptyArray OpType = 263
|
||||
OpStructFieldMap OpType = 264
|
||||
OpStructFieldOmitEmptyMap OpType = 265
|
||||
OpStructEndMap OpType = 266
|
||||
OpStructEndOmitEmptyMap OpType = 267
|
||||
OpStructFieldSlice OpType = 268
|
||||
OpStructFieldOmitEmptySlice OpType = 269
|
||||
OpStructEndSlice OpType = 270
|
||||
OpStructEndOmitEmptySlice OpType = 271
|
||||
OpStructFieldStruct OpType = 272
|
||||
OpStructFieldOmitEmptyStruct OpType = 273
|
||||
OpStructEndStruct OpType = 274
|
||||
OpStructEndOmitEmptyStruct OpType = 275
|
||||
OpStructFieldMarshalJSON OpType = 276
|
||||
OpStructFieldOmitEmptyMarshalJSON OpType = 277
|
||||
OpStructEndMarshalJSON OpType = 278
|
||||
OpStructEndOmitEmptyMarshalJSON OpType = 279
|
||||
OpStructFieldMarshalText OpType = 280
|
||||
OpStructFieldOmitEmptyMarshalText OpType = 281
|
||||
OpStructEndMarshalText OpType = 282
|
||||
OpStructEndOmitEmptyMarshalText OpType = 283
|
||||
OpStructFieldIntString OpType = 284
|
||||
OpStructFieldOmitEmptyIntString OpType = 285
|
||||
OpStructEndIntString OpType = 286
|
||||
OpStructEndOmitEmptyIntString OpType = 287
|
||||
OpStructFieldUintString OpType = 288
|
||||
OpStructFieldOmitEmptyUintString OpType = 289
|
||||
OpStructEndUintString OpType = 290
|
||||
OpStructEndOmitEmptyUintString OpType = 291
|
||||
OpStructFieldFloat32String OpType = 292
|
||||
OpStructFieldOmitEmptyFloat32String OpType = 293
|
||||
OpStructEndFloat32String OpType = 294
|
||||
OpStructEndOmitEmptyFloat32String OpType = 295
|
||||
OpStructFieldFloat64String OpType = 296
|
||||
OpStructFieldOmitEmptyFloat64String OpType = 297
|
||||
OpStructEndFloat64String OpType = 298
|
||||
OpStructEndOmitEmptyFloat64String OpType = 299
|
||||
OpStructFieldBoolString OpType = 300
|
||||
OpStructFieldOmitEmptyBoolString OpType = 301
|
||||
OpStructEndBoolString OpType = 302
|
||||
OpStructEndOmitEmptyBoolString OpType = 303
|
||||
OpStructFieldStringString OpType = 304
|
||||
OpStructFieldOmitEmptyStringString OpType = 305
|
||||
OpStructEndStringString OpType = 306
|
||||
OpStructEndOmitEmptyStringString OpType = 307
|
||||
OpStructFieldNumberString OpType = 308
|
||||
OpStructFieldOmitEmptyNumberString OpType = 309
|
||||
OpStructEndNumberString OpType = 310
|
||||
OpStructEndOmitEmptyNumberString OpType = 311
|
||||
OpStructFieldIntPtr OpType = 312
|
||||
OpStructFieldOmitEmptyIntPtr OpType = 313
|
||||
OpStructEndIntPtr OpType = 314
|
||||
OpStructEndOmitEmptyIntPtr OpType = 315
|
||||
OpStructFieldUintPtr OpType = 316
|
||||
OpStructFieldOmitEmptyUintPtr OpType = 317
|
||||
OpStructEndUintPtr OpType = 318
|
||||
OpStructEndOmitEmptyUintPtr OpType = 319
|
||||
OpStructFieldFloat32Ptr OpType = 320
|
||||
OpStructFieldOmitEmptyFloat32Ptr OpType = 321
|
||||
OpStructEndFloat32Ptr OpType = 322
|
||||
OpStructEndOmitEmptyFloat32Ptr OpType = 323
|
||||
OpStructFieldFloat64Ptr OpType = 324
|
||||
OpStructFieldOmitEmptyFloat64Ptr OpType = 325
|
||||
OpStructEndFloat64Ptr OpType = 326
|
||||
OpStructEndOmitEmptyFloat64Ptr OpType = 327
|
||||
OpStructFieldBoolPtr OpType = 328
|
||||
OpStructFieldOmitEmptyBoolPtr OpType = 329
|
||||
OpStructEndBoolPtr OpType = 330
|
||||
OpStructEndOmitEmptyBoolPtr OpType = 331
|
||||
OpStructFieldStringPtr OpType = 332
|
||||
OpStructFieldOmitEmptyStringPtr OpType = 333
|
||||
OpStructEndStringPtr OpType = 334
|
||||
OpStructEndOmitEmptyStringPtr OpType = 335
|
||||
OpStructFieldBytesPtr OpType = 336
|
||||
OpStructFieldOmitEmptyBytesPtr OpType = 337
|
||||
OpStructEndBytesPtr OpType = 338
|
||||
OpStructEndOmitEmptyBytesPtr OpType = 339
|
||||
OpStructFieldNumberPtr OpType = 340
|
||||
OpStructFieldOmitEmptyNumberPtr OpType = 341
|
||||
OpStructEndNumberPtr OpType = 342
|
||||
OpStructEndOmitEmptyNumberPtr OpType = 343
|
||||
OpStructFieldArrayPtr OpType = 344
|
||||
OpStructFieldOmitEmptyArrayPtr OpType = 345
|
||||
OpStructEndArrayPtr OpType = 346
|
||||
OpStructEndOmitEmptyArrayPtr OpType = 347
|
||||
OpStructFieldMapPtr OpType = 348
|
||||
OpStructFieldOmitEmptyMapPtr OpType = 349
|
||||
OpStructEndMapPtr OpType = 350
|
||||
OpStructEndOmitEmptyMapPtr OpType = 351
|
||||
OpStructFieldSlicePtr OpType = 352
|
||||
OpStructFieldOmitEmptySlicePtr OpType = 353
|
||||
OpStructEndSlicePtr OpType = 354
|
||||
OpStructEndOmitEmptySlicePtr OpType = 355
|
||||
OpStructFieldMarshalJSONPtr OpType = 356
|
||||
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 357
|
||||
OpStructEndMarshalJSONPtr OpType = 358
|
||||
OpStructEndOmitEmptyMarshalJSONPtr OpType = 359
|
||||
OpStructFieldMarshalTextPtr OpType = 360
|
||||
OpStructFieldOmitEmptyMarshalTextPtr OpType = 361
|
||||
OpStructEndMarshalTextPtr OpType = 362
|
||||
OpStructEndOmitEmptyMarshalTextPtr OpType = 363
|
||||
OpStructFieldInterfacePtr OpType = 364
|
||||
OpStructFieldOmitEmptyInterfacePtr OpType = 365
|
||||
OpStructEndInterfacePtr OpType = 366
|
||||
OpStructEndOmitEmptyInterfacePtr OpType = 367
|
||||
OpStructFieldIntPtrString OpType = 368
|
||||
OpStructFieldOmitEmptyIntPtrString OpType = 369
|
||||
OpStructEndIntPtrString OpType = 370
|
||||
OpStructEndOmitEmptyIntPtrString OpType = 371
|
||||
OpStructFieldUintPtrString OpType = 372
|
||||
OpStructFieldOmitEmptyUintPtrString OpType = 373
|
||||
OpStructEndUintPtrString OpType = 374
|
||||
OpStructEndOmitEmptyUintPtrString OpType = 375
|
||||
OpStructFieldFloat32PtrString OpType = 376
|
||||
OpStructFieldOmitEmptyFloat32PtrString OpType = 377
|
||||
OpStructEndFloat32PtrString OpType = 378
|
||||
OpStructEndOmitEmptyFloat32PtrString OpType = 379
|
||||
OpStructFieldFloat64PtrString OpType = 380
|
||||
OpStructFieldOmitEmptyFloat64PtrString OpType = 381
|
||||
OpStructEndFloat64PtrString OpType = 382
|
||||
OpStructEndOmitEmptyFloat64PtrString OpType = 383
|
||||
OpStructFieldBoolPtrString OpType = 384
|
||||
OpStructFieldOmitEmptyBoolPtrString OpType = 385
|
||||
OpStructEndBoolPtrString OpType = 386
|
||||
OpStructEndOmitEmptyBoolPtrString OpType = 387
|
||||
OpStructFieldStringPtrString OpType = 388
|
||||
OpStructFieldOmitEmptyStringPtrString OpType = 389
|
||||
OpStructEndStringPtrString OpType = 390
|
||||
OpStructEndOmitEmptyStringPtrString OpType = 391
|
||||
OpStructFieldNumberPtrString OpType = 392
|
||||
OpStructFieldOmitEmptyNumberPtrString OpType = 393
|
||||
OpStructEndNumberPtrString OpType = 394
|
||||
OpStructEndOmitEmptyNumberPtrString OpType = 395
|
||||
OpStructField OpType = 396
|
||||
OpStructFieldOmitEmpty OpType = 397
|
||||
OpStructEnd OpType = 398
|
||||
OpStructEndOmitEmpty OpType = 399
|
||||
OpInterfaceEnd OpType = 13
|
||||
OpStructAnonymousEnd OpType = 14
|
||||
OpInt OpType = 15
|
||||
OpUint OpType = 16
|
||||
OpFloat32 OpType = 17
|
||||
OpFloat64 OpType = 18
|
||||
OpBool OpType = 19
|
||||
OpString OpType = 20
|
||||
OpBytes OpType = 21
|
||||
OpNumber OpType = 22
|
||||
OpArray OpType = 23
|
||||
OpMap OpType = 24
|
||||
OpSlice OpType = 25
|
||||
OpStruct OpType = 26
|
||||
OpMarshalJSON OpType = 27
|
||||
OpMarshalText OpType = 28
|
||||
OpIntString OpType = 29
|
||||
OpUintString OpType = 30
|
||||
OpFloat32String OpType = 31
|
||||
OpFloat64String OpType = 32
|
||||
OpBoolString OpType = 33
|
||||
OpStringString OpType = 34
|
||||
OpNumberString OpType = 35
|
||||
OpIntPtr OpType = 36
|
||||
OpUintPtr OpType = 37
|
||||
OpFloat32Ptr OpType = 38
|
||||
OpFloat64Ptr OpType = 39
|
||||
OpBoolPtr OpType = 40
|
||||
OpStringPtr OpType = 41
|
||||
OpBytesPtr OpType = 42
|
||||
OpNumberPtr OpType = 43
|
||||
OpArrayPtr OpType = 44
|
||||
OpMapPtr OpType = 45
|
||||
OpSlicePtr OpType = 46
|
||||
OpMarshalJSONPtr OpType = 47
|
||||
OpMarshalTextPtr OpType = 48
|
||||
OpInterfacePtr OpType = 49
|
||||
OpIntPtrString OpType = 50
|
||||
OpUintPtrString OpType = 51
|
||||
OpFloat32PtrString OpType = 52
|
||||
OpFloat64PtrString OpType = 53
|
||||
OpBoolPtrString OpType = 54
|
||||
OpStringPtrString OpType = 55
|
||||
OpNumberPtrString OpType = 56
|
||||
OpStructHeadInt OpType = 57
|
||||
OpStructHeadOmitEmptyInt OpType = 58
|
||||
OpStructPtrHeadInt OpType = 59
|
||||
OpStructPtrHeadOmitEmptyInt OpType = 60
|
||||
OpStructHeadUint OpType = 61
|
||||
OpStructHeadOmitEmptyUint OpType = 62
|
||||
OpStructPtrHeadUint OpType = 63
|
||||
OpStructPtrHeadOmitEmptyUint OpType = 64
|
||||
OpStructHeadFloat32 OpType = 65
|
||||
OpStructHeadOmitEmptyFloat32 OpType = 66
|
||||
OpStructPtrHeadFloat32 OpType = 67
|
||||
OpStructPtrHeadOmitEmptyFloat32 OpType = 68
|
||||
OpStructHeadFloat64 OpType = 69
|
||||
OpStructHeadOmitEmptyFloat64 OpType = 70
|
||||
OpStructPtrHeadFloat64 OpType = 71
|
||||
OpStructPtrHeadOmitEmptyFloat64 OpType = 72
|
||||
OpStructHeadBool OpType = 73
|
||||
OpStructHeadOmitEmptyBool OpType = 74
|
||||
OpStructPtrHeadBool OpType = 75
|
||||
OpStructPtrHeadOmitEmptyBool OpType = 76
|
||||
OpStructHeadString OpType = 77
|
||||
OpStructHeadOmitEmptyString OpType = 78
|
||||
OpStructPtrHeadString OpType = 79
|
||||
OpStructPtrHeadOmitEmptyString OpType = 80
|
||||
OpStructHeadBytes OpType = 81
|
||||
OpStructHeadOmitEmptyBytes OpType = 82
|
||||
OpStructPtrHeadBytes OpType = 83
|
||||
OpStructPtrHeadOmitEmptyBytes OpType = 84
|
||||
OpStructHeadNumber OpType = 85
|
||||
OpStructHeadOmitEmptyNumber OpType = 86
|
||||
OpStructPtrHeadNumber OpType = 87
|
||||
OpStructPtrHeadOmitEmptyNumber OpType = 88
|
||||
OpStructHeadArray OpType = 89
|
||||
OpStructHeadOmitEmptyArray OpType = 90
|
||||
OpStructPtrHeadArray OpType = 91
|
||||
OpStructPtrHeadOmitEmptyArray OpType = 92
|
||||
OpStructHeadMap OpType = 93
|
||||
OpStructHeadOmitEmptyMap OpType = 94
|
||||
OpStructPtrHeadMap OpType = 95
|
||||
OpStructPtrHeadOmitEmptyMap OpType = 96
|
||||
OpStructHeadSlice OpType = 97
|
||||
OpStructHeadOmitEmptySlice OpType = 98
|
||||
OpStructPtrHeadSlice OpType = 99
|
||||
OpStructPtrHeadOmitEmptySlice OpType = 100
|
||||
OpStructHeadStruct OpType = 101
|
||||
OpStructHeadOmitEmptyStruct OpType = 102
|
||||
OpStructPtrHeadStruct OpType = 103
|
||||
OpStructPtrHeadOmitEmptyStruct OpType = 104
|
||||
OpStructHeadMarshalJSON OpType = 105
|
||||
OpStructHeadOmitEmptyMarshalJSON OpType = 106
|
||||
OpStructPtrHeadMarshalJSON OpType = 107
|
||||
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 108
|
||||
OpStructHeadMarshalText OpType = 109
|
||||
OpStructHeadOmitEmptyMarshalText OpType = 110
|
||||
OpStructPtrHeadMarshalText OpType = 111
|
||||
OpStructPtrHeadOmitEmptyMarshalText OpType = 112
|
||||
OpStructHeadIntString OpType = 113
|
||||
OpStructHeadOmitEmptyIntString OpType = 114
|
||||
OpStructPtrHeadIntString OpType = 115
|
||||
OpStructPtrHeadOmitEmptyIntString OpType = 116
|
||||
OpStructHeadUintString OpType = 117
|
||||
OpStructHeadOmitEmptyUintString OpType = 118
|
||||
OpStructPtrHeadUintString OpType = 119
|
||||
OpStructPtrHeadOmitEmptyUintString OpType = 120
|
||||
OpStructHeadFloat32String OpType = 121
|
||||
OpStructHeadOmitEmptyFloat32String OpType = 122
|
||||
OpStructPtrHeadFloat32String OpType = 123
|
||||
OpStructPtrHeadOmitEmptyFloat32String OpType = 124
|
||||
OpStructHeadFloat64String OpType = 125
|
||||
OpStructHeadOmitEmptyFloat64String OpType = 126
|
||||
OpStructPtrHeadFloat64String OpType = 127
|
||||
OpStructPtrHeadOmitEmptyFloat64String OpType = 128
|
||||
OpStructHeadBoolString OpType = 129
|
||||
OpStructHeadOmitEmptyBoolString OpType = 130
|
||||
OpStructPtrHeadBoolString OpType = 131
|
||||
OpStructPtrHeadOmitEmptyBoolString OpType = 132
|
||||
OpStructHeadStringString OpType = 133
|
||||
OpStructHeadOmitEmptyStringString OpType = 134
|
||||
OpStructPtrHeadStringString OpType = 135
|
||||
OpStructPtrHeadOmitEmptyStringString OpType = 136
|
||||
OpStructHeadNumberString OpType = 137
|
||||
OpStructHeadOmitEmptyNumberString OpType = 138
|
||||
OpStructPtrHeadNumberString OpType = 139
|
||||
OpStructPtrHeadOmitEmptyNumberString OpType = 140
|
||||
OpStructHeadIntPtr OpType = 141
|
||||
OpStructHeadOmitEmptyIntPtr OpType = 142
|
||||
OpStructPtrHeadIntPtr OpType = 143
|
||||
OpStructPtrHeadOmitEmptyIntPtr OpType = 144
|
||||
OpStructHeadUintPtr OpType = 145
|
||||
OpStructHeadOmitEmptyUintPtr OpType = 146
|
||||
OpStructPtrHeadUintPtr OpType = 147
|
||||
OpStructPtrHeadOmitEmptyUintPtr OpType = 148
|
||||
OpStructHeadFloat32Ptr OpType = 149
|
||||
OpStructHeadOmitEmptyFloat32Ptr OpType = 150
|
||||
OpStructPtrHeadFloat32Ptr OpType = 151
|
||||
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 152
|
||||
OpStructHeadFloat64Ptr OpType = 153
|
||||
OpStructHeadOmitEmptyFloat64Ptr OpType = 154
|
||||
OpStructPtrHeadFloat64Ptr OpType = 155
|
||||
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 156
|
||||
OpStructHeadBoolPtr OpType = 157
|
||||
OpStructHeadOmitEmptyBoolPtr OpType = 158
|
||||
OpStructPtrHeadBoolPtr OpType = 159
|
||||
OpStructPtrHeadOmitEmptyBoolPtr OpType = 160
|
||||
OpStructHeadStringPtr OpType = 161
|
||||
OpStructHeadOmitEmptyStringPtr OpType = 162
|
||||
OpStructPtrHeadStringPtr OpType = 163
|
||||
OpStructPtrHeadOmitEmptyStringPtr OpType = 164
|
||||
OpStructHeadBytesPtr OpType = 165
|
||||
OpStructHeadOmitEmptyBytesPtr OpType = 166
|
||||
OpStructPtrHeadBytesPtr OpType = 167
|
||||
OpStructPtrHeadOmitEmptyBytesPtr OpType = 168
|
||||
OpStructHeadNumberPtr OpType = 169
|
||||
OpStructHeadOmitEmptyNumberPtr OpType = 170
|
||||
OpStructPtrHeadNumberPtr OpType = 171
|
||||
OpStructPtrHeadOmitEmptyNumberPtr OpType = 172
|
||||
OpStructHeadArrayPtr OpType = 173
|
||||
OpStructHeadOmitEmptyArrayPtr OpType = 174
|
||||
OpStructPtrHeadArrayPtr OpType = 175
|
||||
OpStructPtrHeadOmitEmptyArrayPtr OpType = 176
|
||||
OpStructHeadMapPtr OpType = 177
|
||||
OpStructHeadOmitEmptyMapPtr OpType = 178
|
||||
OpStructPtrHeadMapPtr OpType = 179
|
||||
OpStructPtrHeadOmitEmptyMapPtr OpType = 180
|
||||
OpStructHeadSlicePtr OpType = 181
|
||||
OpStructHeadOmitEmptySlicePtr OpType = 182
|
||||
OpStructPtrHeadSlicePtr OpType = 183
|
||||
OpStructPtrHeadOmitEmptySlicePtr OpType = 184
|
||||
OpStructHeadMarshalJSONPtr OpType = 185
|
||||
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 186
|
||||
OpStructPtrHeadMarshalJSONPtr OpType = 187
|
||||
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 188
|
||||
OpStructHeadMarshalTextPtr OpType = 189
|
||||
OpStructHeadOmitEmptyMarshalTextPtr OpType = 190
|
||||
OpStructPtrHeadMarshalTextPtr OpType = 191
|
||||
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 192
|
||||
OpStructHeadInterfacePtr OpType = 193
|
||||
OpStructHeadOmitEmptyInterfacePtr OpType = 194
|
||||
OpStructPtrHeadInterfacePtr OpType = 195
|
||||
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 196
|
||||
OpStructHeadIntPtrString OpType = 197
|
||||
OpStructHeadOmitEmptyIntPtrString OpType = 198
|
||||
OpStructPtrHeadIntPtrString OpType = 199
|
||||
OpStructPtrHeadOmitEmptyIntPtrString OpType = 200
|
||||
OpStructHeadUintPtrString OpType = 201
|
||||
OpStructHeadOmitEmptyUintPtrString OpType = 202
|
||||
OpStructPtrHeadUintPtrString OpType = 203
|
||||
OpStructPtrHeadOmitEmptyUintPtrString OpType = 204
|
||||
OpStructHeadFloat32PtrString OpType = 205
|
||||
OpStructHeadOmitEmptyFloat32PtrString OpType = 206
|
||||
OpStructPtrHeadFloat32PtrString OpType = 207
|
||||
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 208
|
||||
OpStructHeadFloat64PtrString OpType = 209
|
||||
OpStructHeadOmitEmptyFloat64PtrString OpType = 210
|
||||
OpStructPtrHeadFloat64PtrString OpType = 211
|
||||
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 212
|
||||
OpStructHeadBoolPtrString OpType = 213
|
||||
OpStructHeadOmitEmptyBoolPtrString OpType = 214
|
||||
OpStructPtrHeadBoolPtrString OpType = 215
|
||||
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 216
|
||||
OpStructHeadStringPtrString OpType = 217
|
||||
OpStructHeadOmitEmptyStringPtrString OpType = 218
|
||||
OpStructPtrHeadStringPtrString OpType = 219
|
||||
OpStructPtrHeadOmitEmptyStringPtrString OpType = 220
|
||||
OpStructHeadNumberPtrString OpType = 221
|
||||
OpStructHeadOmitEmptyNumberPtrString OpType = 222
|
||||
OpStructPtrHeadNumberPtrString OpType = 223
|
||||
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 224
|
||||
OpStructHead OpType = 225
|
||||
OpStructHeadOmitEmpty OpType = 226
|
||||
OpStructPtrHead OpType = 227
|
||||
OpStructPtrHeadOmitEmpty OpType = 228
|
||||
OpStructFieldInt OpType = 229
|
||||
OpStructFieldOmitEmptyInt OpType = 230
|
||||
OpStructEndInt OpType = 231
|
||||
OpStructEndOmitEmptyInt OpType = 232
|
||||
OpStructFieldUint OpType = 233
|
||||
OpStructFieldOmitEmptyUint OpType = 234
|
||||
OpStructEndUint OpType = 235
|
||||
OpStructEndOmitEmptyUint OpType = 236
|
||||
OpStructFieldFloat32 OpType = 237
|
||||
OpStructFieldOmitEmptyFloat32 OpType = 238
|
||||
OpStructEndFloat32 OpType = 239
|
||||
OpStructEndOmitEmptyFloat32 OpType = 240
|
||||
OpStructFieldFloat64 OpType = 241
|
||||
OpStructFieldOmitEmptyFloat64 OpType = 242
|
||||
OpStructEndFloat64 OpType = 243
|
||||
OpStructEndOmitEmptyFloat64 OpType = 244
|
||||
OpStructFieldBool OpType = 245
|
||||
OpStructFieldOmitEmptyBool OpType = 246
|
||||
OpStructEndBool OpType = 247
|
||||
OpStructEndOmitEmptyBool OpType = 248
|
||||
OpStructFieldString OpType = 249
|
||||
OpStructFieldOmitEmptyString OpType = 250
|
||||
OpStructEndString OpType = 251
|
||||
OpStructEndOmitEmptyString OpType = 252
|
||||
OpStructFieldBytes OpType = 253
|
||||
OpStructFieldOmitEmptyBytes OpType = 254
|
||||
OpStructEndBytes OpType = 255
|
||||
OpStructEndOmitEmptyBytes OpType = 256
|
||||
OpStructFieldNumber OpType = 257
|
||||
OpStructFieldOmitEmptyNumber OpType = 258
|
||||
OpStructEndNumber OpType = 259
|
||||
OpStructEndOmitEmptyNumber OpType = 260
|
||||
OpStructFieldArray OpType = 261
|
||||
OpStructFieldOmitEmptyArray OpType = 262
|
||||
OpStructEndArray OpType = 263
|
||||
OpStructEndOmitEmptyArray OpType = 264
|
||||
OpStructFieldMap OpType = 265
|
||||
OpStructFieldOmitEmptyMap OpType = 266
|
||||
OpStructEndMap OpType = 267
|
||||
OpStructEndOmitEmptyMap OpType = 268
|
||||
OpStructFieldSlice OpType = 269
|
||||
OpStructFieldOmitEmptySlice OpType = 270
|
||||
OpStructEndSlice OpType = 271
|
||||
OpStructEndOmitEmptySlice OpType = 272
|
||||
OpStructFieldStruct OpType = 273
|
||||
OpStructFieldOmitEmptyStruct OpType = 274
|
||||
OpStructEndStruct OpType = 275
|
||||
OpStructEndOmitEmptyStruct OpType = 276
|
||||
OpStructFieldMarshalJSON OpType = 277
|
||||
OpStructFieldOmitEmptyMarshalJSON OpType = 278
|
||||
OpStructEndMarshalJSON OpType = 279
|
||||
OpStructEndOmitEmptyMarshalJSON OpType = 280
|
||||
OpStructFieldMarshalText OpType = 281
|
||||
OpStructFieldOmitEmptyMarshalText OpType = 282
|
||||
OpStructEndMarshalText OpType = 283
|
||||
OpStructEndOmitEmptyMarshalText OpType = 284
|
||||
OpStructFieldIntString OpType = 285
|
||||
OpStructFieldOmitEmptyIntString OpType = 286
|
||||
OpStructEndIntString OpType = 287
|
||||
OpStructEndOmitEmptyIntString OpType = 288
|
||||
OpStructFieldUintString OpType = 289
|
||||
OpStructFieldOmitEmptyUintString OpType = 290
|
||||
OpStructEndUintString OpType = 291
|
||||
OpStructEndOmitEmptyUintString OpType = 292
|
||||
OpStructFieldFloat32String OpType = 293
|
||||
OpStructFieldOmitEmptyFloat32String OpType = 294
|
||||
OpStructEndFloat32String OpType = 295
|
||||
OpStructEndOmitEmptyFloat32String OpType = 296
|
||||
OpStructFieldFloat64String OpType = 297
|
||||
OpStructFieldOmitEmptyFloat64String OpType = 298
|
||||
OpStructEndFloat64String OpType = 299
|
||||
OpStructEndOmitEmptyFloat64String OpType = 300
|
||||
OpStructFieldBoolString OpType = 301
|
||||
OpStructFieldOmitEmptyBoolString OpType = 302
|
||||
OpStructEndBoolString OpType = 303
|
||||
OpStructEndOmitEmptyBoolString OpType = 304
|
||||
OpStructFieldStringString OpType = 305
|
||||
OpStructFieldOmitEmptyStringString OpType = 306
|
||||
OpStructEndStringString OpType = 307
|
||||
OpStructEndOmitEmptyStringString OpType = 308
|
||||
OpStructFieldNumberString OpType = 309
|
||||
OpStructFieldOmitEmptyNumberString OpType = 310
|
||||
OpStructEndNumberString OpType = 311
|
||||
OpStructEndOmitEmptyNumberString OpType = 312
|
||||
OpStructFieldIntPtr OpType = 313
|
||||
OpStructFieldOmitEmptyIntPtr OpType = 314
|
||||
OpStructEndIntPtr OpType = 315
|
||||
OpStructEndOmitEmptyIntPtr OpType = 316
|
||||
OpStructFieldUintPtr OpType = 317
|
||||
OpStructFieldOmitEmptyUintPtr OpType = 318
|
||||
OpStructEndUintPtr OpType = 319
|
||||
OpStructEndOmitEmptyUintPtr OpType = 320
|
||||
OpStructFieldFloat32Ptr OpType = 321
|
||||
OpStructFieldOmitEmptyFloat32Ptr OpType = 322
|
||||
OpStructEndFloat32Ptr OpType = 323
|
||||
OpStructEndOmitEmptyFloat32Ptr OpType = 324
|
||||
OpStructFieldFloat64Ptr OpType = 325
|
||||
OpStructFieldOmitEmptyFloat64Ptr OpType = 326
|
||||
OpStructEndFloat64Ptr OpType = 327
|
||||
OpStructEndOmitEmptyFloat64Ptr OpType = 328
|
||||
OpStructFieldBoolPtr OpType = 329
|
||||
OpStructFieldOmitEmptyBoolPtr OpType = 330
|
||||
OpStructEndBoolPtr OpType = 331
|
||||
OpStructEndOmitEmptyBoolPtr OpType = 332
|
||||
OpStructFieldStringPtr OpType = 333
|
||||
OpStructFieldOmitEmptyStringPtr OpType = 334
|
||||
OpStructEndStringPtr OpType = 335
|
||||
OpStructEndOmitEmptyStringPtr OpType = 336
|
||||
OpStructFieldBytesPtr OpType = 337
|
||||
OpStructFieldOmitEmptyBytesPtr OpType = 338
|
||||
OpStructEndBytesPtr OpType = 339
|
||||
OpStructEndOmitEmptyBytesPtr OpType = 340
|
||||
OpStructFieldNumberPtr OpType = 341
|
||||
OpStructFieldOmitEmptyNumberPtr OpType = 342
|
||||
OpStructEndNumberPtr OpType = 343
|
||||
OpStructEndOmitEmptyNumberPtr OpType = 344
|
||||
OpStructFieldArrayPtr OpType = 345
|
||||
OpStructFieldOmitEmptyArrayPtr OpType = 346
|
||||
OpStructEndArrayPtr OpType = 347
|
||||
OpStructEndOmitEmptyArrayPtr OpType = 348
|
||||
OpStructFieldMapPtr OpType = 349
|
||||
OpStructFieldOmitEmptyMapPtr OpType = 350
|
||||
OpStructEndMapPtr OpType = 351
|
||||
OpStructEndOmitEmptyMapPtr OpType = 352
|
||||
OpStructFieldSlicePtr OpType = 353
|
||||
OpStructFieldOmitEmptySlicePtr OpType = 354
|
||||
OpStructEndSlicePtr OpType = 355
|
||||
OpStructEndOmitEmptySlicePtr OpType = 356
|
||||
OpStructFieldMarshalJSONPtr OpType = 357
|
||||
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 358
|
||||
OpStructEndMarshalJSONPtr OpType = 359
|
||||
OpStructEndOmitEmptyMarshalJSONPtr OpType = 360
|
||||
OpStructFieldMarshalTextPtr OpType = 361
|
||||
OpStructFieldOmitEmptyMarshalTextPtr OpType = 362
|
||||
OpStructEndMarshalTextPtr OpType = 363
|
||||
OpStructEndOmitEmptyMarshalTextPtr OpType = 364
|
||||
OpStructFieldInterfacePtr OpType = 365
|
||||
OpStructFieldOmitEmptyInterfacePtr OpType = 366
|
||||
OpStructEndInterfacePtr OpType = 367
|
||||
OpStructEndOmitEmptyInterfacePtr OpType = 368
|
||||
OpStructFieldIntPtrString OpType = 369
|
||||
OpStructFieldOmitEmptyIntPtrString OpType = 370
|
||||
OpStructEndIntPtrString OpType = 371
|
||||
OpStructEndOmitEmptyIntPtrString OpType = 372
|
||||
OpStructFieldUintPtrString OpType = 373
|
||||
OpStructFieldOmitEmptyUintPtrString OpType = 374
|
||||
OpStructEndUintPtrString OpType = 375
|
||||
OpStructEndOmitEmptyUintPtrString OpType = 376
|
||||
OpStructFieldFloat32PtrString OpType = 377
|
||||
OpStructFieldOmitEmptyFloat32PtrString OpType = 378
|
||||
OpStructEndFloat32PtrString OpType = 379
|
||||
OpStructEndOmitEmptyFloat32PtrString OpType = 380
|
||||
OpStructFieldFloat64PtrString OpType = 381
|
||||
OpStructFieldOmitEmptyFloat64PtrString OpType = 382
|
||||
OpStructEndFloat64PtrString OpType = 383
|
||||
OpStructEndOmitEmptyFloat64PtrString OpType = 384
|
||||
OpStructFieldBoolPtrString OpType = 385
|
||||
OpStructFieldOmitEmptyBoolPtrString OpType = 386
|
||||
OpStructEndBoolPtrString OpType = 387
|
||||
OpStructEndOmitEmptyBoolPtrString OpType = 388
|
||||
OpStructFieldStringPtrString OpType = 389
|
||||
OpStructFieldOmitEmptyStringPtrString OpType = 390
|
||||
OpStructEndStringPtrString OpType = 391
|
||||
OpStructEndOmitEmptyStringPtrString OpType = 392
|
||||
OpStructFieldNumberPtrString OpType = 393
|
||||
OpStructFieldOmitEmptyNumberPtrString OpType = 394
|
||||
OpStructEndNumberPtrString OpType = 395
|
||||
OpStructEndOmitEmptyNumberPtrString OpType = 396
|
||||
OpStructField OpType = 397
|
||||
OpStructFieldOmitEmpty OpType = 398
|
||||
OpStructEnd OpType = 399
|
||||
OpStructEndOmitEmpty OpType = 400
|
||||
)
|
||||
|
||||
func (t OpType) String() string {
|
||||
if int(t) >= 400 {
|
||||
if int(t) >= 401 {
|
||||
return ""
|
||||
}
|
||||
return opTypeStrings[int(t)]
|
||||
|
|
|
|||
7
vendor/github.com/goccy/go-json/internal/encoder/string.go
generated
vendored
7
vendor/github.com/goccy/go-json/internal/encoder/string.go
generated
vendored
|
|
@ -405,7 +405,10 @@ func stringToUint64Slice(s string) []uint64 {
|
|||
}))
|
||||
}
|
||||
|
||||
func AppendEscapedString(buf []byte, s string) []byte {
|
||||
func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte {
|
||||
if ctx.Option.Flag&HTMLEscapeOption == 0 {
|
||||
return appendString(buf, s)
|
||||
}
|
||||
valLen := len(s)
|
||||
if valLen == 0 {
|
||||
return append(buf, `""`...)
|
||||
|
|
@ -531,7 +534,7 @@ ESCAPE_END:
|
|||
return append(append(buf, s[i:]...), '"')
|
||||
}
|
||||
|
||||
func AppendString(buf []byte, s string) []byte {
|
||||
func appendString(buf []byte, s string) []byte {
|
||||
valLen := len(s)
|
||||
if valLen == 0 {
|
||||
return append(buf, `""`...)
|
||||
|
|
|
|||
13
vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go
generated
vendored
13
vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go
generated
vendored
|
|
@ -6,15 +6,22 @@ import (
|
|||
"github.com/goccy/go-json/internal/encoder"
|
||||
)
|
||||
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||
defer func() {
|
||||
var code *encoder.Opcode
|
||||
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
|
||||
code = codeSet.EscapeKeyCode
|
||||
} else {
|
||||
code = codeSet.NoescapeKeyCode
|
||||
}
|
||||
|
||||
if err := recover(); err != nil {
|
||||
fmt.Println("=============[DEBUG]===============")
|
||||
fmt.Println("* [TYPE]")
|
||||
fmt.Println(codeSet.Type)
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [ALL OPCODE]")
|
||||
fmt.Println(codeSet.Code.Dump())
|
||||
fmt.Println(code.Dump())
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [CONTEXT]")
|
||||
fmt.Printf("%+v\n", ctx)
|
||||
|
|
@ -23,5 +30,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
|||
}
|
||||
}()
|
||||
|
||||
return Run(ctx, b, codeSet, opt)
|
||||
return Run(ctx, b, codeSet)
|
||||
}
|
||||
|
|
|
|||
6
vendor/github.com/goccy/go-json/internal/encoder/vm/hack.go
generated
vendored
6
vendor/github.com/goccy/go-json/internal/encoder/vm/hack.go
generated
vendored
|
|
@ -2,8 +2,8 @@ package vm
|
|||
|
||||
import (
|
||||
// HACK: compile order
|
||||
// `vm`, `vm_escaped`, `vm_indent`, `vm_escaped_indent` packages uses a lot of memory to compile,
|
||||
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
|
||||
// so forcibly make dependencies and avoid compiling in concurrent.
|
||||
// dependency order: vm => vm_escaped => vm_indent => vm_escaped_indent
|
||||
_ "github.com/goccy/go-json/internal/encoder/vm_escaped"
|
||||
// dependency order: vm => vm_indent => vm_color => vm_color_indent
|
||||
_ "github.com/goccy/go-json/internal/encoder/vm_indent"
|
||||
)
|
||||
|
|
|
|||
82
vendor/github.com/goccy/go-json/internal/encoder/vm/util.go
generated
vendored
82
vendor/github.com/goccy/go-json/internal/encoder/vm/util.go
generated
vendored
|
|
@ -33,24 +33,33 @@ type emptyInterface struct {
|
|||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
type nonEmptyInterface struct {
|
||||
itab *struct {
|
||||
ityp *runtime.Type // static interface type
|
||||
typ *runtime.Type // dynamic concrete type
|
||||
// unused fields...
|
||||
}
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func errUnimplementedOp(op encoder.OpType) error {
|
||||
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
|
||||
}
|
||||
|
||||
func load(base uintptr, idx uintptr) uintptr {
|
||||
addr := base + idx
|
||||
func load(base uintptr, idx uint32) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
return **(**uintptr)(unsafe.Pointer(&addr))
|
||||
}
|
||||
|
||||
func store(base uintptr, idx uintptr, p uintptr) {
|
||||
addr := base + idx
|
||||
func store(base uintptr, idx uint32, p uintptr) {
|
||||
addr := base + uintptr(idx)
|
||||
**(**uintptr)(unsafe.Pointer(&addr)) = p
|
||||
}
|
||||
|
||||
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr {
|
||||
addr := base + idx
|
||||
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
p := **(**uintptr)(unsafe.Pointer(&addr))
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -70,8 +79,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
|
|||
func ptrToPtr(p uintptr) uintptr {
|
||||
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
|
||||
}
|
||||
func ptrToNPtr(p uintptr, ptrNum int) uintptr {
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -90,22 +99,22 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
|
|||
}))
|
||||
}
|
||||
|
||||
func appendBool(b []byte, v bool) []byte {
|
||||
func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte {
|
||||
if v {
|
||||
return append(b, "true"...)
|
||||
}
|
||||
return append(b, "false"...)
|
||||
}
|
||||
|
||||
func appendNull(b []byte) []byte {
|
||||
func appendNull(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, "null"...)
|
||||
}
|
||||
|
||||
func appendComma(b []byte) []byte {
|
||||
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, ',')
|
||||
}
|
||||
|
||||
func appendColon(b []byte) []byte {
|
||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
last := len(b) - 1
|
||||
b[last] = ':'
|
||||
return b
|
||||
|
|
@ -123,45 +132,12 @@ func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte
|
|||
return b
|
||||
}
|
||||
|
||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, _ *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalLength := uintptr(codeSet.CodeLength)
|
||||
nextTotalLength := uintptr(ifaceCodeSet.CodeLength)
|
||||
|
||||
curlen := uintptr(len(ctx.Ptrs))
|
||||
offsetNum := ptrOffset / uintptrSize
|
||||
|
||||
newLen := offsetNum + totalLength + nextTotalLength
|
||||
if curlen < newLen {
|
||||
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
|
||||
}
|
||||
oldPtrs := ctx.Ptrs
|
||||
|
||||
newPtrs := ctx.Ptrs[(ptrOffset+totalLength*uintptrSize)/uintptrSize:]
|
||||
newPtrs[0] = uintptr(iface.ptr)
|
||||
|
||||
ctx.Ptrs = newPtrs
|
||||
|
||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.Ptrs = oldPtrs
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalJSON(ctx, code, b, v, false)
|
||||
return encoder.AppendMarshalJSON(ctx, code, b, v)
|
||||
}
|
||||
|
||||
func appendMarshalText(code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalText(code, b, v, false)
|
||||
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalText(ctx, code, b, v)
|
||||
}
|
||||
|
||||
func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
|
||||
|
|
@ -174,11 +150,11 @@ func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []by
|
|||
return append(b, ',')
|
||||
}
|
||||
|
||||
func appendEmptyArray(b []byte) []byte {
|
||||
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '[', ']', ',')
|
||||
}
|
||||
|
||||
func appendEmptyObject(b []byte) []byte {
|
||||
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{', '}', ',')
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +164,7 @@ func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []b
|
|||
return append(b, ',')
|
||||
}
|
||||
|
||||
func appendStructHead(b []byte) []byte {
|
||||
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{')
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +180,7 @@ func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode,
|
|||
last := len(b) - 1
|
||||
if b[last] == ',' {
|
||||
b[last] = '}'
|
||||
return appendComma(b)
|
||||
return appendComma(ctx, b)
|
||||
}
|
||||
return appendStructEnd(ctx, code, b)
|
||||
}
|
||||
|
|
|
|||
3265
vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go
generated
vendored
3265
vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go
generated
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
package vm_escaped_indent
|
||||
package vm_color
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -6,7 +6,14 @@ import (
|
|||
"github.com/goccy/go-json/internal/encoder"
|
||||
)
|
||||
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||
var code *encoder.Opcode
|
||||
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
|
||||
code = codeSet.EscapeKeyCode
|
||||
} else {
|
||||
code = codeSet.NoescapeKeyCode
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Println("=============[DEBUG]===============")
|
||||
|
|
@ -14,7 +21,7 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
|||
fmt.Println(codeSet.Type)
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [ALL OPCODE]")
|
||||
fmt.Println(codeSet.Code.Dump())
|
||||
fmt.Println(code.Dump())
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [CONTEXT]")
|
||||
fmt.Printf("%+v\n", ctx)
|
||||
|
|
@ -23,5 +30,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
|||
}
|
||||
}()
|
||||
|
||||
return Run(ctx, b, codeSet, opt)
|
||||
return Run(ctx, b, codeSet)
|
||||
}
|
||||
9
vendor/github.com/goccy/go-json/internal/encoder/vm_color/hack.go
generated
vendored
Normal file
9
vendor/github.com/goccy/go-json/internal/encoder/vm_color/hack.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package vm_color
|
||||
|
||||
import (
|
||||
// HACK: compile order
|
||||
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
|
||||
// so forcibly make dependencies and avoid compiling in concurrent.
|
||||
// dependency order: vm => vm_indent => vm_color => vm_color_indent
|
||||
_ "github.com/goccy/go-json/internal/encoder/vm_color_indent"
|
||||
)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package vm_escaped
|
||||
package vm_color
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
|
@ -12,13 +12,6 @@ import (
|
|||
const uintptrSize = 4 << (^uintptr(0) >> 63)
|
||||
|
||||
var (
|
||||
appendInt = encoder.AppendInt
|
||||
appendUint = encoder.AppendUint
|
||||
appendFloat32 = encoder.AppendFloat32
|
||||
appendFloat64 = encoder.AppendFloat64
|
||||
appendString = encoder.AppendEscapedString
|
||||
appendByteSlice = encoder.AppendByteSlice
|
||||
appendNumber = encoder.AppendNumber
|
||||
errUnsupportedValue = encoder.ErrUnsupportedValue
|
||||
errUnsupportedFloat = encoder.ErrUnsupportedFloat
|
||||
mapiterinit = encoder.MapIterInit
|
||||
|
|
@ -33,24 +26,33 @@ type emptyInterface struct {
|
|||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func errUnimplementedOp(op encoder.OpType) error {
|
||||
return fmt.Errorf("encoder (escaped): opcode %s has not been implemented", op)
|
||||
type nonEmptyInterface struct {
|
||||
itab *struct {
|
||||
ityp *runtime.Type // static interface type
|
||||
typ *runtime.Type // dynamic concrete type
|
||||
// unused fields...
|
||||
}
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func load(base uintptr, idx uintptr) uintptr {
|
||||
addr := base + idx
|
||||
func errUnimplementedOp(op encoder.OpType) error {
|
||||
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
|
||||
}
|
||||
|
||||
func load(base uintptr, idx uint32) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
return **(**uintptr)(unsafe.Pointer(&addr))
|
||||
}
|
||||
|
||||
func store(base uintptr, idx uintptr, p uintptr) {
|
||||
addr := base + idx
|
||||
func store(base uintptr, idx uint32, p uintptr) {
|
||||
addr := base + uintptr(idx)
|
||||
**(**uintptr)(unsafe.Pointer(&addr)) = p
|
||||
}
|
||||
|
||||
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr {
|
||||
addr := base + idx
|
||||
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
p := **(**uintptr)(unsafe.Pointer(&addr))
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -70,8 +72,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
|
|||
func ptrToPtr(p uintptr) uintptr {
|
||||
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
|
||||
}
|
||||
func ptrToNPtr(p uintptr, ptrNum int) uintptr {
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -90,78 +92,111 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
|
|||
}))
|
||||
}
|
||||
|
||||
func appendBool(b []byte, v bool) []byte {
|
||||
if v {
|
||||
return append(b, "true"...)
|
||||
func appendInt(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
||||
format := ctx.Option.ColorScheme.Int
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendInt(ctx, b, v, code)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendUint(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
||||
format := ctx.Option.ColorScheme.Uint
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendUint(ctx, b, v, code)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte {
|
||||
format := ctx.Option.ColorScheme.Float
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendFloat32(ctx, b, v)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte {
|
||||
format := ctx.Option.ColorScheme.Float
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendFloat64(ctx, b, v)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte {
|
||||
format := ctx.Option.ColorScheme.String
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendString(ctx, b, v)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte {
|
||||
format := ctx.Option.ColorScheme.Binary
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendByteSlice(ctx, b, src)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) {
|
||||
format := ctx.Option.ColorScheme.Int
|
||||
b = append(b, format.Header...)
|
||||
bb, err := encoder.AppendNumber(ctx, b, n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(b, "false"...)
|
||||
return append(bb, format.Footer...), nil
|
||||
}
|
||||
|
||||
func appendNull(b []byte) []byte {
|
||||
return append(b, "null"...)
|
||||
func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte {
|
||||
format := ctx.Option.ColorScheme.Bool
|
||||
b = append(b, format.Header...)
|
||||
if v {
|
||||
b = append(b, "true"...)
|
||||
} else {
|
||||
b = append(b, "false"...)
|
||||
}
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendComma(b []byte) []byte {
|
||||
func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte {
|
||||
format := ctx.Option.ColorScheme.Null
|
||||
b = append(b, format.Header...)
|
||||
b = append(b, "null"...)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, ',')
|
||||
}
|
||||
|
||||
func appendColon(b []byte) []byte {
|
||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
last := len(b) - 1
|
||||
b[last] = ':'
|
||||
return b
|
||||
}
|
||||
|
||||
func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte {
|
||||
b = append(b, key...)
|
||||
b[len(b)-1] = ':'
|
||||
b = append(b, key[:len(key)-1]...)
|
||||
b = append(b, ':')
|
||||
return append(b, value...)
|
||||
}
|
||||
|
||||
func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
|
||||
b[len(b)-1] = '}'
|
||||
last := len(b) - 1
|
||||
b[last] = '}'
|
||||
b = append(b, ',')
|
||||
return b
|
||||
}
|
||||
|
||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, _ *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalLength := uintptr(codeSet.CodeLength)
|
||||
nextTotalLength := uintptr(ifaceCodeSet.CodeLength)
|
||||
|
||||
curlen := uintptr(len(ctx.Ptrs))
|
||||
offsetNum := ptrOffset / uintptrSize
|
||||
|
||||
newLen := offsetNum + totalLength + nextTotalLength
|
||||
if curlen < newLen {
|
||||
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
|
||||
}
|
||||
oldPtrs := ctx.Ptrs
|
||||
|
||||
newPtrs := ctx.Ptrs[(ptrOffset+totalLength*uintptrSize)/uintptrSize:]
|
||||
newPtrs[0] = uintptr(iface.ptr)
|
||||
|
||||
ctx.Ptrs = newPtrs
|
||||
|
||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.Ptrs = oldPtrs
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalJSON(ctx, code, b, v, true)
|
||||
return encoder.AppendMarshalJSON(ctx, code, b, v)
|
||||
}
|
||||
|
||||
func appendMarshalText(code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalText(code, b, v, true)
|
||||
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
format := ctx.Option.ColorScheme.String
|
||||
b = append(b, format.Header...)
|
||||
bb, err := encoder.AppendMarshalText(ctx, code, b, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(bb, format.Footer...), nil
|
||||
}
|
||||
|
||||
func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
|
||||
|
|
@ -174,11 +209,11 @@ func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []by
|
|||
return append(b, ',')
|
||||
}
|
||||
|
||||
func appendEmptyArray(b []byte) []byte {
|
||||
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '[', ']', ',')
|
||||
}
|
||||
|
||||
func appendEmptyObject(b []byte) []byte {
|
||||
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{', '}', ',')
|
||||
}
|
||||
|
||||
|
|
@ -188,12 +223,17 @@ func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []b
|
|||
return append(b, ',')
|
||||
}
|
||||
|
||||
func appendStructHead(b []byte) []byte {
|
||||
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{')
|
||||
}
|
||||
|
||||
func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
|
||||
return append(b, code.EscapedKey...)
|
||||
func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
|
||||
format := ctx.Option.ColorScheme.ObjectKey
|
||||
b = append(b, format.Header...)
|
||||
b = append(b, code.Key[:len(code.Key)-1]...)
|
||||
b = append(b, format.Footer...)
|
||||
|
||||
return append(b, ':')
|
||||
}
|
||||
|
||||
func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
|
||||
|
|
@ -204,7 +244,7 @@ func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode,
|
|||
last := len(b) - 1
|
||||
if b[last] == ',' {
|
||||
b[last] = '}'
|
||||
return appendComma(b)
|
||||
return appendComma(ctx, b)
|
||||
}
|
||||
return appendStructEnd(ctx, code, b)
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
package vm_escaped
|
||||
package vm_color_indent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -6,7 +6,14 @@ import (
|
|||
"github.com/goccy/go-json/internal/encoder"
|
||||
)
|
||||
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||
var code *encoder.Opcode
|
||||
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
|
||||
code = codeSet.EscapeKeyCode
|
||||
} else {
|
||||
code = codeSet.NoescapeKeyCode
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Println("=============[DEBUG]===============")
|
||||
|
|
@ -14,7 +21,7 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
|||
fmt.Println(codeSet.Type)
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [ALL OPCODE]")
|
||||
fmt.Println(codeSet.Code.Dump())
|
||||
fmt.Println(code.Dump())
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [CONTEXT]")
|
||||
fmt.Printf("%+v\n", ctx)
|
||||
|
|
@ -23,5 +30,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
|||
}
|
||||
}()
|
||||
|
||||
return Run(ctx, b, codeSet, opt)
|
||||
return Run(ctx, b, codeSet)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package vm_escaped_indent
|
||||
package vm_color_indent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
|
@ -12,15 +12,8 @@ import (
|
|||
const uintptrSize = 4 << (^uintptr(0) >> 63)
|
||||
|
||||
var (
|
||||
appendInt = encoder.AppendInt
|
||||
appendUint = encoder.AppendUint
|
||||
appendFloat32 = encoder.AppendFloat32
|
||||
appendFloat64 = encoder.AppendFloat64
|
||||
appendString = encoder.AppendString
|
||||
appendByteSlice = encoder.AppendByteSlice
|
||||
appendNumber = encoder.AppendNumber
|
||||
appendStructEnd = encoder.AppendStructEndIndent
|
||||
appendIndent = encoder.AppendIndent
|
||||
appendStructEnd = encoder.AppendStructEndIndent
|
||||
errUnsupportedValue = encoder.ErrUnsupportedValue
|
||||
errUnsupportedFloat = encoder.ErrUnsupportedFloat
|
||||
mapiterinit = encoder.MapIterInit
|
||||
|
|
@ -35,24 +28,33 @@ type emptyInterface struct {
|
|||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func errUnimplementedOp(op encoder.OpType) error {
|
||||
return fmt.Errorf("encoder (indent+escaped): opcode %s has not been implemented", op)
|
||||
type nonEmptyInterface struct {
|
||||
itab *struct {
|
||||
ityp *runtime.Type // static interface type
|
||||
typ *runtime.Type // dynamic concrete type
|
||||
// unused fields...
|
||||
}
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func load(base uintptr, idx uintptr) uintptr {
|
||||
addr := base + idx
|
||||
func errUnimplementedOp(op encoder.OpType) error {
|
||||
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
|
||||
}
|
||||
|
||||
func load(base uintptr, idx uint32) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
return **(**uintptr)(unsafe.Pointer(&addr))
|
||||
}
|
||||
|
||||
func store(base uintptr, idx uintptr, p uintptr) {
|
||||
addr := base + idx
|
||||
func store(base uintptr, idx uint32, p uintptr) {
|
||||
addr := base + uintptr(idx)
|
||||
**(**uintptr)(unsafe.Pointer(&addr)) = p
|
||||
}
|
||||
|
||||
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr {
|
||||
addr := base + idx
|
||||
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
p := **(**uintptr)(unsafe.Pointer(&addr))
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -72,8 +74,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
|
|||
func ptrToPtr(p uintptr) uintptr {
|
||||
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
|
||||
}
|
||||
func ptrToNPtr(p uintptr, ptrNum int) uintptr {
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -92,62 +94,84 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
|
|||
}))
|
||||
}
|
||||
|
||||
func appendBool(b []byte, v bool) []byte {
|
||||
if v {
|
||||
return append(b, "true"...)
|
||||
func appendInt(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
||||
format := ctx.Option.ColorScheme.Int
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendInt(ctx, b, v, code)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendUint(ctx *encoder.RuntimeContext, b []byte, v uint64, code *encoder.Opcode) []byte {
|
||||
format := ctx.Option.ColorScheme.Uint
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendUint(ctx, b, v, code)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte {
|
||||
format := ctx.Option.ColorScheme.Float
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendFloat32(ctx, b, v)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte {
|
||||
format := ctx.Option.ColorScheme.Float
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendFloat64(ctx, b, v)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte {
|
||||
format := ctx.Option.ColorScheme.String
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendString(ctx, b, v)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte {
|
||||
format := ctx.Option.ColorScheme.Binary
|
||||
b = append(b, format.Header...)
|
||||
b = encoder.AppendByteSlice(ctx, b, src)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) {
|
||||
format := ctx.Option.ColorScheme.Int
|
||||
b = append(b, format.Header...)
|
||||
bb, err := encoder.AppendNumber(ctx, b, n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(b, "false"...)
|
||||
return append(bb, format.Footer...), nil
|
||||
}
|
||||
|
||||
func appendNull(b []byte) []byte {
|
||||
return append(b, "null"...)
|
||||
func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte {
|
||||
format := ctx.Option.ColorScheme.Bool
|
||||
b = append(b, format.Header...)
|
||||
if v {
|
||||
b = append(b, "true"...)
|
||||
} else {
|
||||
b = append(b, "false"...)
|
||||
}
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendComma(b []byte) []byte {
|
||||
func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte {
|
||||
format := ctx.Option.ColorScheme.Null
|
||||
b = append(b, format.Header...)
|
||||
b = append(b, "null"...)
|
||||
return append(b, format.Footer...)
|
||||
}
|
||||
|
||||
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, ',', '\n')
|
||||
}
|
||||
|
||||
func appendColon(b []byte) []byte {
|
||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, ':', ' ')
|
||||
}
|
||||
|
||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, code *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalLength := uintptr(codeSet.CodeLength)
|
||||
nextTotalLength := uintptr(ifaceCodeSet.CodeLength)
|
||||
|
||||
curlen := uintptr(len(ctx.Ptrs))
|
||||
offsetNum := ptrOffset / uintptrSize
|
||||
|
||||
newLen := offsetNum + totalLength + nextTotalLength
|
||||
if curlen < newLen {
|
||||
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
|
||||
}
|
||||
oldPtrs := ctx.Ptrs
|
||||
|
||||
newPtrs := ctx.Ptrs[(ptrOffset+totalLength*uintptrSize)/uintptrSize:]
|
||||
newPtrs[0] = uintptr(iface.ptr)
|
||||
|
||||
ctx.Ptrs = newPtrs
|
||||
|
||||
oldBaseIndent := ctx.BaseIndent
|
||||
ctx.BaseIndent = code.Indent
|
||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.BaseIndent = oldBaseIndent
|
||||
|
||||
ctx.Ptrs = oldPtrs
|
||||
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte {
|
||||
b = appendIndent(ctx, b, code.Indent+1)
|
||||
b = append(b, key...)
|
||||
|
|
@ -175,11 +199,11 @@ func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte)
|
|||
return append(b, ']', ',', '\n')
|
||||
}
|
||||
|
||||
func appendEmptyArray(b []byte) []byte {
|
||||
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '[', ']', ',', '\n')
|
||||
}
|
||||
|
||||
func appendEmptyObject(b []byte) []byte {
|
||||
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{', '}', ',', '\n')
|
||||
}
|
||||
|
||||
|
|
@ -191,21 +215,32 @@ func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte
|
|||
}
|
||||
|
||||
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalJSONIndent(ctx, code, b, v, true)
|
||||
return encoder.AppendMarshalJSONIndent(ctx, code, b, v)
|
||||
}
|
||||
|
||||
func appendMarshalText(code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalTextIndent(code, b, v, true)
|
||||
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
format := ctx.Option.ColorScheme.String
|
||||
b = append(b, format.Header...)
|
||||
bb, err := encoder.AppendMarshalTextIndent(ctx, code, b, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(bb, format.Footer...), nil
|
||||
}
|
||||
|
||||
func appendStructHead(b []byte) []byte {
|
||||
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{', '\n')
|
||||
}
|
||||
|
||||
func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
|
||||
b = appendIndent(ctx, b, code.Indent)
|
||||
b = append(b, code.EscapedKey...)
|
||||
return append(b, ' ')
|
||||
|
||||
format := ctx.Option.ColorScheme.ObjectKey
|
||||
b = append(b, format.Header...)
|
||||
b = append(b, code.Key[:len(code.Key)-1]...)
|
||||
b = append(b, format.Footer...)
|
||||
|
||||
return append(b, ':', ' ')
|
||||
}
|
||||
|
||||
func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
|
||||
|
|
@ -221,15 +256,15 @@ func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode,
|
|||
b = appendIndent(ctx, b, code.Indent-1)
|
||||
b = append(b, '}')
|
||||
}
|
||||
return appendComma(b)
|
||||
return appendComma(ctx, b)
|
||||
}
|
||||
|
||||
func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) {
|
||||
ctx.BaseIndent = int(load(ctxptr, code.Length))
|
||||
ctx.BaseIndent = uint32(load(ctxptr, code.Length))
|
||||
}
|
||||
|
||||
func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) {
|
||||
store(ctxptr, code.End.Next.Length, indent)
|
||||
store(ctxptr, code.Length, indent)
|
||||
}
|
||||
|
||||
func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
|
||||
File diff suppressed because it is too large
Load diff
9
vendor/github.com/goccy/go-json/internal/encoder/vm_escaped/hack.go
generated
vendored
9
vendor/github.com/goccy/go-json/internal/encoder/vm_escaped/hack.go
generated
vendored
|
|
@ -1,9 +0,0 @@
|
|||
package vm_escaped
|
||||
|
||||
import (
|
||||
// HACK: compile order
|
||||
// `vm`, `vm_escaped`, `vm_indent`, `vm_escaped_indent` packages uses a lot of memory to compile,
|
||||
// so forcibly make dependencies and avoid compiling in concurrent.
|
||||
// dependency order: vm => vm_escaped => vm_indent => vm_escaped_indent
|
||||
_ "github.com/goccy/go-json/internal/encoder/vm_indent"
|
||||
)
|
||||
6
vendor/github.com/goccy/go-json/internal/encoder/vm_escaped_indent/hack.go
generated
vendored
6
vendor/github.com/goccy/go-json/internal/encoder/vm_escaped_indent/hack.go
generated
vendored
|
|
@ -1,6 +0,0 @@
|
|||
package vm_escaped_indent
|
||||
|
||||
// HACK: compile order
|
||||
// `vm`, `vm_escaped`, `vm_indent`, `vm_escaped_indent` packages uses a lot of memory to compile,
|
||||
// so forcibly make dependencies and avoid compiling in concurrent.
|
||||
// dependency order: vm => vm_escaped => vm_indent => vm_escaped_indent
|
||||
13
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go
generated
vendored
13
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go
generated
vendored
|
|
@ -6,7 +6,14 @@ import (
|
|||
"github.com/goccy/go-json/internal/encoder"
|
||||
)
|
||||
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||
var code *encoder.Opcode
|
||||
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
|
||||
code = codeSet.EscapeKeyCode
|
||||
} else {
|
||||
code = codeSet.NoescapeKeyCode
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Println("=============[DEBUG]===============")
|
||||
|
|
@ -14,7 +21,7 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
|||
fmt.Println(codeSet.Type)
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [ALL OPCODE]")
|
||||
fmt.Println(codeSet.Code.Dump())
|
||||
fmt.Println(code.Dump())
|
||||
fmt.Printf("\n")
|
||||
fmt.Println("* [CONTEXT]")
|
||||
fmt.Printf("%+v\n", ctx)
|
||||
|
|
@ -23,5 +30,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
|||
}
|
||||
}()
|
||||
|
||||
return Run(ctx, b, codeSet, opt)
|
||||
return Run(ctx, b, codeSet)
|
||||
}
|
||||
|
|
|
|||
6
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/hack.go
generated
vendored
6
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/hack.go
generated
vendored
|
|
@ -2,8 +2,8 @@ package vm_indent
|
|||
|
||||
import (
|
||||
// HACK: compile order
|
||||
// `vm`, `vm_escaped`, `vm_indent`, `vm_escaped_indent` packages uses a lot of memory to compile,
|
||||
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
|
||||
// so forcibly make dependencies and avoid compiling in concurrent.
|
||||
// dependency order: vm => vm_escaped => vm_indent => vm_escaped_indent
|
||||
_ "github.com/goccy/go-json/internal/encoder/vm_escaped_indent"
|
||||
// dependency order: vm => vm_indent => vm_color => vm_color_indent
|
||||
_ "github.com/goccy/go-json/internal/encoder/vm_color"
|
||||
)
|
||||
|
|
|
|||
90
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go
generated
vendored
90
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go
generated
vendored
|
|
@ -35,24 +35,33 @@ type emptyInterface struct {
|
|||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
type nonEmptyInterface struct {
|
||||
itab *struct {
|
||||
ityp *runtime.Type // static interface type
|
||||
typ *runtime.Type // dynamic concrete type
|
||||
// unused fields...
|
||||
}
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func errUnimplementedOp(op encoder.OpType) error {
|
||||
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
|
||||
}
|
||||
|
||||
func load(base uintptr, idx uintptr) uintptr {
|
||||
addr := base + idx
|
||||
func load(base uintptr, idx uint32) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
return **(**uintptr)(unsafe.Pointer(&addr))
|
||||
}
|
||||
|
||||
func store(base uintptr, idx uintptr, p uintptr) {
|
||||
addr := base + idx
|
||||
func store(base uintptr, idx uint32, p uintptr) {
|
||||
addr := base + uintptr(idx)
|
||||
**(**uintptr)(unsafe.Pointer(&addr)) = p
|
||||
}
|
||||
|
||||
func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr {
|
||||
addr := base + idx
|
||||
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
|
||||
addr := base + uintptr(idx)
|
||||
p := **(**uintptr)(unsafe.Pointer(&addr))
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -72,8 +81,8 @@ func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader
|
|||
func ptrToPtr(p uintptr) uintptr {
|
||||
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
|
||||
}
|
||||
func ptrToNPtr(p uintptr, ptrNum int) uintptr {
|
||||
for i := 0; i < ptrNum; i++ {
|
||||
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
|
||||
for i := uint8(0); i < ptrNum; i++ {
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -92,62 +101,25 @@ func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
|
|||
}))
|
||||
}
|
||||
|
||||
func appendBool(b []byte, v bool) []byte {
|
||||
func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte {
|
||||
if v {
|
||||
return append(b, "true"...)
|
||||
}
|
||||
return append(b, "false"...)
|
||||
}
|
||||
|
||||
func appendNull(b []byte) []byte {
|
||||
func appendNull(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, "null"...)
|
||||
}
|
||||
|
||||
func appendComma(b []byte) []byte {
|
||||
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, ',', '\n')
|
||||
}
|
||||
|
||||
func appendColon(b []byte) []byte {
|
||||
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, ':', ' ')
|
||||
}
|
||||
|
||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, code *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalLength := uintptr(codeSet.CodeLength)
|
||||
nextTotalLength := uintptr(ifaceCodeSet.CodeLength)
|
||||
|
||||
curlen := uintptr(len(ctx.Ptrs))
|
||||
offsetNum := ptrOffset / uintptrSize
|
||||
|
||||
newLen := offsetNum + totalLength + nextTotalLength
|
||||
if curlen < newLen {
|
||||
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
|
||||
}
|
||||
oldPtrs := ctx.Ptrs
|
||||
|
||||
newPtrs := ctx.Ptrs[(ptrOffset+totalLength*uintptrSize)/uintptrSize:]
|
||||
newPtrs[0] = uintptr(iface.ptr)
|
||||
|
||||
ctx.Ptrs = newPtrs
|
||||
|
||||
oldBaseIndent := ctx.BaseIndent
|
||||
ctx.BaseIndent = code.Indent
|
||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.BaseIndent = oldBaseIndent
|
||||
|
||||
ctx.Ptrs = oldPtrs
|
||||
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte {
|
||||
b = appendIndent(ctx, b, code.Indent+1)
|
||||
b = append(b, key...)
|
||||
|
|
@ -175,11 +147,11 @@ func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte)
|
|||
return append(b, ']', ',', '\n')
|
||||
}
|
||||
|
||||
func appendEmptyArray(b []byte) []byte {
|
||||
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '[', ']', ',', '\n')
|
||||
}
|
||||
|
||||
func appendEmptyObject(b []byte) []byte {
|
||||
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{', '}', ',', '\n')
|
||||
}
|
||||
|
||||
|
|
@ -191,14 +163,14 @@ func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte
|
|||
}
|
||||
|
||||
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalJSONIndent(ctx, code, b, v, false)
|
||||
return encoder.AppendMarshalJSONIndent(ctx, code, b, v)
|
||||
}
|
||||
|
||||
func appendMarshalText(code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalTextIndent(code, b, v, false)
|
||||
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
|
||||
return encoder.AppendMarshalTextIndent(ctx, code, b, v)
|
||||
}
|
||||
|
||||
func appendStructHead(b []byte) []byte {
|
||||
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
|
||||
return append(b, '{', '\n')
|
||||
}
|
||||
|
||||
|
|
@ -221,15 +193,15 @@ func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode,
|
|||
b = appendIndent(ctx, b, code.Indent-1)
|
||||
b = append(b, '}')
|
||||
}
|
||||
return appendComma(b)
|
||||
return appendComma(ctx, b)
|
||||
}
|
||||
|
||||
func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) {
|
||||
ctx.BaseIndent = int(load(ctxptr, code.Length))
|
||||
ctx.BaseIndent = uint32(load(ctxptr, code.Length))
|
||||
}
|
||||
|
||||
func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) {
|
||||
store(ctxptr, code.End.Next.Length, indent)
|
||||
store(ctxptr, code.Length, indent)
|
||||
}
|
||||
|
||||
func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
|
||||
|
|
|
|||
3265
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go
generated
vendored
3265
vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go
generated
vendored
File diff suppressed because it is too large
Load diff
7
vendor/github.com/goccy/go-json/internal/errors/error.go
generated
vendored
7
vendor/github.com/goccy/go-json/internal/errors/error.go
generated
vendored
|
|
@ -155,3 +155,10 @@ func ErrInvalidCharacter(c byte, context string, cursor int64) *SyntaxError {
|
|||
Offset: cursor,
|
||||
}
|
||||
}
|
||||
|
||||
func ErrInvalidBeginningOfValue(c byte, cursor int64) *SyntaxError {
|
||||
return &SyntaxError{
|
||||
msg: fmt.Sprintf("invalid character '%c' looking for beginning of value", c),
|
||||
Offset: cursor,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
51
vendor/github.com/goccy/go-json/json.go
generated
vendored
51
vendor/github.com/goccy/go-json/json.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package json
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/goccy/go-json/internal/encoder"
|
||||
|
|
@ -13,6 +14,12 @@ type Marshaler interface {
|
|||
MarshalJSON() ([]byte, error)
|
||||
}
|
||||
|
||||
// MarshalerContext is the interface implemented by types that
|
||||
// can marshal themselves into valid JSON with context.Context.
|
||||
type MarshalerContext interface {
|
||||
MarshalJSON(context.Context) ([]byte, error)
|
||||
}
|
||||
|
||||
// Unmarshaler is the interface implemented by types
|
||||
// that can unmarshal a JSON description of themselves.
|
||||
// The input can be assumed to be a valid encoding of
|
||||
|
|
@ -25,6 +32,12 @@ type Unmarshaler interface {
|
|||
UnmarshalJSON([]byte) error
|
||||
}
|
||||
|
||||
// UnmarshalerContext is the interface implemented by types
|
||||
// that can unmarshal with context.Context a JSON description of themselves.
|
||||
type UnmarshalerContext interface {
|
||||
UnmarshalJSON(context.Context, []byte) error
|
||||
}
|
||||
|
||||
// Marshal returns the JSON encoding of v.
|
||||
//
|
||||
// Marshal traverses the value v recursively.
|
||||
|
|
@ -158,18 +171,19 @@ func Marshal(v interface{}) ([]byte, error) {
|
|||
return MarshalWithOption(v)
|
||||
}
|
||||
|
||||
// MarshalNoEscape
|
||||
// MarshalNoEscape returns the JSON encoding of v and doesn't escape v.
|
||||
func MarshalNoEscape(v interface{}) ([]byte, error) {
|
||||
return marshalNoEscape(v, EncodeOptionHTMLEscape)
|
||||
return marshalNoEscape(v)
|
||||
}
|
||||
|
||||
// MarshalContext returns the JSON encoding of v with context.Context and EncodeOption.
|
||||
func MarshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||
return marshalContext(ctx, v, optFuncs...)
|
||||
}
|
||||
|
||||
// MarshalWithOption returns the JSON encoding of v with EncodeOption.
|
||||
func MarshalWithOption(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||
opt := EncodeOptionHTMLEscape
|
||||
for _, optFunc := range optFuncs {
|
||||
opt = optFunc(opt)
|
||||
}
|
||||
return marshal(v, opt)
|
||||
return marshal(v, optFuncs...)
|
||||
}
|
||||
|
||||
// MarshalIndent is like Marshal but applies Indent to format the output.
|
||||
|
|
@ -181,11 +195,7 @@ func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
|
|||
|
||||
// MarshalIndentWithOption is like Marshal but applies Indent to format the output with EncodeOption.
|
||||
func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||
opt := EncodeOptionHTMLEscape | EncodeOptionIndent
|
||||
for _, optFunc := range optFuncs {
|
||||
opt = optFunc(opt)
|
||||
}
|
||||
return marshalIndent(v, prefix, indent, opt)
|
||||
return marshalIndent(v, prefix, indent, optFuncs...)
|
||||
}
|
||||
|
||||
// Unmarshal parses the JSON-encoded data and stores the result
|
||||
|
|
@ -266,8 +276,19 @@ func Unmarshal(data []byte, v interface{}) error {
|
|||
return unmarshal(data, v)
|
||||
}
|
||||
|
||||
func UnmarshalNoEscape(data []byte, v interface{}) error {
|
||||
return unmarshalNoEscape(data, v)
|
||||
// UnmarshalContext parses the JSON-encoded data and stores the result
|
||||
// in the value pointed to by v. If you implement the UnmarshalerContext interface,
|
||||
// call it with ctx as an argument.
|
||||
func UnmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||
return unmarshalContext(ctx, data, v)
|
||||
}
|
||||
|
||||
func UnmarshalWithOption(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||
return unmarshal(data, v, optFuncs...)
|
||||
}
|
||||
|
||||
func UnmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||
return unmarshalNoEscape(data, v, optFuncs...)
|
||||
}
|
||||
|
||||
// A Token holds a value of one of these types:
|
||||
|
|
@ -326,7 +347,7 @@ func HTMLEscape(dst *bytes.Buffer, src []byte) {
|
|||
if err := dec.Decode(&v); err != nil {
|
||||
return
|
||||
}
|
||||
buf, _ := marshal(v, EncodeOptionHTMLEscape)
|
||||
buf, _ := marshal(v)
|
||||
dst.Write(buf)
|
||||
}
|
||||
|
||||
|
|
|
|||
45
vendor/github.com/goccy/go-json/option.go
generated
vendored
45
vendor/github.com/goccy/go-json/option.go
generated
vendored
|
|
@ -1,15 +1,46 @@
|
|||
package json
|
||||
|
||||
type EncodeOptionFunc func(EncodeOption) EncodeOption
|
||||
import (
|
||||
"github.com/goccy/go-json/internal/decoder"
|
||||
"github.com/goccy/go-json/internal/encoder"
|
||||
)
|
||||
|
||||
func UnorderedMap() func(EncodeOption) EncodeOption {
|
||||
return func(opt EncodeOption) EncodeOption {
|
||||
return opt | EncodeOptionUnorderedMap
|
||||
type EncodeOption = encoder.Option
|
||||
type EncodeOptionFunc func(*EncodeOption)
|
||||
|
||||
// UnorderedMap doesn't sort when encoding map type.
|
||||
func UnorderedMap() EncodeOptionFunc {
|
||||
return func(opt *EncodeOption) {
|
||||
opt.Flag |= encoder.UnorderedMapOption
|
||||
}
|
||||
}
|
||||
|
||||
func Debug() func(EncodeOption) EncodeOption {
|
||||
return func(opt EncodeOption) EncodeOption {
|
||||
return opt | EncodeOptionDebug
|
||||
// Debug outputs debug information when panic occurs during encoding.
|
||||
func Debug() EncodeOptionFunc {
|
||||
return func(opt *EncodeOption) {
|
||||
opt.Flag |= encoder.DebugOption
|
||||
}
|
||||
}
|
||||
|
||||
// Colorize add an identifier for coloring to the string of the encoded result.
|
||||
func Colorize(scheme *ColorScheme) EncodeOptionFunc {
|
||||
return func(opt *EncodeOption) {
|
||||
opt.Flag |= encoder.ColorizeOption
|
||||
opt.ColorScheme = scheme
|
||||
}
|
||||
}
|
||||
|
||||
type DecodeOption = decoder.Option
|
||||
type DecodeOptionFunc func(*DecodeOption)
|
||||
|
||||
// DecodeFieldPriorityFirstWin
|
||||
// in the default behavior, go-json, like encoding/json,
|
||||
// will reflect the result of the last evaluation when a field with the same name exists.
|
||||
// This option allow you to change this behavior.
|
||||
// this option reflects the result of the first evaluation if a field with the same name exists.
|
||||
// This behavior has a performance advantage as it allows the subsequent strings to be skipped if all fields have been evaluated.
|
||||
func DecodeFieldPriorityFirstWin() DecodeOptionFunc {
|
||||
return func(opt *DecodeOption) {
|
||||
opt.Flags |= decoder.FirstWinOption
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
vendor/github.com/goccy/go-json/rtype.go
generated
vendored
27
vendor/github.com/goccy/go-json/rtype.go
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type rtype = runtime.Type
|
||||
|
||||
type emptyInterface struct {
|
||||
typ *rtype
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func rtype_ptrTo(t *rtype) *rtype {
|
||||
return runtime.PtrTo(t)
|
||||
}
|
||||
|
||||
func rtype2type(t *rtype) reflect.Type {
|
||||
return runtime.RType2Type(t)
|
||||
}
|
||||
|
||||
func type2rtype(t reflect.Type) *rtype {
|
||||
return runtime.Type2RType(t)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue