pax_global_header00006660000000000000000000000064146355527660014535gustar00rootroot0000000000000052 comment=409f6478dae55ec63b12537561d28ba570d2d5a8 golang-github-goccy-go-json-0.10.3/000077500000000000000000000000001463555276600170215ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/.codecov.yml000066400000000000000000000007271463555276600212520ustar00rootroot00000000000000codecov: require_ci_to_pass: yes coverage: precision: 2 round: down range: "70...100" status: project: default: target: 70% threshold: 2% patch: off changes: no parsers: gcov: branch_detection: conditional: yes loop: yes method: no macro: no comment: layout: "header,diff" behavior: default require_changes: no ignore: - internal/encoder/vm_color - internal/encoder/vm_color_indent golang-github-goccy-go-json-0.10.3/.github/000077500000000000000000000000001463555276600203615ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/.github/FUNDING.yml000066400000000000000000000000201463555276600221660ustar00rootroot00000000000000github: [goccy] golang-github-goccy-go-json-0.10.3/.github/workflows/000077500000000000000000000000001463555276600224165ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/.github/workflows/go.yml000066400000000000000000000044701463555276600235530ustar00rootroot00000000000000name: Go on: push: branches: - master pull_request: jobs: build: name: Build on limited environment runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 - name: build run: docker-compose run go-json test: name: Test strategy: matrix: os: [ "ubuntu-latest", "macos-latest", "windows-latest" ] go-version: [ "1.19", "1.20", "1.21" ] runs-on: ${{ matrix.os }} steps: - name: setup Go ${{ matrix.go-version }} uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} - name: checkout uses: actions/checkout@v3 - name: simple test run: go test -v ./... -count=1 - name: test with GC pressure run: go test -v ./... -count=1 env: GOGC: 1 - name: test with race detector run: go test -v -race ./... -count=1 lint: name: Lint runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 - name: setup Go uses: actions/setup-go@v3 with: go-version: '1.21' - name: lint run: | make lint bench: name: Benchmark runs-on: ubuntu-latest steps: - name: setup Go uses: actions/setup-go@v3 with: go-version: '1.21' - name: checkout ( feature ) uses: actions/checkout@v3 - name: run benchmark ( feature ) run: cd benchmarks && go test -bench GoJson | tee $HOME/new.txt - name: install benchstat run: go install golang.org/x/perf/cmd/benchstat@latest - name: checkout ( master ) uses: actions/checkout@v3 with: ref: master - name: run benchmark ( master ) run: cd benchmarks && go test -bench GoJson | tee $HOME/old.txt - name: compare benchmark results run: benchstat $HOME/old.txt $HOME/new.txt coverage: name: Coverage runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 - name: setup Go uses: actions/setup-go@v3 with: go-version: '1.21' - name: measure coverage run: make cover - uses: codecov/codecov-action@v4 with: fail_ci_if_error: true verbose: true token: ${{ secrets.CODECOV_TOKEN }} golang-github-goccy-go-json-0.10.3/.gitignore000066400000000000000000000000251463555276600210060ustar00rootroot00000000000000cover.html cover.out golang-github-goccy-go-json-0.10.3/.golangci.yml000066400000000000000000000027301463555276600214070ustar00rootroot00000000000000run: skip-files: - encode_optype.go - ".*_test\\.go$" linters-settings: govet: enable-all: true disable: - shadow linters: enable-all: true disable: - dogsled - dupl - exhaustive - exhaustivestruct - errorlint - forbidigo - funlen - gci - gochecknoglobals - gochecknoinits - gocognit - gocritic - gocyclo - godot - godox - goerr113 - gofumpt - gomnd - gosec - ifshort - lll - makezero - nakedret - nestif - nlreturn - paralleltest - testpackage - thelper - wrapcheck - interfacer - lll - nakedret - nestif - nlreturn - testpackage - wsl - varnamelen - nilnil - ireturn - govet - forcetypeassert - cyclop - containedctx - revive - nosnakecase - exhaustruct - depguard issues: exclude-rules: # not needed - path: /*.go text: "ST1003: should not use underscores in package names" linters: - stylecheck - path: /*.go text: "don't use an underscore in package name" linters: - golint - path: rtype.go linters: - golint - stylecheck - path: error.go linters: - staticcheck # Maximum issues count per one linter. Set to 0 to disable. Default is 50. max-issues-per-linter: 0 # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. max-same-issues: 0 golang-github-goccy-go-json-0.10.3/CHANGELOG.md000066400000000000000000000265201463555276600206370ustar00rootroot00000000000000# v0.10.2 - 2023/03/20 ### New features * Support DebugDOT option for debugging encoder ( #440 ) ### Fix bugs * Fix combination of embedding structure and omitempty option ( #442 ) # v0.10.1 - 2023/03/13 ### Fix bugs * Fix checkptr error for array decoder ( #415 ) * Fix added buffer size check when decoding key ( #430 ) * Fix handling of anonymous fields other than struct ( #431 ) * Fix to not optimize when lower conversion can't handle byte-by-byte ( #432 ) * Fix a problem that MarshalIndent does not work when UnorderedMap is specified ( #435 ) * Fix mapDecoder.DecodeStream() for empty objects containing whitespace ( #425 ) * Fix an issue that could not set the correct NextField for fields in the embedded structure ( #438 ) # v0.10.0 - 2022/11/29 ### New features * Support JSON Path ( #250 ) ### Fix bugs * Fix marshaler for map's key ( #409 ) # v0.9.11 - 2022/08/18 ### Fix bugs * Fix unexpected behavior when buffer ends with backslash ( #383 ) * Fix stream decoding of escaped character ( #387 ) # v0.9.10 - 2022/07/15 ### Fix bugs * Fix boundary exception of type caching ( #382 ) # v0.9.9 - 2022/07/15 ### Fix bugs * Fix encoding of directed interface with typed nil ( #377 ) * Fix embedded primitive type encoding using alias ( #378 ) * Fix slice/array type encoding with types implementing MarshalJSON ( #379 ) * Fix unicode decoding when the expected buffer state is not met after reading ( #380 ) # v0.9.8 - 2022/06/30 ### Fix bugs * Fix decoding of surrogate-pair ( #365 ) * Fix handling of embedded primitive type ( #366 ) * Add validation of escape sequence for decoder ( #367 ) * Fix stream tokenizing respecting UseNumber ( #369 ) * Fix encoding when struct pointer type that implements Marshal JSON is embedded ( #375 ) ### Improve performance * Improve performance of linkRecursiveCode ( #368 ) # v0.9.7 - 2022/04/22 ### Fix bugs #### Encoder * Add filtering process for encoding on slow path ( #355 ) * Fix encoding of interface{} with pointer type ( #363 ) #### Decoder * Fix map key decoder that implements UnmarshalJSON ( #353 ) * Fix decoding of []uint8 type ( #361 ) ### New features * Add DebugWith option for encoder ( #356 ) # v0.9.6 - 2022/03/22 ### Fix bugs * Correct the handling of the minimum value of int type for decoder ( #344 ) * Fix bugs of stream decoder's bufferSize ( #349 ) * Add a guard to use typeptr more safely ( #351 ) ### Improve decoder performance * Improve escapeString's performance ( #345 ) ### Others * Update go version for CI ( #347 ) # v0.9.5 - 2022/03/04 ### Fix bugs * Fix panic when decoding time.Time with context ( #328 ) * Fix reading the next character in buffer to nul consideration ( #338 ) * Fix incorrect handling on skipValue ( #341 ) ### Improve decoder performance * Improve performance when a payload contains escape sequence ( #334 ) # v0.9.4 - 2022/01/21 * Fix IsNilForMarshaler for string type with omitempty ( #323 ) * Fix the case where the embedded field is at the end ( #326 ) # v0.9.3 - 2022/01/14 * Fix logic of removing struct field for decoder ( #322 ) # v0.9.2 - 2022/01/14 * Add invalid decoder to delay type error judgment at decode ( #321 ) # v0.9.1 - 2022/01/11 * Fix encoding of MarshalText/MarshalJSON operation with head offset ( #319 ) # v0.9.0 - 2022/01/05 ### New feature * Supports dynamic filtering of struct fields ( #314 ) ### Improve encoding performance * Improve map encoding performance ( #310 ) * Optimize encoding path for escaped string ( #311 ) * Add encoding option for performance ( #312 ) ### Fix bugs * Fix panic at encoding map value on 1.18 ( #310 ) * Fix MarshalIndent for interface type ( #317 ) # v0.8.1 - 2021/12/05 * Fix operation conversion from PtrHead to Head in Recursive type ( #305 ) # v0.8.0 - 2021/12/02 * Fix embedded field conflict behavior ( #300 ) * Refactor compiler for encoder ( #301 #302 ) # v0.7.10 - 2021/10/16 * Fix conversion from pointer to uint64 ( #294 ) # v0.7.9 - 2021/09/28 * Fix encoding of nil value about interface type that has method ( #291 ) # 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 * Add type addrShift to enable bigger encoder/decoder cache ( #213 ) ### Fix decoder * Keep original reference of slice element ( #229 ) ### Refactor * Refactor Debug mode for encoding ( #226 ) * Generate VM sources for encoding ( #227 ) * Refactor validator for null/true/false for decoding ( #221 ) # v0.5.0 - 2021/5/9 ### Supports using omitempty and string tags at the same time ( #216 ) ### Fix decoder * Fix stream decoder for unicode char ( #215 ) * Fix decoding of slice element ( #219 ) * Fix calculating of buffer length for stream decoder ( #220 ) ### Refactor * replace skipWhiteSpace goto by loop ( #212 ) # v0.4.14 - 2021/5/4 ### Benchmark * Add valyala/fastjson to benchmark ( #193 ) * Add benchmark task for CI ( #211 ) ### Fix decoder * Fix decoding of slice with unmarshal json type ( #198 ) * Fix decoding of null value for interface type that does not implement Unmarshaler ( #205 ) * Fix decoding of null value to []byte by json.Unmarshal ( #206 ) * Fix decoding of backslash char at the end of string ( #207 ) * Fix stream decoder for null/true/false value ( #208 ) * Fix stream decoder for slow reader ( #211 ) ### Performance * If cap of slice is enough, reuse slice data for compatibility with encoding/json ( #200 ) # v0.4.13 - 2021/4/20 ### Fix json.Compact and json.Indent * Support validation the input buffer for json.Compact and json.Indent ( #189 ) * Optimize json.Compact and json.Indent ( improve memory footprint ) ( #190 ) # v0.4.12 - 2021/4/15 ### Fix encoder * Fix unnecessary indent for empty slice type ( #181 ) * Fix encoding of omitempty feature for the slice or interface type ( #183 ) * Fix encoding custom types zero values with omitempty when marshaller exists ( #187 ) ### Fix decoder * Fix decoder for invalid top level value ( #184 ) * Fix decoder for invalid number value ( #185 ) # v0.4.11 - 2021/4/3 * Improve decoder performance for interface type # v0.4.10 - 2021/4/2 ### Fix encoder * Fixed a bug when encoding slice and map containing recursive structures * Fixed a logic to determine if indirect reference # v0.4.9 - 2021/3/29 ### Add debug mode If you use `json.MarshalWithOption(v, json.Debug())` and `panic` occurred in `go-json`, produces debug information to console. ### Support a new feature to compatible with encoding/json - invalid UTF-8 is coerced to valid UTF-8 ( without performance down ) ### Fix encoder - Fixed handling of MarshalJSON of function type ### Fix decoding of slice of pointer type If there is a pointer value, go-json will use it. (This behavior is necessary to achieve the ability to prioritize pre-filled values). However, since slices are reused internally, there was a bug that referred to the previous pointer value. Therefore, it is not necessary to refer to the pointer value in advance for the slice element, so we explicitly initialize slice element by `nil`. # v0.4.8 - 2021/3/21 ### Reduce memory usage at compile time * go-json have used about 2GB of memory at compile time, but now it can compile with about less than 550MB. ### Fix any encoder's bug * Add many test cases for encoder * Fix composite type ( slice/array/map ) * Fix pointer types * Fix encoding of MarshalJSON or MarshalText or json.Number type ### Refactor encoder * Change package layout for reducing memory usage at compile * Remove anonymous and only operation * Remove root property from encodeCompileContext and opcode ### Fix CI * Add Go 1.16 * Remove Go 1.13 * Fix `make cover` task ### Number/Delim/Token/RawMessage use the types defined in encoding/json by type alias # v0.4.7 - 2021/02/22 ### Fix decoder * Fix decoding of deep recursive structure * Fix decoding of embedded unexported pointer field * Fix invalid test case * Fix decoding of invalid value * Fix decoding of prefilled value * Fix not being able to return UnmarshalTypeError when it should be returned * Fix decoding of null value * Fix decoding of type of null string * Use pre allocated pointer if exists it at decoding ### Reduce memory usage at compile * Integrate int/int8/int16/int32/int64 and uint/uint8/uint16/uint32/uint64 operation to reduce memory usage at compile ### Remove unnecessary optype golang-github-goccy-go-json-0.10.3/LICENSE000066400000000000000000000020601463555276600200240ustar00rootroot00000000000000MIT License Copyright (c) 2020 Masaaki Goshima Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-goccy-go-json-0.10.3/Makefile000066400000000000000000000015541463555276600204660ustar00rootroot00000000000000PKG := github.com/goccy/go-json BIN_DIR := $(CURDIR)/bin PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test) COVER_PKGS := $(foreach pkg,$(PKGS),$(subst $(PKG),.,$(pkg))) COMMA := , EMPTY := SPACE := $(EMPTY) $(EMPTY) COVERPKG_OPT := $(subst $(SPACE),$(COMMA),$(COVER_PKGS)) $(BIN_DIR): @mkdir -p $(BIN_DIR) .PHONY: cover cover: go test -coverpkg=$(COVERPKG_OPT) -coverprofile=cover.out ./... .PHONY: cover-html cover-html: cover go tool cover -html=cover.out .PHONY: lint lint: golangci-lint $(BIN_DIR)/golangci-lint run golangci-lint: | $(BIN_DIR) @{ \ set -e; \ GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \ cd $$GOLANGCI_LINT_TMP_DIR; \ go mod init tmp; \ GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2; \ rm -rf $$GOLANGCI_LINT_TMP_DIR; \ } .PHONY: generate generate: go generate ./internal/... golang-github-goccy-go-json-0.10.3/README.md000066400000000000000000000474461463555276600203170ustar00rootroot00000000000000# go-json ![Go](https://github.com/goccy/go-json/workflows/Go/badge.svg) [![GoDoc](https://godoc.org/github.com/goccy/go-json?status.svg)](https://pkg.go.dev/github.com/goccy/go-json?tab=doc) [![codecov](https://codecov.io/gh/goccy/go-json/branch/master/graph/badge.svg)](https://codecov.io/gh/goccy/go-json) Fast JSON encoder/decoder compatible with encoding/json for Go # Roadmap ``` * version ( expected release date ) * v0.9.0 | | while maintaining compatibility with encoding/json, we will add convenient APIs | v * v1.0.0 ``` We are accepting requests for features that will be implemented between v0.9.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). # 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` - Can dynamically filter the fields of the structure type-safely # Installation ``` go get github.com/goccy/go-json ``` # How to use Replace import statement from `encoding/json` to `github.com/goccy/go-json` ``` -import "encoding/json" +import "github.com/goccy/go-json" ``` # JSON library comparison | name | encoder | decoder | compatible with `encoding/json` | | :----: | :------: | :-----: | :-----------------------------: | | encoding/json | yes | yes | N/A | | [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 | 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 (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 ``` $ cd benchmarks $ go test -bench . ``` ## Encode ## Decode # Fuzzing [go-json-fuzz](https://github.com/goccy/go-json-fuzz) is the repository for fuzzing tests. If you run the test in this repository and find a bug, please commit to corpus to go-json-fuzz and report the issue to [go-json](https://github.com/goccy/go-json/issues). # How it works `go-json` is very fast in both encoding and decoding compared to other libraries. It's easier to implement by using automatic code generation for performance or by using a dedicated interface, but `go-json` dares to stick to compatibility with `encoding/json` and is the simple interface. Despite this, we are developing with the aim of being the fastest library. Here, we explain the various speed-up techniques implemented by `go-json`. ## Basic technique The techniques listed here are the ones used by most of the libraries listed above. ### Buffer reuse Since the only value required for the result of `json.Marshal(interface{}) ([]byte, error)` is `[]byte`, the only value that must be allocated during encoding is the return value `[]byte` . Also, as the number of allocations increases, the performance will be affected, so the number of allocations should be kept as low as possible when creating `[]byte`. Therefore, there is a technique to reduce the number of times a new buffer must be allocated by reusing the buffer used for the previous encoding by using `sync.Pool`. Finally, you allocate a buffer that is as long as the resulting buffer and copy the contents into it, you only need to allocate the buffer once in theory. ```go type buffer struct { data []byte } var bufPool = sync.Pool{ New: func() interface{} { return &buffer{data: make([]byte, 0, 1024)} }, } buf := bufPool.Get().(*buffer) data := encode(buf.data) // reuse buf.data newBuf := make([]byte, len(data)) copy(newBuf, buf) buf.data = data bufPool.Put(buf) ``` ### Elimination of reflection As you know, the reflection operation is very slow. Therefore, using the fact that the address position where the type information is stored is fixed for each binary ( we call this `typeptr` ), we can use the address in the type information to call a pre-built optimized process. For example, you can get the address to the type information from `interface{}` as follows and you can use that information to call a process that does not have reflection. To process without reflection, pass a pointer (`unsafe.Pointer`) to the value is stored. ```go type emptyInterface struct { typ unsafe.Pointer ptr unsafe.Pointer } var typeToEncoder = map[uintptr]func(unsafe.Pointer)([]byte, error){} func Marshal(v interface{}) ([]byte, error) { iface := (*emptyInterface)(unsafe.Pointer(&v) typeptr := uintptr(iface.typ) if enc, exists := typeToEncoder[typeptr]; exists { return enc(iface.ptr) } ... } ``` ※ In reality, `typeToEncoder` can be referenced by multiple goroutines, so exclusive control is required. ## Unique speed-up technique ## Encoder ### Do not escape arguments of `Marshal` `json.Marshal` and `json.Unmarshal` receive `interface{}` value and they perform type determination dynamically to process. In normal case, you need to use the `reflect` library to determine the type dynamically, but since `reflect.Type` is defined as `interface`, when you call the method of `reflect.Type`, The reflect's argument is escaped. Therefore, the arguments for `Marshal` and `Unmarshal` are always escaped to the heap. However, `go-json` can use the feature of `reflect.Type` while avoiding escaping. `reflect.Type` is defined as `interface`, but in reality `reflect.Type` is implemented only by the structure `rtype` defined in the `reflect` package. 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 [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 ) Initially this feature was the default behavior of `go-json`. But after careful testing, I found that I passed a large value to `json.Marshal()` and if the argument could not be assigned to the stack, it could not be properly escaped to the heap (a bug in the Go compiler). Therefore, this feature will be provided as an **optional** until this issue is resolved. To use it, add `NoEscape` like `MarshalNoEscape()` ### Encoding using opcode sequence I explained that you can use `typeptr` to call a pre-built process from type information. In other libraries, this dedicated process is processed by making it an function calling like anonymous function, but function calls are inherently slow processes and should be avoided as much as possible. Therefore, `go-json` adopted the Instruction-based execution processing system, which is also used to implement virtual machines for programming language. If it is the first type to encode, create the opcode ( instruction ) sequence required for encoding. From the second time onward, use `typeptr` to get the cached pre-built opcode sequence and encode it based on it. An example of the opcode sequence is shown below. ```go json.Marshal(struct{ X int `json:"x"` Y string `json:"y"` }{X: 1, Y: "hello"}) ``` When encoding a structure like the one above, create a sequence of opcodes like this: ``` - opStructFieldHead ( `{` ) - opStructFieldInt ( `"x": 1,` ) - opStructFieldString ( `"y": "hello"` ) - opStructEnd ( `}` ) - opEnd ``` ※ When processing each operation, write the letters on the right. In addition, each opcode is managed by the following structure ( Pseudo code ). ```go type opType int const ( opStructFieldHead opType = iota opStructFieldInt opStructFieldStirng opStructEnd opEnd ) type opcode struct { op opType key []byte next *opcode } ``` The process of encoding using the opcode sequence is roughly implemented as follows. ```go func encode(code *opcode, b []byte, p unsafe.Pointer) ([]byte, error) { for { switch code.op { case opStructFieldHead: b = append(b, '{') code = code.next case opStructFieldInt: b = append(b, code.key...) b = appendInt((*int)(unsafe.Pointer(uintptr(p)+code.offset))) code = code.next case opStructFieldString: b = append(b, code.key...) b = appendString((*string)(unsafe.Pointer(uintptr(p)+code.offset))) code = code.next case opStructEnd: b = append(b, '}') code = code.next case opEnd: goto END } } END: return b, nil } ``` In this way, the huge `switch-case` is used to encode by manipulating the linked list opcodes to avoid unnecessary function calls. ### Opcode sequence optimization One of the advantages of encoding using the opcode sequence is the ease of optimization. The opcode sequence mentioned above is actually converted into the following optimized operations and used. ``` - opStructFieldHeadInt ( `{"x": 1,` ) - opStructEndString ( `"y": "hello"}` ) - opEnd ``` It has been reduced from 5 opcodes to 3 opcodes ! Reducing the number of opcodees means reducing the number of branches with `switch-case`. In other words, the closer the number of operations is to 1, the faster the processing can be performed. In `go-json`, optimization to reduce the number of opcodes itself like the above and it speeds up by preparing opcodes with optimized paths. ### Change recursive call from CALL to JMP Recursive processing is required during encoding if the type is defined recursively as follows: ```go type T struct { X int U *U } type U struct { T *T } b, err := json.Marshal(&T{ X: 1, U: &U{ T: &T{ X: 2, }, }, }) fmt.Println(string(b)) // {"X":1,"U":{"T":{"X":2,"U":null}}} ``` In `go-json`, recursive processing is processed by the operation type of ` opStructFieldRecursive`. In this operation, after acquiring the opcode sequence used for recursive processing, the function is **not** called recursively as it is, but the necessary values ​​are saved by itself and implemented by moving to the next operation. The technique of implementing recursive processing with the `JMP` operation while avoiding the `CALL` operation is a famous technique for implementing a high-speed virtual machine. For more details, please refer to [the article](https://engineering.mercari.com/blog/entry/1599563768-081104c850) ( but Japanese only ). ### Dispatch by typeptr from map to slice When retrieving the data cached from the type information by `typeptr`, we usually use map. Map requires exclusive control, so use `sync.Map` for a naive implementation. However, this is slow, so it's a good idea to use the `atomic` package for exclusive control as implemented by `segmentio/encoding/json` ( https://github.com/segmentio/encoding/blob/master/json/codec.go#L41-L55 ). This implementation slows down the set instead of speeding up the get, but it works well because of the nature of the library, it encodes much more for the same type. However, as a result of profiling, I noticed that `runtime.mapaccess2` accounts for a significant percentage of the execution time. So I thought if I could change the lookup from map to slice. There is an API named `typelinks` defined in the `runtime` package that the `reflect` package uses internally. This allows you to get all the type information defined in the binary at runtime. The fact that all type information can be acquired means that by constructing slices in advance with the acquired total number of type information, it is possible to look up with the value of `typeptr` without worrying about out-of-range access. However, if there is too much type information, it will use a lot of memory, so by default we will only use this optimization if the slice size fits within **2Mib** . 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/internal/runtime/type.go#L36-L100) ## Decoder ### Dispatch by typeptr from map to slice Like the encoder, the decoder also uses typeptr to call the dedicated process. ### Faster termination character inspection using NUL character In order to decode, you have to traverse the input buffer character by position. At that time, if you check whether the buffer has reached the end, it will be very slow. `buf` : `[]byte` type variable. holds the string passed to the decoder `cursor` : `int64` type variable. holds the current read position ```go buflen := len(buf) for ; cursor < buflen; cursor++ { // compare cursor and buflen at all times, it is so slow. switch buf[cursor] { case ' ', '\n', '\r', '\t': } } ``` Therefore, by adding the `NUL` (`\000`) character to the end of the read buffer as shown below, it is possible to check the termination character at the same time as other characters. ```go for { switch buf[cursor] { case ' ', '\n', '\r', '\t': case '\000': return nil } cursor++ } ``` ### Use Boundary Check Elimination Due to the `NUL` character optimization, the Go compiler does a boundary check every time, even though `buf[cursor]` does not cause out-of-range access. Therefore, `go-json` eliminates boundary check by fetching characters for hotspot by pointer operation. For example, the following code. ```go func char(ptr unsafe.Pointer, offset int64) byte { return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset))) } p := (*sliceHeader)(&unsafe.Pointer(buf)).data for { switch char(p, cursor) { case ' ', '\n', '\r', '\t': case '\000': return nil } cursor++ } ``` ### Checking the existence of fields of struct using Bitmaps I found by the profiling result, in the struct decode, lookup process for field was taking a long time. For example, consider decoding a string like `{"a":1,"b":2,"c":3}` into the following structure: ```go type T struct { A int `json:"a"` B int `json:"b"` C int `json:"c"` } ``` At this time, it was found that it takes a lot of time to acquire the decoding process corresponding to the field from the field name as shown below during the decoding process. ```go fieldName := decodeKey(buf, cursor) // "a" or "b" or "c" decoder, exists := fieldToDecoderMap[fieldName] // so slow if exists { decoder(buf, cursor) } else { skipValue(buf, cursor) } ``` To improve this process, `json-iterator/go` is optimized so that it can be branched by switch-case when the number of fields in the structure is 10 or less (switch-case is faster than map). However, there is a risk of hash collision because the value hashed by the FNV algorithm is used for conditional branching. Also, `gojay` processes this part at high speed by letting the library user yourself write `switch-case`. `go-json` considers and implements a new approach that is different from these. I call this **bitmap field optimization**. The range of values ​​per character can be represented by `[256]byte`. Also, if the number of fields in the structure is 8 or less, `int8` type can represent the state of each field. In other words, it has the following structure. - Base ( 8bit ): `00000000` - Key "a": `00000001` ( assign key "a" to the first bit ) - Key "b": `00000010` ( assign key "b" to the second bit ) - Key "c": `00000100` ( assign key "c" to the third bit ) Bitmap structure is the following ``` | key index(0) | ------------------------ 0 | 00000000 | 1 | 00000000 | ~~ | | 97 (a) | 00000001 | 98 (b) | 00000010 | 99 (c) | 00000100 | ~~ | | 255 | 00000000 | ``` You can think of this as a Bitmap with a height of `256` and a width of the maximum string length in the field name. In other words, it can be represented by the following type . ```go [maxFieldKeyLength][256]int8 ``` When decoding a field character, check whether the corresponding character exists by referring to the pre-built bitmap like the following. ```go var curBit int8 = math.MaxInt8 // 11111111 c := char(buf, cursor) bit := bitmap[keyIdx][c] curBit &= bit if curBit == 0 { // not found field } ``` If `curBit` is not `0` until the end of the field string, then the string is You may have hit one of the fields. But the possibility is that if the decoded string is shorter than the field string, you will get a false hit. - input: `{"a":1}` ```go type T struct { X int `json:"abc"` } ``` ※ Since `a` is shorter than `abc`, it can decode to the end of the field character without `curBit` being 0. Rest assured. In this case, it doesn't matter because you can tell if you hit by comparing the string length of `a` with the string length of `abc`. Finally, calculate the position of the bit where `1` is set and get the corresponding value, and you're done. Using this technique, field lookups are possible with only bitwise operations and access to slices. `go-json` uses a similar technique for fields with 9 or more and 16 or less fields. At this time, Bitmap is constructed as `[maxKeyLen][256]int16` type. Currently, this optimization is not performed when the maximum length of the field name is long (specifically, 64 bytes or more) in addition to the limitation of the number of fields from the viewpoint of saving memory usage. ### Others I have done a lot of other optimizations. I will find time to write about them. If you have any questions about what's written here or other optimizations, please visit the `#go-json` channel on `gophers.slack.com` . ## Reference Regarding the story of go-json, there are the following articles in Japanese only. - https://speakerdeck.com/goccy/zui-su-falsejsonraiburariwoqiu-mete - https://engineering.mercari.com/blog/entry/1599563768-081104c850/ # Looking for Sponsors I'm looking for sponsors this library. This library is being developed as a personal project in my spare time. If you want a quick response or problem resolution when using this library in your project, please register as a [sponsor](https://github.com/sponsors/goccy). I will cooperate as much as possible. Of course, this library is developed as an MIT license, so you can use it freely for free. # License MIT golang-github-goccy-go-json-0.10.3/benchmarks/000077500000000000000000000000001463555276600211365ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/benchmarks/bench_test.go000066400000000000000000000331751463555276600236140ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Large data benchmark. // The JSON data is a summary of agl's changes in the // go, webkit, and chromium open source projects. // We benchmark converting between the JSON form // and in-memory data structures. package benchmark import ( "bytes" "compress/gzip" "fmt" "io" "os" "strings" "testing" stdjson "encoding/json" "github.com/goccy/go-json" jsoniter "github.com/json-iterator/go" segmentiojson "github.com/segmentio/encoding/json" "github.com/wI2L/jettison" ) type codeResponse struct { Tree *codeNode `json:"tree"` Username string `json:"username"` } type codeNode struct { Name string `json:"name"` Kids []*codeNode `json:"kids"` CLWeight float64 `json:"cl_weight"` Touches int `json:"touches"` MinT int64 `json:"min_t"` MaxT int64 `json:"max_t"` MeanT int64 `json:"mean_t"` } var codeJSON []byte var codeStruct codeResponse func codeInit() { f, err := os.Open("testdata/code.json.gz") if err != nil { panic(err) } defer f.Close() gz, err := gzip.NewReader(f) if err != nil { panic(err) } data, err := io.ReadAll(gz) if err != nil { panic(err) } codeJSON = data if err := stdjson.Unmarshal(codeJSON, &codeStruct); err != nil { panic("unmarshal code.json: " + err.Error()) } { stdjsonbytes, err := stdjson.Marshal(&codeStruct) if err != nil { panic("marshal code.json: " + err.Error()) } jsonbytes, err := json.Marshal(&codeStruct) if err != nil { panic("marshal code.json: " + err.Error()) } if len(stdjsonbytes) != len(jsonbytes) { panic(fmt.Sprintf("stdjson = %d but go-json = %d", len(stdjsonbytes), len(jsonbytes))) } } if _, err := json.Marshal(&codeStruct); err != nil { panic("marshal code.json: " + err.Error()) } if !bytes.Equal(data, codeJSON) { println("different lengths", len(data), len(codeJSON)) for i := 0; i < len(data) && i < len(codeJSON); i++ { if data[i] != codeJSON[i] { println("re-marshal: changed at byte", i) println("orig: ", string(codeJSON[i-10:i+10])) println("new: ", string(data[i-10:i+10])) break } } panic("re-marshal code.json: different result") } } func Benchmark_EncodeBigData_GoJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { enc := json.NewEncoder(io.Discard) for pb.Next() { if err := enc.Encode(&codeStruct); err != nil { b.Fatal("Encode:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_EncodeBigData_EncodingJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { enc := stdjson.NewEncoder(io.Discard) for pb.Next() { if err := enc.Encode(&codeStruct); err != nil { b.Fatal("Encode:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_EncodeBigData_JsonIter(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } var json = jsoniter.ConfigCompatibleWithStandardLibrary b.RunParallel(func(pb *testing.PB) { enc := json.NewEncoder(io.Discard) for pb.Next() { if err := enc.Encode(&codeStruct); err != nil { b.Fatal("Encode:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_EncodeBigData_SegmentioJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { enc := segmentiojson.NewEncoder(io.Discard) for pb.Next() { if err := enc.Encode(&codeStruct); err != nil { b.Fatal("Encode:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_MarshalBigData_GoJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := json.Marshal(&codeStruct); err != nil { b.Fatal("Marshal:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_MarshalBigData_EncodingJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := stdjson.Marshal(&codeStruct); err != nil { b.Fatal("Marshal:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_MarshalBigData_JsonIter(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } var json = jsoniter.ConfigCompatibleWithStandardLibrary b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := json.Marshal(&codeStruct); err != nil { b.Fatal("Marshal:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_MarshalBigData_Jettison(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := jettison.Marshal(&codeStruct); err != nil { b.Fatal("Marshal:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func Benchmark_MarshalBigData_SegmentioJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := segmentiojson.Marshal(&codeStruct); err != nil { b.Fatal("Marshal:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func benchMarshalBytes(n int, marshaler func(interface{}) ([]byte, error)) func(*testing.B) { sample := []byte("hello world") // Use a struct pointer, to avoid an allocation when passing it as an // interface parameter to Marshal. v := &struct { Bytes []byte }{ bytes.Repeat(sample, (n/len(sample))+1)[:n], } return func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := marshaler(v); err != nil { b.Fatal("Marshal:", err) } } } } func Benchmark_MarshalBytes_EncodingJson(b *testing.B) { // 32 fits within encodeState.scratch. b.Run("32", benchMarshalBytes(32, stdjson.Marshal)) // 256 doesn't fit in encodeState.scratch, but is small enough to // allocate and avoid the slower base64.NewEncoder. b.Run("256", benchMarshalBytes(256, stdjson.Marshal)) // 4096 is large enough that we want to avoid allocating for it. b.Run("4096", benchMarshalBytes(4096, stdjson.Marshal)) } func Benchmark_MarshalBytes_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary // 32 fits within encodeState.scratch. b.Run("32", benchMarshalBytes(32, json.Marshal)) // 256 doesn't fit in encodeState.scratch, but is small enough to // allocate and avoid the slower base64.NewEncoder. b.Run("256", benchMarshalBytes(256, json.Marshal)) // 4096 is large enough that we want to avoid allocating for it. b.Run("4096", benchMarshalBytes(4096, json.Marshal)) } func Benchmark_MarshalBytes_GoJson(b *testing.B) { b.ReportAllocs() // 32 fits within encodeState.scratch. b.Run("32", benchMarshalBytes(32, json.Marshal)) // 256 doesn't fit in encodeState.scratch, but is small enough to // allocate and avoid the slower base64.NewEncoder. b.Run("256", benchMarshalBytes(256, json.Marshal)) // 4096 is large enough that we want to avoid allocating for it. b.Run("4096", benchMarshalBytes(4096, json.Marshal)) } func Benchmark_EncodeRawMessage_EncodingJson(b *testing.B) { b.ReportAllocs() m := struct { A int B json.RawMessage }{} b.RunParallel(func(pb *testing.PB) { enc := stdjson.NewEncoder(io.Discard) for pb.Next() { if err := enc.Encode(&m); err != nil { b.Fatal("Encode:", err) } } }) } func Benchmark_EncodeRawMessage_JsonIter(b *testing.B) { b.ReportAllocs() m := struct { A int B json.RawMessage }{} var json = jsoniter.ConfigCompatibleWithStandardLibrary b.RunParallel(func(pb *testing.PB) { enc := json.NewEncoder(io.Discard) for pb.Next() { if err := enc.Encode(&m); err != nil { b.Fatal("Encode:", err) } } }) } func Benchmark_EncodeRawMessage_GoJson(b *testing.B) { b.ReportAllocs() m := struct { A int B json.RawMessage }{} b.RunParallel(func(pb *testing.PB) { enc := json.NewEncoder(io.Discard) for pb.Next() { if err := enc.Encode(&m); err != nil { b.Fatal("Encode:", err) } } }) } func Benchmark_MarshalString_EncodingJson(b *testing.B) { b.ReportAllocs() j := struct { Bar string `json:"bar,string"` }{ Bar: `foobar`, } b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := stdjson.Marshal(&j); err != nil { b.Fatal(err) } } }) } func Benchmark_MarshalString_JsonIter(b *testing.B) { b.ReportAllocs() j := struct { Bar string `json:"bar,string"` }{ Bar: `foobar`, } var json = jsoniter.ConfigCompatibleWithStandardLibrary b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := json.Marshal(&j); err != nil { b.Fatal(err) } } }) } func Benchmark_MarshalString_GoJson(b *testing.B) { b.ReportAllocs() j := struct { Bar string `json:"bar,string"` }{ Bar: `foobar`, } b.RunParallel(func(pb *testing.PB) { for pb.Next() { if _, err := json.Marshal(&j); err != nil { b.Fatal(err) } } }) } func BenchmarkCodeDecoder(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { var buf bytes.Buffer dec := json.NewDecoder(&buf) var r codeResponse for pb.Next() { buf.Write(codeJSON) // hide EOF buf.WriteByte('\n') buf.WriteByte('\n') buf.WriteByte('\n') if err := dec.Decode(&r); err != nil { if err != io.EOF { b.Fatal("Decode:", err) } } } }) b.SetBytes(int64(len(codeJSON))) } func BenchmarkUnicodeDecoder(b *testing.B) { b.ReportAllocs() j := []byte(`"\uD83D\uDE01"`) b.SetBytes(int64(len(j))) r := bytes.NewReader(j) dec := json.NewDecoder(r) var out string b.ResetTimer() for i := 0; i < b.N; i++ { if err := dec.Decode(&out); err != nil { if err != io.EOF { b.Fatal("Decode:", err) } } r.Seek(0, 0) } } func BenchmarkDecoderStream(b *testing.B) { b.ReportAllocs() b.StopTimer() var buf bytes.Buffer dec := json.NewDecoder(&buf) buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n") var x interface{} if err := dec.Decode(&x); err != nil { b.Fatal("Decode:", err) } ones := strings.Repeat(" 1\n", 300000) + "\n\n\n" b.StartTimer() for i := 0; i < b.N; i++ { if i%300000 == 0 { buf.WriteString(ones) } x = nil if err := dec.Decode(&x); err != nil || x != 1.0 { if err != io.EOF { b.Fatalf("Decode: %v after %d", err, i) } } } } func BenchmarkCodeUnmarshal(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { for pb.Next() { var r codeResponse if err := json.Unmarshal(codeJSON, &r); err != nil { b.Fatal("Unmarshal:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func BenchmarkCodeUnmarshalReuse(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } b.RunParallel(func(pb *testing.PB) { var r codeResponse for pb.Next() { if err := json.Unmarshal(codeJSON, &r); err != nil { b.Fatal("Unmarshal:", err) } } }) b.SetBytes(int64(len(codeJSON))) } func BenchmarkUnmarshalString(b *testing.B) { b.ReportAllocs() data := []byte(`"hello, world"`) b.RunParallel(func(pb *testing.PB) { var s string for pb.Next() { if err := json.Unmarshal(data, &s); err != nil { b.Fatal("Unmarshal:", err) } } }) } func BenchmarkUnmarshalFloat64(b *testing.B) { b.ReportAllocs() data := []byte(`3.14`) b.RunParallel(func(pb *testing.PB) { var f float64 for pb.Next() { if err := json.Unmarshal(data, &f); err != nil { b.Fatal("Unmarshal:", err) } } }) } func BenchmarkUnmarshalInt64(b *testing.B) { b.ReportAllocs() data := []byte(`3`) b.RunParallel(func(pb *testing.PB) { var x int64 for pb.Next() { if err := json.Unmarshal(data, &x); err != nil { b.Fatal("Unmarshal:", err) } } }) } func BenchmarkIssue10335(b *testing.B) { b.ReportAllocs() j := []byte(`{"a":{ }}`) b.RunParallel(func(pb *testing.PB) { var s struct{} for pb.Next() { if err := json.Unmarshal(j, &s); err != nil { b.Fatal(err) } } }) } func BenchmarkUnmapped(b *testing.B) { b.ReportAllocs() j := []byte(`{"s": "hello", "y": 2, "o": {"x": 0}, "a": [1, 99, {"x": 1}]}`) b.RunParallel(func(pb *testing.PB) { var s struct{} for pb.Next() { if err := json.Unmarshal(j, &s); err != nil { b.Fatal(err) } } }) } func Benchmark_Compact_EncodingJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } for i := 0; i < b.N; i++ { var buf bytes.Buffer if err := stdjson.Compact(&buf, codeJSON); err != nil { b.Fatal(err) } } } func Benchmark_Compact_GoJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } for i := 0; i < b.N; i++ { var buf bytes.Buffer if err := json.Compact(&buf, codeJSON); err != nil { b.Fatal(err) } } } func Benchmark_Indent_EncodingJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } for i := 0; i < b.N; i++ { var buf bytes.Buffer if err := stdjson.Indent(&buf, codeJSON, "-", " "); err != nil { b.Fatal(err) } } } func Benchmark_Indent_GoJson(b *testing.B) { b.ReportAllocs() if codeJSON == nil { b.StopTimer() codeInit() b.StartTimer() } for i := 0; i < b.N; i++ { var buf bytes.Buffer if err := json.Indent(&buf, codeJSON, "-", " "); err != nil { b.Fatal(err) } } } golang-github-goccy-go-json-0.10.3/benchmarks/decode_test.go000066400000000000000000000272771463555276600237660ustar00rootroot00000000000000package benchmark import ( "bytes" "encoding/json" "testing" gojay "github.com/francoispqt/gojay" gojson "github.com/goccy/go-json" jsoniter "github.com/json-iterator/go" segmentiojson "github.com/segmentio/encoding/json" fastjson "github.com/valyala/fastjson" ) func Benchmark_Decode_SmallStruct_Unmarshal_EncodingJson(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := SmallPayload{} if err := json.Unmarshal(SmallFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Unmarshal_FastJson(b *testing.B) { smallFixture := string(SmallFixture) b.ReportAllocs() for n := 0; n < b.N; n++ { var p fastjson.Parser if _, err := p.Parse(smallFixture); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Unmarshal_SegmentioJson(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := SmallPayload{} if err := segmentiojson.Unmarshal(SmallFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Unmarshal_JsonIter(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := SmallPayload{} if err := jsoniter.Unmarshal(SmallFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Unmarshal_GoJay(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := SmallPayload{} if err := gojay.UnmarshalJSONObject(SmallFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Unmarshal_GoJayUnsafe(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := SmallPayload{} if err := gojay.Unsafe.UnmarshalJSONObject(SmallFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Unmarshal_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := SmallPayload{} if err := gojson.Unmarshal(SmallFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Unmarshal_GoJsonNoEscape(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := SmallPayload{} if err := gojson.UnmarshalNoEscape(SmallFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Stream_EncodingJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(SmallFixture) for i := 0; i < b.N; i++ { result := SmallPayload{} reader.Reset(SmallFixture) if err := json.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Stream_SegmentioJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(SmallFixture) for i := 0; i < b.N; i++ { result := SmallPayload{} reader.Reset(SmallFixture) if err := segmentiojson.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Stream_JsonIter(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(SmallFixture) for i := 0; i < b.N; i++ { result := SmallPayload{} reader.Reset(SmallFixture) if err := jsoniter.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Stream_GoJay(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(SmallFixture) for n := 0; n < b.N; n++ { reader.Reset(SmallFixture) result := SmallPayload{} if err := gojay.NewDecoder(reader).DecodeObject(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_SmallStruct_Stream_GoJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(SmallFixture) for i := 0; i < b.N; i++ { result := SmallPayload{} reader.Reset(SmallFixture) if err := gojson.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_EncodingJson(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := MediumPayload{} if err := json.Unmarshal(MediumFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_FastJson(b *testing.B) { mediumFixture := string(MediumFixture) b.ReportAllocs() for n := 0; n < b.N; n++ { var p fastjson.Parser if _, err := p.Parse(mediumFixture); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_SegmentioJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := MediumPayload{} if err := segmentiojson.Unmarshal(MediumFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_JsonIter(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := MediumPayload{} if err := jsoniter.Unmarshal(MediumFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_GoJay(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := MediumPayload{} if err := gojay.UnmarshalJSONObject(MediumFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_GoJayUnsafe(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := MediumPayload{} if err := gojay.Unsafe.UnmarshalJSONObject(MediumFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := MediumPayload{} if err := gojson.Unmarshal(MediumFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Unmarshal_GoJsonNoEscape(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := MediumPayload{} if err := gojson.UnmarshalNoEscape(MediumFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Stream_EncodingJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(MediumFixture) for i := 0; i < b.N; i++ { result := MediumPayload{} reader.Reset(MediumFixture) if err := json.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Stream_SegmentioJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(MediumFixture) for n := 0; n < b.N; n++ { reader.Reset(MediumFixture) result := MediumPayload{} if err := segmentiojson.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Stream_JsonIter(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(MediumFixture) for i := 0; i < b.N; i++ { result := MediumPayload{} reader.Reset(MediumFixture) if err := jsoniter.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Stream_GoJay(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(MediumFixture) for n := 0; n < b.N; n++ { reader.Reset(MediumFixture) result := MediumPayload{} if err := gojay.NewDecoder(reader).DecodeObject(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_MediumStruct_Stream_GoJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(MediumFixture) for i := 0; i < b.N; i++ { result := MediumPayload{} reader.Reset(MediumFixture) if err := gojson.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_EncodingJson(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := LargePayload{} if err := json.Unmarshal(LargeFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_FastJson(b *testing.B) { largeFixture := string(LargeFixture) b.ReportAllocs() for n := 0; n < b.N; n++ { var p fastjson.Parser if _, err := p.Parse(largeFixture); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_SegmentioJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := LargePayload{} if err := segmentiojson.Unmarshal(LargeFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_JsonIter(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := LargePayload{} if err := jsoniter.Unmarshal(LargeFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_GoJay(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { result := LargePayload{} if err := gojay.UnmarshalJSONObject(LargeFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_GoJayUnsafe(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := LargePayload{} if err := gojay.Unsafe.UnmarshalJSONObject(LargeFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := LargePayload{} if err := gojson.Unmarshal(LargeFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_GoJsonNoEscape(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := LargePayload{} if err := gojson.UnmarshalNoEscape(LargeFixture, &result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_GoJsonFirstWinMode(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := LargePayload{} if err := gojson.UnmarshalWithOption( LargeFixture, &result, gojson.DecodeFieldPriorityFirstWin(), ); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Unmarshal_GoJsonNoEscapeFirstWinMode(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { result := LargePayload{} if err := gojson.UnmarshalNoEscape( LargeFixture, &result, gojson.DecodeFieldPriorityFirstWin(), ); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Stream_EncodingJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(LargeFixture) for i := 0; i < b.N; i++ { result := LargePayload{} reader.Reset(LargeFixture) if err := json.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Stream_SegmentioJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(LargeFixture) for i := 0; i < b.N; i++ { result := LargePayload{} reader.Reset(LargeFixture) if err := segmentiojson.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Stream_JsonIter(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(LargeFixture) for i := 0; i < b.N; i++ { result := LargePayload{} reader.Reset(LargeFixture) if err := jsoniter.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Stream_GoJay(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(LargeFixture) for n := 0; n < b.N; n++ { reader.Reset(LargeFixture) result := LargePayload{} if err := gojay.NewDecoder(reader).DecodeObject(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Stream_GoJson(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(LargeFixture) for i := 0; i < b.N; i++ { result := LargePayload{} reader.Reset(LargeFixture) if err := gojson.NewDecoder(reader).Decode(&result); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeStruct_Stream_GoJsonFirstWinMode(b *testing.B) { b.ReportAllocs() reader := bytes.NewReader(LargeFixture) for i := 0; i < b.N; i++ { result := LargePayload{} reader.Reset(LargeFixture) if err := gojson.NewDecoder(reader).DecodeWithOption( &result, gojson.DecodeFieldPriorityFirstWin(), ); err != nil { b.Fatal(err) } } } func Benchmark_Decode_LargeSlice_EscapedString_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { var v []string if err := gojson.Unmarshal(LargeSliceEscapedString, &v); err != nil { b.Fatal(err) } } } golang-github-goccy-go-json-0.10.3/benchmarks/encode_test.go000066400000000000000000000464421463555276600237730ustar00rootroot00000000000000package benchmark import ( "bytes" "context" "encoding/json" "testing" gojay "github.com/francoispqt/gojay" gojson "github.com/goccy/go-json" jsoniter "github.com/json-iterator/go" "github.com/pquerna/ffjson/ffjson" segmentiojson "github.com/segmentio/encoding/json" "github.com/wI2L/jettison" ) func Benchmark_Encode_SmallStruct_EncodingJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(NewSmallPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_FFJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := ffjson.Marshal(NewSmallPayloadFFJson()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(NewSmallPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_EasyJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := NewSmallPayloadEasyJson().MarshalJSON(); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_Jettison(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(NewSmallPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_GoJay(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojay.MarshalJSONObject(NewSmallPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_SegmentioJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(NewSmallPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_GoJsonColored(b *testing.B) { colorOpt := gojson.Colorize(gojson.DefaultColorScheme) b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalWithOption(NewSmallPayload(), colorOpt); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(NewSmallPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStruct_GoJsonNoEscape(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalNoEscape(NewSmallPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_EncodingJson(b *testing.B) { cached := NewSmallPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_FFJson(b *testing.B) { cached := NewSmallPayloadFFJson() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := ffjson.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary cached := NewSmallPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_EasyJson(b *testing.B) { cached := NewSmallPayloadEasyJson() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := cached.MarshalJSON(); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_Jettison(b *testing.B) { cached := NewSmallPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_GoJay(b *testing.B) { cached := NewSmallPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojay.MarshalJSONObject(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_SegmentioJson(b *testing.B) { cached := NewSmallPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_GoJsonColored(b *testing.B) { cached := NewSmallPayload() colorOpt := gojson.Colorize(gojson.DefaultColorScheme) b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalWithOption(cached, colorOpt); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_GoJson(b *testing.B) { cached := NewSmallPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_SmallStructCached_GoJsonNoEscape(b *testing.B) { cached := NewSmallPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalNoEscape(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_EncodingJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(NewMediumPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(NewMediumPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_EasyJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := NewMediumPayloadEasyJson().MarshalJSON(); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_Jettison(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(NewMediumPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_GoJay(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojay.MarshalJSONObject(NewMediumPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_SegmentioJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(NewMediumPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_GoJsonColored(b *testing.B) { colorOpt := gojson.Colorize(gojson.DefaultColorScheme) b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalWithOption(NewMediumPayload(), colorOpt); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(NewMediumPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStruct_GoJsonNoEscape(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalNoEscape(NewMediumPayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_EncodingJson(b *testing.B) { cached := NewMediumPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary cached := NewMediumPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_EasyJson(b *testing.B) { cached := NewMediumPayloadEasyJson() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := cached.MarshalJSON(); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_Jettison(b *testing.B) { cached := NewMediumPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_GoJay(b *testing.B) { cached := NewMediumPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojay.MarshalJSONObject(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_SegmentioJson(b *testing.B) { cached := NewMediumPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_GoJsonColored(b *testing.B) { cached := NewMediumPayload() colorOpt := gojson.Colorize(gojson.DefaultColorScheme) b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalWithOption(cached, colorOpt); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_GoJson(b *testing.B) { cached := NewMediumPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MediumStructCached_GoJsonNoEscape(b *testing.B) { cached := NewMediumPayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalNoEscape(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_EncodingJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(NewLargePayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(NewLargePayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_EasyJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := NewLargePayloadEasyJson().MarshalJSON(); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_Jettison(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(NewLargePayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_GoJay(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojay.MarshalJSONObject(NewLargePayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_SegmentioJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(NewLargePayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_GoJsonColored(b *testing.B) { colorOpt := gojson.Colorize(gojson.DefaultColorScheme) b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalWithOption(NewLargePayload(), colorOpt); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(NewLargePayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStruct_GoJsonNoEscape(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalNoEscape(NewLargePayload()); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_EncodingJson(b *testing.B) { cached := NewLargePayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary cached := NewLargePayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_EasyJson(b *testing.B) { cached := NewLargePayloadEasyJson() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := cached.MarshalJSON(); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_Jettison(b *testing.B) { cached := NewLargePayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_GoJay(b *testing.B) { cached := NewLargePayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojay.MarshalJSONObject(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_SegmentioJson(b *testing.B) { cached := NewLargePayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_GoJsonColored(b *testing.B) { cached := NewLargePayload() colorOpt := gojson.Colorize(gojson.DefaultColorScheme) b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalWithOption(cached, colorOpt); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_GoJson(b *testing.B) { cached := NewLargePayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(cached); err != nil { b.Fatal(err) } } } func Benchmark_Encode_LargeStructCached_GoJsonNoEscape(b *testing.B) { cached := NewLargePayload() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalNoEscape(cached); err != nil { b.Fatal(err) } } } func benchMapValue() map[string]interface{} { return map[string]interface{}{ "a": 1, "b": 2.1, "c": "hello", "d": struct { V int }{ V: 1, }, "e": true, } } func Benchmark_Encode_MapInterface_EncodingJson(b *testing.B) { v := benchMapValue() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MapInterface_JsonIter(b *testing.B) { v := benchMapValue() var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MapInterface_Jettison(b *testing.B) { v := benchMapValue() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MapInterface_SegmentioJson(b *testing.B) { v := benchMapValue() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MapInterface_GoJson(b *testing.B) { v := benchMapValue() b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Interface_SegmentioJson(b *testing.B) { v := []interface{}{1} b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Interface_GoJson(b *testing.B) { v := []interface{}{1} b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Bool_EncodingJson(b *testing.B) { b.ReportAllocs() var buf bytes.Buffer enc := json.NewEncoder(&buf) for i := 0; i < b.N; i++ { if err := enc.Encode(true); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Bool_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() var buf bytes.Buffer enc := json.NewEncoder(&buf) for i := 0; i < b.N; i++ { if err := enc.Encode(true); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Bool_SegmentioJson(b *testing.B) { b.ReportAllocs() var buf bytes.Buffer enc := segmentiojson.NewEncoder(&buf) for i := 0; i < b.N; i++ { if err := enc.Encode(true); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Bool_GoJson(b *testing.B) { b.ReportAllocs() var buf bytes.Buffer enc := gojson.NewEncoder(&buf) for i := 0; i < b.N; i++ { if err := enc.Encode(true); err != nil { b.Fatal(err) } } } func Benchmark_Marshal_Bool_EncodingJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(true); err != nil { b.Fatal(err) } } } func Benchmark_Marshal_Bool_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(true); err != nil { b.Fatal(err) } } } func Benchmark_Marshal_Bool_Jettison(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(true); err != nil { b.Fatal(err) } } } func Benchmark_Marshal_Bool_SegmentioJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(true); err != nil { b.Fatal(err) } } } func Benchmark_Marshal_Bool_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(true); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Int_EncodingJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(1); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Int_JsonIter(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(1); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Int_Jettison(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(1); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Int_SegmentioJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(1); err != nil { b.Fatal(err) } } } func Benchmark_Encode_Int_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(1); err != nil { b.Fatal(err) } } } type marshaler struct{} func (*marshaler) MarshalJSON() ([]byte, error) { return []byte(`"hello"`), nil } func Benchmark_Encode_MarshalJSON_EncodingJson(b *testing.B) { v := &marshaler{} b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MarshalJSON_JsonIter(b *testing.B) { v := &marshaler{} var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := json.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MarshalJSON_Jettison(b *testing.B) { v := &marshaler{} b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := jettison.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MarshalJSON_SegmentioJson(b *testing.B) { v := &marshaler{} b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := segmentiojson.Marshal(v); err != nil { b.Fatal(err) } } } func Benchmark_Encode_MarshalJSON_GoJson(b *testing.B) { v := &marshaler{} b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.Marshal(v); err != nil { b.Fatal(err) } } } type queryTestX struct { XA int XB string XC *queryTestY XD bool XE float32 } type queryTestY struct { YA int YB string YC bool YD float32 } func Benchmark_Encode_FilterByMap(b *testing.B) { v := &queryTestX{ XA: 1, XB: "xb", XC: &queryTestY{ YA: 2, YB: "yb", YC: true, YD: 4, }, XD: true, XE: 5, } b.ReportAllocs() for i := 0; i < b.N; i++ { filteredMap := map[string]interface{}{ "XA": v.XA, "XB": v.XB, "XC": map[string]interface{}{ "YA": v.XC.YA, "YB": v.XC.YB, }, } if _, err := gojson.Marshal(filteredMap); err != nil { b.Fatal(err) } } } func Benchmark_Encode_FilterByFieldQuery(b *testing.B) { query, err := gojson.BuildFieldQuery( "XA", "XB", gojson.BuildSubFieldQuery("XC").Fields( "YA", "YB", ), ) if err != nil { b.Fatal(err) } v := &queryTestX{ XA: 1, XB: "xb", XC: &queryTestY{ YA: 2, YB: "yb", YC: true, YD: 4, }, XD: true, XE: 5, } ctx := gojson.SetFieldQueryToContext(context.Background(), query) b.ReportAllocs() for i := 0; i < b.N; i++ { if _, err := gojson.MarshalContext(ctx, v); err != nil { b.Fatal(err) } } } golang-github-goccy-go-json-0.10.3/benchmarks/go.mod000066400000000000000000000011771463555276600222520ustar00rootroot00000000000000module benchmark go 1.19 require ( github.com/francoispqt/gojay v1.2.13 github.com/goccy/go-json v0.0.0-00010101000000-000000000000 github.com/json-iterator/go v1.1.10 github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 github.com/segmentio/encoding v0.2.4 github.com/valyala/fastjson v1.6.3 github.com/wI2L/jettison v0.7.1 ) require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/stretchr/testify v1.7.0 // indirect ) replace github.com/goccy/go-json => ../ golang-github-goccy-go-json-0.10.3/benchmarks/go.sum000066400000000000000000000472241463555276600223020ustar00rootroot00000000000000cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFlmsC6B9sbuo2fP8OFP1ABjt4kPz+w= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20= github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/segmentio/encoding v0.1.10/go.mod h1:RWhr02uzMB9gQC1x+MfYxedtmBibb9cZ6Vv9VxRSSbw= github.com/segmentio/encoding v0.2.4 h1:TQRXhTlXj4urZe3Z5QVgxs9Ad1i7GYHg9peAtjOPe28= github.com/segmentio/encoding v0.2.4/go.mod h1:MJjRE6bMDocliO2FyFC2Dusp+uYdBfHWh5Bw7QyExto= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc= github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/wI2L/jettison v0.7.1 h1:XNq/WvSOAiJhFww9F5JZZcBZtKFL2Y/9WHHEHLDq9TE= github.com/wI2L/jettison v0.7.1/go.mod h1:dj49nOP41M7x6Jql62BqqF/+nW+XJgBaWzJR0hd6M84= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= golang-github-goccy-go-json-0.10.3/benchmarks/large_payload.go000066400000000000000000000764431463555276600243060ustar00rootroot00000000000000package benchmark import ( "strconv" "strings" "github.com/francoispqt/gojay" ) type DSUser struct { Username string } func (m *DSUser) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "username": return dec.AddString(&m.Username) } return nil } func (m *DSUser) NKeys() int { return 1 } func (m *DSUser) IsNil() bool { return m == nil } func (m *DSUser) MarshalJSONObject(enc *gojay.Encoder) { enc.AddStringKey("username", m.Username) } type DSTopic struct { Id int Slug string } func (m *DSTopic) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "id": return dec.AddInt(&m.Id) case "slug": return dec.AddString(&m.Slug) } return nil } func (m *DSTopic) NKeys() int { return 2 } func (m *DSTopic) IsNil() bool { return m == nil } func (m *DSTopic) MarshalJSONObject(enc *gojay.Encoder) { enc.AddIntKey("id", m.Id) enc.AddStringKey("slug", m.Slug) } type DSTopics []*DSTopic func (t *DSTopics) UnmarshalJSONArray(dec *gojay.Decoder) error { dsTopic := &DSTopic{} *t = append(*t, dsTopic) return dec.AddObject(dsTopic) } func (m *DSTopics) MarshalJSONArray(enc *gojay.Encoder) { for _, e := range *m { enc.AddObject(e) } } func (m *DSTopics) IsNil() bool { return m == nil } type DSTopicsList struct { Topics DSTopics MoreTopicsUrl string } func (m *DSTopicsList) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "topics": m.Topics = DSTopics{} return dec.AddArray(&m.Topics) case "more_topics_url": return dec.AddString(&m.MoreTopicsUrl) } return nil } func (m *DSTopicsList) NKeys() int { return 2 } func (m *DSTopicsList) IsNil() bool { return m == nil } func (m *DSTopicsList) MarshalJSONObject(enc *gojay.Encoder) { enc.AddArrayKey("users", &m.Topics) enc.AddStringKey("more_topics_url", m.MoreTopicsUrl) } type DSUsers []*DSUser func (t *DSUsers) UnmarshalJSONArray(dec *gojay.Decoder) error { dsUser := DSUser{} *t = append(*t, &dsUser) return dec.AddObject(&dsUser) } func (m *DSUsers) MarshalJSONArray(enc *gojay.Encoder) { for _, e := range *m { enc.AddObject(e) } } func (m *DSUsers) IsNil() bool { return m == nil } type LargePayload struct { Users DSUsers Topics *DSTopicsList } //easyjson:json type LargePayloadEasyJson struct { Users DSUsers Topics *DSTopicsList } func (m *LargePayload) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "users": return dec.AddArray(&m.Users) case "topics": m.Topics = &DSTopicsList{} return dec.AddObject(m.Topics) } return nil } func (m *LargePayload) NKeys() int { return 2 } func (m *LargePayload) MarshalJSONObject(enc *gojay.Encoder) { enc.AddArrayKey("users", &m.Users) enc.AddObjectKey("topics", m.Topics) } func (m *LargePayload) IsNil() bool { return m == nil } var LargeFixture = []byte(` {"users":[{"id":-1,"username":"system","avatar_template":"/user_avatar/discourse.metabase.com/system/{size}/6_1.png"},{"id":89,"username":"zergot","avatar_template":"https://avatars.discourse.org/v2/letter/z/0ea827/{size}.png"},{"id":1,"username":"sameer","avatar_template":"https://avatars.discourse.org/v2/letter/s/bbce88/{size}.png"},{"id":84,"username":"HenryMirror","avatar_template":"https://avatars.discourse.org/v2/letter/h/ecd19e/{size}.png"},{"id":73,"username":"fimp","avatar_template":"https://avatars.discourse.org/v2/letter/f/ee59a6/{size}.png"},{"id":14,"username":"agilliland","avatar_template":"/user_avatar/discourse.metabase.com/agilliland/{size}/26_1.png"},{"id":87,"username":"amir","avatar_template":"https://avatars.discourse.org/v2/letter/a/c37758/{size}.png"},{"id":82,"username":"waseem","avatar_template":"https://avatars.discourse.org/v2/letter/w/9dc877/{size}.png"},{"id":78,"username":"tovenaar","avatar_template":"https://avatars.discourse.org/v2/letter/t/9de0a6/{size}.png"},{"id":74,"username":"Ben","avatar_template":"https://avatars.discourse.org/v2/letter/b/df788c/{size}.png"},{"id":71,"username":"MarkLaFay","avatar_template":"https://avatars.discourse.org/v2/letter/m/3bc359/{size}.png"},{"id":72,"username":"camsaul","avatar_template":"/user_avatar/discourse.metabase.com/camsaul/{size}/70_1.png"},{"id":53,"username":"mhjb","avatar_template":"/user_avatar/discourse.metabase.com/mhjb/{size}/54_1.png"},{"id":58,"username":"jbwiv","avatar_template":"https://avatars.discourse.org/v2/letter/j/6bbea6/{size}.png"},{"id":70,"username":"Maggs","avatar_template":"https://avatars.discourse.org/v2/letter/m/bbce88/{size}.png"},{"id":69,"username":"andrefaria","avatar_template":"/user_avatar/discourse.metabase.com/andrefaria/{size}/65_1.png"},{"id":60,"username":"bencarter78","avatar_template":"/user_avatar/discourse.metabase.com/bencarter78/{size}/59_1.png"},{"id":55,"username":"vikram","avatar_template":"https://avatars.discourse.org/v2/letter/v/e47774/{size}.png"},{"id":68,"username":"edchan77","avatar_template":"/user_avatar/discourse.metabase.com/edchan77/{size}/66_1.png"},{"id":9,"username":"karthikd","avatar_template":"https://avatars.discourse.org/v2/letter/k/cab0a1/{size}.png"},{"id":23,"username":"arthurz","avatar_template":"/user_avatar/discourse.metabase.com/arthurz/{size}/32_1.png"},{"id":3,"username":"tom","avatar_template":"/user_avatar/discourse.metabase.com/tom/{size}/21_1.png"},{"id":50,"username":"LeoNogueira","avatar_template":"/user_avatar/discourse.metabase.com/leonogueira/{size}/52_1.png"},{"id":66,"username":"ss06vi","avatar_template":"https://avatars.discourse.org/v2/letter/s/3ab097/{size}.png"},{"id":34,"username":"mattcollins","avatar_template":"/user_avatar/discourse.metabase.com/mattcollins/{size}/41_1.png"},{"id":51,"username":"krmmalik","avatar_template":"/user_avatar/discourse.metabase.com/krmmalik/{size}/53_1.png"},{"id":46,"username":"odysseas","avatar_template":"https://avatars.discourse.org/v2/letter/o/5f8ce5/{size}.png"},{"id":5,"username":"jonthewayne","avatar_template":"/user_avatar/discourse.metabase.com/jonthewayne/{size}/18_1.png"},{"id":11,"username":"anandiyer","avatar_template":"/user_avatar/discourse.metabase.com/anandiyer/{size}/23_1.png"},{"id":25,"username":"alnorth","avatar_template":"/user_avatar/discourse.metabase.com/alnorth/{size}/34_1.png"},{"id":52,"username":"j_at_svg","avatar_template":"https://avatars.discourse.org/v2/letter/j/96bed5/{size}.png"},{"id":42,"username":"styts","avatar_template":"/user_avatar/discourse.metabase.com/styts/{size}/47_1.png"}],"topics":{"can_create_topic":false,"more_topics_url":"/c/uncategorized/l/latest?page=1","draft":null,"draft_key":"new_topic","draft_sequence":null,"per_page":30,"topics":[{"id":8,"title":"Welcome to Metabase's Discussion Forum","fancy_title":"Welcome to Metabase’s Discussion Forum","slug":"welcome-to-metabases-discussion-forum","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":"/images/welcome/discourse-edit-post-animated.gif","created_at":"2015-10-17T00:14:49.526Z","last_posted_at":"2015-10-17T00:14:49.557Z","bumped":true,"bumped_at":"2015-10-21T02:32:22.486Z","unseen":false,"pinned":true,"unpinned":null,"excerpt":"Welcome to Metabase's discussion forum. This is a place to get help on installation, setting up as well as sharing tips and tricks.","visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":197,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"system","category_id":1,"pinned_globally":true,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":-1}]},{"id":169,"title":"Formatting Dates","fancy_title":"Formatting Dates","slug":"formatting-dates","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2016-01-14T06:30:45.311Z","last_posted_at":"2016-01-14T06:30:45.397Z","bumped":true,"bumped_at":"2016-01-14T06:30:45.397Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":11,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":89}]},{"id":168,"title":"Setting for google api key","fancy_title":"Setting for google api key","slug":"setting-for-google-api-key","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2016-01-13T17:14:31.799Z","last_posted_at":"2016-01-14T06:24:03.421Z","bumped":true,"bumped_at":"2016-01-14T06:24:03.421Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":16,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":89}]},{"id":167,"title":"Cannot see non-US timezones on the admin","fancy_title":"Cannot see non-US timezones on the admin","slug":"cannot-see-non-us-timezones-on-the-admin","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2016-01-13T17:07:36.764Z","last_posted_at":"2016-01-13T17:07:36.831Z","bumped":true,"bumped_at":"2016-01-13T17:07:36.831Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":11,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":89}]},{"id":164,"title":"External (Metabase level) linkages in data schema","fancy_title":"External (Metabase level) linkages in data schema","slug":"external-metabase-level-linkages-in-data-schema","posts_count":4,"reply_count":1,"highest_post_number":4,"image_url":null,"created_at":"2016-01-11T13:51:02.286Z","last_posted_at":"2016-01-12T11:06:37.259Z","bumped":true,"bumped_at":"2016-01-12T11:06:37.259Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":32,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":89},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":155,"title":"Query working on \"Questions\" but not in \"Pulses\"","fancy_title":"Query working on “Questions” but not in “Pulses”","slug":"query-working-on-questions-but-not-in-pulses","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2016-01-01T14:06:10.083Z","last_posted_at":"2016-01-08T22:37:51.772Z","bumped":true,"bumped_at":"2016-01-08T22:37:51.772Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":72,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"agilliland","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":84},{"extras":null,"description":"Frequent Poster","user_id":73},{"extras":"latest","description":"Most Recent Poster","user_id":14}]},{"id":161,"title":"Pulses posted to Slack don't show question output","fancy_title":"Pulses posted to Slack don’t show question output","slug":"pulses-posted-to-slack-dont-show-question-output","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":"/uploads/default/original/1X/9d2806517bf3598b10be135b2c58923b47ba23e7.png","created_at":"2016-01-08T22:09:58.205Z","last_posted_at":"2016-01-08T22:28:44.685Z","bumped":true,"bumped_at":"2016-01-08T22:28:44.685Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":34,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":87},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":152,"title":"Should we build Kafka connecter or Kafka plugin","fancy_title":"Should we build Kafka connecter or Kafka plugin","slug":"should-we-build-kafka-connecter-or-kafka-plugin","posts_count":4,"reply_count":1,"highest_post_number":4,"image_url":null,"created_at":"2015-12-28T20:37:23.501Z","last_posted_at":"2015-12-31T18:16:45.477Z","bumped":true,"bumped_at":"2015-12-31T18:16:45.477Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":84,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":82},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":147,"title":"Change X and Y on graph","fancy_title":"Change X and Y on graph","slug":"change-x-and-y-on-graph","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-12-21T17:52:46.581Z","last_posted_at":"2015-12-21T17:52:46.684Z","bumped":true,"bumped_at":"2015-12-21T18:19:13.003Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":68,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"tovenaar","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":78}]},{"id":142,"title":"Issues sending mail via office365 relay","fancy_title":"Issues sending mail via office365 relay","slug":"issues-sending-mail-via-office365-relay","posts_count":5,"reply_count":2,"highest_post_number":5,"image_url":null,"created_at":"2015-12-16T10:38:47.315Z","last_posted_at":"2015-12-21T09:26:27.167Z","bumped":true,"bumped_at":"2015-12-21T09:26:27.167Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":122,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"Ben","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":74},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":137,"title":"I see triplicates of my mongoDB collections","fancy_title":"I see triplicates of my mongoDB collections","slug":"i-see-triplicates-of-my-mongodb-collections","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2015-12-14T13:33:03.426Z","last_posted_at":"2015-12-17T18:40:05.487Z","bumped":true,"bumped_at":"2015-12-17T18:40:05.487Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":97,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"MarkLaFay","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":71},{"extras":null,"description":"Frequent Poster","user_id":14}]},{"id":140,"title":"Google Analytics plugin","fancy_title":"Google Analytics plugin","slug":"google-analytics-plugin","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-12-15T13:00:55.644Z","last_posted_at":"2015-12-15T13:00:55.705Z","bumped":true,"bumped_at":"2015-12-15T13:00:55.705Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":105,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"fimp","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":73}]},{"id":138,"title":"With-mongo-connection failed: bad connection details:","fancy_title":"With-mongo-connection failed: bad connection details:","slug":"with-mongo-connection-failed-bad-connection-details","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-12-14T17:28:11.041Z","last_posted_at":"2015-12-14T17:28:11.111Z","bumped":true,"bumped_at":"2015-12-14T17:28:11.111Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":56,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"MarkLaFay","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":71}]},{"id":133,"title":"\"We couldn't understand your question.\" when I query mongoDB","fancy_title":"“We couldn’t understand your question.” when I query mongoDB","slug":"we-couldnt-understand-your-question-when-i-query-mongodb","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2015-12-11T17:38:30.576Z","last_posted_at":"2015-12-14T13:31:26.395Z","bumped":true,"bumped_at":"2015-12-14T13:31:26.395Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":107,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"MarkLaFay","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":71},{"extras":null,"description":"Frequent Poster","user_id":72}]},{"id":129,"title":"My bar charts are all thin","fancy_title":"My bar charts are all thin","slug":"my-bar-charts-are-all-thin","posts_count":4,"reply_count":1,"highest_post_number":4,"image_url":"/uploads/default/original/1X/41bcf3b2a00dc7cfaff01cb3165d35d32a85bf1d.png","created_at":"2015-12-09T22:09:56.394Z","last_posted_at":"2015-12-11T19:00:45.289Z","bumped":true,"bumped_at":"2015-12-11T19:00:45.289Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":116,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"mhjb","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":53},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":106,"title":"What is the expected return order of columns for graphing results when using raw SQL?","fancy_title":"What is the expected return order of columns for graphing results when using raw SQL?","slug":"what-is-the-expected-return-order-of-columns-for-graphing-results-when-using-raw-sql","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2015-11-24T19:07:14.561Z","last_posted_at":"2015-12-11T17:04:14.149Z","bumped":true,"bumped_at":"2015-12-11T17:04:14.149Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":153,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"jbwiv","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":58},{"extras":null,"description":"Frequent Poster","user_id":14}]},{"id":131,"title":"Set site url from admin panel","fancy_title":"Set site url from admin panel","slug":"set-site-url-from-admin-panel","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-12-10T06:22:46.042Z","last_posted_at":"2015-12-10T19:12:57.449Z","bumped":true,"bumped_at":"2015-12-10T19:12:57.449Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":77,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":70},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":127,"title":"Internationalization (i18n)","fancy_title":"Internationalization (i18n)","slug":"internationalization-i18n","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-12-08T16:55:37.397Z","last_posted_at":"2015-12-09T16:49:55.816Z","bumped":true,"bumped_at":"2015-12-09T16:49:55.816Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":85,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"agilliland","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":69},{"extras":"latest","description":"Most Recent Poster","user_id":14}]},{"id":109,"title":"Returning raw data with no filters always returns We couldn't understand your question","fancy_title":"Returning raw data with no filters always returns We couldn’t understand your question","slug":"returning-raw-data-with-no-filters-always-returns-we-couldnt-understand-your-question","posts_count":3,"reply_count":1,"highest_post_number":3,"image_url":null,"created_at":"2015-11-25T21:35:01.315Z","last_posted_at":"2015-12-09T10:26:12.255Z","bumped":true,"bumped_at":"2015-12-09T10:26:12.255Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":133,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"bencarter78","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":60},{"extras":null,"description":"Frequent Poster","user_id":14}]},{"id":103,"title":"Support for Cassandra?","fancy_title":"Support for Cassandra?","slug":"support-for-cassandra","posts_count":5,"reply_count":1,"highest_post_number":5,"image_url":null,"created_at":"2015-11-20T06:45:31.741Z","last_posted_at":"2015-12-09T03:18:51.274Z","bumped":true,"bumped_at":"2015-12-09T03:18:51.274Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":169,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"vikram","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":55},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":128,"title":"Mongo query with Date breaks [solved: Mongo 3.0 required]","fancy_title":"Mongo query with Date breaks [solved: Mongo 3.0 required]","slug":"mongo-query-with-date-breaks-solved-mongo-3-0-required","posts_count":5,"reply_count":0,"highest_post_number":5,"image_url":null,"created_at":"2015-12-08T18:30:56.562Z","last_posted_at":"2015-12-08T21:03:02.421Z","bumped":true,"bumped_at":"2015-12-08T21:03:02.421Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":102,"like_count":1,"has_summary":false,"archetype":"regular","last_poster_username":"edchan77","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":68},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":23,"title":"Can this connect to MS SQL Server?","fancy_title":"Can this connect to MS SQL Server?","slug":"can-this-connect-to-ms-sql-server","posts_count":7,"reply_count":1,"highest_post_number":7,"image_url":null,"created_at":"2015-10-21T18:52:37.987Z","last_posted_at":"2015-12-07T17:41:51.609Z","bumped":true,"bumped_at":"2015-12-07T17:41:51.609Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":367,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":9},{"extras":null,"description":"Frequent Poster","user_id":23},{"extras":null,"description":"Frequent Poster","user_id":3},{"extras":null,"description":"Frequent Poster","user_id":50},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":121,"title":"Cannot restart metabase in docker","fancy_title":"Cannot restart metabase in docker","slug":"cannot-restart-metabase-in-docker","posts_count":5,"reply_count":1,"highest_post_number":5,"image_url":null,"created_at":"2015-12-04T21:28:58.137Z","last_posted_at":"2015-12-04T23:02:00.488Z","bumped":true,"bumped_at":"2015-12-04T23:02:00.488Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":96,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":66},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":85,"title":"Edit Max Rows Count","fancy_title":"Edit Max Rows Count","slug":"edit-max-rows-count","posts_count":4,"reply_count":2,"highest_post_number":4,"image_url":null,"created_at":"2015-11-11T23:46:52.917Z","last_posted_at":"2015-11-24T01:01:14.569Z","bumped":true,"bumped_at":"2015-11-24T01:01:14.569Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":169,"like_count":1,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":34},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":96,"title":"Creating charts by querying more than one table at a time","fancy_title":"Creating charts by querying more than one table at a time","slug":"creating-charts-by-querying-more-than-one-table-at-a-time","posts_count":6,"reply_count":4,"highest_post_number":6,"image_url":null,"created_at":"2015-11-17T11:20:18.442Z","last_posted_at":"2015-11-21T02:12:25.995Z","bumped":true,"bumped_at":"2015-11-21T02:12:25.995Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":217,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":51},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":90,"title":"Trying to add RDS postgresql as the database fails silently","fancy_title":"Trying to add RDS postgresql as the database fails silently","slug":"trying-to-add-rds-postgresql-as-the-database-fails-silently","posts_count":4,"reply_count":2,"highest_post_number":4,"image_url":null,"created_at":"2015-11-14T23:45:02.967Z","last_posted_at":"2015-11-21T01:08:45.915Z","bumped":true,"bumped_at":"2015-11-21T01:08:45.915Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":162,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":46},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":17,"title":"Deploy to Heroku isn't working","fancy_title":"Deploy to Heroku isn’t working","slug":"deploy-to-heroku-isnt-working","posts_count":9,"reply_count":3,"highest_post_number":9,"image_url":null,"created_at":"2015-10-21T16:42:03.096Z","last_posted_at":"2015-11-20T18:34:14.044Z","bumped":true,"bumped_at":"2015-11-20T18:34:14.044Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":332,"like_count":2,"has_summary":false,"archetype":"regular","last_poster_username":"agilliland","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":5},{"extras":null,"description":"Frequent Poster","user_id":3},{"extras":null,"description":"Frequent Poster","user_id":11},{"extras":null,"description":"Frequent Poster","user_id":25},{"extras":"latest","description":"Most Recent Poster","user_id":14}]},{"id":100,"title":"Can I use DATEPART() in SQL queries?","fancy_title":"Can I use DATEPART() in SQL queries?","slug":"can-i-use-datepart-in-sql-queries","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-11-17T23:15:58.033Z","last_posted_at":"2015-11-18T00:19:48.763Z","bumped":true,"bumped_at":"2015-11-18T00:19:48.763Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":112,"like_count":1,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":53},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":98,"title":"Feature Request: LDAP Authentication","fancy_title":"Feature Request: LDAP Authentication","slug":"feature-request-ldap-authentication","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-11-17T17:22:44.484Z","last_posted_at":"2015-11-17T17:22:44.577Z","bumped":true,"bumped_at":"2015-11-17T17:22:44.577Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":97,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"j_at_svg","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":52}]},{"id":87,"title":"Migrating from internal H2 to Postgres","fancy_title":"Migrating from internal H2 to Postgres","slug":"migrating-from-internal-h2-to-postgres","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-11-12T14:36:06.745Z","last_posted_at":"2015-11-12T18:05:10.796Z","bumped":true,"bumped_at":"2015-11-12T18:05:10.796Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":111,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":42},{"extras":"latest","description":"Most Recent Poster","user_id":1}]}]}} `) func NewLargePayload() *LargePayload { dsUsers := DSUsers{} dsTopics := DSTopics{} for i := 0; i < 100; i++ { str := "test" + strconv.Itoa(i) dsUsers = append( dsUsers, &DSUser{ Username: str, }, ) dsTopics = append( dsTopics, &DSTopic{ Id: i, Slug: str, }, ) } return &LargePayload{ Users: dsUsers, Topics: &DSTopicsList{ Topics: dsTopics, MoreTopicsUrl: "http://test.com", }, } } func NewLargePayloadEasyJson() *LargePayloadEasyJson { dsUsers := DSUsers{} dsTopics := DSTopics{} for i := 0; i < 100; i++ { str := "test" + strconv.Itoa(i) dsUsers = append( dsUsers, &DSUser{ Username: str, }, ) dsTopics = append( dsTopics, &DSTopic{ Id: i, Slug: str, }, ) } return &LargePayloadEasyJson{ Users: dsUsers, Topics: &DSTopicsList{ Topics: dsTopics, MoreTopicsUrl: "http://test.com", }, } } var LargeSliceEscapedString = []byte("[" + strings.Repeat(",\"simple plain text\\r\\n\"", 10000)[1:] + "]") golang-github-goccy-go-json-0.10.3/benchmarks/large_payload_easyjson.go000066400000000000000000000156751463555276600262210ustar00rootroot00000000000000// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package benchmark import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjsonD519278DecodeBenchmark(in *jlexer.Lexer, out *LargePayloadEasyJson) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "Users": if in.IsNull() { in.Skip() out.Users = nil } else { in.Delim('[') if out.Users == nil { if !in.IsDelim(']') { out.Users = make(DSUsers, 0, 8) } else { out.Users = DSUsers{} } } else { out.Users = (out.Users)[:0] } for !in.IsDelim(']') { var v1 *DSUser if in.IsNull() { in.Skip() v1 = nil } else { if v1 == nil { v1 = new(DSUser) } easyjsonD519278DecodeBenchmark1(in, v1) } out.Users = append(out.Users, v1) in.WantComma() } in.Delim(']') } case "Topics": if in.IsNull() { in.Skip() out.Topics = nil } else { if out.Topics == nil { out.Topics = new(DSTopicsList) } easyjsonD519278DecodeBenchmark2(in, out.Topics) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonD519278EncodeBenchmark(out *jwriter.Writer, in LargePayloadEasyJson) { out.RawByte('{') first := true _ = first { const prefix string = ",\"Users\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Users == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { out.RawString("null") } else { out.RawByte('[') for v2, v3 := range in.Users { if v2 > 0 { out.RawByte(',') } if v3 == nil { out.RawString("null") } else { easyjsonD519278EncodeBenchmark1(out, *v3) } } out.RawByte(']') } } { const prefix string = ",\"Topics\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Topics == nil { out.RawString("null") } else { easyjsonD519278EncodeBenchmark2(out, *in.Topics) } } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v LargePayloadEasyJson) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjsonD519278EncodeBenchmark(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v LargePayloadEasyJson) MarshalEasyJSON(w *jwriter.Writer) { easyjsonD519278EncodeBenchmark(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *LargePayloadEasyJson) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjsonD519278DecodeBenchmark(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *LargePayloadEasyJson) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjsonD519278DecodeBenchmark(l, v) } func easyjsonD519278DecodeBenchmark2(in *jlexer.Lexer, out *DSTopicsList) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "Topics": if in.IsNull() { in.Skip() out.Topics = nil } else { in.Delim('[') if out.Topics == nil { if !in.IsDelim(']') { out.Topics = make(DSTopics, 0, 8) } else { out.Topics = DSTopics{} } } else { out.Topics = (out.Topics)[:0] } for !in.IsDelim(']') { var v4 *DSTopic if in.IsNull() { in.Skip() v4 = nil } else { if v4 == nil { v4 = new(DSTopic) } easyjsonD519278DecodeBenchmark3(in, v4) } out.Topics = append(out.Topics, v4) in.WantComma() } in.Delim(']') } case "MoreTopicsUrl": out.MoreTopicsUrl = string(in.String()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonD519278EncodeBenchmark2(out *jwriter.Writer, in DSTopicsList) { out.RawByte('{') first := true _ = first { const prefix string = ",\"Topics\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Topics == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { out.RawString("null") } else { out.RawByte('[') for v5, v6 := range in.Topics { if v5 > 0 { out.RawByte(',') } if v6 == nil { out.RawString("null") } else { easyjsonD519278EncodeBenchmark3(out, *v6) } } out.RawByte(']') } } { const prefix string = ",\"MoreTopicsUrl\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.MoreTopicsUrl)) } out.RawByte('}') } func easyjsonD519278DecodeBenchmark3(in *jlexer.Lexer, out *DSTopic) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "Id": out.Id = int(in.Int()) case "Slug": out.Slug = string(in.String()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonD519278EncodeBenchmark3(out *jwriter.Writer, in DSTopic) { out.RawByte('{') first := true _ = first { const prefix string = ",\"Id\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Id)) } { const prefix string = ",\"Slug\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Slug)) } out.RawByte('}') } func easyjsonD519278DecodeBenchmark1(in *jlexer.Lexer, out *DSUser) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "Username": out.Username = string(in.String()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjsonD519278EncodeBenchmark1(out *jwriter.Writer, in DSUser) { out.RawByte('{') first := true _ = first { const prefix string = ",\"Username\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Username)) } out.RawByte('}') } golang-github-goccy-go-json-0.10.3/benchmarks/medium_payload.go000066400000000000000000000156061463555276600244660ustar00rootroot00000000000000package benchmark import "github.com/francoispqt/gojay" // Response from Clearbit API. Size: 2.4kb var MediumFixture = []byte(`{ "person": { "id": "d50887ca-a6ce-4e59-b89f-14f0b5d03b03", "name": { "fullName": "Leonid Bugaev", "givenName": "Leonid", "familyName": "Bugaev" }, "email": "leonsbox@gmail.com", "gender": "male", "location": "Saint Petersburg, Saint Petersburg, RU", "geo": { "city": "Saint Petersburg", "state": "Saint Petersburg", "country": "Russia", "lat": 59.9342802, "lng": 30.3350986 }, "bio": "Senior engineer at Granify.com", "site": "http://flickfaver.com", "avatar": "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/d50887ca-a6ce-4e59-b89f-14f0b5d03b03", "employment": { "name": "www.latera.ru", "title": "Software Engineer", "domain": "gmail.com" }, "facebook": { "handle": "leonid.bugaev" }, "github": { "handle": "buger", "id": 14009, "avatar": "https://avatars.githubusercontent.com/u/14009?v=3", "company": "Granify", "blog": "http://leonsbox.com", "followers": 95, "following": 10 }, "twitter": { "handle": "flickfaver", "id": 77004410, "bio": null, "followers": 2, "following": 1, "statuses": 5, "favorites": 0, "location": "", "site": "http://flickfaver.com", "avatar": null }, "linkedin": { "handle": "in/leonidbugaev" }, "googleplus": { "handle": null }, "angellist": { "handle": "leonid-bugaev", "id": 61541, "bio": "Senior engineer at Granify.com", "blog": "http://buger.github.com", "site": "http://buger.github.com", "followers": 41, "avatar": "https://d1qb2nb5cznatu.cloudfront.net/users/61541-medium_jpg?1405474390" }, "klout": { "handle": null, "score": null }, "foursquare": { "handle": null }, "aboutme": { "handle": "leonid.bugaev", "bio": null, "avatar": null }, "gravatar": { "handle": "buger", "urls": [ ], "avatar": "http://1.gravatar.com/avatar/f7c8edd577d13b8930d5522f28123510", "avatars": [ { "url": "http://1.gravatar.com/avatar/f7c8edd577d13b8930d5522f28123510", "type": "thumbnail" } ] }, "fuzzy": false }, "company": null }`) type CBAvatar struct { Url string } func (m *CBAvatar) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "avatars": return dec.AddString(&m.Url) } return nil } func (m *CBAvatar) NKeys() int { return 1 } func (m *CBAvatar) MarshalJSONObject(enc *gojay.Encoder) { enc.AddStringKey("url", m.Url) } func (m *CBAvatar) IsNil() bool { return m == nil } type Avatars []*CBAvatar func (t *Avatars) UnmarshalJSONArray(dec *gojay.Decoder) error { avatar := CBAvatar{} *t = append(*t, &avatar) return dec.AddObject(&avatar) } func (m *Avatars) MarshalJSONArray(enc *gojay.Encoder) { for _, e := range *m { enc.AddObject(e) } } func (m *Avatars) IsNil() bool { return m == nil } type CBGravatar struct { Avatars Avatars } func (m *CBGravatar) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "avatars": return dec.AddArray(&m.Avatars) } return nil } func (m *CBGravatar) NKeys() int { return 1 } func (m *CBGravatar) MarshalJSONObject(enc *gojay.Encoder) { enc.AddArrayKey("avatars", &m.Avatars) } func (m *CBGravatar) IsNil() bool { return m == nil } type CBGithub struct { Followers int } func (m *CBGithub) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "followers": return dec.AddInt(&m.Followers) } return nil } func (m *CBGithub) NKeys() int { return 1 } func (m *CBGithub) MarshalJSONObject(enc *gojay.Encoder) { enc.AddIntKey("followers", m.Followers) } func (m *CBGithub) IsNil() bool { return m == nil } type CBName struct { FullName string `json:"fullName"` } func (m *CBName) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "fullName": return dec.AddString(&m.FullName) } return nil } func (m *CBName) NKeys() int { return 1 } func (m *CBName) MarshalJSONObject(enc *gojay.Encoder) { enc.AddStringKey("fullName", m.FullName) } func (m *CBName) IsNil() bool { return m == nil } type CBPerson struct { Name *CBName `json:"name"` Github *CBGithub `json:"github"` Gravatar *CBGravatar } func (m *CBPerson) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "name": m.Name = &CBName{} return dec.AddObject(m.Name) case "github": m.Github = &CBGithub{} return dec.AddObject(m.Github) case "gravatar": m.Gravatar = &CBGravatar{} return dec.AddObject(m.Gravatar) } return nil } func (m *CBPerson) NKeys() int { return 3 } func (m *CBPerson) MarshalJSONObject(enc *gojay.Encoder) { enc.AddObjectKey("name", m.Name) enc.AddObjectKey("github", m.Github) enc.AddObjectKey("gravatar", m.Gravatar) } func (m *CBPerson) IsNil() bool { return m == nil } type MediumPayload struct { Person *CBPerson `json:"person"` Company string `json:"company"` } //easyjson:json type MediumPayloadEasyJson struct { Person *CBPerson `json:"person"` Company string `json:"company"` } func (m *MediumPayload) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "person": m.Person = &CBPerson{} return dec.AddObject(m.Person) case "company": dec.AddString(&m.Company) } return nil } func (m *MediumPayload) NKeys() int { return 2 } func (m *MediumPayload) MarshalJSONObject(enc *gojay.Encoder) { enc.AddObjectKey("person", m.Person) // enc.AddStringKey("company", m.Company) } func (m *MediumPayload) IsNil() bool { return m == nil } func NewMediumPayload() *MediumPayload { return &MediumPayload{ Company: "test", Person: &CBPerson{ Name: &CBName{ FullName: "test", }, Github: &CBGithub{ Followers: 100, }, Gravatar: &CBGravatar{ Avatars: Avatars{ &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, }, }, }, } } func NewMediumPayloadEasyJson() *MediumPayloadEasyJson { return &MediumPayloadEasyJson{ Company: "test", Person: &CBPerson{ Name: &CBName{ FullName: "test", }, Github: &CBGithub{ Followers: 100, }, Gravatar: &CBGravatar{ Avatars: Avatars{ &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, &CBAvatar{ Url: "http://test.com", }, }, }, }, } } golang-github-goccy-go-json-0.10.3/benchmarks/medium_payload_easyjson.go000066400000000000000000000206741463555276600264020ustar00rootroot00000000000000// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package benchmark import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjson8ca7813eDecodeBenchmark(in *jlexer.Lexer, out *MediumPayloadEasyJson) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "person": if in.IsNull() { in.Skip() out.Person = nil } else { if out.Person == nil { out.Person = new(CBPerson) } easyjson8ca7813eDecodeBenchmark1(in, out.Person) } case "company": out.Company = string(in.String()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson8ca7813eEncodeBenchmark(out *jwriter.Writer, in MediumPayloadEasyJson) { out.RawByte('{') first := true _ = first { const prefix string = ",\"person\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Person == nil { out.RawString("null") } else { easyjson8ca7813eEncodeBenchmark1(out, *in.Person) } } { const prefix string = ",\"company\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Company)) } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v MediumPayloadEasyJson) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjson8ca7813eEncodeBenchmark(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v MediumPayloadEasyJson) MarshalEasyJSON(w *jwriter.Writer) { easyjson8ca7813eEncodeBenchmark(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *MediumPayloadEasyJson) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjson8ca7813eDecodeBenchmark(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *MediumPayloadEasyJson) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson8ca7813eDecodeBenchmark(l, v) } func easyjson8ca7813eDecodeBenchmark1(in *jlexer.Lexer, out *CBPerson) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "name": if in.IsNull() { in.Skip() out.Name = nil } else { if out.Name == nil { out.Name = new(CBName) } easyjson8ca7813eDecodeBenchmark2(in, out.Name) } case "github": if in.IsNull() { in.Skip() out.Github = nil } else { if out.Github == nil { out.Github = new(CBGithub) } easyjson8ca7813eDecodeBenchmark3(in, out.Github) } case "Gravatar": if in.IsNull() { in.Skip() out.Gravatar = nil } else { if out.Gravatar == nil { out.Gravatar = new(CBGravatar) } easyjson8ca7813eDecodeBenchmark4(in, out.Gravatar) } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson8ca7813eEncodeBenchmark1(out *jwriter.Writer, in CBPerson) { out.RawByte('{') first := true _ = first { const prefix string = ",\"name\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Name == nil { out.RawString("null") } else { easyjson8ca7813eEncodeBenchmark2(out, *in.Name) } } { const prefix string = ",\"github\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Github == nil { out.RawString("null") } else { easyjson8ca7813eEncodeBenchmark3(out, *in.Github) } } { const prefix string = ",\"Gravatar\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Gravatar == nil { out.RawString("null") } else { easyjson8ca7813eEncodeBenchmark4(out, *in.Gravatar) } } out.RawByte('}') } func easyjson8ca7813eDecodeBenchmark4(in *jlexer.Lexer, out *CBGravatar) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "Avatars": if in.IsNull() { in.Skip() out.Avatars = nil } else { in.Delim('[') if out.Avatars == nil { if !in.IsDelim(']') { out.Avatars = make(Avatars, 0, 8) } else { out.Avatars = Avatars{} } } else { out.Avatars = (out.Avatars)[:0] } for !in.IsDelim(']') { var v1 *CBAvatar if in.IsNull() { in.Skip() v1 = nil } else { if v1 == nil { v1 = new(CBAvatar) } easyjson8ca7813eDecodeBenchmark5(in, v1) } out.Avatars = append(out.Avatars, v1) in.WantComma() } in.Delim(']') } default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson8ca7813eEncodeBenchmark4(out *jwriter.Writer, in CBGravatar) { out.RawByte('{') first := true _ = first { const prefix string = ",\"Avatars\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } if in.Avatars == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { out.RawString("null") } else { out.RawByte('[') for v2, v3 := range in.Avatars { if v2 > 0 { out.RawByte(',') } if v3 == nil { out.RawString("null") } else { easyjson8ca7813eEncodeBenchmark5(out, *v3) } } out.RawByte(']') } } out.RawByte('}') } func easyjson8ca7813eDecodeBenchmark5(in *jlexer.Lexer, out *CBAvatar) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "Url": out.Url = string(in.String()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson8ca7813eEncodeBenchmark5(out *jwriter.Writer, in CBAvatar) { out.RawByte('{') first := true _ = first { const prefix string = ",\"Url\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Url)) } out.RawByte('}') } func easyjson8ca7813eDecodeBenchmark3(in *jlexer.Lexer, out *CBGithub) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "Followers": out.Followers = int(in.Int()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson8ca7813eEncodeBenchmark3(out *jwriter.Writer, in CBGithub) { out.RawByte('{') first := true _ = first { const prefix string = ",\"Followers\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Followers)) } out.RawByte('}') } func easyjson8ca7813eDecodeBenchmark2(in *jlexer.Lexer, out *CBName) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "fullName": out.FullName = string(in.String()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson8ca7813eEncodeBenchmark2(out *jwriter.Writer, in CBName) { out.RawByte('{') first := true _ = first { const prefix string = ",\"fullName\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.FullName)) } out.RawByte('}') } golang-github-goccy-go-json-0.10.3/benchmarks/path_test.go000066400000000000000000000006471463555276600234670ustar00rootroot00000000000000package benchmark import ( "testing" gojson "github.com/goccy/go-json" ) func Benchmark_Decode_SmallStruct_UnmarshalPath_GoJson(b *testing.B) { path, err := gojson.CreatePath("$.st") if err != nil { b.Fatal(err) } b.ReportAllocs() for i := 0; i < b.N; i++ { var v int if err := path.Unmarshal(SmallFixture, &v); err != nil { b.Fatal(err) } if v != 1 { b.Fatal("failed to unmarshal path") } } } golang-github-goccy-go-json-0.10.3/benchmarks/slow_reader_test.go000066400000000000000000000035001463555276600250300ustar00rootroot00000000000000package benchmark import ( "bytes" "encoding/json" "fmt" "reflect" "testing" gojson "github.com/goccy/go-json" ) // Benchmark decoding from a slow io.Reader that never fills the buffer completely func Benchmark_Decode_SlowReader_EncodingJson(b *testing.B) { var expected LargePayload if err := json.Unmarshal(LargeFixture, &expected); err != nil { b.Fatal(err) } for _, chunkSize := range [5]int{16384, 4096, 1024, 256, 64} { b.Run(fmt.Sprintf("chunksize %v", chunkSize), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { index = 0 var got LargePayload if err := json.NewDecoder(slowReader{chunkSize: chunkSize}).Decode(&got); err != nil { b.Fatal(err) } if !reflect.DeepEqual(expected, got) { b.Fatalf("failed to decode. expected:[%+v] but got:[%+v]", expected, got) } } }) } } func Benchmark_Decode_SlowReader_GoJson(b *testing.B) { var expected LargePayload if err := json.Unmarshal(LargeFixture, &expected); err != nil { b.Fatal(err) } for _, chunkSize := range []int{16384, 4096, 1024, 256, 64} { b.Run(fmt.Sprintf("chunksize %v", chunkSize), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { index = 0 var got LargePayload if err := gojson.NewDecoder(slowReader{chunkSize: chunkSize}).Decode(&got); err != nil { b.Fatal(err) } if !reflect.DeepEqual(expected, got) { b.Fatalf("failed to decode. expected:[%+v] but got:[%+v]", expected, got) } } }) } } type slowReader struct { chunkSize int } var index int func (s slowReader) Read(p []byte) (n int, err error) { smallBuf := make([]byte, Min(s.chunkSize, len(p))) x := bytes.NewReader(LargeFixture) n, err = x.ReadAt(smallBuf, int64(index)) index += n copy(p, smallBuf) return } func Min(x, y int) int { if x < y { return x } return y } golang-github-goccy-go-json-0.10.3/benchmarks/small_payload.go000066400000000000000000000044301463555276600243070ustar00rootroot00000000000000package benchmark import "github.com/francoispqt/gojay" var SmallFixture = []byte(`{"st": 1,"sid": 486,"tt": "active","gr": 0,"uuid": "de305d54-75b4-431b-adb2-eb6b9e546014","ip": "127.0.0.1","ua": "user_agent","tz": -6,"v": 1}`) // ffjson:skip type SmallPayload struct { St int Sid int Tt string Gr int Uuid string Ip string Ua string Tz int V int } type SmallPayloadFFJson struct { St int Sid int Tt string Gr int Uuid string Ip string Ua string Tz int V int } //easyjson:json type SmallPayloadEasyJson struct { St int Sid int Tt string Gr int Uuid string Ip string Ua string Tz int V int } func (t *SmallPayload) MarshalJSONObject(enc *gojay.Encoder) { enc.AddIntKey("st", t.St) enc.AddIntKey("sid", t.Sid) enc.AddStringKey("tt", t.Tt) enc.AddIntKey("gr", t.Gr) enc.AddStringKey("uuid", t.Uuid) enc.AddStringKey("ip", t.Ip) enc.AddStringKey("ua", t.Ua) enc.AddIntKey("tz", t.Tz) enc.AddIntKey("v", t.V) } func (t *SmallPayload) IsNil() bool { return t == nil } func (t *SmallPayload) UnmarshalJSONObject(dec *gojay.Decoder, key string) error { switch key { case "st": return dec.AddInt(&t.St) case "sid": return dec.AddInt(&t.Sid) case "gr": return dec.AddInt(&t.Gr) case "tz": return dec.AddInt(&t.Tz) case "v": return dec.AddInt(&t.V) case "tt": return dec.AddString(&t.Tt) case "uuid": return dec.AddString(&t.Uuid) case "ip": return dec.AddString(&t.Ip) case "ua": return dec.AddString(&t.Ua) } return nil } func (t *SmallPayload) NKeys() int { return 9 } func NewSmallPayload() *SmallPayload { return &SmallPayload{ St: 1, Sid: 2, Tt: "TestString", Gr: 4, Uuid: "8f9a65eb-4807-4d57-b6e0-bda5d62f1429", Ip: "127.0.0.1", Ua: "Mozilla", Tz: 8, V: 6, } } func NewSmallPayloadEasyJson() *SmallPayloadEasyJson { return &SmallPayloadEasyJson{ St: 1, Sid: 2, Tt: "TestString", Gr: 4, Uuid: "8f9a65eb-4807-4d57-b6e0-bda5d62f1429", Ip: "127.0.0.1", Ua: "Mozilla", Tz: 8, V: 6, } } func NewSmallPayloadFFJson() *SmallPayloadFFJson { return &SmallPayloadFFJson{ St: 1, Sid: 2, Tt: "TestString", Gr: 4, Uuid: "8f9a65eb-4807-4d57-b6e0-bda5d62f1429", Ip: "127.0.0.1", Ua: "Mozilla", Tz: 8, V: 6, } } golang-github-goccy-go-json-0.10.3/benchmarks/small_payload_easyjson.go000066400000000000000000000070461463555276600262300ustar00rootroot00000000000000// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. package benchmark import ( json "encoding/json" easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" ) // suppress unused package warning var ( _ *json.RawMessage _ *jlexer.Lexer _ *jwriter.Writer _ easyjson.Marshaler ) func easyjson21677a1cDecodeBenchmark(in *jlexer.Lexer, out *SmallPayloadEasyJson) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { in.Consumed() } in.Skip() return } in.Delim('{') for !in.IsDelim('}') { key := in.UnsafeString() in.WantColon() if in.IsNull() { in.Skip() in.WantComma() continue } switch key { case "St": out.St = int(in.Int()) case "Sid": out.Sid = int(in.Int()) case "Tt": out.Tt = string(in.String()) case "Gr": out.Gr = int(in.Int()) case "Uuid": out.Uuid = string(in.String()) case "Ip": out.Ip = string(in.String()) case "Ua": out.Ua = string(in.String()) case "Tz": out.Tz = int(in.Int()) case "V": out.V = int(in.Int()) default: in.SkipRecursive() } in.WantComma() } in.Delim('}') if isTopLevel { in.Consumed() } } func easyjson21677a1cEncodeBenchmark(out *jwriter.Writer, in SmallPayloadEasyJson) { out.RawByte('{') first := true _ = first { const prefix string = ",\"St\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.St)) } { const prefix string = ",\"Sid\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Sid)) } { const prefix string = ",\"Tt\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Tt)) } { const prefix string = ",\"Gr\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Gr)) } { const prefix string = ",\"Uuid\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Uuid)) } { const prefix string = ",\"Ip\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Ip)) } { const prefix string = ",\"Ua\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.String(string(in.Ua)) } { const prefix string = ",\"Tz\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.Tz)) } { const prefix string = ",\"V\":" if first { first = false out.RawString(prefix[1:]) } else { out.RawString(prefix) } out.Int(int(in.V)) } out.RawByte('}') } // MarshalJSON supports json.Marshaler interface func (v SmallPayloadEasyJson) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjson21677a1cEncodeBenchmark(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface func (v SmallPayloadEasyJson) MarshalEasyJSON(w *jwriter.Writer) { easyjson21677a1cEncodeBenchmark(w, v) } // UnmarshalJSON supports json.Unmarshaler interface func (v *SmallPayloadEasyJson) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjson21677a1cDecodeBenchmark(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *SmallPayloadEasyJson) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson21677a1cDecodeBenchmark(l, v) } golang-github-goccy-go-json-0.10.3/benchmarks/small_payload_ffjson.go000066400000000000000000000304771463555276600256660ustar00rootroot00000000000000// Code generated by ffjson . DO NOT EDIT. // source: small_payload.go package benchmark import ( "bytes" "fmt" fflib "github.com/pquerna/ffjson/fflib/v1" ) // MarshalJSON marshal bytes to json - template func (j *SmallPayloadFFJson) MarshalJSON() ([]byte, error) { var buf fflib.Buffer if j == nil { buf.WriteString("null") return buf.Bytes(), nil } err := j.MarshalJSONBuf(&buf) if err != nil { return nil, err } return buf.Bytes(), nil } // MarshalJSONBuf marshal buff to json - template func (j *SmallPayloadFFJson) MarshalJSONBuf(buf fflib.EncodingBuffer) error { if j == nil { buf.WriteString("null") return nil } var err error var obj []byte _ = obj _ = err buf.WriteString(`{"St":`) fflib.FormatBits2(buf, uint64(j.St), 10, j.St < 0) buf.WriteString(`,"Sid":`) fflib.FormatBits2(buf, uint64(j.Sid), 10, j.Sid < 0) buf.WriteString(`,"Tt":`) fflib.WriteJsonString(buf, string(j.Tt)) buf.WriteString(`,"Gr":`) fflib.FormatBits2(buf, uint64(j.Gr), 10, j.Gr < 0) buf.WriteString(`,"Uuid":`) fflib.WriteJsonString(buf, string(j.Uuid)) buf.WriteString(`,"Ip":`) fflib.WriteJsonString(buf, string(j.Ip)) buf.WriteString(`,"Ua":`) fflib.WriteJsonString(buf, string(j.Ua)) buf.WriteString(`,"Tz":`) fflib.FormatBits2(buf, uint64(j.Tz), 10, j.Tz < 0) buf.WriteString(`,"V":`) fflib.FormatBits2(buf, uint64(j.V), 10, j.V < 0) buf.WriteByte('}') return nil } const ( ffjtSmallPayloadFFJsonbase = iota ffjtSmallPayloadFFJsonnosuchkey ffjtSmallPayloadFFJsonSt ffjtSmallPayloadFFJsonSid ffjtSmallPayloadFFJsonTt ffjtSmallPayloadFFJsonGr ffjtSmallPayloadFFJsonUuid ffjtSmallPayloadFFJsonIp ffjtSmallPayloadFFJsonUa ffjtSmallPayloadFFJsonTz ffjtSmallPayloadFFJsonV ) var ffjKeySmallPayloadFFJsonSt = []byte("St") var ffjKeySmallPayloadFFJsonSid = []byte("Sid") var ffjKeySmallPayloadFFJsonTt = []byte("Tt") var ffjKeySmallPayloadFFJsonGr = []byte("Gr") var ffjKeySmallPayloadFFJsonUuid = []byte("Uuid") var ffjKeySmallPayloadFFJsonIp = []byte("Ip") var ffjKeySmallPayloadFFJsonUa = []byte("Ua") var ffjKeySmallPayloadFFJsonTz = []byte("Tz") var ffjKeySmallPayloadFFJsonV = []byte("V") // UnmarshalJSON umarshall json - template of ffjson func (j *SmallPayloadFFJson) UnmarshalJSON(input []byte) error { fs := fflib.NewFFLexer(input) return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) } // UnmarshalJSONFFLexer fast json unmarshall - template ffjson func (j *SmallPayloadFFJson) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { var err error currentKey := ffjtSmallPayloadFFJsonbase _ = currentKey tok := fflib.FFTok_init wantedTok := fflib.FFTok_init mainparse: for { tok = fs.Scan() // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) if tok == fflib.FFTok_error { goto tokerror } switch state { case fflib.FFParse_map_start: if tok != fflib.FFTok_left_bracket { wantedTok = fflib.FFTok_left_bracket goto wrongtokenerror } state = fflib.FFParse_want_key continue case fflib.FFParse_after_value: if tok == fflib.FFTok_comma { state = fflib.FFParse_want_key } else if tok == fflib.FFTok_right_bracket { goto done } else { wantedTok = fflib.FFTok_comma goto wrongtokenerror } case fflib.FFParse_want_key: // json {} ended. goto exit. woo. if tok == fflib.FFTok_right_bracket { goto done } if tok != fflib.FFTok_string { wantedTok = fflib.FFTok_string goto wrongtokenerror } kn := fs.Output.Bytes() if len(kn) <= 0 { // "" case. hrm. currentKey = ffjtSmallPayloadFFJsonnosuchkey state = fflib.FFParse_want_colon goto mainparse } else { switch kn[0] { case 'G': if bytes.Equal(ffjKeySmallPayloadFFJsonGr, kn) { currentKey = ffjtSmallPayloadFFJsonGr state = fflib.FFParse_want_colon goto mainparse } case 'I': if bytes.Equal(ffjKeySmallPayloadFFJsonIp, kn) { currentKey = ffjtSmallPayloadFFJsonIp state = fflib.FFParse_want_colon goto mainparse } case 'S': if bytes.Equal(ffjKeySmallPayloadFFJsonSt, kn) { currentKey = ffjtSmallPayloadFFJsonSt state = fflib.FFParse_want_colon goto mainparse } else if bytes.Equal(ffjKeySmallPayloadFFJsonSid, kn) { currentKey = ffjtSmallPayloadFFJsonSid state = fflib.FFParse_want_colon goto mainparse } case 'T': if bytes.Equal(ffjKeySmallPayloadFFJsonTt, kn) { currentKey = ffjtSmallPayloadFFJsonTt state = fflib.FFParse_want_colon goto mainparse } else if bytes.Equal(ffjKeySmallPayloadFFJsonTz, kn) { currentKey = ffjtSmallPayloadFFJsonTz state = fflib.FFParse_want_colon goto mainparse } case 'U': if bytes.Equal(ffjKeySmallPayloadFFJsonUuid, kn) { currentKey = ffjtSmallPayloadFFJsonUuid state = fflib.FFParse_want_colon goto mainparse } else if bytes.Equal(ffjKeySmallPayloadFFJsonUa, kn) { currentKey = ffjtSmallPayloadFFJsonUa state = fflib.FFParse_want_colon goto mainparse } case 'V': if bytes.Equal(ffjKeySmallPayloadFFJsonV, kn) { currentKey = ffjtSmallPayloadFFJsonV state = fflib.FFParse_want_colon goto mainparse } } if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonV, kn) { currentKey = ffjtSmallPayloadFFJsonV state = fflib.FFParse_want_colon goto mainparse } if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonTz, kn) { currentKey = ffjtSmallPayloadFFJsonTz state = fflib.FFParse_want_colon goto mainparse } if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonUa, kn) { currentKey = ffjtSmallPayloadFFJsonUa state = fflib.FFParse_want_colon goto mainparse } if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonIp, kn) { currentKey = ffjtSmallPayloadFFJsonIp state = fflib.FFParse_want_colon goto mainparse } if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonUuid, kn) { currentKey = ffjtSmallPayloadFFJsonUuid state = fflib.FFParse_want_colon goto mainparse } if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonGr, kn) { currentKey = ffjtSmallPayloadFFJsonGr state = fflib.FFParse_want_colon goto mainparse } if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonTt, kn) { currentKey = ffjtSmallPayloadFFJsonTt state = fflib.FFParse_want_colon goto mainparse } if fflib.EqualFoldRight(ffjKeySmallPayloadFFJsonSid, kn) { currentKey = ffjtSmallPayloadFFJsonSid state = fflib.FFParse_want_colon goto mainparse } if fflib.EqualFoldRight(ffjKeySmallPayloadFFJsonSt, kn) { currentKey = ffjtSmallPayloadFFJsonSt state = fflib.FFParse_want_colon goto mainparse } currentKey = ffjtSmallPayloadFFJsonnosuchkey state = fflib.FFParse_want_colon goto mainparse } case fflib.FFParse_want_colon: if tok != fflib.FFTok_colon { wantedTok = fflib.FFTok_colon goto wrongtokenerror } state = fflib.FFParse_want_value continue case fflib.FFParse_want_value: if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { switch currentKey { case ffjtSmallPayloadFFJsonSt: goto handle_St case ffjtSmallPayloadFFJsonSid: goto handle_Sid case ffjtSmallPayloadFFJsonTt: goto handle_Tt case ffjtSmallPayloadFFJsonGr: goto handle_Gr case ffjtSmallPayloadFFJsonUuid: goto handle_Uuid case ffjtSmallPayloadFFJsonIp: goto handle_Ip case ffjtSmallPayloadFFJsonUa: goto handle_Ua case ffjtSmallPayloadFFJsonTz: goto handle_Tz case ffjtSmallPayloadFFJsonV: goto handle_V case ffjtSmallPayloadFFJsonnosuchkey: err = fs.SkipField(tok) if err != nil { return fs.WrapErr(err) } state = fflib.FFParse_after_value goto mainparse } } else { goto wantedvalue } } } handle_St: /* handler: j.St type=int kind=int quoted=false*/ { if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok)) } } { if tok == fflib.FFTok_null { } else { tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) if err != nil { return fs.WrapErr(err) } j.St = int(tval) } } state = fflib.FFParse_after_value goto mainparse handle_Sid: /* handler: j.Sid type=int kind=int quoted=false*/ { if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok)) } } { if tok == fflib.FFTok_null { } else { tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) if err != nil { return fs.WrapErr(err) } j.Sid = int(tval) } } state = fflib.FFParse_after_value goto mainparse handle_Tt: /* handler: j.Tt type=string kind=string quoted=false*/ { { if tok != fflib.FFTok_string && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) } } if tok == fflib.FFTok_null { } else { outBuf := fs.Output.Bytes() j.Tt = string(string(outBuf)) } } state = fflib.FFParse_after_value goto mainparse handle_Gr: /* handler: j.Gr type=int kind=int quoted=false*/ { if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok)) } } { if tok == fflib.FFTok_null { } else { tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) if err != nil { return fs.WrapErr(err) } j.Gr = int(tval) } } state = fflib.FFParse_after_value goto mainparse handle_Uuid: /* handler: j.Uuid type=string kind=string quoted=false*/ { { if tok != fflib.FFTok_string && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) } } if tok == fflib.FFTok_null { } else { outBuf := fs.Output.Bytes() j.Uuid = string(string(outBuf)) } } state = fflib.FFParse_after_value goto mainparse handle_Ip: /* handler: j.Ip type=string kind=string quoted=false*/ { { if tok != fflib.FFTok_string && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) } } if tok == fflib.FFTok_null { } else { outBuf := fs.Output.Bytes() j.Ip = string(string(outBuf)) } } state = fflib.FFParse_after_value goto mainparse handle_Ua: /* handler: j.Ua type=string kind=string quoted=false*/ { { if tok != fflib.FFTok_string && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) } } if tok == fflib.FFTok_null { } else { outBuf := fs.Output.Bytes() j.Ua = string(string(outBuf)) } } state = fflib.FFParse_after_value goto mainparse handle_Tz: /* handler: j.Tz type=int kind=int quoted=false*/ { if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok)) } } { if tok == fflib.FFTok_null { } else { tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) if err != nil { return fs.WrapErr(err) } j.Tz = int(tval) } } state = fflib.FFParse_after_value goto mainparse handle_V: /* handler: j.V type=int kind=int quoted=false*/ { if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok)) } } { if tok == fflib.FFTok_null { } else { tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) if err != nil { return fs.WrapErr(err) } j.V = int(tval) } } state = fflib.FFParse_after_value goto mainparse wantedvalue: return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) wrongtokenerror: return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) tokerror: if fs.BigError != nil { return fs.WrapErr(fs.BigError) } err = fs.Error.ToError() if err != nil { return fs.WrapErr(err) } panic("ffjson-generated: unreachable, please report bug.") done: return nil } golang-github-goccy-go-json-0.10.3/benchmarks/testdata/000077500000000000000000000000001463555276600227475ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/benchmarks/testdata/code.json.gz000066400000000000000000003531601463555276600252030ustar00rootroot00000000000000]o#9r_X߂&rCm-YRZҌ}߯ؒ-V7~fл(i~,U"/*Ͽ/l /_~y.f/?;m^jja!{E~~.i'2_l)/SŌB){i|}9}V|1zrYtVNqo6<܈6l{W&L7Oښ쳾Uڬ:|﵍l}a)#e,#G > ;x+ʒo Mֵz]oCv Pɩv*-)URG.< N9ȭrC lbּ?.46`(aB'F1'>_-)Nz`Nm@溜"_ƶHŕ)> Z* BC &ӂdD-\ If8"K'Lq3:KDX+I8Bqj8(sRa,cH')B Q`hiN؄K 1oO~J_B}6(`dd¸B:ˇh1@P¤:>EA_g#Ø竼ʶ`mWC' dK5b(lsH1a^Hvxc40b}V4!(Lam%BwTj@R3 K7^f&vw0nQ'8*`Rn' tg=BSʏO|cOpTf몜lc5C6LQialf8npO Jԥ ʳY 9F[,,Z{#{^Ygٞ6|ϴ5B)N'ΰę1i=bzn}(phX|!'A$}[.d\oQi h0߃!b$ɍPgdDi !6 -:N ,mQıҝ`e{x7 Adt&  sO5@:i$7t0Ѽb B({c : jmT6L5{"4T D!\<w:iAE%HVi"+4iJX9C9߆vbzA1%>>{@t>NAQ)lRPO9J ̌14Gv ~>Wu6;uFf"@134WJ@PzD:#1G(%[̠OXºUS(C F7(DHdZ?eLKAZRNiy@z *A|}ư˪T#-r,x^:rob-GUš¢ D#Xzǒ0`M0 n\*p G lf!8 -[ҭ 4r$ wdu]d),Pvl) %-x"\m--c+>HNicdN9ƜGGJj]VOIꁆf٬%1kO>cuuo6'6kOT>@ r8Na߰*|%N[⫟cf%FB,܍Fv7м-_p)Nyeez祎Jg9Γ;YCi/bNM\`qFߟEאf HxzoN0N83K9BSU =*vsS-~0k]z|ȡ 0 ވ->(9KL54gxV-*5="Z f F MhZsV^k^!Nztz~= *s GÁ9wl?*ԶI= Uʕ A^:&+\Q^UAP62Bщ3Y|FSLc:F`04`nyw9&<[#`rU"+$,t cqo'k0M34V-Gi-k!Rqo^] DsD-mGe҂D*t%aD<-\gį<'Ə"fjcPʼn! F \eFjEyn\eIALJ0В+z 2>B넛{|Hjh*f@WB9 mj^ctC喡ԣ[%UJCxx|muB/"\ho^L ;Q*˦)tOǛlZȪD{$yW4q|x=J-DMhcs&!/X#ɰhz؁]{W%ZJX_4hh; *m/w9=굠\2:mB~qƄPP@夙-;뫽eb/gTw_7O In)|*) Tm {8jf9.G|$y㞆Nayg8o< ~/oF. #A+3Gim<#cݘޠjVz"xn)L8FOt,9 re忳faO:#ZsezJ^ DKl%=bi߾z%v }!gw>6|nl Eݧ*e uo&q~LOprofnȖqXJ<8КU1;X?])^C!*=}ڛ)Btq[>J[]xg9OYpVSl9S)~;y;ZlFC)#'2'l;NLJPs  'AxafJ:rB|^wxBYg[|6ZЙFRB `LC؜00C!;:In26O)؄U!-n m[8AHM$0 -3% HKFdۣWɺZ+tn [:@0sOt^&38ʅv&NB Wa]˟<!##2֎BCwbri63V]"O *tS:鍫1')?hN%=ΫO*J0 %RX<+J A}v.U(v Ih5FkWxrhƧ,I^-ߞ6ltk2С@MocD i ^ԂJcϗ=N7HD.W_>'y{Ok l7ǬxygiQPM:M$/.s0&ztMB+/,=$y *0Я,[P5V\o;<{'6z4>zQH: KKI [ o!@C t$rcs5ax){ОP¿']!Mc7-^I8US8 tD8FG F 18cUv܄yy,=!ፄ082'A_qҿCъ@=sphf1X6ĭ"aX!s 1om ,7xŲh` :sPHZ 6a(w% %@i}ib?ܤZk6(Do^A'nqS bΊUvOdSFdmG01ymi(h"430ڔY\5Rt:pq:Fpu6X vLel7A|ĵ>>t ހV$p~.CW2iNg? )Wӿ/mv, b f3He"te/8B6r=TZVq x*|#y3О'-WjРXFKHc|_NF8t&79춏& Gs> & j=XVdP:\JFo#<1;XN9=g_o摼Mu{Z3CzkJ3B:<ڭ"9}Vi}<~jTZ[a !n`&O.~DRsUIjq Up]IUvGy 9'W.# f;[؍̇ӿ>M8q~Ltn{fhlT.YThX/(Z[/W[Tﶩq-n˾\o[hSy W7u*.xaa7vִm[mJ>>|>tnhTMH1JѬ'C9]KGW)|@G4B4L"M$ }JٖjGuXsdqZ.M4̪L?D̪'VF &%Tc\3K=lZU_o$&qݸyyY <̯o:R_b]|)V${>Ch$vO8eV&J];vWӱ uj$'cSxޡBЌ[&wɇqg)zKU7ZJ؟`z\09sfeFG[~?/,bI(G7<{$Ųyuq\]C :bnQadJxCcNi~:f'Y_sUێ*^Σ9NBt*f'M\];z8K|5NZ136* tpkuo[r͙*w4T{ }3L281NRrA\wxZ⓺8V.Js7+z}K,ןEnXwJh"aU!Bm<(Tn܏~: ZXP"Tņ_B&0[*.[.oCALA؝=l{ηń[k>4 %'ع~/V)OfXˍ:(5{X?,'gsn?ߋ握͵6~BkĒT?ƨ%4?TAh>0ĭ}xV00PcOU,6U(%Ҍ\o3'^ֻEI"e}&ha0"Lb{twf5϶Wͦ֯koنFcm UWCe7wf_/T4TeA}4w#fb#"! +dw˿~@ [<ݲ)5Cygcլ˨^_F펟~iBC:%pQeYNlI;r:;$ sνR%\1e5<ȃ .y[rju_DhTfYL,]rp]S ;u(&ŴKncMM&ܤ?s)zt_\߿e!$R3n9{I 3b삤B4f>Ă@mݺ.FrebR`r >dGek1dE:* [Iؘ9(%M=fi=WqT̗ŵ?ވ[J#?XabPgV52 {Z/0rՖ < sRC8Rmmvy'oDۿ+orLh8؝h1!f0h5ӣb,"oB' 0U ӏl1/F49*"Q"Tܰ|kt<dΌ7Kss:umD{,n R))npCuV`q=X)^@0.n =xn[@DW FعR8bPoڧe('1hELD`Lm&p$ DQ{9м9 ֊O1P:QH̥?~Qr0T.cOG]NGv[^/P#}ϛOEW/flvVݓzc4+cbiu~8wi4]c_?5E  "\ h;jm2G\F;tof-L,hG~׾8>ؔs=MߝZlc<tjOhV΋f9+娙+H.!<kiCQȊފhӰ7O0QnSu+ Tpf5ncFrr'遄&eKxB0C;(gy î.Ǿ|lHpP 9WL25iߪ#)\Ԫ6YbX@bXMp30iŘƩHfߧ8LO #u1H&r; C \:JH[Nq2dq u UN xބ[!ar뎾i3^a9A$oi{&Lɉ1( hXmSUFNYN@K]Lȟ]eUJZG.7w܀Lj Ǜ0"%x;z Z2ƍ~;c`-ݻ! =t~+)j8AKێ +{VX2}PE5aNC@}."nlRY|B6iji?cgtdmr&ϼ>})Ft֧JL%v6>{ǢzO/Ͼ9|5xDO(゚ogiEg˜rgќ ue,grK<4a>Π*gw$u5Y3~(oA܄_O:?Lԥ-A*~_mU72&;|6yW~,W$YQKVbsO h 3jvT X˼LuLʒ %EPuHb)Ȍv [knfr~C_0 :\Qn,}@ =^߱ܦ ?ռҬ0r`KF$}rzS{kUpO-y~oAއkoׇbZ~\M(>W{1^GzC:8/Ns'ɒl9Ug[ۼ>vNO(N-<-!ъamv; -?#t*((L*$*! soeIc/6 /bN:Qbſ^Oδ?}۞{4vI㇗ {=(Zz  N{{!uj1M\lS;Z~%ɮp !yKCp6X33TnpǸ #VdPOjm-6|^VfkT,fiwmE #X.zÊ;%Lm}֟MuIaqGLh-9VdBX@0Fz$e` eN%$Vɻ0'>Ah'r5Tc$$ddq DyMM f+xE#5Si CS߇+#9,+Pgg0Xvz&^O\$}`D v\+GĞa3rLW}5!1d"% ;bAnx͛΋8W l`C }M8\%"Hsp^ipnE.,tv r'jU&*WqNsEP F4 lbޔA"ӧVCp9I";,ʝaxڻR H<-&M11ļRRʾ@5{3[XX6dJ-FAS1`c(2eϼ>hYh!!7Oe0]L!f- _{Nʗ<]Sxx6`XPT@P}A Qg{'0էj`X VKxV9)/ ,'Rb sJ:z>b3~XLòQuR)DB;hK/ mS=th0ˆK;t+"zØgt 8Cx "J$ `*&b <*f]j}HY>pC7#M3X@te(2_%SEd85̒^$nת&\̛7ؘw~RGwP)= ;[Z/rUOˬW@mHM!܇.xA2NZJGQJV#mfܰk^?LOb= =im~VC2F [ZgnA[yìηV 3i'.w5ݽ}(:M(VyHh,hQ/&MhVkCxSĕ=n41 fiڵm<" VvFm"LŚA 0%'EK8w:y.+84+QD:E={O7-xY0N;^+ؖrs>0d 8ۆOIؖg vYm l U@b3_gOQz.Uw~R)@BP4=Q΃''t9C!r h$IY %Ӱj\@ LZ2-1=:OdF/ */kFZwA aCX==|5ƤW6f$y:"^$4$~~S,5;_"PB$tX+^K6^t3Z\T!l{qmin;4SB.C}Mte{CUYh zlؿ|tn&v+m]ye.9+x_! Pאk @rR=ɐMhTr%]IXI23N 974WLvT? 𒓶@^ Hkw>SzܡRGh1<+` w%]]מ,6 =H D)Q`!0BpILhd%}~#ZjUN>ᆃヌI(`KK(C%20`!Vu8Gt؋fzBf21آ-5nB iτ KS|4jC %6CZ<: FZb5Y>UrXVɃ/ +HvB_iJ_G|uM Wƀ0veS̈́w),ꦾ%fzƳr!\k`ch-~KH{Dhr6>|+Ψ$d6ɩd%ZfLZSMR@ DZdc{6n !W9<=L 5>|\"(`=6wn3;y5,z<۬`,cX c2 "_<5 )„(Dsj"x1ti^c.ae</(]3Х-aK GHm1fx( dk11_/΋6/FU1p0셩B )hWl3K5SN( ɋ"JMY0f'8۾xOD-$+CN"E'QEVcK#B,gH=%H@/A#~4#Ym8U0rB!5 D:7%Vjb0<@D ʥFp4k(h8'E=eiՊjӵsJ-倘;:iidtEzBe%^}At<2U-zxC~9>̪nyBQY7y缤!ړnwauua`הhtƢ:3W8:J5Gm-GU5HKgܞ.Ss i\wTMvDU߹6KXqõfeOtr[U[ ax%ʝS JJ>Iejle㢘8dxՇ#;UO[g)|ڶEi' O(J  >qVp %|h/!W!m-V~m@`Ǫ}6iiWY|Fh\( EPt;K<$x~js$,1 J+|Ebie(1<( W{զC hCL+$S-e5ҥcavUifա\|g-H,Tw\܏ɧaܣk<"fOv<^c%@{Rt@n<$(c0n&AMH:7Z9E1;d|*J(kx3#͹a$ft GDr٩p7ʙl KRu=>wY`~Tx/ˑYvQڂ(0각SA1YE>x\C'uz4aU cL[H_\WP}U3Hmșz>q؂|C͋@HBN@ζ]}Yokp~u Y MFbdǤeT=Wy O '$b`PSZg+HS1ǦRea ] XāpݹC|q3 s'TxSucvHm M6+R*]2 Lq"ȕtV;K2$]3BfP|qu٨147PMJl@éO ,:Eŵ>ոlЮ3<{qYCVX2p{0ӝ360{Ug9yV eeqʍj*J`YT:"WU1Х-Y0,::Чʯ-˓*$FX(j10~|tE4!tȦsb/_w5:XD 8521"ϕ }i $^0@@i1z?Y7`i-p8Qwmz?r3ye3«SWL(ϣEac$^VC?KhH1 X?da)F<)b/JG[ <"ob,KS?X@q,@pC.<} jaJ)/޿eïN8ZHgEi8ӹ&QyQV<]NaF ZNM!4~uRV"4>#Q>KU=a+- Ɍݘ@ڴ}>ǯo&m̻fu1 cp`7$Ԃ"dQ9a5¿w8 8&'$+Vru 5RrHK-]]=7zvډrmF-0 az]?Ť_@9uּ;lgu4 U7dTMn,5`s6;YS덖ZVW Li<{^|$ Ȉ/CRcr f#֑R*Ԕ>,1ХgJYBIW2r}SCi,mb$&fToUyT|}FoR5o0l+$ ]p c:! >:XS<ڷ%@p„cf"EeD5HCAhĻPûxB2e'1֟M#0ʖCZF`zlP&O*Z,4XP홬B ,LbC1s4Q$bDlֽD^qܽRzaVp1v V k%4dv 0̔B' g[ K%Gah%T nD)eu5Fsv [Emn'GH|?DbK =V d: mKitXpsi/e>\ OCM@(=ITs' #iBbs@9 Փ<,MHql7\ #˷f=IEZ-6RWRP kbm]d!I[Ґ$2¦\m:al&k:Dѭ/&ӈ5N@wsla,D)+p#u VZ;6MF`$LnЍ @(-Ҕ^uKЪ,J',v>ߝ& ЅQ~ RA"݃#Ia9wEu4^V_u cU Yfw:B^TM/dfb}pE1D-b>yLK"6{PEApdg YLzZ:\szԠ#S@#>pbuPX<`i5S'3LI01ԙӾpdD# 0 mzG`#4&Iu A8ޕ$׏}Q`q׀U!3wQZc!մva+r%ZB` T ]_+bPpay/(p)^los 8j: `'t 7^CpxP-P+(e]ف/0oOO[.RŦjNh+{4򇍬7GATFϲ~6:6H U |5T͜s"T>I ,)U>ʗdUErjmXrTo\', ,WaN0 ޗ\Nu"W"D,Ebfa fID~yn r۞wTgN)pEXkvhf/mv'5A:-X&P{M"hneRm$ޘ>Dzp ̮Ƹ<^ f K/F]MUh¿X]lEV,Pkc! e dEIE*AMrvp.™$,4C7ig:EpWU$!v\>YuDA2Pa|[,vE<@ZؒhLΨ4|WչO'pEL+?hwM Lun/(>8\tm>˶h諳]{'>neY] Q_tiYxN'~Io}`n-v<ݕUӂՉ˻}7UE4 ALz>9cuq᝛(̼2?EsiX`ҫ<=* VYiװTq?:[~mupb6Vˆqڕ)L-"xd4Xa`\s2&^9׶{sǐc5,# ƔqWyqAɿ!w0l HOaiHcSh7SL׶0t/X҇:QIhѩ$_vUu%ޣU DBx ΄zo%Y*$RqXk9`V- _Vq'\^A€|fxw1I W6؈&cY0c-4p1sk8HT,,As.R!fDAuu cSti$Zw)R=Hb3yI:eA]+!ڵ,֍>ThRD!|]UcM y<;Osw܍5_p4t0&,iahyZTY0lj8"28`z1Gp[t-WP`(a># ]/һ";5pXg!N`Sڝx=i:`FO[{LԙFF5BnI'{7BQ~ aWpe0`-)bX!4T˜.3cjl=6݌Z\|0@Nm.GØ|~mrWѼ:lU=UxDXdi*kCrR@7<}0Y%$344vt `?s] H+%+bcR/eIkGl?A LYj1D|2Wu1Y,aHP cؑr[tRz=P^T-gDJ13pL9Ӂ|ODL)Uu)Mb͈aI ^0 7wלJSci袲F{y>O']%B<$MߏB =k3,]vg'(G[HuYNCr3yA#k/ _ z_w-Q(Tlb]O)Z\vꥩE7vr|Ju8%\>?ST=;ϜJw/I~WGWe!\]P@~I:`SyYȵf. ] c S˚qjOdOn#rTeW W&ƴ4$^ƔtnjK0͉p,||vEψۡo r2$E1zjC%Uʮ]Yb]VSf K9^M45R[ǘ%cK̗ Q=S}(p(DtTlVl~b1'!$wDj΋ Xq4t~Ӑi; uy5^"&JK 0o@,ic?& dGXLR *K ٲGI$oTUNk@%qDJSZ#k=]P!"065תN*/v2:_uT{ k<[T](B$SX2$ nl2niq*3|Ə܉S:4"B́mf5Ҡb]dҍ-zy2m emb[956v?]&@9%f~)c~6tzka,wLL?}- ]cѭ:7Nvڹĉa:+s1}Uct )zDel~?DxeP)a6fC-(k`i RGd_!y-obB0M.AUE"yȔ>NEAhhzj5Giζ}!(kDe?SNߔ %4fDjl ÒY ufE!X+^% Jwלp"`CQ@[+ ,uP?> >o`RjԹ_JTyeE,GsJFYDXوveїC lD?Z)rl,4zx j8Eyb ɰ3m0I75eMݺe' .It x%#:_LcaSu)4z]W\B!UzNS,Y.c1]hſ?}}A'ވ,<&Fl, \HD5N{BDt M`% FXEPd~_ aDB4;boI;1TQIXUH gL{YY+i}&M[nI<փ^?_x,lwrrۼ#2WĔY. >reVxls9RM*U(6ϥ `9R@#.31yjb"!d ,k3^*BI =枈!p~ND`{I5d$tEPa)fW,! oHh^P $GvFcny8rvi3э0&1U/Ѕ4"<>Ank!٫8%| 7*ֻMyE%Y .z]v8%nIƎhlfOsuX ۖ|.1\^֏M74-w]iP). I\~epfCG㰨:+ Yo%S&Dj&J$4tD,r">ff+ݫrwL-8 uWf#a ^E cS ۢB`SXQ#U%-[4ofSdK1aI ʰoZ4d`ؐ=[-N:T`fq–m4U7s Owxg& I (oH٩].GCԯ?[4 "lh^^'RXTdy Ǔ詫\SuWC8(4}=(qQ:Bp %G=`'KN[ +p8ܦ-lv,}H':*-Yk!@%z?w9\}bAM݉}+ xL&E(!JCosl2#C,bSNTIs2$J&q0ME̓/h}S MuDݱ<$㱟g>=$k1,rmAܬ[e̴z"1gΰn/n?1ВY̖ʌZ5y1ȋĦFsHtyW4QPk &R*"B璧 SPzEKYU*D7HA:D9K@jx8 "<PB=ӆp ahcWD'Fյ0+?Vӗ;{ܒrAqL1^T ]RۗX@g:4Y]o 8 h' BZ6N [AH>&b!U8Yˮݚ VPdIL0ͫ"D9^3e|,PLX7yi08d*R\[X}(73I,KKg`%Cvǔĥyp0gQ09O"rO>դ 1&B9FDJ˲jm; 9S!`[I?ĴdU>C9DJm>4&Y>{5+ @S͖D9LRlPsšt_ ѭAx~lH^nEDVTy':֞/ cJB\8+OӼJPyjL&b$2W.K%=e5Y7-R{$Z*ίv=P-ߌ9*`ј.*AD~iv;~Ⱦ˗w8GPEH|cmGVE#a/_(-b/֨Lsrx2bdtcT+ͮm* VaHcT %*fDVz`js1jKyZM_h}}hYdO8őkuS031\sf6^0`0V lyu{tUZJC=~lj<=p\ NheŠUV"8 N6mDQwP4!²ƅz8@צVY/cu }]I1aL͐HꬫUn ]Η%kNcU'>_tk[.jqS]&*3H\qX1cy0xoL& l6xkpRA~l|s+NWi$̤T~Q$rpjrq ҵcNx/C[FxWaK"C#y%|'p9zԚeMbN,f`k"`S%]z_SϿٞD4:G,HxXQKG\L%Li#! ]V}& }I&mj??U%0Asj>kM`,3 5j/E Ae3rZ( EflYM+KH$JB6[(xNA44Ɂŷpť>Xz3H>E{[O1{i?F;^X`}5˲`ms{,"(UayYQQ%#Nfv`=`Dy\gžq8@0VT|boJYt[71jI!<_M6itLI@Siu5NwޜGBRvND^B E`!۴NiG/I6o6E:O]}ܧERju(w`s󏉌Q6Jecaj6+HeUuH3ٯyQ_V>`:I_4/S"N"vZ*\=\_j{d6!]<_)ͳ~-kYϬnM5YZoe8H'tMYm=uP6!I`i^-vm>fX>s仴~O h>`4>ok/k =Lmet|oYyw?rZXG6?| 6QU@lW٦hX5?D X{DY]Wف'޼[Pu4>p\31/cIybHPx~sU~x: w/Ob<HlwF+wdɆ]F0C'`ʀ}֛~>Tuzx'OG@DS)Y09ygaHM{R .rs͏{?Ygp:AӦ8n!i?`zJܡ)ˊQ< !3aG9W8'2@+o;d h6(A-;HHʛh[lb{`;O L,aF'gYo6~UρtO,idU RwStƳHnwyq8DBk/;Iݣι2\B5]ƗQ~O2.lJE>F; %,\ֻ wbg|5)/ /u5Hއv_N3ϞW w'5߳Ou?ΡlCZcbHN V97&];>C/@`:@o`X@?\9U,6`v\ {e\u: /9D\ڃ]kɓէ'ӝ,%[ c`=1 Is( :GrrM/~0q^;4=%CWs\!+ hPe% aQCwW{EL}0iNf>(S}fvOj8FՉbO߮W]h'~:xN' hd8Gr.~s,'hPrl9&vwjY뉣u>RC򝶖hNM\879i^6<ƃE9?/_DEs.Pz79_ty|w냦TlʩK0) ܩ'kM#Q,Cm>=>@p{qFjI d|t'2>?_s$f4"bz>h{|3?WAy7K2{nӻa{s!׫Z_kq/[kq%[ZoZxbkq%dZM#'kzНMYTF|C€o%Yq9]B_|Kã唣W c:T?Cf{ /cVui ~G>&i.B&>i<_< c(l%^Ns giix"</X/juCu^he/G.ΐk$J?Ym{ʈF40 F@{H[ rti$\=fL\}_&B\|L8IY>ht ze^0#ku f~xO=wj4orC"u q4)ym}A[_di G#TjҼPYiWWH*Bi{U՝Y*u%&ozUw { }W6{l- tܓoy X~Es4/${$:e`7Uޝq0&]9_>ry8ӧMqIL v\״,`$n/T| Mg/9%4~J`x7hHuܣ{wSoz7~^)f,07#3I@BSgHY?_mVkTyV듬/5dzQǽq.&A$atkMs!U+zpбpXy\Ej'lv_zLǜ[Zd6qOWcKIO*ze}|,}kQyڦƳ>u'"}i;쟳-پM Y|%JKkSvAqnOlSG?ɿ#vɗ^uwn7SF&:{I!˽&+<_\~mZKdOV,GO*I2_mҼww>h.Ggm} ʜ IbW}S>srpfv}1/ɩ|Xt"m^`1l?*+7^( xy{1hgcgzvjRG 5NG$h\$?0Or"iEb7O;U7i'|*|9r*mUޘ2hYhfP =2K{p]58k"^L(FQ" 9d(<ϛ/\(=)r{0{$ӓd#}zl>"HΨmY<wzclύpQmtÓ:w6UIGX/lAix'6p[Ayy!l4?qŎ# ?(W$ͩ3I,OIke~L_;sƫ6z$kU5#4On2 s/ }ᘝ~_ƏFS?bN*9sïB!~l":as z*>vU82Nul1@Mu?yikn}rk/4sȯE+qxASdKOlͦqnl}zpN|{΁cjUӮxV5{Mr Es$ЇsAarЋ(Ovu>'cwؾt׼߫&acg92 t`i\Ao84D5G}9s߽t0굇 }ѩ~_,0s|r'|Wx| 9=| f~۷2i󰮳CUU t!kt*;"mQuܣx^mg4D寷țU Tm"݀j[AqۛIYVi.әv_m")i{ןJoFsU0|H} '.ZctPL9+Ϸudr[=O?O7>٧;7 ͷi}@~NoGI0~ON>{0k<-{<i'f@2㉘{H}VgƇ@g:ΙإDPoxEQWiS{躴ރy{ ;&+ _r^~Fʇk-/[>Yti}Ҥ6s㬝>%U7Ë/Xv OUg*02ΉXvEuAg>oЉϸGDuwիƱ>]W2=ML؝/˄.?|p6u僛ۇ"\S3:C/ӧ o=yp\}҇G_(yxp {PW;l Up]в}9J~pO+{x`8j\Ng&i g%1˦d[~_U"[n&oŁG9=͚UɋQ5\%Ӱrm07PkH:MH GFK/3zR*CS|/:.xאѫ^79蹧R^xN2/w>uːv}3έ;uO~Hkl( &0ŻexydPg .{ >˙{,r&b^o&9}` kgiLpxxuiLE+(q"g-; rS[vv)ͪyl*F.hse…Ø|.r̋R3OuKwU"T\YJH:PNI&6~ӦWe[Wؓ6Ԯw$%(Rlj,%!Ɓ"?U%}?qB]^MqT:.CcCLyOkp 5p:|9pK N R2S1E,[w;-`ZbI(>Ƣ{%K9n(;0 .!"S@3VoK^6mZڭyFd#;kdo$7W]]}[?z:ۭ.í~rprvǃNXfF' >"_TY-5z~ŏIEFq0qќ()ht1"4S6`; lӮw{I- v,6 ( %5Eӥ4llhLjU\1myiwtSWꐶe:VzmV5VsU|o0]0PꪭhFwU+tO:yfM..+:ߜ.f¢ҳDx)5 C[,i@8T J8g笮֛nZ*!fɮc=P1+cۢW-1diwÉg}?77 uҎLo?"P0"}`Fr@䡋u9Ypf6e=Gđ-cde[^!<r0bi|gzgM  OA*F?!K[yVlߛj )]2<@{X4V$'G1|rHq1<5,rX~->o̟U8'kHP5%r$n< K(K|mLT$Chi<`]xǃ~G( B瀲OmV6n͠ 9t*ӋQ7s89I$+9sBĝ6L@ RXI #&  x)$#}J5=/f׷K:, ȍxZd̬%;FP$2V4g CHR|Fk9e\eXfe iC>ʹc6*)X:]?N$(>ȵMl=u @ uYu pSto|=z9+ \ۡC}T/'JtmǁO-0km fi=@iS@d@rBg>_3F[2ZuW| 7Xq4ĭY4gzb0:N(=r~=ngWyTJLϏrM/K&l^AY9ͺJ?l MehpC^rO/8?|kltm|paG9lE%SeBngħp$ o4˅?YO-ot%1 d!/$jrm9N|}Ʀ[lӼjEx v CkrrxrL^Iy)g4-B'5u$U'ͼܗ M1٦S8;>JhX3H%'E^׎a/l ynu"t xⱽ8иy ^zO %%vH% F%[5OtT E$EpzLVpDY<ۗkxp~w?(A r`WXB 1 ~ ܷy}~4قgrTCN`&< 28axۏ_~:zXy[TVnS[ݥN 4y("{i}憍n_ǿzOa᛿AJH]X/2n%LsJO h#n_?H<2!N0L&eHYݏ}qu [@Yd]k#ܤUn}HzI$ҏMuיFR)|Z^v| trsۋ$& #_$hkgE/T]"rۦwxrPt=ҙDC)cNN!`bxOKBݮLu)Xa0&ΓF @ -Teڢ}Zlk+"$Q@'jm%cX>YoJ_f M>-lݴiݮ~sr8dڪKLWL2$*łq H>u`O E c LܼBHeYYvbz}0!ӭT![,S茅xLm7QwGex˚ /L'8VXDRHtwIWBysbL`yyy["Yb߰͟r *QSX0a܊,/Ca=ĨujaۣoFLVɺc`M)mr)t;s)2yHb~l[}OVvmٿi}wY'$]ZDI] &A |rɒXP/Y:{[!m% oSGG:9 d o Ex3o^cOi 4Foi,Xw֥a 0<̇YX3FOCґS?&6?`/I]aviK?\a2j}6Mccֺ#zSs9i66`e^)Yozыsfޜ?skXݰjp!ǞHgL֬g jPcwA*9_ߠ^uv㉒Do˼18,О$,A[sb2,u鋫r㉻2,ֻcrL"*nu\t7}{y|K`ͻs:CAϞp[i4c2Q~ !=x̡ =Nӯ^p|7[c9gk ıpǶeaÿrWu45 H@H߁>ń$o1EBI:);plZ.>XF]F"nlRg= ɳvcHg_op44Zy ,,NC IXe*/% }%E?%0. %F9 ',aL=e@nYAYG:Vˉ5s'h./yi ۯ2n3 >qP(E_J%9\yMnŤ! J?6n6|qw̋F >? tX% փ 9 'S,tӂs@IUX2+@B4,p0obƅ,: /M" '$8 Xȹ;5 h ;"H( !n]2Wq5hr•Y0Z8ƩbunkE!(, ]̲alR)u_FZRq YGf]=euo3+#q,bF@̔~LB(dEhB(aDD ~%Ģu 3Ɣ49]'mCc HIoS Ʊ `D5i“h2~ a D l2Qym(BR^~1 4>I@JQIFhE`L+\GyJ]:lfYCWl|\}߸M>No뫵t(uӋ{Sv'!cUtyHtM4zWYbTG0mzh^H MpuQri~yaF,&d~r)GP<1 G dY V!QјDJ\Q8 :R  - sePӕ(L=e,fHZGE 1e`d92)Ϟ*օ&EEDa*@X]O~BNLMq@~B=&#UBEA DqK$\ٿ/}Kmp OV D|ꬩ&Ӷ ,ބd&&ʩ <qr55JO3|w8sY] bHC+K#aa}E,*)!q0݇'=LAz.ص6qC`p(`"U Ir41H.&yǬ^֘j0.4$D9&`!f`.C0ØM-DP Hc: Q@owY~i2 /SFj1;Ki3 YQ_ӏz|I)c 4R,5Ǫ\^2i4 $ I~'3`f@'BT d7"Q=ݫDx"3ݡ6n)'kv9H_cYFuUsC_*uٖre,ʵ($sX "bNg̛&t$ ax$vG ՊEPfpTPȅ&{l#n2zl:(L x/ըd1cw{JVQ.q= ^ |)>xؿ,Z&qɞ¬xT܍ 2pӎ<1Bf1]m= W\Y@ax5!̘$"E`{ex#$F+t1?-ԫ@c&t6mD`,|UFAǶ7E(X=A0-yd%n]6B&!aj a} @ާ-f;QSK.a uH7N!жI{Ņ]HrK1z#O/)ۛ1>?ޣyziHr 1A> WY}v,o`|>TT}A35xy(ro',npW$" 5ËQi&`DLQcq,Y{$4 割D vh/d3$2׈ Y<ޞ |*&tdždi)O j_ݎcc~YF i[(QpfcpE81:BB*RyHZN.q0[{R@1*heFjc8&+NoyH>]+D<٦m qR[`q$p>w'ߧDwm]B~׻7gAKU+\Ik1ŵ7GKM.썩a'9ː,YT,&sCTıv* /UO,n{chR!d4!z]!EAq(ӿ)Ǧw*}ŊQI+y&2,h0?tJkⲧ<+8n/K: <GeVV&o*VN)߽4>P[zE"&mQrJ~'kk-SIJω@Z~g[;{O__▟ dzWίxUAXn׸<u˶$>#Y.m"g, 82> . > @DA‚跃$HzUBd*9%obLrEP>+g9?ꩌWa>i50L]o?Xq<]dYmp.s nOu$^YL~m-ȥy+t])?s@2uOh(SG\Ym41 #l>ǐ-uNtz՗lwuUSumt2l:z o|Q/7kʈ*bDLCMxq-e9qS_L|g5[Ԃe=7fŸxOBm**(\%žxm%РeWz\@X9)waH9ž'eRSڋXU=@:G c 376 vIbr/ s /[Һ{)`Yy?a7@:B.G#)4Gru]\<%?ac?n*- " t_@yC/WSp0 6m,>پCKVAzs8[ sje:_IOrt;: M2Ϳ j} "oW9g\sKə0ߐ{k}>C6L =r~W) 5VB-lGs79c'v]akx Òh9B9풅sNbԹEzPIgzzʍAa':0'A^ m`%, ֠s[w ^>.Q7sNV [ T$?ym!\iԇx=\6<7 Yz}63~Vw%=wنU)/*4>B:XyPOrB.S~qqF?&>%gww_ʠK]{㲐D }6G OVʴhdSH& 笷Mଁay|c4 0v]8r t3 Smq"eⳀ)4HnȆQz|@}oޠﺟUb# uzR}qKI p"hf!-&E(Dԯ'w?l^5;:^E㜉G fQm3ҏ.Pˀ.pZ9h :5V/5ΓJG8[!J0PN^}鎗H +xI;[{JU>ؼ)eb*~]BҺ#t&&1Dzy=K|*WZ<}@> p4t7IH}CI?QQ-X!M>ZE=( }T`,0TiĊϼLD1*tTN-*{{ԺlY,NxǦiSf(6}._w'ߒ0wRD?*fQ (5gT"#߾?tY}_Ti}6-B˒EloRVFEo8FykR~+Jf𳿑/kϝϓx~7>3Q[H~kՄ- W_uW#߲O _RwWKB***GhQf q;|Q9mDu^˕ϘOk\UQy(AWt($R,vԧ-bég2`zZzhL(m'vϗyDT(ӗ4og˓,$6vO>9QLr~7j||dIBcdtNœhFqOi)I;[k],0M H"gDQvY2 C idbSEQzz4:R\ߝc eM P.B~yxѧS@T~da qC;>Sӷ+/p27?LGL4~yQx|[ig ?d[J!o]>ҋ@h%QBFQI<&Y#to"C peuSkr2:1doʢ923&A Q, CFE("7&f)MP/ZO͵)nOyK"}3ʹŎW"9#\@g] ݂3Ƈ"2bW?5OY=K?b4F@5vH؜ޔ剫*)7ӛr ,/ M!q6KиlFE6K!%^#LMTOgg>%Ff7 &j6A,t]Aȸj3g~Ȥz%i\`yRd*# 4N"2`dv!׭VXmz?v'42o'<ݟKEuzܵp(w믢sU`B ܰO!(nxk+z}M4CPS{xߚI}z8 蘿혬__/ 㮬aSRe3>G g&@ D[|/뙯 JN"I |!iĖ$֖BH.BCXH z[75~nH>3BE6g~I2#^,i;ҞvH IE]#r hH42܎cBM-1jȺs7=W?AZYitLF cHw26164p-Onug^y;. >HdKŽt9Lj")gZ_ꖢ ] ͊{_Okd[̜s$0pgM B0 xJ|Ą'=c%]t^# e&`8ǰ}¢"xO.& sliF%e/6(li SO;sb;W(#;K2ɴ#5/QOɉZZ/cl\P[Y\8gua4i*<gKau}n[mŭתƝ$WhVh_ˤi\JZk֒SrFŰAG zE-ׁh2c%/JnU ?284ӧ DZNM+VtSOK09LM<)01G7 xkay휖me0WիzC1&:!*#I~ !42 8_Fdpv=uE`>jKu."ؠPl:S3Ft% ?\͠bbDP\ ̬@Vo}0#3#>٬ E7%4Qduhr$3] ܪLw`xw(gFQZ }j9L#B!_ "Uк?6iNCXwK ]rp,"C#$xE̝ Cͷs+=ʽ⾒;R)898Wr`eu(&r/ͽEy:SOR .>gw煵` 7#|[B:┷C'3+ғܷH-vv|` !>ʠMٳNlZ4 4LµL\Gct{Ũ\ITxkiw8!W99 +3 A|Ow՟DvQ~kqm=իoӒES+|8T<״oIw+Umu`by0#hsz%=@-?OYF,GSw쵎{, 8H^ۙv_en<+p ڣ D:zxug@< ݤu)ph$uȂVsp2!#_iBFOoQb Lڸm5h~pN{ _tU\ɖCx9'+L :O74CI2 dHUܤ]iAtA.Hq|s,8A 1m;~u;Ĩ8oML&yr o7tñ]1cbqo 1^UjIFB#UpDÙvn{ XW]:HgNWD6g."E_I\)Df{ƺܰ!*€)!g5 3.ثNTgvv .Pɑi0oT )L񩕾dElѓhR"!أ~|ZVw'!uaN;b9M~ ע3 ª0yZP`$;G&3tc4ݹƳ{_t5kr/Yd[vٙ{g;k";4Cu*Ж18?z" nI-wӟ1G}uV]3\5}LXH;(Q[pD)L2T_&_nOIoqg ԅzD曥vb\]QDZr.nP}4Sg؟C# zxkq[~Dݮ!>gE\k 5) {e -h\O }FnQ?=if@fm oɥvkzFV(gW& b9ӵ;2>ŗJrr~W'0bXh=% y.@_oft*~J3 OsPՇ+3I0l]<Ԧv,xLd & eyL^@x-uK\63**W^MLCvV!._\QQ1y X1zP%ʶipecҼlv M{uyO1ރq[MzJ2> M8Z2Xd}(>?2f+A^~5-mz~?Ay6 ]k~׸ln78s!q^5`a!Y/E@ږ<淴z LrF98^Ĵ3k!X}`f8f u.~V(Nw30Vs1'o 3=3f0T-`\u;`nOedT -M;An@KBVN,b,>Z.P֨Bgc1^rGuWtu5Պkpk`tLٺj:݆}QΤ,9; T |p{4+tY!: c[fl@r3zߙPp!V6@`3xqm_k_.qi YUex:=_k,w֬oHYoj@ xY2®e3> :_TV76cސgפ97,&\v1ɢd S>W*3h9uTAJk]1x.w qe 'i6i^Tx|5mڋ\@=?6KsRYzp{qFl58Ƌ@oK|n{;%DE\7\s$>}c* }iwrd׵7<__a7]3b#k'{G]s|yaч[Uv5g0J#F4ăW. Ɖzӓ)ikR{dRģlҚ#UK)߼/03+wH[eFT-Vk\r`^s}.DrZյw[Armw!tf3Rp^4_UC\gf j\]Q2lH 3iT3|F]XP Ry}9FG[ /O7{wR(o3v oiK6⚛[=\CR8z4rmVB/vF˒lmq ji<*Z nA}vm=Jùg18~'ΔT9[] {6EsZv- h@ |GBl!񆽏>?VFŐ֠lj#*nq0׾?٭:ma ,S=]Ԗ_$ui1 ޠ(fի7 u ``XK cW(Uh%umM͈TRH,ͣyOӨ"&̑irɨs@~,_7Է9ʄ x\<y̹Ų עX ulK?zz*MNnN~ urS #\71aŦ[v KDOL}ùcâRcǏw-Bځ^c˧uȐ&uiQ D 32&JE~)nUwD2r]N*[Y\*WQQ0Uڇ3@'Cc3۔K!oy.B_=t6(PAr6̓y \ RŠ*[m瑊ⳀHmhJQ>zhg(R}NPB Udxl66n6{G*_x~8E*OLB\,6̢Rpq Z߶㝒̶wXA jb7;$wm)|f!&@Ͽݵ>;-Km99W 〙LA (!K}]@ZAUK|bOz:Yի`#*  O\l^\i9M n ۱r\'y$( &@9@\KuWIY~C͈{OC5_?U?3CꉞRy;c ׯC|#%OxޟLA2G1\_%e_\v)oIhs,)O(!aReA -z=UoԀ[U,|^ivYK܈H z}_6.vG\`3[{t*Uח;W2>ʘLI)*8YPGU jC`ݻ{ISkZ> jJ"\ȃ'S,D6嵙'̽j gG^IS4o`P:V _ gpU/IUcH `sL>4j?5fTj}5GV<]8R#ZG|^9REޏAhO};GM}`uahBK*iPbfF4Wkь/~m2ٝhLM۬+ ` \UƧpG,v7l>(+s0҃꽶#YWY7.4zuz,QּxCVH`?s8-3p3v`ݜsn C{MM"+%1i@:h!jjpE\ ИOBv``C?$3E ңS|>O{9 uC66?2iYg'4 ElA*ڙs 3b(fOs ^ 0ؼ:wE[)\')KO_<߶SK19vf ӷ:i "\i 8jjS<5:K1$)tޮ:I92}BIU`y8t`عJLL0xi8'aaBsp[.[b €:n,p)g0}/uls)κ}AUA (!H 4} B#mf7X߭뫻S?ZxoX[Vi@H矄aKKJ#\`eWn޹uSh?λ}_jkQMkl2kA1DJBL?QZ/3=s jrΛ4)['>:E)?brMO.U_ KʮU"?ԦypM˨6{vh=!R疗I|zmnfnv56ڮwS-{:Oqpg9F dwGw"[>8mx(m; K0ȵj ˇ08:>} ICʄbBñ l"Þ=*ފ]b.Qh/&Z v`A>S"@4 R]{c\6;5 BF ĉLv5W?60֊ip]rlUksut++%\]z 4׷|y(#Pee Dx*8 .Á1'Ni؉ђt8iY0?Ɖ[\"u ;GE. >EzuzZl zdքY:'uBȢNE^+lcLDDR*{9PMpnsgV u~a<ʤJO 9!^GBP >o~L{SV5mz+ҳ.=ercލ+hW-I鷤]|Om}wOe}sY8vItO]?ޟnyk{`ޭm- ш03D&sYsb+籔'-er 2Ϳzu=5foF\bf[$>{Ap6K_1gֹBM4q̶%늴 k͔̓s}3j {qgGV33%x?~v$hNv)U3n$`ÏAMax?U 6]PSU tƼq爀Mah[ wNNeWxw`yw`8At"u+pP/:7>v}|Hc.]f %oռh>+ f H-IG%ih#_$A4AVHGd*%QAEТɭ${P,^0]qN Nkپyk;gDV٦^  ҏ ]I7_8 3 ŗkr~bu&ObcGCE8Lvt3~: [srN0çG8'[+ AD}U÷V~UK5O3ʹө(vEތoP "8pv 0cSn@[uI2PKlDѽ%$skl+Az>~};8 eet%TE)0c?X7eX4. 4&˜H!(2;d zlL\%k=9)-vx7~SanL/°u"rNCG@?UEv^ҝ f fy~/ʝtRWUZ5u7Gy;5;>kP] Z.Ȣeu| =*.;N5F/QP.@j06* 6paT7C(k3NB Ц Zٝl/J‘F_ /ȵ3Z_z8psm6-Atösl&9 '~rnZWNE8mW_8^ }ZP[c31A" KQAY(?W<{y,v!'.ahGǶ[XV8 ne8fx>Y*b̙ *\{u@֙܌ݭ#{5ڟ ~Lf1$t1a U vFyĦxS19+Gn Sdz SZ ɦǔaWl~N9 h@ |HKM3z}g:-ɜ[X9B3Y@ Wf" ~TdY|Ub;kGr'ڻc#sRM2՟AnI#)[= I#j;"a/M>GHnTnq8sapϡڧȄ_ޮBiObPrpBZ5O4[6i;b&\oOGbpM j}GHPo\ @K2VU8CvQ&Ճ!G_:HJbΠR{Q<ëWa{ %"="+U;"pfBz=!K5T7EP~؟3;UDJw)pi3I},yIrk&!iz~K  H\r!w&է$D\0h<ǂ(Qh"AH~?'>yLY,?ͽޚ^y''Q BƗ=fM(΄~ǜ!\3Fidx϶wv Ӣu?H9)!>b۶Vq%^ɋXH8#ИPGS'ogz)Ҥ˽kZ'^uOv4/p|߲cm;&8/Kq85 sl=Az1 {01 ڟg}(9LXQd"exp Ԧevy1gw i ՠZp[V0y  ETzAe$9A5 j/&Z_ب߯w۹NCMnwDu.Ǧ;#.zK?6W~M*˼q"\⚔(/{=婬e} SB=@I*ӗ8 cf. Aȳwhu}DMd1MZ6`+T]HB@؜3nQFqH!MtN5!%Bi5dA<6 8 !&jPhe"] ޳vi]s{-[c_uyoh>-_O4K:C#Jx|>܁b>oym}%qӭ¾;Y2Ϋ碼I1@vM\+?az 떄:"74"R([#/{ϒ >q߻w>4=uƬBhE*ײ:,Ko>߄eDݱu9U|[esS|R*<^йS5)ˢIH&?9U^q1(S(%ɒK__r4DW4|edu̵W+.Y[쩄,I u$Յ yUB}"#~$?,Ma, M YZ%2=G$;SqBv ,r%`m&F9U풵;k|5UCc ޣT#>z1Jop[ *KDέyҁc+_QݞIdZn*ڥ4q"OUji㔕zJ;j2=_UT7XYƐA}Ӱȹhתf16m_ӷvMV4 t;= kb.*_Ze)KcUr&!5Uzk>LU]㲲_5#ȚbGSU1R=j?ڸ8C.:ݴ}0mK eõv E}qN;m w:ibsrs 8s[Pf;x[0)v)ruAP3"55uh iڞ] ]w[=:6H:x{ō sQٚu-[RpnZ{C^mc4P{ʐs`y9 LuXtοR46"d >~t#JvǛC vFAT a4꜆+g1ȸ*JF珁9E.bdK&90 vuvHC͖9V-[&D\?`-\^,κܟJfw "~z>$X3xMo"8ABGnD Op1,>~ɤ 4/귙7}>2̏Sgka50>X C]BEH3UYH:BTZg"ٰj "vDO^|uI+BKL" ϗ䉊Ͽꈭ}zwg zny͖UqYsjb$gYQ AE'ɡ /0!p~m@d, P 9KHob<< \ǥLY4uJZLu%?@< |D Úd0 | ͨw$sZvd D2 Np!UU 9B ER&zVavYܒΰz݁\2V__7Bx1F^TtP$< kz>'=V[?*P T^=' v}AcU6!2 "LU* &$+qv}۝jز*J@ 1@'$,;@vTdUZc-EBe(-I1ffSRkd5XAlmQkwwIVǨ\7e +!G}/|`#\Kӟ*r!kRv)˲n朣DRvLwWh?GMɹϼ̫czj";u)3*o.jj,p*TY5N7@f@޵Z mx 3{LL^^pJ\\m*GXiS6B˒XrZdy=M0t&tn%)?bcBCA0a< Lͨ´@[~tpA/vѱGwzwJih1{/;rdŗ$yT1iڎv`豱wAae$ѹ4(gֈ,Їs(օmǘM:Mգ?!?jv>qO5G\կ]|/Jt@LQsG6k"Eo{UB_m.If_ 8E^i3ק8}+}K) \ϙΟŧp `3x+@8hm#AMa( ېI.4fkטOvEǧ2nmz )JX}P{1lwSs^@&d-0ӹWu\SٔWWw8`!1!m[-aPkt1ahmFyO9W  kwk{Qٯ\li?-=" U]qS36u tNE( sJ1 u;{UIY߻[Wݫ4V@IFx 9eL{e^.%olTJc'2AI('a(|>n0]bCީLO_߽J^xp)YLO.Q768:nԳE:n ][,'紵 .xעJ}QR9U`Km9DSLH'|Uds~N` CL:V ZTFuL2)c7wOE6_Ooע_sfg, ʛ^YYsJ(dAzO<־eK~>lHq~ۻaq@>iRܬ=TVE9%oIs Ww!@\eti!*? N:gz[B-xil^j8ALoyLp=Q, fqmpڑ Fkw)ΐZT[uDp9'|/`WȸTj5~[U  vDVdLs]sx4Ӗ?>5KzZ t q9mAg1ʦf`\l^ {&cpYqWŭ |G*C_3Cdg̚sӡ)Eirux.:' ,erB+P~yo5>ihŭF쁶sE_2\dsݑeWEy:G5b٨Ǚ.)5QTJW"1A;; r= E|hU@|8H\cHUDJs 8Vaϡp~ަ"/4nD"FrD98~e}U%~{/pKs.%b_ay|jxXޞ::cs5"\%ʚF >aA(A"'@i!.?$y_!/;)U-\cwG n^xA(^"B8KN6қ|'q %LaH9. B%%PF+C9nO}gFޏ(½+ .bH %u2%#׷ ڶ\ Ra+sN KN"N!VE0{|7%vaǢs8>q"?'uR?*䝊˓>$PHKh}"84pK/CH(*1'@~]Ñ. LW]\Pz@QG-]0Ι5*$xGA{Yu; c3C:CPꕐ~m!3 H9acs8Ӈ+T}kDܰ Py?CALA o x֚#V` q8LéLHXTDXtLH=` w}LIeDH6A@& v wa`RATVF,XhHFSo0j/89X B ߠB  _!X5,pu0?|d~@OÚ# |>í5b: {W$nK\rϐ I&Aȏiya{`m*o 6=€D*oؕiii޹ ¿yUdE$-T?R/ OdA0P `ۏ{%#H(:3u&.4&~3Qe5fW)΅ }CA>$קL5TEbQF{흶w7'V^3.ȽqxpK -vV6h,JAPB>^Ypvs{>r *ys(%2ޟq{9h?'2_r&Bs2шK.ِF970k'`o2 P}i{SMէ~w_gi<ǷN[\E=989@ ER&l~sA2=dnDO#"*H3y4qvv bwDZ`ӪՀ[Ej ML: -[-w+;;SR'ouV{^vNNER\ہ@Zz.߳=F T#}3kyi>„c|NUtN)S{.ٟk=5NpʃT|?Y`]m뛉w cWbj~ёפ<%y$%._Rk({|0PQ>3DEӲ~ς%w'ę$"0է8W3'J\Ki ʗ2>J)4 #2aZYIiD":DA(2fϫg^2ZQ*q36*͈B5^pA{tMET\⇥?R[R^-juRk N/ڍOєKsc8N,[|e/[k&k|.{_#+}.rKa Gu tʰhh N?4‡UCӶjwY#{IYӊ<W}x(#lADa6VtQm-~Cd#'ΟW;Q+z.Ko.YEyG0f9`|7Z;XW8C=(fiI7%^~*np3ٲ?-1)QQK84-AEjşa/:B8a(bholkbE8#1*dʋ{h!*5˕A?7W6wm^ikk=9ݟP7B=?X9Ƨ^QS䛊6^Q[]TPؔy2jAvԖThSiWk{VYJ|?AD!! 5G5 +{J,wiE`4\5ūK$NCؿU dJ!W㼰e!!U2&%靈*?>淟oTq~"OM%/^sZ~saLe> Vgj %s ,GY䛘Dr0ߚN{=V?v3Ǡ e `}j?)#{5OYҋ 2>f Z4 nb>w,nnwQz h:5{N˪DwPA:-R%sw\ڌv`]")_y׉iİ%_ׅ 21DU-E<mb05%"öv-N&b˯E^)Tt![-vy[ 41ig1ml!C4pKv0ZAÓn#,r9D#V'寀:83Tsi|찄b;'\]N%'nHLK WC kc Kɳ^ݫ(wNY ©{՟j/^ݗsqĽq-Ehr u(s<:ϔok#Mʓnm_ `{l3T~C@cy˻*;6^r@TƊDt 70n0uwx*elS5yD5iʽ6Hj] Tyzq~nE*Iƽ!TDt|TjVt+j4t7>!˄nαY<५m2?)PVY*r:-; 9?(meIӐީ2Ϋ碼XU(*S QCjmQ0=TaSob8S?.J`y%}a{q^Vڵec|յisQx5$-K+ aw~ F\kou]*n+|-pN|f4|uy{ZN(YvrqM? ӗN hEo=k'o~Wmy@;Bo5Qr &9ȕG״xų4>bEJں6*Tu%&ܪoO\O .?BV^L os;իC=h+O.D4l;: 3FƟ;pxu@#s9z]:To$/DFpQ%qyz{F%xO|heR'zVw@=4Z aLqII)%g"4'|̈.PogB@(9(j]cTX|nG Y4: ,6Pʤd mLFUE+H&瀹׼yU^n2Y\JoOϬTVcM'\)ͪS]: f늞1$yp:0p-dӕ8ҵ!U2֖EݧMѹ^z>љ_Z<+J jJ/)fMGQxY֜,>\D}dM{^~B^uvw=ˋTФr*):/e|Ez0oj.\<֗LoHʼYDx um;i )qHglֹ~f>mar\{u:Wq:#p()2vWl9ⵜb30n$s sHXDI3UPR_&jJ9ۋ} U@H %&X:ӣݡ$ELX7%z2'wҽm+x{muroIYO4;:T[0F( ,Ρ~? |,,)9fl @=o(1oz|¾u]eNBEr35s/ g, JAVx|.?ŷ MozΊ_2E+g=-Ht#Z-)Z7M`MatM'B!.&JT4Tu SqNN8sWWp3rV0Do`:TP'3\NLwp YD WXDlpy qή,9ty7:g Wŀt|.uk J&XrA8 #A udPp@kyVx@oNȹm |:JP5cz2~>i'`o(PWZϽo?-$ߩVe3]Z-OO4*eN8SDM 상6TM"Y5Ν1=*7|$5qkyzGj`I7g 9VP5֨[~_:J;kQ9j<@gx;iu?Ev/ػ 1RQF)UHK|?#ZSm$XrELF@mb7d8G AWxCyЄP;1h~3̶\tL [`bP}$ d^9&x*) ~CS)* QaT1FpY9BB 8d2_|$Aam+^&I0~2A.ܼceu0D"&-OA,+bcpZ?^!_O!V_k/#n,B'Uuo4MqߥM.AAVf6hpQ ?E ;lc+7T?^ٌjX "dqﴓq:eM.=&=G("?<ۻoGTaT_՟7&lDB}$>#~$?lpI7t4֯C&S; l"C7"'Clkfl`Vusk>%W"؄^X@{zMEpI\nM|)Po3ߧP_<[2V y2קOez#˴NŻpRKs()+*۵;QZZE/k眆'-6hV@ M{ߟQ791&L! B=+nĵsyS6GEšB9DǧE|͢je)^k/U/ͽ[]IQ$of&1nUvheR~@ RJ>x~AyśWٻ;OE+szRt^~)WV 9e+{S\\4>m\F oBɈsIH?xF俥oޒ⊴2JDtlfi}z1^{*.4+Ϧ{w-Xi;/v~⧪n*G~buG͟P;s.ӢA<ێ w)"|Sw@%M# #+seE۱Pf .r@Z:AXyl;ce6!9iيҫ:~>B*ⳀIDbZ0iِrFvJQ?%qAZ;-<=R k~5y.qy"_4g6!4Sz ے=vr/O^*MOڬĄѯgxpWGژb'q}+#nGrE]`0.0LUћhBZ\v\pogNjf`PnAmQ4cF\`\iQƙQ\)##p1!K;$0hD<\`5I#h)h/rly9G™ՓLfC']ʵ9݃F:lF5Q`D+؞p%G"= ۻgPIU BuͿ9uƣjZq[+!"!h0C͕=!hI*C۟.lApfp+m`0z:bBpOJ6؄6gvQ ne3NYzAZy*Udg(y @#\\5:4?~6anr'o$ |HM."p.A 7d3@HF_éy_f:#0uRst+zAƮOE\~{NYOACV/.)$W/н?tPl+V% ]K_tk^>')>}5&!rňE,{YSR*ΘW^[O,/Iʱ WݞK!%e5;%#!'"җBE<8 뭵5%)?ٮSA~ݩWeU A('}-K^RzF{b9R 2kQՋ@8"^DD:)NNKb#_ZgHCtnER[STT: $rڵ~zH[DHCZ@|n>lb b B|d'{%n,ְ[\Fmf)@eZ;H?B y,8C,lk@WhZ 5FZ][{`Jv&uSd]#\~BD֟\p mm|?m]Ƈ\]uM85Շ-fr8QP0JB tE@:*OKt6C;"">wQ$o~#cvr0!Y@}l?O<\Z$Cf(9aJ){_#>)W_if6XʗfL+kTUu..q-'wLϺpc?2גfZK BF6 _D/0zg PZ&``O$D0l3pYTp+3Jڋ+eƟ2)]Y t([N8>Ova-@kߍ^nY^㲞}Rz_ױ "DXRaӝ8?Y;*L3l052.Qd u(1 cQQBB+D b aႌ^(j\oUCmпT6%,McNA%e!d8ƨO#Rp 솂/"`*`]NEc"RLɨ-r[斎1~DʋD~U o50ia[w)fٜyceqCos %bwiHQ$-B)*.zo[ZW aI$;\T _&%\|-!
3E T(T-߿!U8H1^(Mhb0vǨJ"gwI`DEm2b}Hj8&4LI@uBtSI#X/*V4kU+>!iYdnj{ FY36uFj1YװlQ(a(uPgQ=&;i> !P1+V\}8a--ָ[Fex";1i`4o"n &7!@u F08Slq \A=u6 '!GY!a7-LǤ!nlGcJZ ՟4%fTBBK":GihBᜲ T0p!p/ TLy"%ؼT3szIL!#!4b93ی»y rw*OAۄ)(ԇhZ)idPidX7z!@jTQ[Qhdh5c42t]7A )IѴw (!ׄ y~p$D,f˼y( G[.Re\dBNqSmzy/F.i,cXw+DZd%(vhQqDE,a~ƂDQ,8&Z0Z;R "*m+1 0echb2G- %c(m*Q"?rP oH2|ht! 0Pºd "_(k="*([P&E`2qL]&"8*m/?܍2H[>/I*  5D#ӀijH!P5'_@0]ej "C}7I@ uUG0Bqa)<٬uTXlAtPzRc4(j}X/?Ia2姙퉃:HX,mXw*S= FOq LxFR\&A&ێiQ( 8$}颁A`HCjO+@ZUHрKG:!XKtڳLF1pPv#+{Y?< Lc"c>`?&AdmnBC0٦Āruܴ#?5Xhtv1 C fr)X!*!V1fJ-6@i 74!4S.lc qymXJsz:˨ R,w\ehE`( GM0^!7D>RA6i,F/ F2 ,e8bwE?l`1 I~#RmjEG[2ި R2T_Ir2 |Cv рj8qU1=Є 2xt]! 82* fF IqIkVF4@4TP4=1z|QrH5 .|B7\@~8c=sY | DC0!*`DCQ'aJ" ŬYQ) ݬ0 pV"(tC*#G `p ' krX<8p rx" a !QHJ GDŽhL#il0{4aF"!=&V!nb_p0>zDzHJrsiqӐq^n.A-4 ݡc+9vV#!#ÅݐT8i^!9:Eh+:@kx X>  dhx2UG {h "QvD2 |핾 \D3:| @f6RA( K@TB N! "RZ5$Z;D3QQ6itsT`Ѿ1`U8;U`g?GlG)E=݂h4f ûv˔Tlbg$UK}TzO)PvBy 4B;K#6UpyR1\E67: 3 !02X*nB`!2*^_5]mr!By^`nVC )%R/j*@,D2"DFu| XuwM|e[O U(L4,.J&b~H}$׌J?2^m6 DqlC&kMNj22A,E/a֛IZs4Mt5EšW+ 5zD AXQl:a#@ }O!o Lj(5D4Y þ%"4k)A7#`R9g:D1- Y扇a(5 @,˜wʄEju>iZpT\Q0 kt'pmlu``~N" T;9^cD ua`M+hTiGƷh%XwxC2 :nrcRZBCɣE~@2@U2B28 Yu\@ՔB^'X&p$ qn& ,EbF" Q@E!_!1F@4*Hh? . 8B|ȝ[z .%rvw`t-dFe`F) .1 '_ 9QDkևT;fQ(Q4@c$j@#*1,޽ϐڡEsy.!1ES=U`&2F`el$rVzƠT*F>(bmh@&<# 0QvoZJs}tbU\@cGCa؁hA}6y > !2<>j>oyj9εEBb_9^$E6;d}ZB8 0 )1"Op&82^%"S{@-|:L,™h~WB4Eޢ*~&?mMHmh& 8,R1Sd`u q5#F&U#$k#"Pk @Ft[ PZよ#r E$>'-_ùa6|Ua9eA{+~ķ1MƧ,gO!pO#<+sRVPT _ȁHԓ*%PwR+KY||qHspL8jb PM5'%YF8NBsNuAILj ` mT)"(S*@)u[D(JAMz;:~ʒ"PlA~ƨR[>A[yP՘p3mxZʞm?KZhT}ҿ Z>߀PM`Lp /]>ڌqPAʡ# [$J,Ω-aU08;a KjamS`Nd ÀCa|ʊV6E/[<.y* ΏLK"DjcZx@Cx|4՟?8=6~PP?&C?"*ӷ4yO__/Yek|JwS,(uڃ-F!|v$B*~F}Jƣ{'YG Q_^%(/uHq&A ^^Y5x@<7G7ΐc X< §. GpEac{_Pm*SՀ-K<~)nGCZךYe[k}-Tm"ڜ&{;.  g,, malh{7r07M@[*v8/u$1'M- cj <]Qb$ O G@{=YUPf=!H<{)+(ab/,}ɿ<u]\^;Exz^cݭ>)]xҍL~AfrZUulLy<ۻ9 }|碨?,L\%Y#0 ]m􌆬kK,yLη%y Vل/Un^9TtZQ9!R-2 ӜME K;T%/r޻j[W8!|Fr,;GM N+j /> M78 $aY|ߤq8eqQ>x_{Μ=H!.FRj*altVZ#=J^u3i,s #*f # X~Xx+=»`2I*ՠ} XA|d)"ѫK$`e\pby*Bw[jH^*རGU==?JcD^qR\/sIr =Mi+,L1״F2wUn؉[{ (oiz%p V)iKݝ!*w̠s fш7Ɱa)jmY)g#]p4'J=X'1$@6/xU^M'!.&Šݰ1Y2ϻ{z*/lJon11=2=^6 k`&VсpcWbmfٽ~l<8darWFqO:F.qY6=c}z9j|@ ~I3[0Mc | ( ՎFV{p, {AHXbw@[8FQ3( z6f kh4 7Z!M7JR眈M4؄[@Z+*3^y`uzt-/$.߀k"1ݍ ůn@9V3 !Wc B#vj ^3:x|-Q pݸ[.\% r#im`tRF7շi7ײ`Õ6X_*E ́։10p$A)k{ۚ0Zoނm|IP@O2(ϺPI~7Ş%qq9e@&\W5b(!I|#x'_)a}.=n.$tFbhJ!-5X ) !S>^CtjihrLΈMxY`",sjI9CWк2ކм3nKa=OaY* +`Pn. vN3{3_C\t<~Liu8п65ѽ%q!NCn—,W"s-_U_M> wb|XgՆ} &o2q AaD/$l3 ;Wr 0MoHcAv؏tw?5^d: zr ,gGudħ:Cӻ7A7_L`cpAHX oSSQ .u`Dn I s~$̇j⑯>@k@}֧`5r B6$<ԥC-[ c[ݨ.TY>oQ e. iGo|C@>f5܎oGz+h2Wz>{bB9alcA3 3}i@ݯ[;]H> x5n" 4CAH+ m B(D 0 @ҵ<&߅OA%q2նT7P)ٝ}ZEFEXmpNYgn`KMۦ6X<-ulnr7Sul=mA\[3 mSD H`kBRaė,kcܖ~^81QyD@?E &Ps6bq,PcBa89j! 𣈇q% qr|~UQ['kcB`嚉R@FRBB\i}NzgEB2?BAAmXIݺo .pV(ɋ\ RA B7èP-~bz l9J50`!JF~5; Xb uD'J}43g2$,_8LH[pRq94Me g!XcaK_zM30wC*v֤po%EЧM💧[Af;ׁc5ţ]pAl- y 8:WA/p :cٚcuN[pAko6kР 6 ­)T'a BM?^.K27&|I//ito"Q 7E2 <|>R*Q a_ùc x aoi_$٭K\~Kr-T/Of֔4""IwוAȠza#BgqvP tawC/eK?H2J[w@KPA(Os^0M@u-3ߓW[3.HzJykU^t#|b7ԧc8 ޴sZ=368fh3u"Ѷl'Že1$ە,ul9gM|b -!aQm;k&l\ 5ΰ"X!eBI`*3Kۄa>W5@sXԣdtw>o{ ܁R׵%d ^!$z#tfc>! c`+\|.c}vT@h߾)Yl;@c ;Xlua` 4mp$CKDCQ͡yTPdf6YKrY01i:l.9B%뷪\ -"ŤrPOEg|W L<o@cC<G?)taw;3 wȠI;WE$Gt A#bމuШ|B"\ybvlVrOĨ&>0ӗs[\GK 9]m&@hc/ŢAFNV m 64~quJ! guF\2}4"AƊP('\(1Bd&P>1n/sǔ30"? $$0B ^O)\ϷC.eXJ先C(}_zG!/I {aĈ#`2"P$)=xF80"kD>@,)J8vJ,>\rA0p@xfLDIRd3, }PDZB+R CvD$F#D(44JM &I(M{/_zi $+ju\NnS:D`EVA&",b _Q2TY/,J)<,ҷN+|:X C6b$*9BN#hb`@!EWD^$b@@ĩo'P[H,035ɵ`88v\A&E x -2Q!"!qp1!dBӑ9EDy31 c2 M[%2"$|S2" غ!}2 c`K>M@eS#l' *< 8~0#,(Q\m R 귂E_+U ,J rIB| ̭q FXo nB,H#;#RT!(%)Xa#@0̛8BdC5~bEI N-0d-/-6D 6rF6,~ZWgC2~ȸR%}KΞN,NE^'ym];:INA`k8ódY3ұʂ0DeȈ'~SE#Ř. )#I/NSAi3?\lzB&q"PQ7GlYq]C1*+?!RVW%^g`( (ʘ\T#X!%;L*R8>vrw=I~A#[1V[xS 8\C\~TV(*3bQA=(UuZ'C^ľX]}}ba *I2)5>%޵LҊ*.ʃ}?َP"s'WYJ jZ蚹ԀńIo `k2q4ێҁQߓa("2 X7. %J]rf,s<9q!YjJAB8GkyQ;OBJ-MHz[퉄;Z/ |E.@[PId2ZߋxPiH\eYv*bC pbPux Bas(Gɗb ?X$"؍ߊּ9%jMn{W/5iAB9x=xrÏ"CߒLz`ܪ-/kK9jBR4X2of2 ^ Ժzחb`vzU"xҕ}@;| " "nZMXZe1= h\ CТl9ag, &!l=\19I#TREl79G:7:X[/Q5mY%'ќ l ^ ,A![lϲcl_dA^ܟ0𔸥/V}(ʱfp:zDɺ;eJhϛXTtC>.˜ Y EN;&GCҨxc (ϱ]hE:2ӟ`d/ `ߨzW r8 \$ igTFl$U;CsZVxυh3v%V6H@!\O,=v0)Ej9smPt>{- ICZˢ㿞Z7U>S- :r9;GO>`ܪ $_.7ziNQw!>qQC(XH 6y\36"ۤԌ*F"1(6-` [;p\xuh. /o9' o&-/t KM#;F\U@uH5W!G{ѡwt9E7Po4uܻHMԡn(N+2\FgMQ5. m?Zlg O?U1!y0A;klskPj2 3}.6;4$>ϭ"Z:焛rizBȹ]ڇb[ 0rx ™Υo'a TO+[Q\S9kĜwaBؑl7> k: (nB50(>drtJ~A53˅gFEW'N`p?Ml j=o#-"CP43ɍL8lGIz({VQv1x2~zP{4,.34VWx.yZW!BZ piE2pOͤsHKiqN ؊Eè)rکg%2Q3]]ںKZRO}9wөµ?"J{շuIT&jpP*2Aѭ2=ej;CXؼrg\:LUTclc:xDr3t]8 !^$8 =h})°+R^{h,Lp.-%ԗJGXO: 6O8N2`Ṱi, wdm¹%i%zCGl7t~1+S*s>@yqL fIM%Bu4x͠3{,#jae3k)Oe#2l_a˂ ]LY|&Quu7V 6^W @J(gzmIq{RkxmB&UqI-c [vw.ďB ,6H 3m`Fʧ&`0h n 9@Q3v'0w0 @* 1'$ qk:=ҽK:0| B s] a#ygFZ#|_n!aLNpkglA߽?ַƧ##Y߇[<)`FqU{u+Wĸs g0@δctc1Ψ+0NNa2=\-;F.em~I!8`ܸ~o\&\g;6u9:"%ed;tT=`*%7v4[=O#sL39~ z{[oʻsK6-bGR?]ʂAM5 -Up G'Ҿ|8&eӃ| |Xo8>!bj5&!@q!yAD2oe}M޽iM!ElH\{CoR0چ*E 1xw;h֡{[]x׆|Y.ÃU.J\b~-h:u=żO!~"= Yo32&qh`b+hGk9ILב% qK((to{Z@VX=Ef  :eA1 ]Anư eIu~(_Hm<\T^@f-WגQs#za3- e) $W&N\EqOVu4Ywv[#J!xhPYXN捴}ꔑySV0P03 j@stHYǡ&lm.dn~19.μwCjF`H-tb#jUe/p Ճrw$`_2ݮʶ-ͯz;XӎuB'5`Yӧ>ę%B±8"P&Ԩrs:TA:$ͤel& -N0p N02 ù /0c#f!Ow*ۭ(ҷ0Eƶj]&s5fu.n3\z"KJGk}>*h'$/y|Wa {@8gR3e U+VӮi6{ά89cEs-oA S(D@6R* 2or3O.N*h:;X0Z0paIVGTPy"pX& B7qns-j b G?KZspK| : 43Ko1(@ ʌs-hx͹F,rN^Lz0`-s$pob2B_D! B`{BeD?H2WKqv`RR~(}qp%P#Ef rܘ&t+šL.7]Sj/ T#pW8`{ಁgs`\3])˚j 7?acݘGG$ї%B5C"(\6c\1 ?LǹPiME]d9 0bw>[_[b b#z Ϊv|}݁We5_&`P>+\{-SbK2$L`ZYzJ/qtT&qmΡa;/YwsB( gUpZyȽpFx>`?E"DI VrA v# xD\0# cagHk\kwyU&յPYzw&$2BK|/( _?m:$_D0`=&d˒ۚe"WqџnB3gWgKaks}DJhHDHh  QqTk Zљ{ȏ'ϔ %ʘ<ͰXFR Z+Uα Bt# mPór Q{uN|oLdSO΍Aqf 5I,0M3&af5Tp*VSE"-V8f BmtwaY_ϝWIfLSilrĦT'u|Jʦ1$pIf Yq-9Imydއ!sNf@5 Euy MX1`1M<1`͎97u֟Q ^$1l:܇gͦ3< 03"r_sh3%1-0$~̈oRƀ55hu OPgWB29'MNKqN_/ s$ O;'ꤣ9gPf ,*OG-8ǵ!_8?{U݄`(gK$ _hҶS02qD|),ݰJ깎@5X[Q_Z-/)Qp(A$= vBK H$sY15bCgw ӀGṛ0 F6Y 5JY8RGgv)26ݡMhU҇5L%#f^8峣3A1ӼΙrB̅] $|aRk2!)W\sNeuUVݡ>w.wN\zf釴)T!@P%8ZkRV^w 5ګSYbgi—"j%T_C$;C= #4I tۋtAke[c#k>>+Hk[]涭ƈЭ$C =K0ί+Z2 n0q, J$.nuGg36Osk\Bn#<8>At'ϐtˀG¸g`q22O TӪY^<)ӓkzUצQ1O7&x/M˳|< Z{ᬂ`see$X$Unl41(sѼ>KfHB41uӛ&#,q b<4i3T\ީPWsھ_>@ BT2@9ĺeKoKXkuG|*փjvmذ, BtqRiBaWF׬‰_oiKqN HRg'Q0 ~#i-+S|/$:g@B62L jp%6[0,m4TǮv,|̓NKT[zk@r yH$j"ީSzN)":4 $#jY> 5 MfG0]~l{+x3TΥumP*:"t{Eңh'GRd~B%y)v,yadsx`IeUPX N6'18\Yp^jbMbV{Ȉ4]ܶ`1FTgR?[ʭgK K0 㨎RI! =Ksr3f~v2Ii(`Lm^[f)g{òrĹge["dM( bs>b}9&""TM:ȍ-Ms.uRէJHHc7f+sLsH)9' o6hj$s.NsϵHdsDː]$-8oCk m(H3Gh̏8Ei! -DԾ]]k{ìU\/9 [0P`2\ #pd\k2|i#@_P_qL7mؤPF8*;AX~|Hz<`Ja|ap99T'c[3Pa&Ȑ,ƪT .]#y~]] Y҄lesη_cPj-GUީ.3/zc!㒅i E/itVkaZf( Ɯ|I7#iP4O ]-MgEH)DDž6CxB9wcxF$ XK}{_#6}L@Wܖd I?>.{/iޖϫk|2/gQH"տpUg=[LdV;W_u̴LN%^C*[u0x SU.?(jRKBCZ_Y!ؠ^ɷ;ŧ"}-[~w0kw%h-X) )g2ҰD]1XH;ÂMFC;@@P G$CԵqgwq.EQu\^e~T*sXxTS-J)}{b6D(!Fz;[$"[Tdg/ͽ8$ԺҨ ~U_/0hFzuo3Un&EÐe놁o&# $shRh{quj1<4, ba?0y>n:yDTհ^h&Οp gsy3|t^6wIkRDpA(F6 I;Es 6!+(s'}&B-8"N-VEuJ-!t&&N(vzI9җRm넻SnnVB- R3^f y\Aę.'9I;h|H]q9{ o ^궦?O wOs y0ƍ7E@ǫ-49EUA,P0J hAՄ#ɸSkwo]j^a436fp-B M ҉<<ťI*9rr'| <߯HW?HЫ+v7NIٮ~~%`192‰b"mu.x#pvDt\ VEwIdYsT,ы՟N>~WS.;su^RJ:|}t9e2np􁯝7,m͑W9hsDxH ~˚ N9 x. d9Kk9I&SD_rN)Z 9~B*<؏gW_osS^cC}ILQQmo""<( CܐЧT{|L&yȌh<o_eqM:U_6 Y_.qZn"NC G Q# .@. )KKC0KJ ?Y<'嗮^B+d%v6K$h_rB(yCHyb/..8:kQym~j`\1(g{jKוr?_Lm5Yߐ=Vt.2KLȀADwf\PLCl#FjhpC>1qyc[\#% +tZTrO86pĚp5fb= Y[皩bPRO'O R %~5~ӂժw-])|&oZW|@ f5ǵ <8/QBl kOKTKE<DdeQ$)nj8\Tk4Q~V G"$҃UHg됶EjwBͩ0ߏ%\}B5/-m;axlw"+J8p"(&oa%(3)4PP>$­Ik"j4![J5is !%BT768-hlLh^_fl3p@{u\ B jy᪵xK 3G)kR8kA"<רVʮg[zK./[i_"7ePʨi_ݴ]KuOx3ʚk_,-Bho,B,lėјusQeI]k;s\sL4/g\hȼpjIqxNNE[t#`$Ag%9`co:8g&HpOG44W`q ?Mn+׬hI Ur~$_βTr%0%Gq:=+ $_S8knLچC9V_4퀀}(`LY|JΨ+GݢA[-bZߊFk oY|o%v'Ǡķ/0 rqfBSW՗ޫ_>q\8/I9y^0(,皩g)eߪF.TѵǙG^^>ٱ䭾RBIaRlx DRM{T3ElrJ ,Rd# >i>BDcMKU"Ksϧi4o@a>!5[4D`|, " bsZ]\W%~1}Y&Uj肥n{r^[@Ƹ0i؏B' U==eU7+ 'D?EAHW AK En!Uz/ifa5Xg#KorU}Xhs~@I,f:i0}4:BDê!o:(ι?-a: 4="dEA9C/vU\L`O/z :>=LJX~΂aD+,s#}h22!bZ5̄QI$H}]Da?FUr;sj[VW]j@6aO"@~n:I}D lS McF!"W3L ѵl[moQVQh~6qvQG2 Y|&H?{?-O*(eIRQA, 5+IyRBeKd̷2Ck BrMe9$z*€KI`C~Jf`q35'Z#1ZL(vQ~)Nyݯ| Y Bl"N2^i,QDW Zn2I2 2n{w 妴1)\1cN60.l3<0w[y7LaM9 .JND8- XBΧ) UQ;,-W3&x$XRm3tP\-y*CTd1/0ԟ Gpc{,<ݲ.qU2yNTtpJ< ԜŎ*Z+ nJ4^Kf@J&#BJeUl$}l*NU%߬7И%")*~FY, ŵm1r+AndjSSW)OUjߒ H׋)SBi蚻k|Mω}3!HDڄ̿_HIO=ŷ|Ί/`sNsU]R>DP^[oL(]su~S~/ \Ts.{*i*7MVPӖf6=L.W %DagӋ͆Q"=s5,HĊs?*k1Rx{ 9MHr> 24l >Op*3]AT9M@cdʮg:J/Wk/{4kޅ*e;:}1 dwg#%6ͧ^*zTzf+oe:)wcsmqd~-ۋpTKeqݚp*O UrCvE.n?=cr32QǯEc#M`&) RV\p>rp: '1Մ[v] {T[Q\)?wlaBc眿, U8&?)\+.#bTٝ:P/9{ĨU[$9oـSL.*̦փaut/Ӌ{[YoqPvV˝Ѵ˹*4ʢt@2vHȫ@%_3#I{sn<:wpnI:g-vhw7Y, ylT|ldWJ8|6ZU7h$uw=A #I |!i4X7"#MJXߚ2='M,V]|ܷ✚6}:eR%ċ+ k:*B fC?S ϿePnza=yzRBeX 8gR0bhw|%{6Y9i})]nwN3Rs3̺1y9dEmx}7u /雲ֺ XR %~ >[{NunFZ0L&S5HzVJ<ͼC% մ{%SQezjȉn0OH0H8튡15{W T('@z&'[nMwN=?a`}oo1^Οڪ{7()6aus2]'^@5X\b0z{s s 3Q6[✆*x*qs|#30@mc. 6|p.C!@\_x7*`46LE:MZ_&X?+_)9;vm zIL+d#Zޯ*2ד=_HV`(?Tx"O*33cc mӼ8`@[cPg5xb$ )eGkeuo1~w?gOɃ),牢s_$V 69­9uK}˳~ YH?YpE$H i5WVKQ^_ww*\) [TiGDJOd>#b *rA15 (]hC聪/iyeqٝFx4[opޞ7ݏ=t?.%EBf$Qv>W>B1l} ^6x7?wܢa9v6=+V=! =|mܮswp/ʂW8-ĕ"^dvU;x W5I0x-rcm?V0^pݨJ!OPЂ}3xarC?ޯ^d]!>u#2Hrx#{.vq!>q^,np`9Q~EC u]ymQt.$`0@^gnEʻċb*,_mvsۛUE3ftݡJHڟ r4=s3h\4@gk?ٽ0l!K k`Gn3{ I DЅBcaIs>8GG3*H48~WW 'MV>k?C%>׫(_bֿ`L1AB^ӷ4yeY3IJH)DHHO mh|s4T D D,T}=y|}f]c":#">=@|"T>"$r(!.Ed1t,m@W1HysP$ElGƎgob4\0 z#>I ӋYe%`u?"h Dps͞L5re(RmO=k}P D+TZ|Bea (g'|Ff >?r枈&azM, b5.ƒ@I6Ҥ}yXHiP| >#JT][L?b0G\^~MKWR1+g" J˙|Z~ҰFLI1J"}dg&#ڀw*8  d5΢xzwn҅<"n|L:9ɛ^|%fJ쪬uHJH$U8uUm<=5yp^!@ܕhj ҐߒSӈ b&"l㱣^S[U(*%2"a"in;8Bm('jotf;$EVf[RGu_]U(~8ow?gUI(o>Huܖ Fg?tBAuhnsO\bUF\ϝv"9 ' ,kz b3]՗qE@gjv4KVЈ%IPLЍ),DC6*+n^6q y3]ETYtѮ>NmA \$\j<:ERO% 5}I(D j>+iI,YAUx2Hܤ;Bk J(D <`KSwj*pSçqslE6*e#a6x(WX$TU&C5w8bQBq7_q("w竡P|#gAܝhs&];]T_%Lƃ[_H x[vYoC-zh`j}@7ߥoGa_G=Yںi_Ccz0&[݊"v^[ϘV0`L-e~lF8NG0P`pO]USS¥N$"&Z`09A`yև۴äLSbsXi_ aơd>eMX1,m|NEyU څS,awTDE}Nir/6 _v%}=^N ʼ:O,|=Op.♐\*Ikbrxsv[;}q֚ۤ^$'O7(oz&taw73b+kDw sSIf<0 ~bI:@YL:kaX< PV߷M7[׺gAߊj76KUHt+o1]g:!9dwŲ( (5Sgd9 9[J5OH/󓭋X^FS'{hNk8o-Nk,Jy@m2u 0xym1o*c`>cXmg61gV`iNm&EV؎5%x5 QPfQl y2'vL(w͖L6U)hw2:0g,e1b)zðqj[dh~25`cP3KYT| ܄˰kB+`0&C_n@=,T`ӛ.RiadWBtNrܽ_P+X𨠋_j1$,I$$]'/Xt UТʝB)\+t[xz1`RX微OEyF-}y%||k-#C!_'ʉþe9WPMD)-MfuŔm%\/t޷1L]?]Z֡cu; KL/wVWdd2 P7៟k Y8>=?Q.N9ݪR<űңL6m?8ɞ+7,hh,CgaPϴ!;mqhP٩xyze8qg$䁂{<٠VK4<3}XYN3ZO>ިw<{Gak{3n@k/g #130G€gX*T]x1g`O9.[f"]__)NnVk?k1^`ϔkdA=giWL 1R|931 ߱0S\F),h*őR!3a#LYm-*:(`U^\GDp1 @g&VcPГB x4r1/N:\" 깛7-N<_zdEk5sJ'M)v?{ѹ;a43}=SO?|g13_]`9 iG}Tbԟ,O,tK_6 |m1v)fsH<6.`~][\ҏ#&e>Wha?ϐY $`2^mϐܳ01L{&@DҚ/ wD5>NEI>ů/88Fby-:cM[b]gf_[sbi)I ؜T8p^ = ׸A%+$^o[Yi9Tve^uSB(ڇn)݀M>tte'vqF$H1m^"{FW45apRˈHűy݋cT4ZTC @^&yX}=>1n K9C>s |fe 43/5@C)H)؉azN.* (F\ȫź 2_]@Ng2MY2Hah^ů 80ϝ`'Pq}g)8͜4;k 4 䂄&E6 \f{f[VΌ Lw# pRlfl 9v1]+'#X16y$c1zb7IZ=[OX.E`!ʙ;qljŌkD]XP*X߅I-7ak^5vV5-ڀILc$I$DL$" ǂ[P1t.x\?YW on-A..D,I&IdSZiUJR%$:L†Kҟ(k ;g(tܶuro\8$q s$=B-ju0j|ëZ1k;xދ)3!C=nTk{owsߔIw8xt-lZ6 5"˜1QB"h~脌Y酸PΦ@zߔ='ӾfeMKinq vCW 0M>@ pT Y G6:ћS&UQd*2.xEF¨8Jjxe`O:ID|R{R1 p@l) E5\3/\ Y͕nKg%`|[mg {~h&jF3~_~FwP¡w P5L<]io!)}G d[ u?2ŁדkK[Z80Dù};iMj:ixp6+ij)Xt{1~B܇/7K 'uօ>6X3y#yY31 ZKhX/1k+-QOHL=Q3ͯ[X ܉G'@=69L򩍰8-vYJ(&T@{miQ-?TUһ頸w 8>0x7w.Suqn҉E-N,XOwWZ#1nPR\ ඹ ŌKY$jY#DQ5|CH)WA =B<<ҵ"k" cH-ep['54fՄF44Itt$~EDK4>ᴯMj?= $b@x#jB^N75E!M璪5v9PdP刨!@T]o X^H;4\AiiD m'ĈHK)bJM*ԅ_#]wyn8'dV L k |]Dj㲀?H"?5˃RPe}yj= e E^ywqq~W_,qGRޗ3J)+P$r%xkSa=Z FB."+V8Cd秐v9I:uOZnT K^~N?My\OrFiJ;5@ HҨ8@Γğ`k<ᡪ% %FAA\C\弔U3|@*}*WCZ?P5qeJ8WMs %u|MrSܚ!zm䐴4EzT#(*ά:0?1D yVynw}(C@[eǬgM\JF*[ j8- 2[ vBoz&JIr.j=TUߏDbm6H`h2Tê|4?(TkEZ`]m8BA: s5c-F=oҦ%z xz*\7ހ'ĆvF)K)hXA-ӑ]S.lRRKhpߥ`dEWm<`+Y}W[UԧLWZ6m 0-HNfB\8\>My)@Zu6[~HpIjz:ݿKy` G͵hb֬at;;Iy 躓9 mf3)GqM˲מ54}gٞ_;#9 -!ӸYh6(xj dppe jl~< 5m~hysg!,hӉ(ޤ7[^dh Vi<Q|MyhR,bC?gDK'0l/AG2\JPQAk?C@q)}yObڥ:";q݂@$̌f s@\ m,9nsNO.o9FVU_gg3R#A"`nߎ~~D~vC(3cIjc8h{~ysH0mR2u:>MV4CnI`dh v!(S;_HVE]m$qBDm)cHFF`dQĆ}"wEdV;o~ir؆ חG8f՘8 *?XwϧCܦkjz lx('- o:>IȐyMWO/u]j[߰]grFZZm<9X\!JFsuT*r&%)$EKK_2JN=fj_E@eZ `5d6,p8̟rR? >º-W,q˜D7%b|CR WqZ\WIX,P7,N˒Odtb-áyԛ[fxRoԖ-'0=*J׼ʮrEצӀl. ֬άmI(x(6h9RN: g/-?*V5^ǿupJ:hPbGҔlIBN$ˏw酮6>n1Zq9wdtk-{y-fԌв,ܝ\XMT*ׇ5h.?*Oe<cZOl#Nh2tQ 58V߷snp54mzyalji@ LS!$bmUsdŶQǮz{+2YL o_i#<֧MAm/Bl> ag?_oa/yivת| ۴,r#Yr!Y0vVCmjGsZjV<<=Fdw }W~=HtC@rvZ8| "D$fGۀlO<`>?#*~Qlnkr\kɡP&ypl͊); 促tX3{i}hVDR2Z,#ϋbi-XͦJy 1sqSBazЊrz7+jk{}XPJgY K zf7Ooibe) yFhx#ivy,M9$K}ZWAj#q9` Qg{&Xܘ ~(6_ X$c  v"dV ==Z.(sӫ'G-|y&({NКQ [uiE<= t[Um탻Apv4En_F&|dz P}dOkЋutDid <MVw^ gU&PYC g[_U;csDmm,ɔx}PMqi p--F(aeHQdFg ֙=t y$aH'\k@^+:)ڻC^Y=`rD+xzZu/@iu>;|103We~K߶ D![neۺpxJO M/c3 #<2APNESB6NL8raLozרWЬp"؝U~f-'?CK^P1Z?hlq:T,6KP1O}of]Â`.THH<É)]MbВHAS1x6'9fH5ut$6h?L[Asc:2HلQaElnv'9"5;TZsm! u ㈇^]6gg >^:cZx6a1r (Z{ߜJeKż)"-et$`ѐ(jlh%(456&Ks e o@ڋ7Qwm^c]Θs6f(T^u"=ŕ;|b6c&\wM< JauԈKio3 !%7h{Zt_s>l #qr;ě|NEޜJ,0| ;7|Yֵcx +ZV^2Z'NxE`-^˃ZfXD!&oK+:q;p :bDW)jKT*![@(aw:'޽,jY$Ⱦi#14#L0Y(I87c)|kOf؀k.gsÎ@5[Z*\gMڴ*?ClK%h >QGm?MV`{z쵾z|Sivld+:˨ ڂeDa3* idCٹ6K; I6o(dTCdx-/|W1NTQب)Φ2iCDR}hXśtR<~9],(`1AKS*, gf)u eP p2;VG2[8H 4N"$%$qi){Ө,ik!PYGsH%K۰8T6,Id{޳Xo]钕js:nuZeN:+KGQ)+p%~._5qs!E]ױ Qg=q{IMyIk]X"t\}r ט/!o䪑 Sߨ)*rb?2 U !ܽ+#ZPTw"@0L"C4AW/aZfi0/z:Ua?^ , D0l QXq&/ӧmY]!;y*?!YlŇADSZk脷;8LDQ}0 j?/nK_=)SOo_u1$LJUW^uNσԊwT':|!/vyIp"BB! 6($m#FDe1}4njH\pvsz̯]Ef,_hfm}XȈHxL?m4f[4ز<&DX ( 8h%$c vG 1s$tj=턔#ZNE7H R@lUzB7%0aw1`u[v*@^SJp5ۘF,ER;#G g'a ocՌ\lB1?y:3nUȣ~y,%;Wm_q+B #jP> ݆c.j]v]?i ɗF6lO}d hq^h1nN{Ns)o6߬?{p|4hҥf*>9=MHGOmv0T#@}]!xC~0.#a;99{?g=ߴ_\My{x_IlRnnCH#eQyI&o+w݇)tF F-kչ9]gL"s4ݹ9"l!mұ6Б I.~7>5y*JSt+eVY= v:P^AQ'uijNy~bXxcK/fQgòwEP"{etvgx߃r[Gԋgq+ۺW BEV+iEi+V1'Bza4_`/#ɬ '};io\PVG=pw~}<<pKiA,B:L[g,52G}6F Vfc_A[O=II =g4%[m2&,aQ[oYYm>.>>$q*^6\g_b,]u a)o],)|"Cؙ<`~q=ik] LYwG`73p&'mCX Ltk/b- n_;8g_y@u3i$맩(,#QjtM1mEr9xv[ϡ s%~mկ?91yb[NL m:sV%Ϟ~Vt/_a}< \֖u~j[䛗Af$1B!IlDq C KeEtSy$>Ւ&;@879]mnh 雛ͤu.,Mtٮ%D]QL"whn~M!$`RԕM F T ]6{Fx AOl[k bcgOGЁrh (G ~*혶F暶Y+͚ ױ=/́Z>7eo8>q,0᜗t8C{;7@і4AW,h 64tݸ]sx) 6I6ieYOE~b ,LeKZ_Z|h~NO҈~N*{:fWǔO[ҷ״W/KtluպeIۿYӿx:9۟~@K:zM|}.yPC{^hU[ot~87sn Z&qHϟ.l`^ Ba"=k=S *GQ!vSJkS1T*6CA4~.=Ն#VOybߊןӗ"M6Fp(.8:AX$Ҏ &DdQ)?qb7! YDjT0I:`C*$DH@ރAH>'(xX Pº!5ē\!QCWJ?S9H!59H4:ި~5 oj/'{ף.29EK-sFؙs^2ɵwc;π :EcOλFݯ7k^'Pt)YvbzJA3/qSKXYERZo88/nߕE0.ZF{Av呻.i5yQDhz is7 h7<0X$MTviMQ(wU*HTpyIkEPt_C$τ`'b̅*@]P9R]2ݲ\}Y>ܟ3ROx"Kp5 ŏ^,򬄩lw&̀Q]K<:($LA¸,MBʟO[5oMctn?! i?D&]Գ`BI?jPJBZdx"p882j15N"yMp@j*sI(`\Ahq7]*TyXͪAސD{Ard)yJʞXpT$baIJEP\ƯAeiŜ (D(Xu5Z%B1AvClQ yZەƪ! (fLӸII2yczz~J 0WbQmjfw.Rqy*{JI+9i6H6o/AKͯqt W+<ת(-ri˟!u ǂƑJKf]R&C,SgWϩʓX"M vȑ='Z茹V3:`ϹITGR"F){f )#ft4OіchiKWzkV49Q >3KKCR. M_&) `xO 5n@A$)=O^)jF!˻DXfrrUұr)_ъfH  t|*) ֖X5p6Q[ʔV HtcWy.} n|:$?o0TO("f!c7MM(>H^m=q^ׇMb6qlNіӬy"MHW<,DfHT_ieMqE\niڱEkTL[=@| v풁CcVߏ$а C?IBRR62- *xA:)&o괄G0xT+4I(|?)1c&Ҋ&I8Pma4Pe4Z퐼B'r&zXcqI2K%Ox VVNVNm Fwu ILXI~J@*}uwgQǿcfԹcAs|K+)+ZGwP33%ͫѬ"R#{~uHNiw||O\sΎ'Fq]:F4k~9T٘WIc?I(A21)1I[h$vn//uG_so H/: qExŇB"GM$+ޔc^i?}^t1G9@Gr2kYOʾa?JhKz^s}c͛?M^dkɲ全 c҄=] OgW~߆ }U<8ݟ6M;pܥ佘2 az?6e?,5KZ>*eD(|Ji'Ib"9/H5]WSl+ק1nP((I 4T rc8ű`$ V D̈B)ea m(EĈ{M~!4&oEM&#UL7`,`LD:hgn?-]AkEwH@9;jJc*D1ABCatM#FFKҐe;Ŗᬩ r1k0} + Ԭ0 tGs Em5I3عyR-K:هoi0kg%ͧ٬}3G>lyR!HL =ƌ/ ŭeSUX 9x<۾iY;H&pגۍE?Mg*%X(D2X>>]2aS'}SA{s҅nC*[ǧoYS$4kKzܫ^V)~O(N>=WƲhrfH:c=KIqRL\%c{sȭ :'\\TRIXپQ ^r06k=qvV:ztUf?Q{8HaФm퍙*6'\f -Ҧ?f9&6me3[lNm)Oknu6Oˌ^M^ =Ay_[iNo޽)s12|2+EDA.'u * B6}lq#15MH"3E^*e3r)]sSnp?yK/QXcAH1M5U@%wS}ipQ-]wo\!:N/ R5Uy~BqGr*r)tY&J\t#灔\F*:Z aBz̏?逢֛PqUvnj%]X^*E0 ,?*b3P=1L/Hh[*{m#=;fT/)Q9 D Y:>~-5 ۘ12rWT 7yXG]G&|̦{N鈻W4~lޅrcI`]b؅: vm7n뛴G -{J%\^{QUsX: a~c}"QT6X)<Qј$ eW Lj^Fl:MCe|?zg@~22uUd^eܪZ+Kq=҄ r qt82 $CsFK^Ix.KW<ڐ:WDp(ީQpE0 l&s>9g|euJKۥ~`TH( 1VS%RQ$U ѝpTȐzNׂPN߮W*QFFBɣ<-z@4ڜ@ɗu͊v- W I?z[QbZu>B('^f.в# 8 w;(߮lN59kWF^F( K'DPps]W7hKZJ[#H߲v\a_6鿾.|ф}siDyBQaϥq`)U2FLb;?f=D1T ]j?Z^zMД^)S-ӗഇgolang-github-goccy-go-json-0.10.3/color.go000066400000000000000000000023701463555276600204700ustar00rootroot00000000000000package 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), } ) golang-github-goccy-go-json-0.10.3/color_test.go000066400000000000000000000015121463555276600215240ustar00rootroot00000000000000package json_test import ( "testing" "github.com/goccy/go-json" ) func TestColorize(t *testing.T) { v := struct { A int B uint C float32 D string E bool F []byte G []int H *struct{} I map[string]interface{} }{ A: 123, B: 456, C: 3.14, D: "hello", E: true, F: []byte("binary"), G: []int{1, 2, 3, 4}, H: nil, I: map[string]interface{}{ "mapA": -10, "mapB": 10, "mapC": nil, }, } t.Run("marshal with color", func(t *testing.T) { b, err := json.MarshalWithOption(v, json.Colorize(json.DefaultColorScheme)) if err != nil { t.Fatal(err) } t.Log(string(b)) }) t.Run("marshal indent with color", func(t *testing.T) { b, err := json.MarshalIndentWithOption(v, "", "\t", json.Colorize(json.DefaultColorScheme)) if err != nil { t.Fatal(err) } t.Log("\n" + string(b)) }) } golang-github-goccy-go-json-0.10.3/decode.go000066400000000000000000000144431463555276600206010ustar00rootroot00000000000000package json import ( "context" "fmt" "io" "reflect" "unsafe" "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 *decoder.Stream } const ( nul = '\000' ) 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) 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, header.ptr) if err != nil { decoder.ReleaseRuntimeContext(ctx) return err } decoder.ReleaseRuntimeContext(ctx) return validateEndBuf(src, cursor) } 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) 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 } 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) } var ( pathDecoder = decoder.NewPathDecoder() ) func extractFromPath(path *Path, data []byte, optFuncs ...DecodeOptionFunc) ([][]byte, error) { if path.path.RootSelectorOnly { return [][]byte{data}, nil } src := make([]byte, len(data)+1) // append nul byte to the end copy(src, data) ctx := decoder.TakeRuntimeContext() ctx.Buf = src ctx.Option.Flags = 0 ctx.Option.Flags |= decoder.PathOption ctx.Option.Path = path.path for _, optFunc := range optFuncs { optFunc(ctx.Option) } paths, cursor, err := pathDecoder.DecodePath(ctx, 0, 0) if err != nil { decoder.ReleaseRuntimeContext(ctx) return nil, err } decoder.ReleaseRuntimeContext(ctx) if err := validateEndBuf(src, cursor); err != nil { return nil, err } return paths, nil } 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) } func validateEndBuf(src []byte, cursor int64) error { for { switch src[cursor] { case ' ', '\t', '\n', '\r': cursor++ continue case nul: return nil } return errors.ErrSyntax( fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]), cursor+1, ) } } //nolint:staticcheck //go:nosplit func noescape(p unsafe.Pointer) unsafe.Pointer { x := uintptr(p) return unsafe.Pointer(x ^ 0) } func validateType(typ *runtime.Type, p uintptr) error { if typ == nil || typ.Kind() != reflect.Ptr || p == 0 { return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)} } return nil } // NewDecoder returns a new decoder that reads from r. // // The decoder introduces its own buffering and may // read data from r beyond the JSON values requested. func NewDecoder(r io.Reader) *Decoder { s := decoder.NewStream(r) return &Decoder{ s: s, } } // 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() } // Decode reads the next JSON-encoded value from its // input and stores it in the value pointed to by v. // // 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 := *(**runtime.Type)(unsafe.Pointer(&typeptr)) if err := validateType(copiedType, ptr); err != nil { return err } dec, err := decoder.CompileToGetDecoder(typ) if err != nil { return err } if err := d.s.PrepareForDecode(); err != nil { return err } s := d.s for _, optFunc := range optFuncs { optFunc(s.Option) } if err := dec.DecodeStream(s, 0, header.ptr); err != nil { return err } s.Reset() return nil } func (d *Decoder) More() bool { return d.s.More() } func (d *Decoder) Token() (Token, error) { 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 } func (d *Decoder) InputOffset() int64 { 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 } golang-github-goccy-go-json-0.10.3/decode_test.go000066400000000000000000003171541463555276600216450ustar00rootroot00000000000000package json_test import ( "bytes" "context" "encoding" stdjson "encoding/json" "errors" "fmt" "image" "math" "math/big" "net" "reflect" "strconv" "strings" "testing" "time" "unsafe" "github.com/goccy/go-json" ) func Test_Decoder(t *testing.T) { t.Run("int", func(t *testing.T) { var v int assertErr(t, json.Unmarshal([]byte(`-1`), &v)) assertEq(t, "int", int(-1), v) }) t.Run("int8", func(t *testing.T) { var v int8 assertErr(t, json.Unmarshal([]byte(`-2`), &v)) assertEq(t, "int8", int8(-2), v) }) t.Run("int16", func(t *testing.T) { var v int16 assertErr(t, json.Unmarshal([]byte(`-3`), &v)) assertEq(t, "int16", int16(-3), v) }) t.Run("int32", func(t *testing.T) { var v int32 assertErr(t, json.Unmarshal([]byte(`-4`), &v)) assertEq(t, "int32", int32(-4), v) }) t.Run("int64", func(t *testing.T) { var v int64 assertErr(t, json.Unmarshal([]byte(`-5`), &v)) assertEq(t, "int64", int64(-5), v) }) t.Run("uint", func(t *testing.T) { var v uint assertErr(t, json.Unmarshal([]byte(`1`), &v)) assertEq(t, "uint", uint(1), v) }) t.Run("uint8", func(t *testing.T) { var v uint8 assertErr(t, json.Unmarshal([]byte(`2`), &v)) assertEq(t, "uint8", uint8(2), v) }) t.Run("uint16", func(t *testing.T) { var v uint16 assertErr(t, json.Unmarshal([]byte(`3`), &v)) assertEq(t, "uint16", uint16(3), v) }) t.Run("uint32", func(t *testing.T) { var v uint32 assertErr(t, json.Unmarshal([]byte(`4`), &v)) assertEq(t, "uint32", uint32(4), v) }) t.Run("uint64", func(t *testing.T) { var v uint64 assertErr(t, json.Unmarshal([]byte(`5`), &v)) assertEq(t, "uint64", uint64(5), v) }) t.Run("bool", func(t *testing.T) { t.Run("true", func(t *testing.T) { var v bool assertErr(t, json.Unmarshal([]byte(`true`), &v)) assertEq(t, "bool", true, v) }) t.Run("false", func(t *testing.T) { v := true assertErr(t, json.Unmarshal([]byte(`false`), &v)) assertEq(t, "bool", false, v) }) }) t.Run("string", func(t *testing.T) { var v string assertErr(t, json.Unmarshal([]byte(`"hello"`), &v)) assertEq(t, "string", "hello", v) }) t.Run("float32", func(t *testing.T) { var v float32 assertErr(t, json.Unmarshal([]byte(`3.14`), &v)) assertEq(t, "float32", float32(3.14), v) }) t.Run("float64", func(t *testing.T) { var v float64 assertErr(t, json.Unmarshal([]byte(`3.14`), &v)) assertEq(t, "float64", float64(3.14), v) }) t.Run("slice", func(t *testing.T) { var v []int assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v)) assertEq(t, "slice", fmt.Sprint([]int{1, 2, 3, 4}), fmt.Sprint(v)) }) t.Run("slice_reuse_data", func(t *testing.T) { v := make([]int, 0, 10) assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v)) assertEq(t, "slice", fmt.Sprint([]int{1, 2, 3, 4}), fmt.Sprint(v)) assertEq(t, "cap", 10, cap(v)) }) t.Run("array", func(t *testing.T) { var v [4]int assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v)) assertEq(t, "array", fmt.Sprint([4]int{1, 2, 3, 4}), fmt.Sprint(v)) }) t.Run("map", func(t *testing.T) { var v map[string]int assertErr(t, json.Unmarshal([]byte(` { "a": 1, "b": 2, "c": 3, "d": 4 } `), &v)) assertEq(t, "map.a", v["a"], 1) assertEq(t, "map.b", v["b"], 2) assertEq(t, "map.c", v["c"], 3) assertEq(t, "map.d", v["d"], 4) t.Run("nested map", func(t *testing.T) { // https://github.com/goccy/go-json/issues/8 content := ` { "a": { "nestedA": "value of nested a" }, "b": { "nestedB": "value of nested b" }, "c": { "nestedC": "value of nested c" } }` var v map[string]interface{} assertErr(t, json.Unmarshal([]byte(content), &v)) assertEq(t, "length", 3, len(v)) }) }) t.Run("struct", func(t *testing.T) { type T struct { AA int `json:"aa"` BB string `json:"bb"` CC bool `json:"cc"` } var v struct { A int `json:"abcd"` B string `json:"str"` C bool D *T E func() } content := []byte(` { "abcd": 123, "str" : "hello", "c" : true, "d" : { "aa": 2, "bb": "world", "cc": true }, "e" : null }`) assertErr(t, json.Unmarshal(content, &v)) assertEq(t, "struct.A", 123, v.A) assertEq(t, "struct.B", "hello", v.B) assertEq(t, "struct.C", true, v.C) assertEq(t, "struct.D.AA", 2, v.D.AA) assertEq(t, "struct.D.BB", "world", v.D.BB) assertEq(t, "struct.D.CC", true, v.D.CC) assertEq(t, "struct.E", true, v.E == nil) t.Run("struct.field null", func(t *testing.T) { var v struct { A string B []string C []int D map[string]interface{} E [2]string F interface{} G func() } assertErr(t, json.Unmarshal([]byte(`{"a":null,"b":null,"c":null,"d":null,"e":null,"f":null,"g":null}`), &v)) assertEq(t, "string", v.A, "") assertNeq(t, "[]string", v.B, nil) assertEq(t, "[]string", len(v.B), 0) assertNeq(t, "[]int", v.C, nil) assertEq(t, "[]int", len(v.C), 0) assertNeq(t, "map", v.D, nil) assertEq(t, "map", len(v.D), 0) assertNeq(t, "array", v.E, nil) assertEq(t, "array", len(v.E), 2) assertEq(t, "interface{}", v.F, nil) assertEq(t, "nilfunc", true, v.G == nil) }) t.Run("struct.pointer must be nil", func(t *testing.T) { var v struct { A *int } json.Unmarshal([]byte(`{"a": "alpha"}`), &v) assertEq(t, "struct.A", v.A, (*int)(nil)) }) }) t.Run("interface", func(t *testing.T) { t.Run("number", func(t *testing.T) { var v interface{} assertErr(t, json.Unmarshal([]byte(`10`), &v)) assertEq(t, "interface.kind", "float64", reflect.TypeOf(v).Kind().String()) assertEq(t, "interface", `10`, fmt.Sprint(v)) }) t.Run("string", func(t *testing.T) { var v interface{} assertErr(t, json.Unmarshal([]byte(`"hello"`), &v)) assertEq(t, "interface.kind", "string", reflect.TypeOf(v).Kind().String()) assertEq(t, "interface", `hello`, fmt.Sprint(v)) }) t.Run("escaped string", func(t *testing.T) { var v interface{} assertErr(t, json.Unmarshal([]byte(`"he\"llo"`), &v)) assertEq(t, "interface.kind", "string", reflect.TypeOf(v).Kind().String()) assertEq(t, "interface", `he"llo`, fmt.Sprint(v)) }) t.Run("bool", func(t *testing.T) { var v interface{} assertErr(t, json.Unmarshal([]byte(`true`), &v)) assertEq(t, "interface.kind", "bool", reflect.TypeOf(v).Kind().String()) assertEq(t, "interface", `true`, fmt.Sprint(v)) }) t.Run("slice", func(t *testing.T) { var v interface{} assertErr(t, json.Unmarshal([]byte(`[1,2,3,4]`), &v)) assertEq(t, "interface.kind", "slice", reflect.TypeOf(v).Kind().String()) assertEq(t, "interface", `[1 2 3 4]`, fmt.Sprint(v)) }) t.Run("map", func(t *testing.T) { var v interface{} assertErr(t, json.Unmarshal([]byte(`{"a": 1, "b": "c"}`), &v)) assertEq(t, "interface.kind", "map", reflect.TypeOf(v).Kind().String()) m := v.(map[string]interface{}) assertEq(t, "interface", `1`, fmt.Sprint(m["a"])) assertEq(t, "interface", `c`, fmt.Sprint(m["b"])) }) t.Run("null", func(t *testing.T) { var v interface{} v = 1 assertErr(t, json.Unmarshal([]byte(`null`), &v)) assertEq(t, "interface", nil, v) }) }) t.Run("func", func(t *testing.T) { var v func() assertErr(t, json.Unmarshal([]byte(`null`), &v)) assertEq(t, "nilfunc", true, v == nil) }) } func TestIssue98(t *testing.T) { data := "[\"\\" var v interface{} if err := json.Unmarshal([]byte(data), &v); err == nil { t.Fatal("expected error") } } func Test_Decoder_UseNumber(t *testing.T) { dec := json.NewDecoder(strings.NewReader(`{"a": 3.14}`)) dec.UseNumber() var v map[string]interface{} assertErr(t, dec.Decode(&v)) assertEq(t, "json.Number", "json.Number", fmt.Sprintf("%T", v["a"])) } func Test_Decoder_DisallowUnknownFields(t *testing.T) { dec := json.NewDecoder(strings.NewReader(`{"x": 1}`)) dec.DisallowUnknownFields() var v struct { x int } err := dec.Decode(&v) if err == nil { t.Fatal("expected unknown field error") } if err.Error() != `json: unknown field "x"` { t.Fatal("expected unknown field error") } } func Test_Decoder_EmptyObjectWithSpace(t *testing.T) { dec := json.NewDecoder(strings.NewReader(`{"obj":{ }}`)) var v struct { Obj map[string]int `json:"obj"` } assertErr(t, dec.Decode(&v)) } type unmarshalJSON struct { v int } func (u *unmarshalJSON) UnmarshalJSON(b []byte) error { var v int if err := json.Unmarshal(b, &v); err != nil { return err } u.v = v return nil } func Test_UnmarshalJSON(t *testing.T) { t.Run("*struct", func(t *testing.T) { var v unmarshalJSON assertErr(t, json.Unmarshal([]byte(`10`), &v)) assertEq(t, "unmarshal", 10, v.v) }) } type unmarshalText struct { v int } func (u *unmarshalText) UnmarshalText(b []byte) error { var v int if err := json.Unmarshal(b, &v); err != nil { return err } u.v = v return nil } func Test_UnmarshalText(t *testing.T) { t.Run("*struct", func(t *testing.T) { var v unmarshalText assertErr(t, json.Unmarshal([]byte(`"11"`), &v)) assertEq(t, "unmarshal", v.v, 11) }) } func Test_InvalidUnmarshalError(t *testing.T) { t.Run("nil", func(t *testing.T) { var v *struct{} err := fmt.Sprint(json.Unmarshal([]byte(`{}`), v)) assertEq(t, "invalid unmarshal error", "json: Unmarshal(nil *struct {})", err) }) t.Run("non pointer", func(t *testing.T) { var v int err := fmt.Sprint(json.Unmarshal([]byte(`{}`), v)) assertEq(t, "invalid unmarshal error", "json: Unmarshal(non-pointer int)", err) }) } func Test_Token(t *testing.T) { dec := json.NewDecoder(strings.NewReader(`{"a": 1, "b": true, "c": [1, "two", null]}`)) cnt := 0 for { if _, err := dec.Token(); err != nil { break } cnt++ } if cnt != 12 { t.Fatal("failed to parse token") } } func Test_DecodeStream(t *testing.T) { const stream = ` [ {"Name": "Ed", "Text": "Knock knock."}, {"Name": "Sam", "Text": "Who's there?"}, {"Name": "Ed", "Text": "Go fmt."}, {"Name": "Sam", "Text": "Go fmt who?"}, {"Name": "Ed", "Text": "Go fmt yourself!"} ] ` type Message struct { Name, Text string } dec := json.NewDecoder(strings.NewReader(stream)) tk, err := dec.Token() assertErr(t, err) assertEq(t, "[", fmt.Sprint(tk), "[") elem := 0 // while the array contains values for dec.More() { var m Message // decode an array value (Message) assertErr(t, dec.Decode(&m)) if m.Name == "" || m.Text == "" { t.Fatal("failed to assign value to struct field") } elem++ } assertEq(t, "decode count", elem, 5) tk, err = dec.Token() assertErr(t, err) assertEq(t, "]", fmt.Sprint(tk), "]") } type T struct { X string Y int Z int `json:"-"` } type U struct { Alphabet string `json:"alpha"` } type V struct { F1 interface{} F2 int32 F3 json.Number F4 *VOuter } type VOuter struct { V V } type W struct { S SS } type P struct { PP PP } type PP struct { T T Ts []T } type SS string func (*SS) UnmarshalJSON(data []byte) error { return &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(SS(""))} } // ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and // without UseNumber var ifaceNumAsFloat64 = map[string]interface{}{ "k1": float64(1), "k2": "s", "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)}, "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)}, } var ifaceNumAsNumber = map[string]interface{}{ "k1": json.Number("1"), "k2": "s", "k3": []interface{}{json.Number("1"), json.Number("2.0"), json.Number("3e-3")}, "k4": map[string]interface{}{"kk1": "s", "kk2": json.Number("2")}, } type tx struct { x int } type u8 uint8 // A type that can unmarshal itself. type unmarshaler struct { T bool } func (u *unmarshaler) UnmarshalJSON(b []byte) error { *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called. return nil } type ustruct struct { M unmarshaler } var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil) type ustructText struct { M unmarshalerText } // u8marshal is an integer type that can marshal/unmarshal itself. type u8marshal uint8 func (u8 u8marshal) MarshalText() ([]byte, error) { return []byte(fmt.Sprintf("u%d", u8)), nil } var errMissingU8Prefix = errors.New("missing 'u' prefix") func (u8 *u8marshal) UnmarshalText(b []byte) error { if !bytes.HasPrefix(b, []byte{'u'}) { return errMissingU8Prefix } n, err := strconv.Atoi(string(b[1:])) if err != nil { return err } *u8 = u8marshal(n) return nil } var _ encoding.TextUnmarshaler = (*u8marshal)(nil) var ( umtrue = unmarshaler{true} umslice = []unmarshaler{{true}} umstruct = ustruct{unmarshaler{true}} umtrueXY = unmarshalerText{"x", "y"} umsliceXY = []unmarshalerText{{"x", "y"}} umstructXY = ustructText{unmarshalerText{"x", "y"}} ummapXY = map[unmarshalerText]bool{{"x", "y"}: true} ) // Test data structures for anonymous fields. type Point struct { Z int } type Top struct { Level0 int Embed0 *Embed0a *Embed0b `json:"e,omitempty"` // treated as named Embed0c `json:"-"` // ignored Loop Embed0p // has Point with X, Y, used Embed0q // has Point with Z, used embed // contains exported field } type Embed0 struct { Level1a int // overridden by Embed0a's Level1a with json tag Level1b int // used because Embed0a's Level1b is renamed Level1c int // used because Embed0a's Level1c is ignored Level1d int // annihilated by Embed0a's Level1d Level1e int `json:"x"` // annihilated by Embed0a.Level1e } type Embed0a struct { Level1a int `json:"Level1a,omitempty"` Level1b int `json:"LEVEL1B,omitempty"` Level1c int `json:"-"` Level1d int // annihilated by Embed0's Level1d Level1f int `json:"x"` // annihilated by Embed0's Level1e } type Embed0b Embed0 type Embed0c Embed0 type Embed0p struct { image.Point } type Embed0q struct { Point } type embed struct { Q int } type Loop struct { Loop1 int `json:",omitempty"` Loop2 int `json:",omitempty"` *Loop } // From reflect test: // The X in S6 and S7 annihilate, but they also block the X in S8.S9. type S5 struct { S6 S7 S8 } type S6 struct { X int } type S7 S6 type S8 struct { S9 } type S9 struct { X int Y int } // From reflect test: // The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. type S10 struct { S11 S12 S13 } type S11 struct { S6 } type S12 struct { S6 } type S13 struct { S8 } type Ambig struct { // Given "hello", the first match should win. First int `json:"HELLO"` Second int `json:"Hello"` } type XYZ struct { X interface{} Y interface{} Z interface{} } type unexportedWithMethods struct{} func (unexportedWithMethods) F() {} type byteWithMarshalJSON byte func (b byteWithMarshalJSON) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf(`"Z%.2x"`, byte(b))), nil } func (b *byteWithMarshalJSON) UnmarshalJSON(data []byte) error { if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' { return fmt.Errorf("bad quoted string") } i, err := strconv.ParseInt(string(data[2:4]), 16, 8) if err != nil { return fmt.Errorf("bad hex") } *b = byteWithMarshalJSON(i) return nil } type byteWithPtrMarshalJSON byte func (b *byteWithPtrMarshalJSON) MarshalJSON() ([]byte, error) { return byteWithMarshalJSON(*b).MarshalJSON() } func (b *byteWithPtrMarshalJSON) UnmarshalJSON(data []byte) error { return (*byteWithMarshalJSON)(b).UnmarshalJSON(data) } type byteWithMarshalText byte func (b byteWithMarshalText) MarshalText() ([]byte, error) { return []byte(fmt.Sprintf(`Z%.2x`, byte(b))), nil } func (b *byteWithMarshalText) UnmarshalText(data []byte) error { if len(data) != 3 || data[0] != 'Z' { return fmt.Errorf("bad quoted string") } i, err := strconv.ParseInt(string(data[1:3]), 16, 8) if err != nil { return fmt.Errorf("bad hex") } *b = byteWithMarshalText(i) return nil } type byteWithPtrMarshalText byte func (b *byteWithPtrMarshalText) MarshalText() ([]byte, error) { return byteWithMarshalText(*b).MarshalText() } func (b *byteWithPtrMarshalText) UnmarshalText(data []byte) error { return (*byteWithMarshalText)(b).UnmarshalText(data) } type intWithMarshalJSON int func (b intWithMarshalJSON) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf(`"Z%.2x"`, int(b))), nil } func (b *intWithMarshalJSON) UnmarshalJSON(data []byte) error { if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' { return fmt.Errorf("bad quoted string") } i, err := strconv.ParseInt(string(data[2:4]), 16, 8) if err != nil { return fmt.Errorf("bad hex") } *b = intWithMarshalJSON(i) return nil } type intWithPtrMarshalJSON int func (b *intWithPtrMarshalJSON) MarshalJSON() ([]byte, error) { return intWithMarshalJSON(*b).MarshalJSON() } func (b *intWithPtrMarshalJSON) UnmarshalJSON(data []byte) error { return (*intWithMarshalJSON)(b).UnmarshalJSON(data) } type intWithMarshalText int func (b intWithMarshalText) MarshalText() ([]byte, error) { return []byte(fmt.Sprintf(`Z%.2x`, int(b))), nil } func (b *intWithMarshalText) UnmarshalText(data []byte) error { if len(data) != 3 || data[0] != 'Z' { return fmt.Errorf("bad quoted string") } i, err := strconv.ParseInt(string(data[1:3]), 16, 8) if err != nil { return fmt.Errorf("bad hex") } *b = intWithMarshalText(i) return nil } type intWithPtrMarshalText int func (b *intWithPtrMarshalText) MarshalText() ([]byte, error) { return intWithMarshalText(*b).MarshalText() } func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error { return (*intWithMarshalText)(b).UnmarshalText(data) } type mapStringToStringData struct { Data map[string]string `json:"data"` } type unmarshalTest struct { in string ptr interface{} // new(type) out interface{} err error useNumber bool golden bool disallowUnknownFields bool } type B struct { B bool `json:",string"` } type DoublePtr struct { I **int J **int } var unmarshalTests = []unmarshalTest{ // basic types {in: `true`, ptr: new(bool), out: true}, // 0 {in: `1`, ptr: new(int), out: 1}, // 1 {in: `1.2`, ptr: new(float64), out: 1.2}, // 2 {in: `-5`, ptr: new(int16), out: int16(-5)}, // 3 {in: `2`, ptr: new(json.Number), out: json.Number("2"), useNumber: true}, // 4 {in: `2`, ptr: new(json.Number), out: json.Number("2")}, // 5 {in: `2`, ptr: new(interface{}), out: float64(2.0)}, // 6 {in: `2`, ptr: new(interface{}), out: json.Number("2"), useNumber: true}, // 7 {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"}, // 8 {in: `"http:\/\/"`, ptr: new(string), out: "http://"}, // 9 {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"}, // 10 {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"}, // 11 {in: "null", ptr: new(interface{}), out: nil}, // 12 {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &json.UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}}, // 13 {in: `{"X": 23}`, ptr: new(T), out: T{}, err: &json.UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, // 14 {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, // 15, 16 {in: `{"x": 1}`, ptr: new(tx), err: fmt.Errorf("json: unknown field \"x\""), disallowUnknownFields: true}, // 17 {in: `{"S": 23}`, ptr: new(W), out: W{}, err: &json.UnmarshalTypeError{"number", reflect.TypeOf(SS("")), 0, "W", "S"}}, // 18 {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: json.Number("3")}}, // 19 {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: json.Number("1"), F2: int32(2), F3: json.Number("3")}, useNumber: true}, // 20 {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64}, // 21 {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true}, // 22 // raw values with whitespace {in: "\n true ", ptr: new(bool), out: true}, // 23 {in: "\t 1 ", ptr: new(int), out: 1}, // 24 {in: "\r 1.2 ", ptr: new(float64), out: 1.2}, // 25 {in: "\t -5 \n", ptr: new(int16), out: int16(-5)}, // 26 {in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"}, // 27 // Z has a "-" tag. {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}}, // 28 {in: `{"Y": 1, "Z": 2}`, ptr: new(T), err: fmt.Errorf("json: unknown field \"Z\""), disallowUnknownFields: true}, // 29 {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}}, // 30 {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true}, // 31 {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}}, // 32 {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}}, // 33 {in: `{"alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true}, // 34 // syntax errors {in: `{"X": "foo", "Y"}`, err: json.NewSyntaxError("invalid character '}' after object key", 17)}, // 35 {in: `[1, 2, 3+]`, err: json.NewSyntaxError("invalid character '+' after array element", 9)}, // 36 {in: `{"X":12x}`, err: json.NewSyntaxError("invalid character 'x' after object key:value pair", 8), useNumber: true}, // 37 {in: `[2, 3`, err: json.NewSyntaxError("unexpected end of JSON input", 5)}, // 38 {in: `{"F3": -}`, ptr: new(V), out: V{F3: json.Number("-")}, err: json.NewSyntaxError("strconv.ParseFloat: parsing \"-\": invalid syntax", 9)}, // 39 // raw value errors {in: "\x01 42", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, // 40 {in: " 42 \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 5)}, // 41 {in: "\x01 true", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, // 42 {in: " false \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 8)}, // 43 {in: "\x01 1.2", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, // 44 {in: " 3.4 \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 6)}, // 45 {in: "\x01 \"string\"", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, // 46 {in: " \"string\" \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 11)}, // 47 // array tests {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}}, // 48 {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}}, // 49 {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}}, // 50 {in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")}, // 51 // empty array to interface test {in: `[]`, ptr: new([]interface{}), out: []interface{}{}}, //52 {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)}, //53 {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}}, //54 {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}}, // 55 // composite tests {in: allValueIndent, ptr: new(All), out: allValue}, // 56 {in: allValueCompact, ptr: new(All), out: allValue}, // 57 {in: allValueIndent, ptr: new(*All), out: &allValue}, // 58 {in: allValueCompact, ptr: new(*All), out: &allValue}, // 59 {in: pallValueIndent, ptr: new(All), out: pallValue}, // 60 {in: pallValueCompact, ptr: new(All), out: pallValue}, // 61 {in: pallValueIndent, ptr: new(*All), out: &pallValue}, // 62 {in: pallValueCompact, ptr: new(*All), out: &pallValue}, // 63 // unmarshal interface test {in: `{"T":false}`, ptr: new(unmarshaler), out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called {in: `{"T":false}`, ptr: new(*unmarshaler), out: &umtrue}, // 65 {in: `[{"T":false}]`, ptr: new([]unmarshaler), out: umslice}, // 66 {in: `[{"T":false}]`, ptr: new(*[]unmarshaler), out: &umslice}, // 67 {in: `{"M":{"T":"x:y"}}`, ptr: new(ustruct), out: umstruct}, // 68 // UnmarshalText interface test {in: `"x:y"`, ptr: new(unmarshalerText), out: umtrueXY}, // 69 {in: `"x:y"`, ptr: new(*unmarshalerText), out: &umtrueXY}, // 70 {in: `["x:y"]`, ptr: new([]unmarshalerText), out: umsliceXY}, // 71 {in: `["x:y"]`, ptr: new(*[]unmarshalerText), out: &umsliceXY}, // 72 {in: `{"M":"x:y"}`, ptr: new(ustructText), out: umstructXY}, // 73 // integer-keyed map test { in: `{"-1":"a","0":"b","1":"c"}`, // 74 ptr: new(map[int]string), out: map[int]string{-1: "a", 0: "b", 1: "c"}, }, { in: `{"0":"a","10":"c","9":"b"}`, // 75 ptr: new(map[u8]string), out: map[u8]string{0: "a", 9: "b", 10: "c"}, }, { in: `{"-9223372036854775808":"min","9223372036854775807":"max"}`, // 76 ptr: new(map[int64]string), out: map[int64]string{math.MinInt64: "min", math.MaxInt64: "max"}, }, { in: `{"18446744073709551615":"max"}`, // 77 ptr: new(map[uint64]string), out: map[uint64]string{math.MaxUint64: "max"}, }, { in: `{"0":false,"10":true}`, // 78 ptr: new(map[uintptr]bool), out: map[uintptr]bool{0: false, 10: true}, }, // Check that MarshalText and UnmarshalText take precedence // over default integer handling in map keys. { in: `{"u2":4}`, // 79 ptr: new(map[u8marshal]int), out: map[u8marshal]int{2: 4}, }, { in: `{"2":4}`, // 80 ptr: new(map[u8marshal]int), err: errMissingU8Prefix, }, // integer-keyed map errors { in: `{"abc":"abc"}`, // 81 ptr: new(map[int]string), err: &json.UnmarshalTypeError{Value: "number a", Type: reflect.TypeOf(0), Offset: 2}, }, { in: `{"256":"abc"}`, // 82 ptr: new(map[uint8]string), err: &json.UnmarshalTypeError{Value: "number 256", Type: reflect.TypeOf(uint8(0)), Offset: 2}, }, { in: `{"128":"abc"}`, // 83 ptr: new(map[int8]string), err: &json.UnmarshalTypeError{Value: "number 128", Type: reflect.TypeOf(int8(0)), Offset: 2}, }, { in: `{"-1":"abc"}`, // 84 ptr: new(map[uint8]string), err: &json.UnmarshalTypeError{Value: "number -", Type: reflect.TypeOf(uint8(0)), Offset: 2}, }, { in: `{"F":{"a":2,"3":4}}`, // 85 ptr: new(map[string]map[int]int), err: &json.UnmarshalTypeError{Value: "number a", Type: reflect.TypeOf(int(0)), Offset: 7}, }, { in: `{"F":{"a":2,"3":4}}`, // 86 ptr: new(map[string]map[uint]int), err: &json.UnmarshalTypeError{Value: "number a", Type: reflect.TypeOf(uint(0)), Offset: 7}, }, // Map keys can be encoding.TextUnmarshalers. {in: `{"x:y":true}`, ptr: new(map[unmarshalerText]bool), out: ummapXY}, // 87 // If multiple values for the same key exists, only the most recent value is used. {in: `{"x:y":false,"x:y":true}`, ptr: new(map[unmarshalerText]bool), out: ummapXY}, // 88 { // 89 in: `{ "Level0": 1, "Level1b": 2, "Level1c": 3, "x": 4, "Level1a": 5, "LEVEL1B": 6, "e": { "Level1a": 8, "Level1b": 9, "Level1c": 10, "Level1d": 11, "x": 12 }, "Loop1": 13, "Loop2": 14, "X": 15, "Y": 16, "Z": 17, "Q": 18 }`, ptr: new(Top), out: Top{ Level0: 1, Embed0: Embed0{ Level1b: 2, Level1c: 3, }, Embed0a: &Embed0a{ Level1a: 5, Level1b: 6, }, Embed0b: &Embed0b{ Level1a: 8, Level1b: 9, Level1c: 10, Level1d: 11, Level1e: 12, }, Loop: Loop{ Loop1: 13, Loop2: 14, }, Embed0p: Embed0p{ Point: image.Point{X: 15, Y: 16}, }, Embed0q: Embed0q{ Point: Point{Z: 17}, }, embed: embed{ Q: 18, }, }, }, { in: `{"hello": 1}`, // 90 ptr: new(Ambig), out: Ambig{First: 1}, }, { in: `{"X": 1,"Y":2}`, // 91 ptr: new(S5), out: S5{S8: S8{S9: S9{Y: 2}}}, }, { in: `{"X": 1,"Y":2}`, // 92 ptr: new(S5), err: fmt.Errorf("json: unknown field \"X\""), disallowUnknownFields: true, }, { in: `{"X": 1,"Y":2}`, // 93 ptr: new(S10), out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}}, }, { in: `{"X": 1,"Y":2}`, // 94 ptr: new(S10), err: fmt.Errorf("json: unknown field \"X\""), disallowUnknownFields: true, }, { in: `{"I": 0, "I": null, "J": null}`, // 95 ptr: new(DoublePtr), out: DoublePtr{I: nil, J: nil}, }, { in: "\"hello\\ud800world\"", // 96 ptr: new(string), out: "hello\ufffdworld", }, { in: "\"hello\\ud800\\ud800world\"", // 97 ptr: new(string), out: "hello\ufffd\ufffdworld", }, { in: "\"hello\\ud800\\ud800world\"", // 98 ptr: new(string), out: "hello\ufffd\ufffdworld", }, // Used to be issue 8305, but time.Time implements encoding.TextUnmarshaler so this works now. { in: `{"2009-11-10T23:00:00Z": "hello world"}`, // 99 ptr: new(map[time.Time]string), out: map[time.Time]string{time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC): "hello world"}, }, // issue 8305 { in: `{"2009-11-10T23:00:00Z": "hello world"}`, // 100 ptr: new(map[Point]string), err: &json.UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(Point{}), Offset: 0}, }, { in: `{"asdf": "hello world"}`, // 101 ptr: new(map[unmarshaler]string), err: &json.UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(unmarshaler{}), Offset: 1}, }, // related to issue 13783. // Go 1.7 changed marshaling a slice of typed byte to use the methods on the byte type, // similar to marshaling a slice of typed int. // These tests check that, assuming the byte type also has valid decoding methods, // either the old base64 string encoding or the new per-element encoding can be // successfully unmarshaled. The custom unmarshalers were accessible in earlier // versions of Go, even though the custom marshaler was not. { in: `"AQID"`, // 102 ptr: new([]byteWithMarshalJSON), out: []byteWithMarshalJSON{1, 2, 3}, }, { in: `["Z01","Z02","Z03"]`, // 103 ptr: new([]byteWithMarshalJSON), out: []byteWithMarshalJSON{1, 2, 3}, golden: true, }, { in: `"AQID"`, // 104 ptr: new([]byteWithMarshalText), out: []byteWithMarshalText{1, 2, 3}, }, { in: `["Z01","Z02","Z03"]`, // 105 ptr: new([]byteWithMarshalText), out: []byteWithMarshalText{1, 2, 3}, golden: true, }, { in: `"AQID"`, // 106 ptr: new([]byteWithPtrMarshalJSON), out: []byteWithPtrMarshalJSON{1, 2, 3}, }, { in: `["Z01","Z02","Z03"]`, // 107 ptr: new([]byteWithPtrMarshalJSON), out: []byteWithPtrMarshalJSON{1, 2, 3}, golden: true, }, { in: `"AQID"`, // 108 ptr: new([]byteWithPtrMarshalText), out: []byteWithPtrMarshalText{1, 2, 3}, }, { in: `["Z01","Z02","Z03"]`, // 109 ptr: new([]byteWithPtrMarshalText), out: []byteWithPtrMarshalText{1, 2, 3}, golden: true, }, // ints work with the marshaler but not the base64 []byte case { in: `["Z01","Z02","Z03"]`, // 110 ptr: new([]intWithMarshalJSON), out: []intWithMarshalJSON{1, 2, 3}, golden: true, }, { in: `["Z01","Z02","Z03"]`, // 111 ptr: new([]intWithMarshalText), out: []intWithMarshalText{1, 2, 3}, golden: true, }, { in: `["Z01","Z02","Z03"]`, // 112 ptr: new([]intWithPtrMarshalJSON), out: []intWithPtrMarshalJSON{1, 2, 3}, golden: true, }, { in: `["Z01","Z02","Z03"]`, // 113 ptr: new([]intWithPtrMarshalText), out: []intWithPtrMarshalText{1, 2, 3}, golden: true, }, {in: `0.000001`, ptr: new(float64), out: 0.000001, golden: true}, // 114 {in: `1e-07`, ptr: new(float64), out: 1e-7, golden: true}, // 115 {in: `100000000000000000000`, ptr: new(float64), out: 100000000000000000000.0, golden: true}, // 116 {in: `1e+21`, ptr: new(float64), out: 1e21, golden: true}, // 117 {in: `-0.000001`, ptr: new(float64), out: -0.000001, golden: true}, // 118 {in: `-1e-07`, ptr: new(float64), out: -1e-7, golden: true}, // 119 {in: `-100000000000000000000`, ptr: new(float64), out: -100000000000000000000.0, golden: true}, // 120 {in: `-1e+21`, ptr: new(float64), out: -1e21, golden: true}, // 121 {in: `999999999999999900000`, ptr: new(float64), out: 999999999999999900000.0, golden: true}, // 122 {in: `9007199254740992`, ptr: new(float64), out: 9007199254740992.0, golden: true}, // 123 {in: `9007199254740993`, ptr: new(float64), out: 9007199254740992.0, golden: false}, // 124 { in: `{"V": {"F2": "hello"}}`, // 125 ptr: new(VOuter), err: &json.UnmarshalTypeError{ Value: `number "`, Struct: "V", Field: "F2", Type: reflect.TypeOf(int32(0)), Offset: 20, }, }, { in: `{"V": {"F4": {}, "F2": "hello"}}`, // 126 ptr: new(VOuter), err: &json.UnmarshalTypeError{ Value: `number "`, Struct: "V", Field: "F2", Type: reflect.TypeOf(int32(0)), Offset: 30, }, }, // issue 15146. // invalid inputs in wrongStringTests below. {in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true}, // 127 {in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true}, // 128 {in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: bool unexpected end of JSON input`)}, // 129 {in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid character as true`)}, // 130 {in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: bool unexpected end of JSON input`)}, // 131 {in: `{"B": "null"}`, ptr: new(B), out: B{false}}, // 132 {in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid character as null`)}, // 133 {in: `{"B": [2, 3]}`, ptr: new(B), err: errors.New(`json: cannot unmarshal array into Go struct field B.B of type string`)}, // 134 // additional tests for disallowUnknownFields { // 135 in: `{ "Level0": 1, "Level1b": 2, "Level1c": 3, "x": 4, "Level1a": 5, "LEVEL1B": 6, "e": { "Level1a": 8, "Level1b": 9, "Level1c": 10, "Level1d": 11, "x": 12 }, "Loop1": 13, "Loop2": 14, "X": 15, "Y": 16, "Z": 17, "Q": 18, "extra": true }`, ptr: new(Top), err: fmt.Errorf("json: unknown field \"extra\""), disallowUnknownFields: true, }, { // 136 in: `{ "Level0": 1, "Level1b": 2, "Level1c": 3, "x": 4, "Level1a": 5, "LEVEL1B": 6, "e": { "Level1a": 8, "Level1b": 9, "Level1c": 10, "Level1d": 11, "x": 12, "extra": null }, "Loop1": 13, "Loop2": 14, "X": 15, "Y": 16, "Z": 17, "Q": 18 }`, ptr: new(Top), err: fmt.Errorf("json: unknown field \"extra\""), disallowUnknownFields: true, }, // issue 26444 // UnmarshalTypeError without field & struct values { in: `{"data":{"test1": "bob", "test2": 123}}`, // 137 ptr: new(mapStringToStringData), err: &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 37, Struct: "mapStringToStringData", Field: "Data"}, }, { in: `{"data":{"test1": 123, "test2": "bob"}}`, // 138 ptr: new(mapStringToStringData), err: &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "Data"}, }, // trying to decode JSON arrays or objects via TextUnmarshaler { in: `[1, 2, 3]`, // 139 ptr: new(MustNotUnmarshalText), err: &json.UnmarshalTypeError{Value: "array", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1}, }, { in: `{"foo": "bar"}`, // 140 ptr: new(MustNotUnmarshalText), err: &json.UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1}, }, // #22369 { in: `{"PP": {"T": {"Y": "bad-type"}}}`, // 141 ptr: new(P), err: &json.UnmarshalTypeError{ Value: `number "`, Struct: "T", Field: "Y", Type: reflect.TypeOf(int(0)), Offset: 29, }, }, { in: `{"Ts": [{"Y": 1}, {"Y": 2}, {"Y": "bad-type"}]}`, // 142 ptr: new(PP), err: &json.UnmarshalTypeError{ Value: `number "`, Struct: "T", Field: "Y", Type: reflect.TypeOf(int(0)), Offset: 29, }, }, // #14702 { in: `invalid`, // 143 ptr: new(json.Number), err: json.NewSyntaxError( `invalid character 'i' looking for beginning of value`, 1, ), }, { in: `"invalid"`, // 144 ptr: new(json.Number), err: fmt.Errorf(`strconv.ParseFloat: parsing "invalid": invalid syntax`), }, { in: `{"A":"invalid"}`, // 145 ptr: new(struct{ A json.Number }), err: fmt.Errorf(`strconv.ParseFloat: parsing "invalid": invalid syntax`), }, { in: `{"A":"invalid"}`, // 146 ptr: new(struct { A json.Number `json:",string"` }), err: fmt.Errorf(`json: json.Number unexpected end of JSON input`), }, { in: `{"A":"invalid"}`, // 147 ptr: new(map[string]json.Number), err: fmt.Errorf(`strconv.ParseFloat: parsing "invalid": invalid syntax`), }, // invalid UTF-8 is coerced to valid UTF-8. { in: "\"hello\xffworld\"", // 148 ptr: new(string), out: "hello\ufffdworld", }, { in: "\"hello\xc2\xc2world\"", // 149 ptr: new(string), out: "hello\ufffd\ufffdworld", }, { in: "\"hello\xc2\xffworld\"", // 150 ptr: new(string), out: "hello\ufffd\ufffdworld", }, { in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"", // 151 ptr: new(string), out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld", }, {in: "-128", ptr: new(int8), out: int8(-128)}, {in: "127", ptr: new(int8), out: int8(127)}, {in: "-32768", ptr: new(int16), out: int16(-32768)}, {in: "32767", ptr: new(int16), out: int16(32767)}, {in: "-2147483648", ptr: new(int32), out: int32(-2147483648)}, {in: "2147483647", ptr: new(int32), out: int32(2147483647)}, } type All struct { Bool bool Int int Int8 int8 Int16 int16 Int32 int32 Int64 int64 Uint uint Uint8 uint8 Uint16 uint16 Uint32 uint32 Uint64 uint64 Uintptr uintptr Float32 float32 Float64 float64 Foo string `json:"bar"` Foo2 string `json:"bar2,dummyopt"` IntStr int64 `json:",string"` UintptrStr uintptr `json:",string"` PBool *bool PInt *int PInt8 *int8 PInt16 *int16 PInt32 *int32 PInt64 *int64 PUint *uint PUint8 *uint8 PUint16 *uint16 PUint32 *uint32 PUint64 *uint64 PUintptr *uintptr PFloat32 *float32 PFloat64 *float64 String string PString *string Map map[string]Small MapP map[string]*Small PMap *map[string]Small PMapP *map[string]*Small EmptyMap map[string]Small NilMap map[string]Small Slice []Small SliceP []*Small PSlice *[]Small PSliceP *[]*Small EmptySlice []Small NilSlice []Small StringSlice []string ByteSlice []byte Small Small PSmall *Small PPSmall **Small Interface interface{} PInterface *interface{} unexported int } type Small struct { Tag string } var allValue = All{ Bool: true, Int: 2, Int8: 3, Int16: 4, Int32: 5, Int64: 6, Uint: 7, Uint8: 8, Uint16: 9, Uint32: 10, Uint64: 11, Uintptr: 12, Float32: 14.1, Float64: 15.1, Foo: "foo", Foo2: "foo2", IntStr: 42, UintptrStr: 44, String: "16", Map: map[string]Small{ "17": {Tag: "tag17"}, "18": {Tag: "tag18"}, }, MapP: map[string]*Small{ "19": {Tag: "tag19"}, "20": nil, }, EmptyMap: map[string]Small{}, Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}}, SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}}, EmptySlice: []Small{}, StringSlice: []string{"str24", "str25", "str26"}, ByteSlice: []byte{27, 28, 29}, Small: Small{Tag: "tag30"}, PSmall: &Small{Tag: "tag31"}, Interface: 5.2, } var pallValue = All{ PBool: &allValue.Bool, PInt: &allValue.Int, PInt8: &allValue.Int8, PInt16: &allValue.Int16, PInt32: &allValue.Int32, PInt64: &allValue.Int64, PUint: &allValue.Uint, PUint8: &allValue.Uint8, PUint16: &allValue.Uint16, PUint32: &allValue.Uint32, PUint64: &allValue.Uint64, PUintptr: &allValue.Uintptr, PFloat32: &allValue.Float32, PFloat64: &allValue.Float64, PString: &allValue.String, PMap: &allValue.Map, PMapP: &allValue.MapP, PSlice: &allValue.Slice, PSliceP: &allValue.SliceP, PPSmall: &allValue.PSmall, PInterface: &allValue.Interface, } var allValueIndent = `{ "Bool": true, "Int": 2, "Int8": 3, "Int16": 4, "Int32": 5, "Int64": 6, "Uint": 7, "Uint8": 8, "Uint16": 9, "Uint32": 10, "Uint64": 11, "Uintptr": 12, "Float32": 14.1, "Float64": 15.1, "bar": "foo", "bar2": "foo2", "IntStr": "42", "UintptrStr": "44", "PBool": null, "PInt": null, "PInt8": null, "PInt16": null, "PInt32": null, "PInt64": null, "PUint": null, "PUint8": null, "PUint16": null, "PUint32": null, "PUint64": null, "PUintptr": null, "PFloat32": null, "PFloat64": null, "String": "16", "PString": null, "Map": { "17": { "Tag": "tag17" }, "18": { "Tag": "tag18" } }, "MapP": { "19": { "Tag": "tag19" }, "20": null }, "PMap": null, "PMapP": null, "EmptyMap": {}, "NilMap": null, "Slice": [ { "Tag": "tag20" }, { "Tag": "tag21" } ], "SliceP": [ { "Tag": "tag22" }, null, { "Tag": "tag23" } ], "PSlice": null, "PSliceP": null, "EmptySlice": [], "NilSlice": null, "StringSlice": [ "str24", "str25", "str26" ], "ByteSlice": "Gxwd", "Small": { "Tag": "tag30" }, "PSmall": { "Tag": "tag31" }, "PPSmall": null, "Interface": 5.2, "PInterface": null }` var allValueCompact = strings.Map(noSpace, allValueIndent) var pallValueIndent = `{ "Bool": false, "Int": 0, "Int8": 0, "Int16": 0, "Int32": 0, "Int64": 0, "Uint": 0, "Uint8": 0, "Uint16": 0, "Uint32": 0, "Uint64": 0, "Uintptr": 0, "Float32": 0, "Float64": 0, "bar": "", "bar2": "", "IntStr": "0", "UintptrStr": "0", "PBool": true, "PInt": 2, "PInt8": 3, "PInt16": 4, "PInt32": 5, "PInt64": 6, "PUint": 7, "PUint8": 8, "PUint16": 9, "PUint32": 10, "PUint64": 11, "PUintptr": 12, "PFloat32": 14.1, "PFloat64": 15.1, "String": "", "PString": "16", "Map": null, "MapP": null, "PMap": { "17": { "Tag": "tag17" }, "18": { "Tag": "tag18" } }, "PMapP": { "19": { "Tag": "tag19" }, "20": null }, "EmptyMap": null, "NilMap": null, "Slice": null, "SliceP": null, "PSlice": [ { "Tag": "tag20" }, { "Tag": "tag21" } ], "PSliceP": [ { "Tag": "tag22" }, null, { "Tag": "tag23" } ], "EmptySlice": null, "NilSlice": null, "StringSlice": null, "ByteSlice": null, "Small": { "Tag": "" }, "PSmall": null, "PPSmall": { "Tag": "tag31" }, "Interface": null, "PInterface": 5.2 }` var pallValueCompact = strings.Map(noSpace, pallValueIndent) type NullTest struct { Bool bool Int int Int8 int8 Int16 int16 Int32 int32 Int64 int64 Uint uint Uint8 uint8 Uint16 uint16 Uint32 uint32 Uint64 uint64 Float32 float32 Float64 float64 String string PBool *bool Map map[string]string Slice []string Interface interface{} PRaw *json.RawMessage PTime *time.Time PBigInt *big.Int PText *MustNotUnmarshalText PBuffer *bytes.Buffer // has methods, just not relevant ones PStruct *struct{} Raw json.RawMessage Time time.Time BigInt big.Int Text MustNotUnmarshalText Buffer bytes.Buffer Struct struct{} } type MustNotUnmarshalJSON struct{} func (x MustNotUnmarshalJSON) UnmarshalJSON(data []byte) error { return errors.New("MustNotUnmarshalJSON was used") } type MustNotUnmarshalText struct{} func (x MustNotUnmarshalText) UnmarshalText(text []byte) error { return errors.New("MustNotUnmarshalText was used") } func isSpace(c byte) bool { return c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') } func noSpace(c rune) rune { if isSpace(byte(c)) { //only used for ascii return -1 } return c } var badUTF8 = []struct { in, out string }{ {"hello\xffworld", `"hello\ufffdworld"`}, {"", `""`}, {"\xff", `"\ufffd"`}, {"\xff\xff", `"\ufffd\ufffd"`}, {"a\xffb", `"a\ufffdb"`}, {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`}, } func TestMarshalAllValue(t *testing.T) { b, err := json.Marshal(allValue) if err != nil { t.Fatalf("Marshal allValue: %v", err) } if string(b) != allValueCompact { t.Errorf("Marshal allValueCompact") diff(t, b, []byte(allValueCompact)) return } b, err = json.Marshal(pallValue) if err != nil { t.Fatalf("Marshal pallValue: %v", err) } if string(b) != pallValueCompact { t.Errorf("Marshal pallValueCompact") diff(t, b, []byte(pallValueCompact)) return } } func TestMarshalBadUTF8(t *testing.T) { for _, tt := range badUTF8 { b, err := json.Marshal(tt.in) if string(b) != tt.out || err != nil { t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out) } } } func TestMarshalNumberZeroVal(t *testing.T) { var n json.Number out, err := json.Marshal(n) if err != nil { t.Fatal(err) } outStr := string(out) if outStr != "0" { t.Fatalf("Invalid zero val for Number: %q", outStr) } } func TestMarshalEmbeds(t *testing.T) { top := &Top{ Level0: 1, Embed0: Embed0{ Level1b: 2, Level1c: 3, }, Embed0a: &Embed0a{ Level1a: 5, Level1b: 6, }, Embed0b: &Embed0b{ Level1a: 8, Level1b: 9, Level1c: 10, Level1d: 11, Level1e: 12, }, Loop: Loop{ Loop1: 13, Loop2: 14, }, Embed0p: Embed0p{ Point: image.Point{X: 15, Y: 16}, }, Embed0q: Embed0q{ Point: Point{Z: 17}, }, embed: embed{ Q: 18, }, } b, err := json.Marshal(top) if err != nil { t.Fatal(err) } want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}" if string(b) != want { t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want) } } func equalError(a, b error) bool { if a == nil { return b == nil } if b == nil { return a == nil } return a.Error() == b.Error() } func TestUnmarshal(t *testing.T) { for i, tt := range unmarshalTests { t.Run(fmt.Sprintf("%d_%q", i, tt.in), func(t *testing.T) { in := []byte(tt.in) if tt.ptr == nil { return } typ := reflect.TypeOf(tt.ptr) if typ.Kind() != reflect.Ptr { t.Errorf("#%d: unmarshalTest.ptr %T is not a pointer type", i, tt.ptr) return } typ = typ.Elem() // v = new(right-type) v := reflect.New(typ) if !reflect.DeepEqual(tt.ptr, v.Interface()) { // There's no reason for ptr to point to non-zero data, // as we decode into new(right-type), so the data is // discarded. // This can easily mean tests that silently don't test // what they should. To test decoding into existing // data, see TestPrefilled. t.Errorf("#%d: unmarshalTest.ptr %#v is not a pointer to a zero value", i, tt.ptr) return } dec := json.NewDecoder(bytes.NewReader(in)) if tt.useNumber { dec.UseNumber() } if tt.disallowUnknownFields { dec.DisallowUnknownFields() } if err := dec.Decode(v.Interface()); !equalError(err, tt.err) { t.Errorf("#%d: %v, want %v", i, err, tt.err) return } else if err != nil { return } if !reflect.DeepEqual(v.Elem().Interface(), tt.out) { t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out) data, _ := json.Marshal(v.Elem().Interface()) println(string(data)) data, _ = json.Marshal(tt.out) println(string(data)) return } // Check round trip also decodes correctly. if tt.err == nil { enc, err := json.Marshal(v.Interface()) if err != nil { t.Errorf("#%d: error re-marshaling: %v", i, err) return } if tt.golden && !bytes.Equal(enc, in) { t.Errorf("#%d: remarshal mismatch:\nhave: %s\nwant: %s", i, enc, in) } vv := reflect.New(reflect.TypeOf(tt.ptr).Elem()) dec = json.NewDecoder(bytes.NewReader(enc)) if tt.useNumber { dec.UseNumber() } if err := dec.Decode(vv.Interface()); err != nil { t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err) return } if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) { t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface()) t.Errorf(" In: %q", strings.Map(noSpace, string(in))) t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc))) return } } }) } } func TestUnmarshalMarshal(t *testing.T) { initBig() var v interface{} if err := json.Unmarshal(jsonBig, &v); err != nil { t.Fatalf("Unmarshal: %v", err) } b, err := json.Marshal(v) if err != nil { t.Fatalf("Marshal: %v", err) } if !bytes.Equal(jsonBig, b) { t.Errorf("Marshal jsonBig") diff(t, b, jsonBig) return } } var numberTests = []struct { in string i int64 intErr string f float64 floatErr string }{ {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1}, {in: "-12", i: -12, f: -12.0}, {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"}, } // Independent of Decode, basic coverage of the accessors in Number func TestNumberAccessors(t *testing.T) { for _, tt := range numberTests { n := json.Number(tt.in) if s := n.String(); s != tt.in { t.Errorf("Number(%q).String() is %q", tt.in, s) } if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i { t.Errorf("Number(%q).Int64() is %d", tt.in, i) } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) { t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err) } if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f { t.Errorf("Number(%q).Float64() is %g", tt.in, f) } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) { t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err) } } } func TestLargeByteSlice(t *testing.T) { s0 := make([]byte, 2000) for i := range s0 { s0[i] = byte(i) } b, err := json.Marshal(s0) if err != nil { t.Fatalf("Marshal: %v", err) } var s1 []byte if err := json.Unmarshal(b, &s1); err != nil { t.Fatalf("Unmarshal: %v", err) } if !bytes.Equal(s0, s1) { t.Errorf("Marshal large byte slice") diff(t, s0, s1) } } type Xint struct { X int } func TestUnmarshalInterface(t *testing.T) { var xint Xint var i interface{} = &xint if err := json.Unmarshal([]byte(`{"X":1}`), &i); err != nil { t.Fatalf("Unmarshal: %v", err) } if xint.X != 1 { t.Fatalf("Did not write to xint") } } func TestUnmarshalPtrPtr(t *testing.T) { var xint Xint pxint := &xint if err := json.Unmarshal([]byte(`{"X":1}`), &pxint); err != nil { t.Fatalf("Unmarshal: %v", err) } if xint.X != 1 { t.Fatalf("Did not write to xint") } } func TestEscape(t *testing.T) { const input = `"foobar"` + " [\u2028 \u2029]" const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"` b, err := json.Marshal(input) if err != nil { t.Fatalf("Marshal error: %v", err) } if s := string(b); s != expected { t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected) } } // WrongString is a struct that's misusing the ,string modifier. type WrongString struct { Message string `json:"result,string"` } type wrongStringTest struct { in, err string } var wrongStringTests = []wrongStringTest{ {`{"result":"x"}`, `invalid character 'x' looking for beginning of value`}, {`{"result":"foo"}`, `invalid character 'f' looking for beginning of value`}, {`{"result":"123"}`, `json: cannot unmarshal number into Go struct field WrongString.Message of type string`}, {`{"result":123}`, `json: cannot unmarshal number into Go struct field WrongString.Message of type string`}, {`{"result":"\""}`, `json: string unexpected end of JSON input`}, {`{"result":"\"foo"}`, `json: string unexpected end of JSON input`}, } // If people misuse the ,string modifier, the error message should be // helpful, telling the user that they're doing it wrong. func TestErrorMessageFromMisusedString(t *testing.T) { for n, tt := range wrongStringTests { r := strings.NewReader(tt.in) var s WrongString err := json.NewDecoder(r).Decode(&s) got := fmt.Sprintf("%v", err) if got != tt.err { t.Errorf("%d. got err = %q, want %q", n, got, tt.err) } } } func TestRefUnmarshal(t *testing.T) { type S struct { // Ref is defined in encode_test.go. R0 Ref R1 *Ref R2 RefText R3 *RefText } want := S{ R0: 12, R1: new(Ref), R2: 13, R3: new(RefText), } *want.R1 = 12 *want.R3 = 13 var got S if err := json.Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil { t.Fatalf("Unmarshal: %v", err) } if !reflect.DeepEqual(got, want) { t.Errorf("got %+v, want %+v", got, want) } } // Test that the empty string doesn't panic decoding when ,string is specified // Issue 3450 func TestEmptyString(t *testing.T) { type T2 struct { Number1 int `json:",string"` Number2 int `json:",string"` } data := `{"Number1":"1", "Number2":""}` dec := json.NewDecoder(strings.NewReader(data)) var t2 T2 err := dec.Decode(&t2) if err == nil { t.Fatal("Decode: did not return error") } if t2.Number1 != 1 { t.Fatal("Decode: did not set Number1") } } // Test that a null for ,string is not replaced with the previous quoted string (issue 7046). // It should also not be an error (issue 2540, issue 8587). func TestNullString(t *testing.T) { type T struct { A int `json:",string"` B int `json:",string"` C *int `json:",string"` } data := []byte(`{"A": "1", "B": null, "C": null}`) var s T s.B = 1 s.C = new(int) *s.C = 2 err := json.Unmarshal(data, &s) if err != nil { t.Fatalf("Unmarshal: %v", err) } if s.B != 1 || s.C != nil { t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C) } } func intp(x int) *int { p := new(int) *p = x return p } func intpp(x *int) **int { pp := new(*int) *pp = x return pp } var interfaceSetTests = []struct { pre interface{} json string post interface{} }{ {"foo", `"bar"`, "bar"}, {"foo", `2`, 2.0}, {"foo", `true`, true}, {"foo", `null`, nil}, {nil, `null`, nil}, {new(int), `null`, nil}, {(*int)(nil), `null`, nil}, //{new(*int), `null`, new(*int)}, {(**int)(nil), `null`, nil}, {intp(1), `null`, nil}, //{intpp(nil), `null`, intpp(nil)}, //{intpp(intp(1)), `null`, intpp(nil)}, } func TestInterfaceSet(t *testing.T) { for idx, tt := range interfaceSetTests { b := struct{ X interface{} }{tt.pre} blob := `{"X":` + tt.json + `}` if err := json.Unmarshal([]byte(blob), &b); err != nil { t.Errorf("Unmarshal %#q: %v", blob, err) continue } if !reflect.DeepEqual(b.X, tt.post) { t.Errorf("%d: Unmarshal %#q into %#v: X=%#v, want %#v", idx, blob, tt.pre, b.X, tt.post) } } } // JSON null values should be ignored for primitives and string values instead of resulting in an error. // Issue 2540 func TestUnmarshalNulls(t *testing.T) { // Unmarshal docs: // The JSON null value unmarshals into an interface, map, pointer, or slice // by setting that Go value to nil. Because null is often used in JSON to mean // ``not present,'' unmarshaling a JSON null into any other Go type has no effect // on the value and produces no error. jsonData := []byte(`{ "Bool" : null, "Int" : null, "Int8" : null, "Int16" : null, "Int32" : null, "Int64" : null, "Uint" : null, "Uint8" : null, "Uint16" : null, "Uint32" : null, "Uint64" : null, "Float32" : null, "Float64" : null, "String" : null, "PBool": null, "Map": null, "Slice": null, "Interface": null, "PRaw": null, "PTime": null, "PBigInt": null, "PText": null, "PBuffer": null, "PStruct": null, "Raw": null, "Time": null, "BigInt": null, "Text": null, "Buffer": null, "Struct": null }`) nulls := NullTest{ Bool: true, Int: 2, Int8: 3, Int16: 4, Int32: 5, Int64: 6, Uint: 7, Uint8: 8, Uint16: 9, Uint32: 10, Uint64: 11, Float32: 12.1, Float64: 13.1, String: "14", PBool: new(bool), Map: map[string]string{}, Slice: []string{}, Interface: new(MustNotUnmarshalJSON), PRaw: new(json.RawMessage), PTime: new(time.Time), PBigInt: new(big.Int), PText: new(MustNotUnmarshalText), PStruct: new(struct{}), PBuffer: new(bytes.Buffer), Raw: json.RawMessage("123"), Time: time.Unix(123456789, 0), BigInt: *big.NewInt(123), } before := nulls.Time.String() err := json.Unmarshal(jsonData, &nulls) if err != nil { t.Errorf("Unmarshal of null values failed: %v", err) } if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 || nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 || nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" { t.Errorf("Unmarshal of null values affected primitives") } if nulls.PBool != nil { t.Errorf("Unmarshal of null did not clear nulls.PBool") } if nulls.Map != nil { t.Errorf("Unmarshal of null did not clear nulls.Map") } if nulls.Slice != nil { t.Errorf("Unmarshal of null did not clear nulls.Slice") } if nulls.Interface != nil { t.Errorf("Unmarshal of null did not clear nulls.Interface") } if nulls.PRaw != nil { t.Errorf("Unmarshal of null did not clear nulls.PRaw") } if nulls.PTime != nil { t.Errorf("Unmarshal of null did not clear nulls.PTime") } if nulls.PBigInt != nil { t.Errorf("Unmarshal of null did not clear nulls.PBigInt") } if nulls.PText != nil { t.Errorf("Unmarshal of null did not clear nulls.PText") } if nulls.PBuffer != nil { t.Errorf("Unmarshal of null did not clear nulls.PBuffer") } if nulls.PStruct != nil { t.Errorf("Unmarshal of null did not clear nulls.PStruct") } if string(nulls.Raw) != "null" { t.Errorf("Unmarshal of RawMessage null did not record null: %v", string(nulls.Raw)) } if nulls.Time.String() != before { t.Errorf("Unmarshal of time.Time null set time to %v", nulls.Time.String()) } if nulls.BigInt.String() != "123" { t.Errorf("Unmarshal of big.Int null set int to %v", nulls.BigInt.String()) } } func TestStringKind(t *testing.T) { type stringKind string var m1, m2 map[stringKind]int m1 = map[stringKind]int{ "foo": 42, } data, err := json.Marshal(m1) if err != nil { t.Errorf("Unexpected error marshaling: %v", err) } err = json.Unmarshal(data, &m2) if err != nil { t.Errorf("Unexpected error unmarshaling: %v", err) } if !reflect.DeepEqual(m1, m2) { t.Error("Items should be equal after encoding and then decoding") } } // Custom types with []byte as underlying type could not be marshaled // and then unmarshaled. // Issue 8962. func TestByteKind(t *testing.T) { type byteKind []byte a := byteKind("hello") data, err := json.Marshal(a) if err != nil { t.Error(err) } var b byteKind err = json.Unmarshal(data, &b) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(a, b) { t.Errorf("expected %v == %v", a, b) } } // The fix for issue 8962 introduced a regression. // Issue 12921. func TestSliceOfCustomByte(t *testing.T) { type Uint8 uint8 a := []Uint8("hello") data, err := json.Marshal(a) if err != nil { t.Fatal(err) } var b []Uint8 err = json.Unmarshal(data, &b) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(a, b) { t.Fatalf("expected %v == %v", a, b) } } var decodeTypeErrorTests = []struct { dest interface{} src string }{ {new(string), `{"user": "name"}`}, // issue 4628. {new(error), `{}`}, // issue 4222 {new(error), `[]`}, {new(error), `""`}, {new(error), `123`}, {new(error), `true`}, } func TestUnmarshalTypeError(t *testing.T) { for _, item := range decodeTypeErrorTests { err := json.Unmarshal([]byte(item.src), item.dest) if _, ok := err.(*json.UnmarshalTypeError); !ok { t.Errorf("expected type error for Unmarshal(%q, type %T): got %T", item.src, item.dest, err) } } } var unmarshalSyntaxTests = []string{ "tru", "fals", "nul", "123e", `"hello`, `[1,2,3`, `{"key":1`, `{"key":1,`, } func TestUnmarshalSyntax(t *testing.T) { var x interface{} for _, src := range unmarshalSyntaxTests { err := json.Unmarshal([]byte(src), &x) if _, ok := err.(*json.SyntaxError); !ok { t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err) } } } // Test handling of unexported fields that should be ignored. // Issue 4660 type unexportedFields struct { Name string m map[string]interface{} `json:"-"` m2 map[string]interface{} `json:"abcd"` s []int `json:"-"` } func TestUnmarshalUnexported(t *testing.T) { input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}, "s": [2, 3]}` want := &unexportedFields{Name: "Bob"} out := &unexportedFields{} err := json.Unmarshal([]byte(input), out) if err != nil { t.Errorf("got error %v, expected nil", err) } if !reflect.DeepEqual(out, want) { t.Errorf("got %q, want %q", out, want) } } // Time3339 is a time.Time which encodes to and from JSON // as an RFC 3339 time in UTC. type Time3339 time.Time func (t *Time3339) UnmarshalJSON(b []byte) error { if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b) } tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1])) if err != nil { return err } *t = Time3339(tm) return nil } func TestUnmarshalJSONLiteralError(t *testing.T) { var t3 Time3339 err := json.Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3) if err == nil { t.Fatalf("expected error; got time %v", time.Time(t3)) } if !strings.Contains(err.Error(), "range") { t.Errorf("got err = %v; want out of range error", err) } } // Test that extra object elements in an array do not result in a // "data changing underfoot" error. // Issue 3717 func TestSkipArrayObjects(t *testing.T) { data := `[{}]` var dest [0]interface{} err := json.Unmarshal([]byte(data), &dest) if err != nil { t.Errorf("got error %q, want nil", err) } } // Test semantics of pre-filled data, such as struct fields, map elements, // slices, and arrays. // Issues 4900 and 8837, among others. func TestPrefilled(t *testing.T) { // Values here change, cannot reuse table across runs. var prefillTests = []struct { in string ptr interface{} out interface{} }{ { in: `{"X": 1, "Y": 2}`, ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5}, out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5}, }, { in: `{"X": 1, "Y": 2}`, ptr: &map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}, out: &map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}, }, { in: `[2]`, ptr: &[]int{1}, out: &[]int{2}, }, { in: `[2, 3]`, ptr: &[]int{1}, out: &[]int{2, 3}, }, { in: `[2, 3]`, ptr: &[...]int{1}, out: &[...]int{2}, }, { in: `[3]`, ptr: &[...]int{1, 2}, out: &[...]int{3, 0}, }, } for _, tt := range prefillTests { ptrstr := fmt.Sprintf("%v", tt.ptr) err := json.Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here if err != nil { t.Errorf("Unmarshal: %v", err) } if !reflect.DeepEqual(tt.ptr, tt.out) { t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out) } } } var invalidUnmarshalTests = []struct { v interface{} want string }{ {nil, "json: Unmarshal(nil)"}, {struct{}{}, "json: Unmarshal(non-pointer struct {})"}, {(*int)(nil), "json: Unmarshal(nil *int)"}, } func TestInvalidUnmarshal(t *testing.T) { buf := []byte(`{"a":"1"}`) for _, tt := range invalidUnmarshalTests { err := json.Unmarshal(buf, tt.v) if err == nil { t.Errorf("Unmarshal expecting error, got nil") continue } if got := err.Error(); got != tt.want { t.Errorf("Unmarshal = %q; want %q", got, tt.want) } } } var invalidUnmarshalTextTests = []struct { v interface{} want string }{ {nil, "json: Unmarshal(nil)"}, {struct{}{}, "json: Unmarshal(non-pointer struct {})"}, {(*int)(nil), "json: Unmarshal(nil *int)"}, {new(net.IP), "json: cannot unmarshal number into Go value of type *net.IP"}, } func TestInvalidUnmarshalText(t *testing.T) { buf := []byte(`123`) for _, tt := range invalidUnmarshalTextTests { err := json.Unmarshal(buf, tt.v) if err == nil { t.Errorf("Unmarshal expecting error, got nil") continue } if got := err.Error(); got != tt.want { t.Errorf("Unmarshal = %q; want %q", got, tt.want) } } } // Test that string option is ignored for invalid types. // Issue 9812. func TestInvalidStringOption(t *testing.T) { num := 0 item := struct { T time.Time `json:",string"` M map[string]string `json:",string"` S []string `json:",string"` A [1]string `json:",string"` I interface{} `json:",string"` P *int `json:",string"` }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num} data, err := json.Marshal(item) if err != nil { t.Fatalf("Marshal: %v", err) } err = json.Unmarshal(data, &item) if err != nil { t.Fatalf("Unmarshal: %v", err) } } // Test unmarshal behavior with regards to embedded unexported structs. // // (Issue 21357) If the embedded struct is a pointer and is unallocated, // this returns an error because unmarshal cannot set the field. // // (Issue 24152) If the embedded struct is given an explicit name, // ensure that the normal unmarshal logic does not panic in reflect. // // (Issue 28145) If the embedded struct is given an explicit name and has // exported methods, don't cause a panic trying to get its value. func TestUnmarshalEmbeddedUnexported(t *testing.T) { type ( embed1 struct{ Q int } embed2 struct{ Q int } embed3 struct { Q int64 `json:",string"` } S1 struct { *embed1 R int } S2 struct { *embed1 Q int } S3 struct { embed1 R int } S4 struct { *embed1 embed2 } S5 struct { *embed3 R int } S6 struct { embed1 `json:"embed1"` } S7 struct { embed1 `json:"embed1"` embed2 } S8 struct { embed1 `json:"embed1"` embed2 `json:"embed2"` Q int } S9 struct { unexportedWithMethods `json:"embed"` } ) tests := []struct { in string ptr interface{} out interface{} err error }{{ // Error since we cannot set S1.embed1, but still able to set S1.R. in: `{"R":2,"Q":1}`, ptr: new(S1), out: &S1{R: 2}, err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json_test.embed1"), }, { // The top level Q field takes precedence. in: `{"Q":1}`, ptr: new(S2), out: &S2{Q: 1}, }, { // No issue with non-pointer variant. in: `{"R":2,"Q":1}`, ptr: new(S3), out: &S3{embed1: embed1{Q: 1}, R: 2}, }, { // No error since both embedded structs have field R, which annihilate each other. // Thus, no attempt is made at setting S4.embed1. in: `{"R":2}`, ptr: new(S4), out: new(S4), }, { // Error since we cannot set S5.embed1, but still able to set S5.R. in: `{"R":2,"Q":1}`, ptr: new(S5), out: &S5{R: 2}, err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json_test.embed3"), }, { // Issue 24152, ensure decodeState.indirect does not panic. in: `{"embed1": {"Q": 1}}`, ptr: new(S6), out: &S6{embed1{1}}, }, { // Issue 24153, check that we can still set forwarded fields even in // the presence of a name conflict. // // This relies on obscure behavior of reflect where it is possible // to set a forwarded exported field on an unexported embedded struct // even though there is a name conflict, even when it would have been // impossible to do so according to Go visibility rules. // Go forbids this because it is ambiguous whether S7.Q refers to // S7.embed1.Q or S7.embed2.Q. Since embed1 and embed2 are unexported, // it should be impossible for an external package to set either Q. // // It is probably okay for a future reflect change to break this. in: `{"embed1": {"Q": 1}, "Q": 2}`, ptr: new(S7), out: &S7{embed1{1}, embed2{2}}, }, { // Issue 24153, similar to the S7 case. in: `{"embed1": {"Q": 1}, "embed2": {"Q": 2}, "Q": 3}`, ptr: new(S8), out: &S8{embed1{1}, embed2{2}, 3}, }, { // Issue 228145, similar to the cases above. in: `{"embed": {}}`, ptr: new(S9), out: &S9{}, }} for i, tt := range tests { err := json.Unmarshal([]byte(tt.in), tt.ptr) if !equalError(err, tt.err) { t.Errorf("#%d: %v, want %v", i, err, tt.err) } if !reflect.DeepEqual(tt.ptr, tt.out) { t.Errorf("#%d: mismatch\ngot: %#+v\nwant: %#+v", i, tt.ptr, tt.out) } } } func TestUnmarshalErrorAfterMultipleJSON(t *testing.T) { tests := []struct { in string err error }{{ in: `1 false null :`, err: json.NewSyntaxError("invalid character '\x00' looking for beginning of value", 14), }, { in: `1 [] [,]`, err: json.NewSyntaxError("invalid character ',' looking for beginning of value", 6), }, { in: `1 [] [true:]`, err: json.NewSyntaxError("json: slice unexpected end of JSON input", 10), }, { in: `1 {} {"x"=}`, err: json.NewSyntaxError("expected colon after object key", 13), }, { in: `falsetruenul#`, err: json.NewSyntaxError("json: invalid character # as null", 12), }} for i, tt := range tests { dec := json.NewDecoder(strings.NewReader(tt.in)) var err error for { var v interface{} if err = dec.Decode(&v); err != nil { break } } if !reflect.DeepEqual(err, tt.err) { t.Errorf("#%d: got %#v, want %#v", i, err, tt.err) } } } type unmarshalPanic struct{} func (unmarshalPanic) UnmarshalJSON([]byte) error { panic(0xdead) } func TestUnmarshalPanic(t *testing.T) { defer func() { if got := recover(); !reflect.DeepEqual(got, 0xdead) { t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) } }() json.Unmarshal([]byte("{}"), &unmarshalPanic{}) t.Fatalf("Unmarshal should have panicked") } // The decoder used to hang if decoding into an interface pointing to its own address. // See golang.org/issues/31740. func TestUnmarshalRecursivePointer(t *testing.T) { var v interface{} v = &v data := []byte(`{"a": "b"}`) if err := json.Unmarshal(data, v); err != nil { t.Fatal(err) } } type textUnmarshalerString string func (m *textUnmarshalerString) UnmarshalText(text []byte) error { *m = textUnmarshalerString(strings.ToLower(string(text))) return nil } // Test unmarshal to a map, where the map key is a user defined type. // See golang.org/issues/34437. func TestUnmarshalMapWithTextUnmarshalerStringKey(t *testing.T) { var p map[textUnmarshalerString]string if err := json.Unmarshal([]byte(`{"FOO": "1"}`), &p); err != nil { t.Fatalf("Unmarshal unexpected error: %v", err) } if _, ok := p["foo"]; !ok { t.Errorf(`Key "foo" does not exist in map: %v`, p) } } func TestUnmarshalRescanLiteralMangledUnquote(t *testing.T) { // See golang.org/issues/38105. var p map[textUnmarshalerString]string if err := json.Unmarshal([]byte(`{"开源":"12345开源"}`), &p); err != nil { t.Fatalf("Unmarshal unexpected error: %v", err) } if _, ok := p["开源"]; !ok { t.Errorf(`Key "开源" does not exist in map: %v`, p) } // See golang.org/issues/38126. type T struct { F1 string `json:"F1,string"` } t1 := T{"aaa\tbbb"} b, err := json.Marshal(t1) if err != nil { t.Fatalf("Marshal unexpected error: %v", err) } var t2 T if err := json.Unmarshal(b, &t2); err != nil { t.Fatalf("Unmarshal unexpected error: %v", err) } if t1 != t2 { t.Errorf("Marshal and Unmarshal roundtrip mismatch: want %q got %q", t1, t2) } // See golang.org/issues/39555. input := map[textUnmarshalerString]string{"FOO": "", `"`: ""} encoded, err := json.Marshal(input) if err != nil { t.Fatalf("Marshal unexpected error: %v", err) } var got map[textUnmarshalerString]string if err := json.Unmarshal(encoded, &got); err != nil { t.Fatalf("Unmarshal unexpected error: %v", err) } want := map[textUnmarshalerString]string{"foo": "", `"`: ""} if !reflect.DeepEqual(want, got) { t.Fatalf("Unexpected roundtrip result:\nwant: %q\ngot: %q", want, got) } } func TestUnmarshalMaxDepth(t *testing.T) { testcases := []struct { name string data string errMaxDepth bool }{ { name: "ArrayUnderMaxNestingDepth", data: `{"a":` + strings.Repeat(`[`, 10000-1) + strings.Repeat(`]`, 10000-1) + `}`, errMaxDepth: false, }, { name: "ArrayOverMaxNestingDepth", data: `{"a":` + strings.Repeat(`[`, 10000) + strings.Repeat(`]`, 10000) + `}`, errMaxDepth: true, }, { name: "ArrayOverStackDepth", data: `{"a":` + strings.Repeat(`[`, 3000000) + strings.Repeat(`]`, 3000000) + `}`, errMaxDepth: true, }, { name: "ObjectUnderMaxNestingDepth", data: `{"a":` + strings.Repeat(`{"a":`, 10000-1) + `0` + strings.Repeat(`}`, 10000-1) + `}`, errMaxDepth: false, }, { name: "ObjectOverMaxNestingDepth", data: `{"a":` + strings.Repeat(`{"a":`, 10000) + `0` + strings.Repeat(`}`, 10000) + `}`, errMaxDepth: true, }, { name: "ObjectOverStackDepth", data: `{"a":` + strings.Repeat(`{"a":`, 3000000) + `0` + strings.Repeat(`}`, 3000000) + `}`, errMaxDepth: true, }, } targets := []struct { name string newValue func() interface{} }{ { name: "unstructured", newValue: func() interface{} { var v interface{} return &v }, }, { name: "typed named field", newValue: func() interface{} { v := struct { A interface{} `json:"a"` }{} return &v }, }, { name: "typed missing field", newValue: func() interface{} { v := struct { B interface{} `json:"b"` }{} return &v }, }, { name: "custom unmarshaler", newValue: func() interface{} { v := unmarshaler{} return &v }, }, } for _, tc := range testcases { for _, target := range targets { t.Run(target.name+"-"+tc.name, func(t *testing.T) { t.Run("unmarshal", func(t *testing.T) { err := json.Unmarshal([]byte(tc.data), target.newValue()) if !tc.errMaxDepth { if err != nil { t.Errorf("unexpected error: %v", err) } } else { if err == nil { t.Errorf("expected error containing 'exceeded max depth', got none") } else if !strings.Contains(err.Error(), "exceeded max depth") { t.Errorf("expected error containing 'exceeded max depth', got: %v", err) } } }) t.Run("stream", func(t *testing.T) { err := json.NewDecoder(strings.NewReader(tc.data)).Decode(target.newValue()) if !tc.errMaxDepth { if err != nil { t.Errorf("unexpected error: %v", err) } } else { if err == nil { t.Errorf("expected error containing 'exceeded max depth', got none") } else if !strings.Contains(err.Error(), "exceeded max depth") { t.Errorf("expected error containing 'exceeded max depth', got: %v", err) } } }) }) } } } func TestDecodeSlice(t *testing.T) { type B struct{ Int int32 } type A struct{ B *B } type X struct{ A []*A } w1 := &X{} w2 := &X{} if err := json.Unmarshal([]byte(`{"a": [ {"b":{"int": 42} } ] }`), w1); err != nil { t.Fatal(err) } w1addr := uintptr(unsafe.Pointer(w1.A[0].B)) if err := json.Unmarshal([]byte(`{"a": [ {"b":{"int": 112} } ] }`), w2); err != nil { t.Fatal(err) } if uintptr(unsafe.Pointer(w1.A[0].B)) != w1addr { t.Fatal("wrong addr") } w2addr := uintptr(unsafe.Pointer(w2.A[0].B)) if w1addr == w2addr { t.Fatal("invaid address") } } func TestDecodeMultipleUnmarshal(t *testing.T) { data := []byte(`[{"AA":{"X":[{"a": "A"},{"b": "B"}],"Y":"y","Z":"z"},"BB":"bb"},{"AA":{"X":[],"Y":"y","Z":"z"},"BB":"bb"}]`) var a []json.RawMessage if err := json.Unmarshal(data, &a); err != nil { t.Fatal(err) } if len(a) != 2 { t.Fatalf("failed to decode: got %v", a) } t.Run("first", func(t *testing.T) { data := a[0] var v map[string]json.RawMessage if err := json.Unmarshal(data, &v); err != nil { t.Fatal(err) } if string(v["AA"]) != `{"X":[{"a": "A"},{"b": "B"}],"Y":"y","Z":"z"}` { t.Fatalf("failed to decode. got %q", v["AA"]) } var aa map[string]json.RawMessage if err := json.Unmarshal(v["AA"], &aa); err != nil { t.Fatal(err) } if string(aa["X"]) != `[{"a": "A"},{"b": "B"}]` { t.Fatalf("failed to decode. got %q", v["X"]) } var x []json.RawMessage if err := json.Unmarshal(aa["X"], &x); err != nil { t.Fatal(err) } if len(x) != 2 { t.Fatalf("failed to decode: %v", x) } if string(x[0]) != `{"a": "A"}` { t.Fatal("failed to decode") } if string(x[1]) != `{"b": "B"}` { t.Fatal("failed to decode") } }) t.Run("second", func(t *testing.T) { data := a[1] var v map[string]json.RawMessage if err := json.Unmarshal(data, &v); err != nil { t.Fatal(err) } if string(v["AA"]) != `{"X":[],"Y":"y","Z":"z"}` { t.Fatalf("failed to decode. got %q", v["AA"]) } var aa map[string]json.RawMessage if err := json.Unmarshal(v["AA"], &aa); err != nil { t.Fatal(err) } if string(aa["X"]) != `[]` { t.Fatalf("failed to decode. got %q", v["X"]) } var x []json.RawMessage if err := json.Unmarshal(aa["X"], &x); err != nil { t.Fatal(err) } if len(x) != 0 { t.Fatalf("failed to decode: %v", x) } }) } func TestMultipleDecodeWithRawMessage(t *testing.T) { original := []byte(`{ "Body": { "List": [ { "Returns": [ { "Value": "10", "nodeType": "Literal" } ], "nodeKind": "Return", "nodeType": "Statement" } ], "nodeKind": "Block", "nodeType": "Statement" }, "nodeType": "Function" }`) var a map[string]json.RawMessage if err := json.Unmarshal(original, &a); err != nil { t.Fatal(err) } var b map[string]json.RawMessage if err := json.Unmarshal(a["Body"], &b); err != nil { t.Fatal(err) } var c []json.RawMessage if err := json.Unmarshal(b["List"], &c); err != nil { t.Fatal(err) } var d map[string]json.RawMessage if err := json.Unmarshal(c[0], &d); err != nil { t.Fatal(err) } var e []json.RawMessage if err := json.Unmarshal(d["Returns"], &e); err != nil { t.Fatal(err) } var f map[string]json.RawMessage if err := json.Unmarshal(e[0], &f); err != nil { t.Fatal(err) } } type intUnmarshaler int func (u *intUnmarshaler) UnmarshalJSON(b []byte) error { if *u != 0 && *u != 10 { return fmt.Errorf("failed to decode of slice with int unmarshaler") } *u = 10 return nil } type arrayUnmarshaler [5]int func (u *arrayUnmarshaler) UnmarshalJSON(b []byte) error { if (*u)[0] != 0 && (*u)[0] != 10 { return fmt.Errorf("failed to decode of slice with array unmarshaler") } (*u)[0] = 10 return nil } type mapUnmarshaler map[string]int func (u *mapUnmarshaler) UnmarshalJSON(b []byte) error { if len(*u) != 0 && len(*u) != 1 { return fmt.Errorf("failed to decode of slice with map unmarshaler") } *u = map[string]int{"a": 10} return nil } type structUnmarshaler struct { A int notFirst bool } func (u *structUnmarshaler) UnmarshalJSON(b []byte) error { if !u.notFirst && u.A != 0 { return fmt.Errorf("failed to decode of slice with struct unmarshaler") } u.A = 10 u.notFirst = true return nil } func TestSliceElemUnmarshaler(t *testing.T) { t.Run("int", func(t *testing.T) { var v []intUnmarshaler if err := json.Unmarshal([]byte(`[1,2,3,4,5]`), &v); err != nil { t.Fatal(err) } if len(v) != 5 { t.Fatalf("failed to decode of slice with int unmarshaler: %v", v) } if v[0] != 10 { t.Fatalf("failed to decode of slice with int unmarshaler: %v", v) } if err := json.Unmarshal([]byte(`[6]`), &v); err != nil { t.Fatal(err) } if len(v) != 1 { t.Fatalf("failed to decode of slice with int unmarshaler: %v", v) } if v[0] != 10 { t.Fatalf("failed to decode of slice with int unmarshaler: %v", v) } }) t.Run("slice", func(t *testing.T) { var v []json.RawMessage if err := json.Unmarshal([]byte(`[1,2,3,4,5]`), &v); err != nil { t.Fatal(err) } if len(v) != 5 { t.Fatalf("failed to decode of slice with slice unmarshaler: %v", v) } if len(v[0]) != 1 { t.Fatalf("failed to decode of slice with slice unmarshaler: %v", v) } if err := json.Unmarshal([]byte(`[6]`), &v); err != nil { t.Fatal(err) } if len(v) != 1 { t.Fatalf("failed to decode of slice with slice unmarshaler: %v", v) } if len(v[0]) != 1 { t.Fatalf("failed to decode of slice with slice unmarshaler: %v", v) } }) t.Run("array", func(t *testing.T) { var v []arrayUnmarshaler if err := json.Unmarshal([]byte(`[1,2,3,4,5]`), &v); err != nil { t.Fatal(err) } if len(v) != 5 { t.Fatalf("failed to decode of slice with array unmarshaler: %v", v) } if v[0][0] != 10 { t.Fatalf("failed to decode of slice with array unmarshaler: %v", v) } if err := json.Unmarshal([]byte(`[6]`), &v); err != nil { t.Fatal(err) } if len(v) != 1 { t.Fatalf("failed to decode of slice with array unmarshaler: %v", v) } if v[0][0] != 10 { t.Fatalf("failed to decode of slice with array unmarshaler: %v", v) } }) t.Run("map", func(t *testing.T) { var v []mapUnmarshaler if err := json.Unmarshal([]byte(`[{"a":1},{"b":2},{"c":3},{"d":4},{"e":5}]`), &v); err != nil { t.Fatal(err) } if len(v) != 5 { t.Fatalf("failed to decode of slice with map unmarshaler: %v", v) } if v[0]["a"] != 10 { t.Fatalf("failed to decode of slice with map unmarshaler: %v", v) } if err := json.Unmarshal([]byte(`[6]`), &v); err != nil { t.Fatal(err) } if len(v) != 1 { t.Fatalf("failed to decode of slice with map unmarshaler: %v", v) } if v[0]["a"] != 10 { t.Fatalf("failed to decode of slice with map unmarshaler: %v", v) } }) t.Run("struct", func(t *testing.T) { var v []structUnmarshaler if err := json.Unmarshal([]byte(`[1,2,3,4,5]`), &v); err != nil { t.Fatal(err) } if len(v) != 5 { t.Fatalf("failed to decode of slice with struct unmarshaler: %v", v) } if v[0].A != 10 { t.Fatalf("failed to decode of slice with struct unmarshaler: %v", v) } if err := json.Unmarshal([]byte(`[6]`), &v); err != nil { t.Fatal(err) } if len(v) != 1 { t.Fatalf("failed to decode of slice with struct unmarshaler: %v", v) } if v[0].A != 10 { t.Fatalf("failed to decode of slice with struct unmarshaler: %v", v) } }) } type keepRefTest struct { A int B string } func (t *keepRefTest) UnmarshalJSON(data []byte) error { v := []interface{}{&t.A, &t.B} return json.Unmarshal(data, &v) } func TestKeepReferenceSlice(t *testing.T) { var v keepRefTest if err := json.Unmarshal([]byte(`[54,"hello"]`), &v); err != nil { t.Fatal(err) } if v.A != 54 { t.Fatal("failed to keep reference for slice") } if v.B != "hello" { t.Fatal("failed to keep reference for slice") } } func TestInvalidTopLevelValue(t *testing.T) { t.Run("invalid end of buffer", func(t *testing.T) { var v struct{} if err := stdjson.Unmarshal([]byte(`{}0`), &v); err == nil { t.Fatal("expected error") } if err := json.Unmarshal([]byte(`{}0`), &v); err == nil { t.Fatal("expected error") } }) t.Run("invalid object", func(t *testing.T) { var v interface{} if err := stdjson.Unmarshal([]byte(`{"a":4}{"a"5}`), &v); err == nil { t.Fatal("expected error") } if err := json.Unmarshal([]byte(`{"a":4}{"a"5}`), &v); err == nil { t.Fatal("expected error") } }) } func TestInvalidNumber(t *testing.T) { t.Run("invalid length of number", func(t *testing.T) { invalidNum := strings.Repeat("1", 30) t.Run("int", func(t *testing.T) { var v int64 stdErr := stdjson.Unmarshal([]byte(invalidNum), &v) if stdErr == nil { t.Fatal("expected error") } err := json.Unmarshal([]byte(invalidNum), &v) if err == nil { t.Fatal("expected error") } if stdErr.Error() != err.Error() { t.Fatalf("unexpected error message. expected: %q but got %q", stdErr.Error(), err.Error()) } }) t.Run("uint", func(t *testing.T) { var v uint64 stdErr := stdjson.Unmarshal([]byte(invalidNum), &v) if stdErr == nil { t.Fatal("expected error") } err := json.Unmarshal([]byte(invalidNum), &v) if err == nil { t.Fatal("expected error") } if stdErr.Error() != err.Error() { t.Fatalf("unexpected error message. expected: %q but got %q", stdErr.Error(), err.Error()) } }) }) t.Run("invalid number of zero", func(t *testing.T) { t.Run("int", func(t *testing.T) { invalidNum := strings.Repeat("0", 10) var v int64 stdErr := stdjson.Unmarshal([]byte(invalidNum), &v) if stdErr == nil { t.Fatal("expected error") } err := json.Unmarshal([]byte(invalidNum), &v) if err == nil { t.Fatal("expected error") } if stdErr.Error() != err.Error() { t.Fatalf("unexpected error message. expected: %q but got %q", stdErr.Error(), err.Error()) } }) t.Run("uint", func(t *testing.T) { invalidNum := strings.Repeat("0", 10) var v uint64 stdErr := stdjson.Unmarshal([]byte(invalidNum), &v) if stdErr == nil { t.Fatal("expected error") } err := json.Unmarshal([]byte(invalidNum), &v) if err == nil { t.Fatal("expected error") } if stdErr.Error() != err.Error() { t.Fatalf("unexpected error message. expected: %q but got %q", stdErr.Error(), err.Error()) } }) }) t.Run("invalid number", func(t *testing.T) { t.Run("int", func(t *testing.T) { t.Run("-0", func(t *testing.T) { var v int64 if err := stdjson.Unmarshal([]byte(`-0`), &v); err != nil { t.Fatal(err) } if err := json.Unmarshal([]byte(`-0`), &v); err != nil { t.Fatal(err) } }) t.Run("+0", func(t *testing.T) { var v int64 if err := stdjson.Unmarshal([]byte(`+0`), &v); err == nil { t.Error("expected error") } if err := json.Unmarshal([]byte(`+0`), &v); err == nil { t.Error("expected error") } }) }) t.Run("uint", func(t *testing.T) { t.Run("-0", func(t *testing.T) { var v uint64 if err := stdjson.Unmarshal([]byte(`-0`), &v); err == nil { t.Error("expected error") } if err := json.Unmarshal([]byte(`-0`), &v); err == nil { t.Error("expected error") } }) t.Run("+0", func(t *testing.T) { var v uint64 if err := stdjson.Unmarshal([]byte(`+0`), &v); err == nil { t.Error("expected error") } if err := json.Unmarshal([]byte(`+0`), &v); err == nil { t.Error("expected error") } }) }) t.Run("float", func(t *testing.T) { t.Run("0.0", func(t *testing.T) { var f float64 if err := stdjson.Unmarshal([]byte(`0.0`), &f); err != nil { t.Fatal(err) } if err := json.Unmarshal([]byte(`0.0`), &f); err != nil { t.Fatal(err) } }) t.Run("0.000000000", func(t *testing.T) { var f float64 if err := stdjson.Unmarshal([]byte(`0.000000000`), &f); err != nil { t.Fatal(err) } if err := json.Unmarshal([]byte(`0.000000000`), &f); err != nil { t.Fatal(err) } }) t.Run("repeat zero a lot with float value", func(t *testing.T) { var f float64 if err := stdjson.Unmarshal([]byte("0."+strings.Repeat("0", 30)), &f); err != nil { t.Fatal(err) } if err := json.Unmarshal([]byte("0."+strings.Repeat("0", 30)), &f); err != nil { t.Fatal(err) } }) }) }) } type someInterface interface { DoesNotMatter() } func TestDecodeUnknownInterface(t *testing.T) { t.Run("unmarshal", func(t *testing.T) { var v map[string]someInterface if err := json.Unmarshal([]byte(`{"a":null,"b":null}`), &v); err != nil { t.Fatal(err) } if len(v) != 2 { t.Fatalf("failed to decode: %v", v) } if a, exists := v["a"]; a != nil || !exists { t.Fatalf("failed to decode: %v", v) } if b, exists := v["b"]; b != nil || !exists { t.Fatalf("failed to decode: %v", v) } }) t.Run("stream", func(t *testing.T) { var v map[string]someInterface if err := json.NewDecoder(strings.NewReader(`{"a":null,"b":null}`)).Decode(&v); err != nil { t.Fatal(err) } if len(v) != 2 { t.Fatalf("failed to decode: %v", v) } if a, exists := v["a"]; a != nil || !exists { t.Fatalf("failed to decode: %v", v) } if b, exists := v["b"]; b != nil || !exists { t.Fatalf("failed to decode: %v", v) } }) } func TestDecodeByteSliceNull(t *testing.T) { t.Run("unmarshal", func(t *testing.T) { var v1 []byte if err := stdjson.Unmarshal([]byte(`null`), &v1); err != nil { t.Fatal(err) } var v2 []byte if err := json.Unmarshal([]byte(`null`), &v2); err != nil { t.Fatal(err) } if v1 == nil && v2 != nil || len(v1) != len(v2) { t.Fatalf("failed to decode null to []byte. expected:%#v but got %#v", v1, v2) } }) t.Run("stream", func(t *testing.T) { var v1 []byte if err := stdjson.NewDecoder(strings.NewReader(`null`)).Decode(&v1); err != nil { t.Fatal(err) } var v2 []byte if err := json.NewDecoder(strings.NewReader(`null`)).Decode(&v2); err != nil { t.Fatal(err) } if v1 == nil && v2 != nil || len(v1) != len(v2) { t.Fatalf("failed to decode null to []byte. expected:%#v but got %#v", v1, v2) } }) } func TestDecodeBackSlash(t *testing.T) { t.Run("unmarshal", func(t *testing.T) { t.Run("string", func(t *testing.T) { var v1 map[string]stdjson.RawMessage if err := stdjson.Unmarshal([]byte(`{"c":"\\"}`), &v1); err != nil { t.Fatal(err) } var v2 map[string]json.RawMessage if err := json.Unmarshal([]byte(`{"c":"\\"}`), &v2); err != nil { t.Fatal(err) } if len(v1) != len(v2) || !bytes.Equal(v1["c"], v2["c"]) { t.Fatalf("failed to decode backslash: expected %#v but got %#v", v1, v2) } }) t.Run("array", func(t *testing.T) { var v1 map[string]stdjson.RawMessage if err := stdjson.Unmarshal([]byte(`{"c":["\\"]}`), &v1); err != nil { t.Fatal(err) } var v2 map[string]json.RawMessage if err := json.Unmarshal([]byte(`{"c":["\\"]}`), &v2); err != nil { t.Fatal(err) } if len(v1) != len(v2) || !bytes.Equal(v1["c"], v2["c"]) { t.Fatalf("failed to decode backslash: expected %#v but got %#v", v1, v2) } }) t.Run("object", func(t *testing.T) { var v1 map[string]stdjson.RawMessage if err := stdjson.Unmarshal([]byte(`{"c":{"\\":"\\"}}`), &v1); err != nil { t.Fatal(err) } var v2 map[string]json.RawMessage if err := json.Unmarshal([]byte(`{"c":{"\\":"\\"}}`), &v2); err != nil { t.Fatal(err) } if len(v1) != len(v2) || !bytes.Equal(v1["c"], v2["c"]) { t.Fatalf("failed to decode backslash: expected %#v but got %#v", v1, v2) } }) }) t.Run("stream", func(t *testing.T) { t.Run("string", func(t *testing.T) { var v1 map[string]stdjson.RawMessage if err := stdjson.NewDecoder(strings.NewReader(`{"c":"\\"}`)).Decode(&v1); err != nil { t.Fatal(err) } var v2 map[string]json.RawMessage if err := json.NewDecoder(strings.NewReader(`{"c":"\\"}`)).Decode(&v2); err != nil { t.Fatal(err) } if len(v1) != len(v2) || !bytes.Equal(v1["c"], v2["c"]) { t.Fatalf("failed to decode backslash: expected %#v but got %#v", v1, v2) } }) t.Run("array", func(t *testing.T) { var v1 map[string]stdjson.RawMessage if err := stdjson.NewDecoder(strings.NewReader(`{"c":["\\"]}`)).Decode(&v1); err != nil { t.Fatal(err) } var v2 map[string]json.RawMessage if err := json.NewDecoder(strings.NewReader(`{"c":["\\"]}`)).Decode(&v2); err != nil { t.Fatal(err) } if len(v1) != len(v2) || !bytes.Equal(v1["c"], v2["c"]) { t.Fatalf("failed to decode backslash: expected %#v but got %#v", v1, v2) } }) t.Run("object", func(t *testing.T) { var v1 map[string]stdjson.RawMessage if err := stdjson.NewDecoder(strings.NewReader(`{"c":{"\\":"\\"}}`)).Decode(&v1); err != nil { t.Fatal(err) } var v2 map[string]json.RawMessage if err := json.NewDecoder(strings.NewReader(`{"c":{"\\":"\\"}}`)).Decode(&v2); err != nil { t.Fatal(err) } if len(v1) != len(v2) || !bytes.Equal(v1["c"], v2["c"]) { t.Fatalf("failed to decode backslash: expected %#v but got %#v", v1, v2) } }) }) } func TestIssue218(t *testing.T) { type A struct { X int } type B struct { Y int } type S struct { A *A `json:"a,omitempty"` B *B `json:"b,omitempty"` } tests := []struct { name string given []S expected []S }{ { name: "A should be correct", given: []S{{ A: &A{ X: 1, }, }}, expected: []S{{ A: &A{ X: 1, }, }}, }, { name: "B should be correct", given: []S{{ B: &B{ Y: 2, }, }}, expected: []S{{ B: &B{ Y: 2, }, }}, }, } for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(test.given); err != nil { t.Fatal(err) } var actual []S if err := json.NewDecoder(bytes.NewReader(buf.Bytes())).Decode(&actual); err != nil { t.Fatal(err) } if !reflect.DeepEqual(test.expected, actual) { t.Fatalf("mismatch value: expected %v but got %v", test.expected, actual) } }) } } func TestDecodeEscapedCharField(t *testing.T) { b := []byte(`{"\u6D88\u606F":"\u6D88\u606F"}`) t.Run("unmarshal", func(t *testing.T) { v := struct { Msg string `json:"消息"` }{} if err := json.Unmarshal(b, &v); err != nil { t.Fatal(err) } if !bytes.Equal([]byte(v.Msg), []byte("消息")) { t.Fatal("failed to decode unicode char") } }) t.Run("stream", func(t *testing.T) { v := struct { Msg string `json:"消息"` }{} if err := json.NewDecoder(bytes.NewBuffer(b)).Decode(&v); err != nil { t.Fatal(err) } if !bytes.Equal([]byte(v.Msg), []byte("消息")) { t.Fatal("failed to decode unicode char") } }) } type unmarshalContextKey struct{} type unmarshalContextStructType struct { v int } func (t *unmarshalContextStructType) UnmarshalJSON(ctx context.Context, b []byte) error { v := ctx.Value(unmarshalContextKey{}) s, ok := v.(string) if !ok { return fmt.Errorf("failed to propagate parent context.Context") } if s != "hello" { return fmt.Errorf("failed to propagate parent context.Context") } t.v = 100 return nil } func TestDecodeContextOption(t *testing.T) { src := []byte("10") buf := bytes.NewBuffer(src) t.Run("UnmarshalContext", func(t *testing.T) { ctx := context.WithValue(context.Background(), unmarshalContextKey{}, "hello") var v unmarshalContextStructType if err := json.UnmarshalContext(ctx, src, &v); err != nil { t.Fatal(err) } if v.v != 100 { t.Fatal("failed to decode with context") } }) t.Run("DecodeContext", func(t *testing.T) { ctx := context.WithValue(context.Background(), unmarshalContextKey{}, "hello") var v unmarshalContextStructType if err := json.NewDecoder(buf).DecodeContext(ctx, &v); err != nil { t.Fatal(err) } if v.v != 100 { t.Fatal("failed to decode with context") } }) } func TestIssue251(t *testing.T) { array := [3]int{1, 2, 3} err := stdjson.Unmarshal([]byte("[ ]"), &array) if err != nil { t.Fatal(err) } t.Log(array) array = [3]int{1, 2, 3} err = json.Unmarshal([]byte("[ ]"), &array) if err != nil { t.Fatal(err) } t.Log(array) array = [3]int{1, 2, 3} err = json.NewDecoder(strings.NewReader(`[ ]`)).Decode(&array) if err != nil { t.Fatal(err) } t.Log(array) } func TestDecodeBinaryTypeWithEscapedChar(t *testing.T) { type T struct { Msg []byte `json:"msg"` } content := []byte(`{"msg":"aGVsbG8K\n"}`) t.Run("unmarshal", func(t *testing.T) { var expected T if err := stdjson.Unmarshal(content, &expected); err != nil { t.Fatal(err) } var got T if err := json.Unmarshal(content, &got); err != nil { t.Fatal(err) } if !bytes.Equal(expected.Msg, got.Msg) { t.Fatalf("failed to decode binary type with escaped char. expected %q but got %q", expected.Msg, got.Msg) } }) t.Run("stream", func(t *testing.T) { var expected T if err := stdjson.NewDecoder(bytes.NewBuffer(content)).Decode(&expected); err != nil { t.Fatal(err) } var got T if err := json.NewDecoder(bytes.NewBuffer(content)).Decode(&got); err != nil { t.Fatal(err) } if !bytes.Equal(expected.Msg, got.Msg) { t.Fatalf("failed to decode binary type with escaped char. expected %q but got %q", expected.Msg, got.Msg) } }) } func TestIssue282(t *testing.T) { var J = []byte(`{ "a": {}, "b": {}, "c": {}, "d": {}, "e": {}, "f": {}, "g": {}, "h": { "m": "1" }, "i": {} }`) type T4 struct { F0 string F1 string F2 string F3 string F4 string F5 string F6 int } type T3 struct { F0 string F1 T4 } type T2 struct { F0 string `json:"m"` F1 T3 } type T0 map[string]T2 // T2 size is 136 bytes. This is indirect type. var v T0 if err := json.Unmarshal(J, &v); err != nil { t.Fatal(err) } if v["h"].F0 != "1" { t.Fatalf("failed to assign map value") } } func TestDecodeStructFieldMap(t *testing.T) { type Foo struct { Bar map[float64]float64 `json:"bar,omitempty"` } var v Foo if err := json.Unmarshal([]byte(`{"name":"test"}`), &v); err != nil { t.Fatal(err) } if v.Bar != nil { t.Fatalf("failed to decode v.Bar = %+v", v.Bar) } } type issue303 struct { Count int Type string Value interface{} } func (t *issue303) UnmarshalJSON(b []byte) error { type tmpType issue303 wrapped := struct { Value json.RawMessage tmpType }{} if err := json.Unmarshal(b, &wrapped); err != nil { return err } *t = issue303(wrapped.tmpType) switch wrapped.Type { case "string": var str string if err := json.Unmarshal(wrapped.Value, &str); err != nil { return err } t.Value = str } return nil } func TestIssue303(t *testing.T) { var v issue303 if err := json.Unmarshal([]byte(`{"Count":7,"Type":"string","Value":"hello"}`), &v); err != nil { t.Fatal(err) } if v.Count != 7 || v.Type != "string" || v.Value != "hello" { t.Fatalf("failed to decode. count = %d type = %s value = %v", v.Count, v.Type, v.Value) } } func TestIssue327(t *testing.T) { var v struct { Date time.Time `json:"date"` } dec := json.NewDecoder(strings.NewReader(`{"date": "2021-11-23T13:47:30+01:00"})`)) if err := dec.DecodeContext(context.Background(), &v); err != nil { t.Fatal(err) } expected := "2021-11-23T13:47:30+01:00" if got := v.Date.Format(time.RFC3339); got != expected { t.Fatalf("failed to decode. expected %q but got %q", expected, got) } } func TestIssue337(t *testing.T) { in := strings.Repeat(" ", 510) + "{}" var m map[string]string if err := json.NewDecoder(strings.NewReader(in)).Decode(&m); err != nil { t.Fatal("unexpected error:", err) } if len(m) != 0 { t.Fatal("unexpected result", m) } } func Benchmark306(b *testing.B) { type T0 struct { Str string } in := []byte(`{"Str":"` + strings.Repeat(`abcd\"`, 10000) + `"}`) b.Run("stdjson", func(b *testing.B) { var x T0 for i := 0; i < b.N; i++ { stdjson.Unmarshal(in, &x) } }) b.Run("go-json", func(b *testing.B) { var x T0 for i := 0; i < b.N; i++ { json.Unmarshal(in, &x) } }) } func TestIssue348(t *testing.T) { in := strings.Repeat("["+strings.Repeat(",1000", 500)[1:]+"]", 2) dec := json.NewDecoder(strings.NewReader(in)) for dec.More() { var foo interface{} if err := dec.Decode(&foo); err != nil { t.Error(err) } } } type issue342 string func (t *issue342) UnmarshalJSON(b []byte) error { panic("unreachable") } func TestIssue342(t *testing.T) { var v map[issue342]int in := []byte(`{"a":1}`) if err := json.Unmarshal(in, &v); err != nil { t.Errorf("unexpected error: %v", err) } expected := 1 if got := v["a"]; got != expected { t.Errorf("unexpected result: got(%v) != expected(%v)", got, expected) } } func TestIssue360(t *testing.T) { var uints []uint8 err := json.Unmarshal([]byte(`[0, 1, 2]`), &uints) if err != nil { t.Errorf("unexpected error: %v", err) } if len(uints) != 3 || !(uints[0] == 0 && uints[1] == 1 && uints[2] == 2) { t.Errorf("unexpected result: %v", uints) } } func TestIssue359(t *testing.T) { var a interface{} = 1 var b interface{} = &a var c interface{} = &b v, err := json.Marshal(c) if err != nil { t.Errorf("unexpected error: %v", err) } if string(v) != "1" { t.Errorf("unexpected result: %v", string(v)) } } func TestIssue364(t *testing.T) { var v struct { Description string `json:"description"` } err := json.Unmarshal([]byte(`{"description":"\uD83D\uDE87 Toledo is a metro station"}`), &v) if err != nil { t.Errorf("unexpected error: %v", err) } if v.Description != "🚇 Toledo is a metro station" { t.Errorf("unexpected result: %v", v.Description) } } func TestIssue362(t *testing.T) { type AliasedPrimitive int type Combiner struct { SomeField int AliasedPrimitive } originalCombiner := Combiner{AliasedPrimitive: 7} b, err := json.Marshal(originalCombiner) assertErr(t, err) newCombiner := Combiner{} err = json.Unmarshal(b, &newCombiner) assertErr(t, err) assertEq(t, "TestEmbeddedPrimitiveAlias", originalCombiner, newCombiner) } func TestIssue335(t *testing.T) { var v []string in := []byte(`["\u","A"]`) err := json.Unmarshal(in, &v) if err == nil { t.Errorf("unexpected success") } } func TestIssue372(t *testing.T) { type A int type T struct { _ int *A } var v T err := json.Unmarshal([]byte(`{"A":7}`), &v) assertErr(t, err) got := *v.A expected := A(7) if got != expected { t.Errorf("unexpected result: %v != %v", got, expected) } } type issue384 struct{} func (t *issue384) UnmarshalJSON(b []byte) error { return nil } func TestIssue384(t *testing.T) { testcases := []string{ `{"data": "` + strings.Repeat("-", 500) + `\""}`, `["` + strings.Repeat("-", 508) + `\""]`, } for _, tc := range testcases { dec := json.NewDecoder(strings.NewReader(tc)) var v issue384 if err := dec.Decode(&v); err != nil { t.Errorf("unexpected error: %v", err) } } } func TestIssue408(t *testing.T) { type T struct { Arr [2]int32 `json:"arr"` } var v T if err := json.Unmarshal([]byte(`{"arr": [1,2]}`), &v); err != nil { t.Fatal(err) } } func TestIssue416(t *testing.T) { b := []byte(`{"Сообщение":"Текст"}`) type T struct { Msg string `json:"Сообщение"` } var x T err := json.Unmarshal(b, &x) assertErr(t, err) assertEq(t, "unexpected result", "Текст", x.Msg) } func TestIssue429(t *testing.T) { var x struct { N int32 } for _, b := range []string{ `{"\u"`, `{"\u0"`, `{"\u00"`, } { if err := json.Unmarshal([]byte(b), &x); err == nil { t.Errorf("unexpected success") } } } golang-github-goccy-go-json-0.10.3/docker-compose.yml000066400000000000000000000004041463555276600224540ustar00rootroot00000000000000version: '2' services: go-json: image: golang:1.18 volumes: - '.:/go/src/go-json' deploy: resources: limits: memory: 620M working_dir: /go/src/go-json command: | sh -c "go test -c . && ls go-json.test" golang-github-goccy-go-json-0.10.3/encode.go000066400000000000000000000215451463555276600206140ustar00rootroot00000000000000package json import ( "context" "io" "os" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/encoder/vm" "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" ) // An Encoder writes JSON values to an output stream. type Encoder struct { w io.Writer enabledIndent bool enabledHTMLEscape bool prefix string indentStr string } // NewEncoder returns a new encoder that writes to w. func NewEncoder(w io.Writer) *Encoder { return &Encoder{w: w, enabledHTMLEscape: true} } // Encode writes the JSON encoding of v to the stream, followed by a newline character. // // See the documentation for Marshal for details about the conversion of Go values to JSON. func (e *Encoder) Encode(v interface{}) error { return e.EncodeWithOption(v) } // 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...) encoder.ReleaseRuntimeContext(ctx) 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...) //nolint: contextcheck encoder.ReleaseRuntimeContext(rctx) return err } func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, optFuncs ...EncodeOptionFunc) error { if e.enabledHTMLEscape { ctx.Option.Flag |= encoder.HTMLEscapeOption } ctx.Option.Flag |= encoder.NormalizeUTF8Option ctx.Option.DebugOut = os.Stdout for _, optFunc := range optFuncs { optFunc(ctx.Option) } var ( buf []byte err error ) if e.enabledIndent { buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr) } else { buf, err = encode(ctx, v) } if err != nil { return err } if e.enabledIndent { buf = buf[:len(buf)-2] } else { buf = buf[:len(buf)-1] } buf = append(buf, '\n') if _, err := e.w.Write(buf); err != nil { return err } return nil } // SetEscapeHTML specifies whether problematic HTML characters should be escaped inside JSON quoted strings. // The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when embedding JSON in HTML. // // In non-HTML settings where the escaping interferes with the readability of the output, SetEscapeHTML(false) disables this behavior. func (e *Encoder) SetEscapeHTML(on bool) { e.enabledHTMLEscape = on } // SetIndent instructs the encoder to format each subsequent encoded value as if indented by the package-level function Indent(dst, src, prefix, indent). // Calling SetIndent("", "") disables indentation. func (e *Encoder) SetIndent(prefix, indent string) { if prefix == "" && indent == "" { e.enabledIndent = false return } e.prefix = prefix e.indentStr = indent e.enabledIndent = true } func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { rctx := encoder.TakeRuntimeContext() rctx.Option.Flag = 0 rctx.Option.Flag = encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | encoder.ContextOption rctx.Option.Context = ctx for _, optFunc := range optFuncs { optFunc(rctx.Option) } buf, err := encode(rctx, v) //nolint: contextcheck 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() ctx.Option.Flag = 0 ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option) for _, optFunc := range optFuncs { optFunc(ctx.Option) } buf, err := encode(ctx, v) if err != nil { encoder.ReleaseRuntimeContext(ctx) 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(ctx) return copied, nil } func marshalNoEscape(v interface{}) ([]byte, error) { ctx := encoder.TakeRuntimeContext() ctx.Option.Flag = 0 ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option) buf, err := encodeNoEscape(ctx, v) if err != nil { encoder.ReleaseRuntimeContext(ctx) 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(ctx) return copied, nil } func marshalIndent(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) { ctx := encoder.TakeRuntimeContext() ctx.Option.Flag = 0 ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | 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 } buf = buf[:len(buf)-2] copied := make([]byte, len(buf)) copy(copied, buf) encoder.ReleaseRuntimeContext(ctx) return copied, nil } func encode(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) { b := ctx.Buf[:0] if v == nil { b = encoder.AppendNull(ctx, b) b = encoder.AppendComma(ctx, b) return b, nil } header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr) if err != nil { return nil, err } p := uintptr(header.ptr) ctx.Init(p, codeSet.CodeLength) ctx.KeepRefs = append(ctx.KeepRefs, header.ptr) buf, err := encodeRunCode(ctx, b, codeSet) if err != nil { return nil, err } ctx.Buf = buf return buf, nil } func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) { b := ctx.Buf[:0] if v == nil { b = encoder.AppendNull(ctx, b) b = encoder.AppendComma(ctx, b) return b, nil } header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr) if err != nil { return nil, err } p := uintptr(header.ptr) ctx.Init(p, codeSet.CodeLength) buf, err := encodeRunCode(ctx, b, codeSet) if err != nil { return nil, err } ctx.Buf = buf return buf, nil } func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent string) ([]byte, error) { b := ctx.Buf[:0] if v == nil { b = encoder.AppendNull(ctx, b) b = encoder.AppendCommaIndent(ctx, b) return b, nil } header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr) if err != nil { return nil, err } p := uintptr(header.ptr) ctx.Init(p, codeSet.CodeLength) buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent) ctx.KeepRefs = append(ctx.KeepRefs, header.ptr) if err != nil { return nil, err } ctx.Buf = buf return buf, nil } 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 (ctx.Option.Flag & encoder.ColorizeOption) != 0 { return vm_color.Run(ctx, b, codeSet) } return vm.Run(ctx, b, codeSet) } func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string) ([]byte, error) { ctx.Prefix = []byte(prefix) ctx.IndentStr = []byte(indent) 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 (ctx.Option.Flag & encoder.ColorizeOption) != 0 { return vm_color_indent.Run(ctx, b, codeSet) } return vm_indent.Run(ctx, b, codeSet) } golang-github-goccy-go-json-0.10.3/encode_test.go000066400000000000000000001760161463555276600216570ustar00rootroot00000000000000package json_test import ( "bytes" "context" "encoding" stdjson "encoding/json" "errors" "fmt" "io" "log" "math" "math/big" "reflect" "regexp" "strconv" "strings" "testing" "time" "github.com/goccy/go-json" ) type recursiveT struct { A *recursiveT `json:"a,omitempty"` B *recursiveU `json:"b,omitempty"` C *recursiveU `json:"c,omitempty"` D string `json:"d,omitempty"` } type recursiveU struct { T *recursiveT `json:"t,omitempty"` } func Test_Marshal(t *testing.T) { t.Run("int", func(t *testing.T) { bytes, err := json.Marshal(-10) assertErr(t, err) assertEq(t, "int", `-10`, string(bytes)) }) t.Run("int8", func(t *testing.T) { bytes, err := json.Marshal(int8(-11)) assertErr(t, err) assertEq(t, "int8", `-11`, string(bytes)) }) t.Run("int16", func(t *testing.T) { bytes, err := json.Marshal(int16(-12)) assertErr(t, err) assertEq(t, "int16", `-12`, string(bytes)) }) t.Run("int32", func(t *testing.T) { bytes, err := json.Marshal(int32(-13)) assertErr(t, err) assertEq(t, "int32", `-13`, string(bytes)) }) t.Run("int64", func(t *testing.T) { bytes, err := json.Marshal(int64(-14)) assertErr(t, err) assertEq(t, "int64", `-14`, string(bytes)) }) t.Run("uint", func(t *testing.T) { bytes, err := json.Marshal(uint(10)) assertErr(t, err) assertEq(t, "uint", `10`, string(bytes)) }) t.Run("uint8", func(t *testing.T) { bytes, err := json.Marshal(uint8(11)) assertErr(t, err) assertEq(t, "uint8", `11`, string(bytes)) }) t.Run("uint16", func(t *testing.T) { bytes, err := json.Marshal(uint16(12)) assertErr(t, err) assertEq(t, "uint16", `12`, string(bytes)) }) t.Run("uint32", func(t *testing.T) { bytes, err := json.Marshal(uint32(13)) assertErr(t, err) assertEq(t, "uint32", `13`, string(bytes)) }) t.Run("uint64", func(t *testing.T) { bytes, err := json.Marshal(uint64(14)) assertErr(t, err) assertEq(t, "uint64", `14`, string(bytes)) }) t.Run("float32", func(t *testing.T) { bytes, err := json.Marshal(float32(3.14)) assertErr(t, err) assertEq(t, "float32", `3.14`, string(bytes)) }) t.Run("float64", func(t *testing.T) { bytes, err := json.Marshal(float64(3.14)) assertErr(t, err) assertEq(t, "float64", `3.14`, string(bytes)) }) t.Run("bool", func(t *testing.T) { bytes, err := json.Marshal(true) assertErr(t, err) assertEq(t, "bool", `true`, string(bytes)) }) t.Run("string", func(t *testing.T) { bytes, err := json.Marshal("hello world") assertErr(t, err) assertEq(t, "string", `"hello world"`, string(bytes)) }) t.Run("struct", func(t *testing.T) { bytes, err := json.Marshal(struct { A int `json:"a"` B uint `json:"b"` C string `json:"c"` D int `json:"-"` // ignore field a int `json:"aa"` // private field }{ A: -1, B: 1, C: "hello world", }) assertErr(t, err) assertEq(t, "struct", `{"a":-1,"b":1,"c":"hello world"}`, string(bytes)) t.Run("null", func(t *testing.T) { type T struct { A *struct{} `json:"a"` } var v T bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "struct", `{"a":null}`, string(bytes)) }) t.Run("recursive", func(t *testing.T) { bytes, err := json.Marshal(recursiveT{ A: &recursiveT{ B: &recursiveU{ T: &recursiveT{ D: "hello", }, }, C: &recursiveU{ T: &recursiveT{ D: "world", }, }, }, }) assertErr(t, err) assertEq(t, "recursive", `{"a":{"b":{"t":{"d":"hello"}},"c":{"t":{"d":"world"}}}}`, string(bytes)) }) t.Run("embedded", func(t *testing.T) { type T struct { A string `json:"a"` } type U struct { *T B string `json:"b"` } type T2 struct { A string `json:"a,omitempty"` } type U2 struct { *T2 B string `json:"b,omitempty"` } t.Run("exists field", func(t *testing.T) { bytes, err := json.Marshal(&U{ T: &T{ A: "aaa", }, B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"a":"aaa","b":"bbb"}`, string(bytes)) t.Run("omitempty", func(t *testing.T) { bytes, err := json.Marshal(&U2{ T2: &T2{ A: "aaa", }, B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"a":"aaa","b":"bbb"}`, string(bytes)) }) }) t.Run("none field", func(t *testing.T) { bytes, err := json.Marshal(&U{ B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"b":"bbb"}`, string(bytes)) t.Run("omitempty", func(t *testing.T) { bytes, err := json.Marshal(&U2{ B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"b":"bbb"}`, string(bytes)) }) }) }) t.Run("embedded with tag", func(t *testing.T) { type T struct { A string `json:"a"` } type U struct { *T `json:"t"` B string `json:"b"` } type T2 struct { A string `json:"a,omitempty"` } type U2 struct { *T2 `json:"t,omitempty"` B string `json:"b,omitempty"` } t.Run("exists field", func(t *testing.T) { bytes, err := json.Marshal(&U{ T: &T{ A: "aaa", }, B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"t":{"a":"aaa"},"b":"bbb"}`, string(bytes)) t.Run("omitempty", func(t *testing.T) { bytes, err := json.Marshal(&U2{ T2: &T2{ A: "aaa", }, B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"t":{"a":"aaa"},"b":"bbb"}`, string(bytes)) }) }) t.Run("none field", func(t *testing.T) { bytes, err := json.Marshal(&U{ B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"t":null,"b":"bbb"}`, string(bytes)) t.Run("omitempty", func(t *testing.T) { bytes, err := json.Marshal(&U2{ B: "bbb", }) assertErr(t, err) assertEq(t, "embedded", `{"b":"bbb"}`, string(bytes)) }) }) }) t.Run("omitempty", func(t *testing.T) { type T struct { A int `json:",omitempty"` B int8 `json:",omitempty"` C int16 `json:",omitempty"` D int32 `json:",omitempty"` E int64 `json:",omitempty"` F uint `json:",omitempty"` G uint8 `json:",omitempty"` H uint16 `json:",omitempty"` I uint32 `json:",omitempty"` J uint64 `json:",omitempty"` K float32 `json:",omitempty"` L float64 `json:",omitempty"` O string `json:",omitempty"` P bool `json:",omitempty"` Q []int `json:",omitempty"` R map[string]interface{} `json:",omitempty"` S *struct{} `json:",omitempty"` T int `json:"t,omitempty"` } var v T v.T = 1 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "struct", `{"t":1}`, string(bytes)) t.Run("int", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B int `json:"b"` } v.B = 1 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "int", `{"b":1}`, string(bytes)) }) t.Run("int8", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B int8 `json:"b"` } v.B = 1 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "int8", `{"b":1}`, string(bytes)) }) t.Run("int16", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B int16 `json:"b"` } v.B = 1 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "int16", `{"b":1}`, string(bytes)) }) t.Run("int32", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B int32 `json:"b"` } v.B = 1 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "int32", `{"b":1}`, string(bytes)) }) t.Run("int64", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B int64 `json:"b"` } v.B = 1 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "int64", `{"b":1}`, string(bytes)) }) t.Run("string", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B string `json:"b"` } v.B = "b" bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "string", `{"b":"b"}`, string(bytes)) }) t.Run("float32", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B float32 `json:"b"` } v.B = 1.1 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "float32", `{"b":1.1}`, string(bytes)) }) t.Run("float64", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B float64 `json:"b"` } v.B = 3.14 bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "float64", `{"b":3.14}`, string(bytes)) }) t.Run("slice", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B []int `json:"b"` } v.B = []int{1, 2, 3} bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "slice", `{"b":[1,2,3]}`, string(bytes)) }) t.Run("array", func(t *testing.T) { var v struct { A int `json:"a,omitempty"` B [2]int `json:"b"` } v.B = [2]int{1, 2} bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "array", `{"b":[1,2]}`, string(bytes)) }) t.Run("map", func(t *testing.T) { v := new(struct { A int `json:"a,omitempty"` B map[string]interface{} `json:"b"` }) v.B = map[string]interface{}{"c": 1} bytes, err := json.Marshal(v) assertErr(t, err) assertEq(t, "array", `{"b":{"c":1}}`, string(bytes)) }) }) t.Run("head_omitempty", func(t *testing.T) { type T struct { A *struct{} `json:"a,omitempty"` } var v T bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "struct", `{}`, string(bytes)) }) t.Run("pointer_head_omitempty", func(t *testing.T) { type V struct{} type U struct { B *V `json:"b,omitempty"` } type T struct { A *U `json:"a"` } bytes, err := json.Marshal(&T{A: &U{}}) assertErr(t, err) assertEq(t, "struct", `{"a":{}}`, string(bytes)) }) t.Run("head_int_omitempty", func(t *testing.T) { type T struct { A int `json:"a,omitempty"` } var v T bytes, err := json.Marshal(&v) assertErr(t, err) assertEq(t, "struct", `{}`, string(bytes)) }) }) t.Run("slice", func(t *testing.T) { t.Run("[]int", func(t *testing.T) { bytes, err := json.Marshal([]int{1, 2, 3, 4}) assertErr(t, err) assertEq(t, "[]int", `[1,2,3,4]`, string(bytes)) }) t.Run("[]interface{}", func(t *testing.T) { bytes, err := json.Marshal([]interface{}{1, 2.1, "hello"}) assertErr(t, err) assertEq(t, "[]interface{}", `[1,2.1,"hello"]`, string(bytes)) }) }) t.Run("array", func(t *testing.T) { bytes, err := json.Marshal([4]int{1, 2, 3, 4}) assertErr(t, err) assertEq(t, "array", `[1,2,3,4]`, string(bytes)) }) t.Run("map", func(t *testing.T) { t.Run("map[string]int", func(t *testing.T) { v := map[string]int{ "a": 1, "b": 2, "c": 3, "d": 4, } bytes, err := json.Marshal(v) assertErr(t, err) assertEq(t, "map", `{"a":1,"b":2,"c":3,"d":4}`, string(bytes)) b, err := json.MarshalWithOption(v, json.UnorderedMap()) assertErr(t, err) assertEq(t, "unordered map", len(`{"a":1,"b":2,"c":3,"d":4}`), len(string(b))) }) t.Run("map[string]interface{}", func(t *testing.T) { type T struct { A int } v := map[string]interface{}{ "a": 1, "b": 2.1, "c": &T{ A: 10, }, "d": 4, } bytes, err := json.Marshal(v) assertErr(t, err) assertEq(t, "map[string]interface{}", `{"a":1,"b":2.1,"c":{"A":10},"d":4}`, string(bytes)) }) }) } type mustErrTypeForDebug struct{} func (mustErrTypeForDebug) MarshalJSON() ([]byte, error) { panic("panic") return nil, fmt.Errorf("panic") } func TestDebugMode(t *testing.T) { defer func() { if err := recover(); err == nil { t.Fatal("expected error") } }() var buf bytes.Buffer json.MarshalWithOption(mustErrTypeForDebug{}, json.Debug(), json.DebugWith(&buf)) } func TestIssue116(t *testing.T) { t.Run("first", func(t *testing.T) { type Boo struct{ B string } type Struct struct { A int Boo *Boo } type Embedded struct { Struct } b, err := json.Marshal(Embedded{Struct: Struct{ A: 1, Boo: &Boo{B: "foo"}, }}) if err != nil { t.Fatal(err) } expected := `{"A":1,"Boo":{"B":"foo"}}` actual := string(b) if actual != expected { t.Fatalf("expected %s but got %s", expected, actual) } }) t.Run("second", func(t *testing.T) { type Boo struct{ B string } type Struct struct { A int B *Boo } type Embedded struct { Struct } b, err := json.Marshal(Embedded{Struct: Struct{ A: 1, B: &Boo{B: "foo"}, }}) if err != nil { t.Fatal(err) } actual := string(b) expected := `{"A":1,"B":{"B":"foo"}}` if actual != expected { t.Fatalf("expected %s but got %s", expected, actual) } }) } type marshalJSON struct{} func (*marshalJSON) MarshalJSON() ([]byte, error) { return []byte(`1`), nil } func Test_MarshalJSON(t *testing.T) { t.Run("*struct", func(t *testing.T) { bytes, err := json.Marshal(&marshalJSON{}) assertErr(t, err) assertEq(t, "MarshalJSON", "1", string(bytes)) }) t.Run("time", func(t *testing.T) { bytes, err := json.Marshal(time.Time{}) assertErr(t, err) assertEq(t, "MarshalJSON", `"0001-01-01T00:00:00Z"`, string(bytes)) }) } func Test_MarshalIndent(t *testing.T) { prefix := "-" indent := "\t" t.Run("struct", func(t *testing.T) { v := struct { A int `json:"a"` B uint `json:"b"` C string `json:"c"` D interface{} `json:"d"` X int `json:"-"` // ignore field a int `json:"aa"` // private field }{ A: -1, B: 1, C: "hello world", D: struct { E bool `json:"e"` }{ E: true, }, } expected, err := stdjson.MarshalIndent(v, prefix, indent) assertErr(t, err) got, err := json.MarshalIndent(v, prefix, indent) assertErr(t, err) assertEq(t, "struct", string(expected), string(got)) }) t.Run("slice", func(t *testing.T) { t.Run("[]int", func(t *testing.T) { bytes, err := json.MarshalIndent([]int{1, 2, 3, 4}, prefix, indent) assertErr(t, err) result := "[\n-\t1,\n-\t2,\n-\t3,\n-\t4\n-]" assertEq(t, "[]int", result, string(bytes)) }) t.Run("[]interface{}", func(t *testing.T) { bytes, err := json.MarshalIndent([]interface{}{1, 2.1, "hello"}, prefix, indent) assertErr(t, err) result := "[\n-\t1,\n-\t2.1,\n-\t\"hello\"\n-]" assertEq(t, "[]interface{}", result, string(bytes)) }) }) t.Run("array", func(t *testing.T) { bytes, err := json.MarshalIndent([4]int{1, 2, 3, 4}, prefix, indent) assertErr(t, err) result := "[\n-\t1,\n-\t2,\n-\t3,\n-\t4\n-]" assertEq(t, "array", result, string(bytes)) }) t.Run("map", func(t *testing.T) { t.Run("map[string]int", func(t *testing.T) { bytes, err := json.MarshalIndent(map[string]int{ "a": 1, "b": 2, "c": 3, "d": 4, }, prefix, indent) assertErr(t, err) result := "{\n-\t\"a\": 1,\n-\t\"b\": 2,\n-\t\"c\": 3,\n-\t\"d\": 4\n-}" assertEq(t, "map", result, string(bytes)) }) t.Run("map[string]interface{}", func(t *testing.T) { type T struct { E int F int } v := map[string]interface{}{ "a": 1, "b": 2.1, "c": &T{ E: 10, F: 11, }, "d": 4, } bytes, err := json.MarshalIndent(v, prefix, indent) assertErr(t, err) result := "{\n-\t\"a\": 1,\n-\t\"b\": 2.1,\n-\t\"c\": {\n-\t\t\"E\": 10,\n-\t\t\"F\": 11\n-\t},\n-\t\"d\": 4\n-}" assertEq(t, "map[string]interface{}", result, string(bytes)) }) }) } type StringTag struct { BoolStr bool `json:",string"` IntStr int64 `json:",string"` UintptrStr uintptr `json:",string"` StrStr string `json:",string"` NumberStr json.Number `json:",string"` } func TestRoundtripStringTag(t *testing.T) { tests := []struct { name string in StringTag want string // empty to just test that we roundtrip }{ { name: "AllTypes", in: StringTag{ BoolStr: true, IntStr: 42, UintptrStr: 44, StrStr: "xzbit", NumberStr: "46", }, want: `{ "BoolStr": "true", "IntStr": "42", "UintptrStr": "44", "StrStr": "\"xzbit\"", "NumberStr": "46" }`, }, { // See golang.org/issues/38173. name: "StringDoubleEscapes", in: StringTag{ StrStr: "\b\f\n\r\t\"\\", NumberStr: "0", // just to satisfy the roundtrip }, want: `{ "BoolStr": "false", "IntStr": "0", "UintptrStr": "0", "StrStr": "\"\\u0008\\u000c\\n\\r\\t\\\"\\\\\"", "NumberStr": "0" }`, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { // Indent with a tab prefix to make the multi-line string // literals in the table nicer to read. got, err := json.MarshalIndent(&test.in, "\t\t\t", "\t") if err != nil { t.Fatal(err) } if got := string(got); got != test.want { t.Fatalf(" got: %s\nwant: %s\n", got, test.want) } // Verify that it round-trips. var s2 StringTag if err := json.Unmarshal(got, &s2); err != nil { t.Fatalf("Decode: %v", err) } if !reflect.DeepEqual(test.in, s2) { t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", test.in, string(got), s2) } }) } } // byte slices are special even if they're renamed types. type renamedByte byte type renamedByteSlice []byte type renamedRenamedByteSlice []renamedByte func TestEncodeRenamedByteSlice(t *testing.T) { s := renamedByteSlice("abc") result, err := json.Marshal(s) if err != nil { t.Fatal(err) } expect := `"YWJj"` if string(result) != expect { t.Errorf(" got %s want %s", result, expect) } r := renamedRenamedByteSlice("abc") result, err = json.Marshal(r) if err != nil { t.Fatal(err) } if string(result) != expect { t.Errorf(" got %s want %s", result, expect) } } func TestMarshalRawMessageValue(t *testing.T) { type ( T1 struct { M json.RawMessage `json:",omitempty"` } T2 struct { M *json.RawMessage `json:",omitempty"` } ) var ( rawNil = json.RawMessage(nil) rawEmpty = json.RawMessage([]byte{}) rawText = json.RawMessage([]byte(`"foo"`)) ) tests := []struct { in interface{} want string ok bool }{ // Test with nil RawMessage. {rawNil, "null", true}, {&rawNil, "null", true}, {[]interface{}{rawNil}, "[null]", true}, {&[]interface{}{rawNil}, "[null]", true}, {[]interface{}{&rawNil}, "[null]", true}, {&[]interface{}{&rawNil}, "[null]", true}, {struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true}, {&struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true}, {struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true}, {&struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true}, {map[string]interface{}{"M": rawNil}, `{"M":null}`, true}, {&map[string]interface{}{"M": rawNil}, `{"M":null}`, true}, {map[string]interface{}{"M": &rawNil}, `{"M":null}`, true}, {&map[string]interface{}{"M": &rawNil}, `{"M":null}`, true}, {T1{rawNil}, "{}", true}, {T2{&rawNil}, `{"M":null}`, true}, {&T1{rawNil}, "{}", true}, {&T2{&rawNil}, `{"M":null}`, true}, // Test with empty, but non-nil, RawMessage. {rawEmpty, "", false}, {&rawEmpty, "", false}, {[]interface{}{rawEmpty}, "", false}, {&[]interface{}{rawEmpty}, "", false}, {[]interface{}{&rawEmpty}, "", false}, {&[]interface{}{&rawEmpty}, "", false}, {struct{ X json.RawMessage }{rawEmpty}, "", false}, {&struct{ X json.RawMessage }{rawEmpty}, "", false}, {struct{ X *json.RawMessage }{&rawEmpty}, "", false}, {&struct{ X *json.RawMessage }{&rawEmpty}, "", false}, {map[string]interface{}{"nil": rawEmpty}, "", false}, {&map[string]interface{}{"nil": rawEmpty}, "", false}, {map[string]interface{}{"nil": &rawEmpty}, "", false}, {&map[string]interface{}{"nil": &rawEmpty}, "", false}, {T1{rawEmpty}, "{}", true}, {T2{&rawEmpty}, "", false}, {&T1{rawEmpty}, "{}", true}, {&T2{&rawEmpty}, "", false}, // Test with RawMessage with some text. // // The tests below marked with Issue6458 used to generate "ImZvbyI=" instead "foo". // This behavior was intentionally changed in Go 1.8. // See https://golang.org/issues/14493#issuecomment-255857318 {rawText, `"foo"`, true}, // Issue6458 {&rawText, `"foo"`, true}, {[]interface{}{rawText}, `["foo"]`, true}, // Issue6458 {&[]interface{}{rawText}, `["foo"]`, true}, // Issue6458 {[]interface{}{&rawText}, `["foo"]`, true}, {&[]interface{}{&rawText}, `["foo"]`, true}, {struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458 {&struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true}, {struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true}, {&struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true}, {map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 {&map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 {map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true}, {&map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true}, {T1{rawText}, `{"M":"foo"}`, true}, // Issue6458 {T2{&rawText}, `{"M":"foo"}`, true}, {&T1{rawText}, `{"M":"foo"}`, true}, {&T2{&rawText}, `{"M":"foo"}`, true}, } for i, tt := range tests { b, err := json.Marshal(tt.in) if ok := (err == nil); ok != tt.ok { if err != nil { t.Errorf("test %d, unexpected failure: %v", i, err) } else { t.Errorf("test %d, unexpected success", i) } } if got := string(b); got != tt.want { t.Errorf("test %d, Marshal(%#v) = %q, want %q", i, tt.in, got, tt.want) } } } type marshalerError struct{} func (*marshalerError) MarshalJSON() ([]byte, error) { return nil, errors.New("unexpected error") } func Test_MarshalerError(t *testing.T) { var v marshalerError _, err := json.Marshal(&v) expect := `json: error calling MarshalJSON for type *json_test.marshalerError: unexpected error` assertEq(t, "marshaler error", expect, fmt.Sprint(err)) } // Ref has Marshaler and Unmarshaler methods with pointer receiver. type Ref int func (*Ref) MarshalJSON() ([]byte, error) { return []byte(`"ref"`), nil } func (r *Ref) UnmarshalJSON([]byte) error { *r = 12 return nil } // Val has Marshaler methods with value receiver. type Val int func (Val) MarshalJSON() ([]byte, error) { return []byte(`"val"`), nil } // RefText has Marshaler and Unmarshaler methods with pointer receiver. type RefText int func (*RefText) MarshalText() ([]byte, error) { return []byte(`"ref"`), nil } func (r *RefText) UnmarshalText([]byte) error { *r = 13 return nil } // ValText has Marshaler methods with value receiver. type ValText int func (ValText) MarshalText() ([]byte, error) { return []byte(`"val"`), nil } func TestRefValMarshal(t *testing.T) { var s = struct { R0 Ref R1 *Ref R2 RefText R3 *RefText V0 Val V1 *Val V2 ValText V3 *ValText }{ R0: 12, R1: new(Ref), R2: 14, R3: new(RefText), V0: 13, V1: new(Val), V2: 15, V3: new(ValText), } const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}` b, err := json.Marshal(&s) if err != nil { t.Fatalf("Marshal: %v", err) } if got := string(b); got != want { t.Errorf("got %q, want %q", got, want) } } // C implements Marshaler and returns unescaped JSON. type C int func (C) MarshalJSON() ([]byte, error) { return []byte(`"<&>"`), nil } // CText implements Marshaler and returns unescaped text. type CText int func (CText) MarshalText() ([]byte, error) { return []byte(`"<&>"`), nil } func TestMarshalerEscaping(t *testing.T) { var c C want := `"\u003c\u0026\u003e"` b, err := json.Marshal(c) if err != nil { t.Fatalf("Marshal(c): %v", err) } if got := string(b); got != want { t.Errorf("Marshal(c) = %#q, want %#q", got, want) } var ct CText want = `"\"\u003c\u0026\u003e\""` b, err = json.Marshal(ct) if err != nil { t.Fatalf("Marshal(ct): %v", err) } if got := string(b); got != want { t.Errorf("Marshal(ct) = %#q, want %#q", got, want) } } type marshalPanic struct{} func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) } func TestMarshalPanic(t *testing.T) { defer func() { if got := recover(); !reflect.DeepEqual(got, 0xdead) { t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) } }() json.Marshal(&marshalPanic{}) t.Error("Marshal should have panicked") } func TestMarshalUncommonFieldNames(t *testing.T) { v := struct { A0, À, Aβ int }{} b, err := json.Marshal(v) if err != nil { t.Fatal("Marshal:", err) } want := `{"A0":0,"À":0,"Aβ":0}` got := string(b) if got != want { t.Fatalf("Marshal: got %s want %s", got, want) } } func TestMarshalerError(t *testing.T) { s := "test variable" st := reflect.TypeOf(s) errText := "json: test error" tests := []struct { err *json.MarshalerError want string }{ { json.NewMarshalerError(st, fmt.Errorf(errText), ""), "json: error calling MarshalJSON for type " + st.String() + ": " + errText, }, { json.NewMarshalerError(st, fmt.Errorf(errText), "TestMarshalerError"), "json: error calling TestMarshalerError for type " + st.String() + ": " + errText, }, } for i, tt := range tests { got := tt.err.Error() if got != tt.want { t.Errorf("MarshalerError test %d, got: %s, want: %s", i, got, tt.want) } } } type unmarshalerText struct { A, B string } // needed for re-marshaling tests func (u unmarshalerText) MarshalText() ([]byte, error) { return []byte(u.A + ":" + u.B), nil } func (u *unmarshalerText) UnmarshalText(b []byte) error { pos := bytes.IndexByte(b, ':') if pos == -1 { return errors.New("missing separator") } u.A, u.B = string(b[:pos]), string(b[pos+1:]) return nil } func TestTextMarshalerMapKeysAreSorted(t *testing.T) { data := map[unmarshalerText]int{ {"x", "y"}: 1, {"y", "x"}: 2, {"a", "z"}: 3, {"z", "a"}: 4, } b, err := json.Marshal(data) if err != nil { t.Fatalf("Failed to Marshal text.Marshaler: %v", err) } const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}` if string(b) != want { t.Errorf("Marshal map with text.Marshaler keys: got %#q, want %#q", b, want) } b, err = stdjson.Marshal(data) if err != nil { t.Fatalf("Failed to std Marshal text.Marshaler: %v", err) } if string(b) != want { t.Errorf("std Marshal map with text.Marshaler keys: got %#q, want %#q", b, want) } } // https://golang.org/issue/33675 func TestNilMarshalerTextMapKey(t *testing.T) { v := map[*unmarshalerText]int{ (*unmarshalerText)(nil): 1, {"A", "B"}: 2, } b, err := json.Marshal(v) if err != nil { t.Fatalf("Failed to Marshal *text.Marshaler: %v", err) } const want = `{"":1,"A:B":2}` if string(b) != want { t.Errorf("Marshal map with *text.Marshaler keys: got %#q, want %#q", b, want) } } var re = regexp.MustCompile // syntactic checks on form of marshaled floating point numbers. var badFloatREs = []*regexp.Regexp{ re(`p`), // no binary exponential notation re(`^\+`), // no leading + sign re(`^-?0[^.]`), // no unnecessary leading zeros re(`^-?\.`), // leading zero required before decimal point re(`\.(e|$)`), // no trailing decimal re(`\.[0-9]+0(e|$)`), // no trailing zero in fraction re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa re(`e[0-9]`), // positive exponent must be signed //re(`e[+-]0`), // exponent must not have leading zeros re(`e-[1-6]$`), // not tiny enough for exponential notation re(`e+(.|1.|20)$`), // not big enough for exponential notation re(`^-?0\.0000000`), // too tiny, should use exponential notation re(`^-?[0-9]{22}`), // too big, should use exponential notation re(`[1-9][0-9]{16}[1-9]`), // too many significant digits in integer re(`[1-9][0-9.]{17}[1-9]`), // too many significant digits in decimal // below here for float32 only re(`[1-9][0-9]{8}[1-9]`), // too many significant digits in integer re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal } func TestMarshalFloat(t *testing.T) { //t.Parallel() nfail := 0 test := func(f float64, bits int) { vf := interface{}(f) if bits == 32 { f = float64(float32(f)) // round vf = float32(f) } bout, err := json.Marshal(vf) if err != nil { t.Errorf("Marshal(%T(%g)): %v", vf, vf, err) nfail++ return } out := string(bout) // result must convert back to the same float g, err := strconv.ParseFloat(out, bits) if err != nil { t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err) nfail++ return } if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0 t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf) nfail++ return } bad := badFloatREs if bits == 64 { bad = bad[:len(bad)-2] } for _, re := range bad { if re.MatchString(out) { t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re) nfail++ return } } } var ( bigger = math.Inf(+1) smaller = math.Inf(-1) ) var digits = "1.2345678901234567890123" for i := len(digits); i >= 2; i-- { if testing.Short() && i < len(digits)-4 { break } for exp := -30; exp <= 30; exp++ { for _, sign := range "+-" { for bits := 32; bits <= 64; bits += 32 { s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp) f, err := strconv.ParseFloat(s, bits) if err != nil { log.Fatal(err) } next := math.Nextafter if bits == 32 { next = func(g, h float64) float64 { return float64(math.Nextafter32(float32(g), float32(h))) } } test(f, bits) test(next(f, bigger), bits) test(next(f, smaller), bits) if nfail > 50 { t.Fatalf("stopping test early") } } } } } test(0, 64) test(math.Copysign(0, -1), 64) test(0, 32) test(math.Copysign(0, -1), 32) } var encodeStringTests = []struct { in string out string }{ {"\x00", `"\u0000"`}, {"\x01", `"\u0001"`}, {"\x02", `"\u0002"`}, {"\x03", `"\u0003"`}, {"\x04", `"\u0004"`}, {"\x05", `"\u0005"`}, {"\x06", `"\u0006"`}, {"\x07", `"\u0007"`}, {"\x08", `"\u0008"`}, {"\x09", `"\t"`}, {"\x0a", `"\n"`}, {"\x0b", `"\u000b"`}, {"\x0c", `"\u000c"`}, {"\x0d", `"\r"`}, {"\x0e", `"\u000e"`}, {"\x0f", `"\u000f"`}, {"\x10", `"\u0010"`}, {"\x11", `"\u0011"`}, {"\x12", `"\u0012"`}, {"\x13", `"\u0013"`}, {"\x14", `"\u0014"`}, {"\x15", `"\u0015"`}, {"\x16", `"\u0016"`}, {"\x17", `"\u0017"`}, {"\x18", `"\u0018"`}, {"\x19", `"\u0019"`}, {"\x1a", `"\u001a"`}, {"\x1b", `"\u001b"`}, {"\x1c", `"\u001c"`}, {"\x1d", `"\u001d"`}, {"\x1e", `"\u001e"`}, {"\x1f", `"\u001f"`}, } func TestEncodeString(t *testing.T) { for _, tt := range encodeStringTests { b, err := json.Marshal(tt.in) if err != nil { t.Errorf("Marshal(%q): %v", tt.in, err) continue } out := string(b) if out != tt.out { t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out) } } } type jsonbyte byte func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) } type textbyte byte func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) } type jsonint int func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) } type textint int func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) } func tenc(format string, a ...interface{}) ([]byte, error) { var buf bytes.Buffer fmt.Fprintf(&buf, format, a...) return buf.Bytes(), nil } // Issue 13783 func TestEncodeBytekind(t *testing.T) { testdata := []struct { data interface{} want string }{ {byte(7), "7"}, {jsonbyte(7), `{"JB":7}`}, {textbyte(4), `"TB:4"`}, {jsonint(5), `{"JI":5}`}, {textint(1), `"TI:1"`}, {[]byte{0, 1}, `"AAE="`}, {[]jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`}, {[][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`}, {[]textbyte{2, 3}, `["TB:2","TB:3"]`}, {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`}, {[]textint{9, 3}, `["TI:9","TI:3"]`}, {[]int{9, 3}, `[9,3]`}, } for i, d := range testdata { js, err := json.Marshal(d.data) if err != nil { t.Error(err) continue } got, want := string(js), d.want if got != want { t.Errorf("%d: got %s, want %s", i, got, want) } } } // golang.org/issue/8582 func TestEncodePointerString(t *testing.T) { type stringPointer struct { N *int64 `json:"n,string"` } var n int64 = 42 b, err := json.Marshal(stringPointer{N: &n}) if err != nil { t.Fatalf("Marshal: %v", err) } if got, want := string(b), `{"n":"42"}`; got != want { t.Errorf("Marshal = %s, want %s", got, want) } var back stringPointer err = json.Unmarshal(b, &back) if err != nil { t.Fatalf("Unmarshal: %v", err) } if back.N == nil { t.Fatalf("Unmarshaled nil N field") } if *back.N != 42 { t.Fatalf("*N = %d; want 42", *back.N) } } type SamePointerNoCycle struct { Ptr1, Ptr2 *SamePointerNoCycle } var samePointerNoCycle = &SamePointerNoCycle{} type PointerCycle struct { Ptr *PointerCycle } var pointerCycle = &PointerCycle{} type PointerCycleIndirect struct { Ptrs []interface{} } var pointerCycleIndirect = &PointerCycleIndirect{} func init() { ptr := &SamePointerNoCycle{} samePointerNoCycle.Ptr1 = ptr samePointerNoCycle.Ptr2 = ptr pointerCycle.Ptr = pointerCycle pointerCycleIndirect.Ptrs = []interface{}{pointerCycleIndirect} } func TestSamePointerNoCycle(t *testing.T) { if _, err := json.Marshal(samePointerNoCycle); err != nil { t.Fatalf("unexpected error: %v", err) } } var unsupportedValues = []interface{}{ math.NaN(), math.Inf(-1), math.Inf(1), pointerCycle, pointerCycleIndirect, } func TestUnsupportedValues(t *testing.T) { for _, v := range unsupportedValues { if _, err := json.Marshal(v); err != nil { if _, ok := err.(*json.UnsupportedValueError); !ok { t.Errorf("for %v, got %T want UnsupportedValueError", v, err) } } else { t.Errorf("for %v, expected error", v) } } } func TestIssue10281(t *testing.T) { type Foo struct { N json.Number } x := Foo{json.Number(`invalid`)} b, err := json.Marshal(&x) if err == nil { t.Errorf("Marshal(&x) = %#q; want error", b) } } func TestHTMLEscape(t *testing.T) { var b, want bytes.Buffer m := `{"M":"foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `"}` want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`)) json.HTMLEscape(&b, []byte(m)) if !bytes.Equal(b.Bytes(), want.Bytes()) { t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes()) } } type BugA struct { S string } type BugB struct { BugA S string } type BugC struct { S string } // Legal Go: We never use the repeated embedded field (S). type BugX struct { A int BugA BugB } // golang.org/issue/16042. // Even if a nil interface value is passed in, as long as // it implements Marshaler, it should be marshaled. type nilJSONMarshaler string func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) { if nm == nil { return json.Marshal("0zenil0") } return json.Marshal("zenil:" + string(*nm)) } // golang.org/issue/34235. // Even if a nil interface value is passed in, as long as // it implements encoding.TextMarshaler, it should be marshaled. type nilTextMarshaler string func (nm *nilTextMarshaler) MarshalText() ([]byte, error) { if nm == nil { return []byte("0zenil0"), nil } return []byte("zenil:" + string(*nm)), nil } // See golang.org/issue/16042 and golang.org/issue/34235. func TestNilMarshal(t *testing.T) { testCases := []struct { v interface{} want string }{ {v: nil, want: `null`}, {v: new(float64), want: `0`}, {v: []interface{}(nil), want: `null`}, {v: []string(nil), want: `null`}, {v: map[string]string(nil), want: `null`}, {v: []byte(nil), want: `null`}, {v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`}, {v: struct{ M json.Marshaler }{}, want: `{"M":null}`}, {v: struct{ M json.Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, {v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`}, {v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`}, {v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, {v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`}, } for i, tt := range testCases { out, err := json.Marshal(tt.v) if err != nil || string(out) != tt.want { t.Errorf("%d: Marshal(%#v) = %#q, %#v, want %#q, nil", i, tt.v, out, err, tt.want) continue } } } // Issue 5245. func TestEmbeddedBug(t *testing.T) { v := BugB{ BugA{"A"}, "B", } b, err := json.Marshal(v) if err != nil { t.Fatal("Marshal:", err) } want := `{"S":"B"}` got := string(b) if got != want { t.Fatalf("Marshal: got %s want %s", got, want) } // Now check that the duplicate field, S, does not appear. x := BugX{ A: 23, } b, err = json.Marshal(x) if err != nil { t.Fatal("Marshal:", err) } want = `{"A":23}` got = string(b) if got != want { t.Fatalf("Marshal: got %s want %s", got, want) } } type BugD struct { // Same as BugA after tagging. XXX string `json:"S"` } // BugD's tagged S field should dominate BugA's. type BugY struct { BugA BugD } // Test that a field with a tag dominates untagged fields. func TestTaggedFieldDominates(t *testing.T) { v := BugY{ BugA{"BugA"}, BugD{"BugD"}, } b, err := json.Marshal(v) if err != nil { t.Fatal("Marshal:", err) } want := `{"S":"BugD"}` got := string(b) if got != want { t.Fatalf("Marshal: got %s want %s", got, want) } } // There are no tags here, so S should not appear. type BugZ struct { BugA BugC BugY // Contains a tagged S field through BugD; should not dominate. } func TestDuplicatedFieldDisappears(t *testing.T) { v := BugZ{ BugA{"BugA"}, BugC{"BugC"}, BugY{ BugA{"nested BugA"}, BugD{"nested BugD"}, }, } b, err := json.Marshal(v) if err != nil { t.Fatal("Marshal:", err) } want := `{}` got := string(b) if got != want { t.Fatalf("Marshal: got %s want %s", got, want) } } func TestAnonymousFields(t *testing.T) { tests := []struct { label string // Test name makeInput func() interface{} // Function to create input value want string // Expected JSON output }{{ // Both S1 and S2 have a field named X. From the perspective of S, // it is ambiguous which one X refers to. // This should not serialize either field. label: "AmbiguousField", makeInput: func() interface{} { type ( S1 struct{ x, X int } S2 struct{ x, X int } S struct { S1 S2 } ) return S{S1{1, 2}, S2{3, 4}} }, want: `{}`, }, { label: "DominantField", // Both S1 and S2 have a field named X, but since S has an X field as // well, it takes precedence over S1.X and S2.X. makeInput: func() interface{} { type ( S1 struct{ x, X int } S2 struct{ x, X int } S struct { S1 S2 x, X int } ) return S{S1{1, 2}, S2{3, 4}, 5, 6} }, want: `{"X":6}`, }, { // Unexported embedded field of non-struct type should not be serialized. label: "UnexportedEmbeddedInt", makeInput: func() interface{} { type ( myInt int S struct{ myInt } ) return S{5} }, want: `{}`, }, { // Exported embedded field of non-struct type should be serialized. label: "ExportedEmbeddedInt", makeInput: func() interface{} { type ( MyInt int S struct{ MyInt } ) return S{5} }, want: `{"MyInt":5}`, }, { // Unexported embedded field of pointer to non-struct type // should not be serialized. label: "UnexportedEmbeddedIntPointer", makeInput: func() interface{} { type ( myInt int S struct{ *myInt } ) s := S{new(myInt)} *s.myInt = 5 return s }, want: `{}`, }, { // Exported embedded field of pointer to non-struct type // should be serialized. label: "ExportedEmbeddedIntPointer", makeInput: func() interface{} { type ( MyInt int S struct{ *MyInt } ) s := S{new(MyInt)} *s.MyInt = 5 return s }, want: `{"MyInt":5}`, }, { // Exported fields of embedded structs should have their // exported fields be serialized regardless of whether the struct types // themselves are exported. label: "EmbeddedStruct", makeInput: func() interface{} { type ( s1 struct{ x, X int } S2 struct{ y, Y int } S struct { s1 S2 } ) return S{s1{1, 2}, S2{3, 4}} }, want: `{"X":2,"Y":4}`, }, { // Exported fields of pointers to embedded structs should have their // exported fields be serialized regardless of whether the struct types // themselves are exported. label: "EmbeddedStructPointer", makeInput: func() interface{} { type ( s1 struct{ x, X int } S2 struct{ y, Y int } S struct { *s1 *S2 } ) return S{&s1{1, 2}, &S2{3, 4}} }, want: `{"X":2,"Y":4}`, }, { // Exported fields on embedded unexported structs at multiple levels // of nesting should still be serialized. label: "NestedStructAndInts", makeInput: func() interface{} { type ( MyInt1 int MyInt2 int myInt int s2 struct { MyInt2 myInt } s1 struct { MyInt1 myInt s2 } S struct { s1 myInt } ) return S{s1{1, 2, s2{3, 4}}, 6} }, want: `{"MyInt1":1,"MyInt2":3}`, }, { // If an anonymous struct pointer field is nil, we should ignore // the embedded fields behind it. Not properly doing so may // result in the wrong output or reflect panics. label: "EmbeddedFieldBehindNilPointer", makeInput: func() interface{} { type ( S2 struct{ Field string } S struct{ *S2 } ) return S{} }, want: `{}`, }} for i, tt := range tests { t.Run(tt.label, func(t *testing.T) { b, err := json.Marshal(tt.makeInput()) if err != nil { t.Fatalf("%d: Marshal() = %v, want nil error", i, err) } if string(b) != tt.want { t.Fatalf("%d: Marshal() = %q, want %q", i, b, tt.want) } }) } } type Optionals struct { Sr string `json:"sr"` So string `json:"so,omitempty"` Sw string `json:"-"` Ir int `json:"omitempty"` // actually named omitempty, not an option Io int `json:"io,omitempty"` Slr []string `json:"slr,random"` Slo []string `json:"slo,omitempty"` Mr map[string]interface{} `json:"mr"` Mo map[string]interface{} `json:",omitempty"` Fr float64 `json:"fr"` Fo float64 `json:"fo,omitempty"` Br bool `json:"br"` Bo bool `json:"bo,omitempty"` Ur uint `json:"ur"` Uo uint `json:"uo,omitempty"` Str struct{} `json:"str"` Sto struct{} `json:"sto,omitempty"` } var optionalsExpected = `{ "sr": "", "omitempty": 0, "slr": null, "mr": {}, "fr": 0, "br": false, "ur": 0, "str": {}, "sto": {} }` func TestOmitEmpty(t *testing.T) { var o Optionals o.Sw = "something" o.Mr = map[string]interface{}{} o.Mo = map[string]interface{}{} got, err := json.MarshalIndent(&o, "", " ") if err != nil { t.Fatal(err) } if got := string(got); got != optionalsExpected { t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected) } } type testNullStr string func (v *testNullStr) MarshalJSON() ([]byte, error) { if *v == "" { return []byte("null"), nil } return []byte(*v), nil } func TestIssue147(t *testing.T) { type T struct { Field1 string `json:"field1"` Field2 testNullStr `json:"field2,omitempty"` } got, err := json.Marshal(T{ Field1: "a", Field2: "b", }) if err != nil { t.Fatal(err) } expect, _ := stdjson.Marshal(T{ Field1: "a", Field2: "b", }) if !bytes.Equal(expect, got) { t.Fatalf("expect %q but got %q", string(expect), string(got)) } } type testIssue144 struct { name string number int64 } func (v *testIssue144) MarshalJSON() ([]byte, error) { if v.name != "" { return json.Marshal(v.name) } return json.Marshal(v.number) } func TestIssue144(t *testing.T) { type Embeded struct { Field *testIssue144 `json:"field,omitempty"` } type T struct { Embeded } { v := T{ Embeded: Embeded{Field: &testIssue144{name: "hoge"}}, } got, err := json.Marshal(v) if err != nil { t.Fatal(err) } expect, _ := stdjson.Marshal(v) if !bytes.Equal(expect, got) { t.Fatalf("expect %q but got %q", string(expect), string(got)) } } { v := &T{ Embeded: Embeded{Field: &testIssue144{name: "hoge"}}, } got, err := json.Marshal(v) if err != nil { t.Fatal(err) } expect, _ := stdjson.Marshal(v) if !bytes.Equal(expect, got) { t.Fatalf("expect %q but got %q", string(expect), string(got)) } } } func TestIssue118(t *testing.T) { type data struct { Columns []string `json:"columns"` Rows1 [][]string `json:"rows1"` Rows2 [][]string `json:"rows2"` } v := data{Columns: []string{"1", "2", "3"}} got, err := json.MarshalIndent(v, "", " ") if err != nil { t.Fatal(err) } expect, _ := stdjson.MarshalIndent(v, "", " ") if !bytes.Equal(expect, got) { t.Fatalf("expect %q but got %q", string(expect), string(got)) } } func TestIssue104(t *testing.T) { type A struct { Field1 string Field2 int Field3 float64 } type T struct { Field A } got, err := json.Marshal(T{}) if err != nil { t.Fatal(err) } expect, _ := stdjson.Marshal(T{}) if !bytes.Equal(expect, got) { t.Fatalf("expect %q but got %q", string(expect), string(got)) } } func TestIssue179(t *testing.T) { data := ` { "t": { "t1": false, "t2": 0, "t3": "", "t4": [], "t5": null, "t6": null } }` type T struct { X struct { T1 bool `json:"t1,omitempty"` T2 float64 `json:"t2,omitempty"` T3 string `json:"t3,omitempty"` T4 []string `json:"t4,omitempty"` T5 *struct{} `json:"t5,omitempty"` T6 interface{} `json:"t6,omitempty"` } `json:"x"` } var v T if err := stdjson.Unmarshal([]byte(data), &v); err != nil { t.Fatal(err) } var v2 T if err := json.Unmarshal([]byte(data), &v2); err != nil { t.Fatal(err) } if !reflect.DeepEqual(v, v2) { t.Fatalf("failed to decode: expected %v got %v", v, v2) } b1, err := stdjson.Marshal(v) if err != nil { t.Fatal(err) } b2, err := json.Marshal(v2) if err != nil { t.Fatal(err) } if !bytes.Equal(b1, b2) { t.Fatalf("failed to equal encoded result: expected %q but got %q", b1, b2) } } func TestIssue180(t *testing.T) { v := struct { T struct { T1 bool `json:"t1"` T2 float64 `json:"t2"` T3 string `json:"t3"` T4 []string `json:"t4"` T5 *struct{} `json:"t5"` T6 interface{} `json:"t6"` T7 [][]string `json:"t7"` } `json:"t"` }{ T: struct { T1 bool `json:"t1"` T2 float64 `json:"t2"` T3 string `json:"t3"` T4 []string `json:"t4"` T5 *struct{} `json:"t5"` T6 interface{} `json:"t6"` T7 [][]string `json:"t7"` }{ T4: []string{}, T7: [][]string{ []string{""}, []string{"hello", "world"}, []string{}, }, }, } b1, err := stdjson.MarshalIndent(v, "", "\t") if err != nil { t.Fatal(err) } b2, err := json.MarshalIndent(v, "", "\t") if err != nil { t.Fatal(err) } if !bytes.Equal(b1, b2) { t.Fatalf("failed to equal encoded result: expected %s but got %s", string(b1), string(b2)) } } func TestIssue235(t *testing.T) { type TaskMessage struct { Type string Payload map[string]interface{} UniqueKey string } msg := TaskMessage{ Payload: map[string]interface{}{ "sent_at": map[string]interface{}{ "Time": "0001-01-01T00:00:00Z", "Valid": false, }, }, } if _, err := json.Marshal(msg); err != nil { t.Fatal(err) } } func TestEncodeMapKeyTypeInterface(t *testing.T) { if _, err := json.Marshal(map[interface{}]interface{}{"a": 1}); err == nil { t.Fatal("expected error") } } type marshalContextKey struct{} type marshalContextStructType struct{} func (t *marshalContextStructType) MarshalJSON(ctx context.Context) ([]byte, error) { v := ctx.Value(marshalContextKey{}) s, ok := v.(string) if !ok { return nil, fmt.Errorf("failed to propagate parent context.Context") } if s != "hello" { return nil, fmt.Errorf("failed to propagate parent context.Context") } return []byte(`"success"`), nil } func TestEncodeContextOption(t *testing.T) { t.Run("MarshalContext", func(t *testing.T) { ctx := context.WithValue(context.Background(), marshalContextKey{}, "hello") b, err := json.MarshalContext(ctx, &marshalContextStructType{}) if err != nil { t.Fatal(err) } if string(b) != `"success"` { t.Fatal("failed to encode with MarshalerContext") } }) t.Run("EncodeContext", func(t *testing.T) { ctx := context.WithValue(context.Background(), marshalContextKey{}, "hello") buf := bytes.NewBuffer([]byte{}) if err := json.NewEncoder(buf).EncodeContext(ctx, &marshalContextStructType{}); err != nil { t.Fatal(err) } if buf.String() != "\"success\"\n" { t.Fatal("failed to encode with EncodeContext") } }) } func TestInterfaceWithPointer(t *testing.T) { var ( ivalue int = 10 uvalue uint = 20 svalue string = "value" bvalue bool = true fvalue float32 = 3.14 nvalue json.Number = "1.23" structv = struct{ A int }{A: 10} slice = []int{1, 2, 3, 4} array = [4]int{1, 2, 3, 4} mapvalue = map[string]int{"a": 1} ) data := map[string]interface{}{ "ivalue": ivalue, "uvalue": uvalue, "svalue": svalue, "bvalue": bvalue, "fvalue": fvalue, "nvalue": nvalue, "struct": structv, "slice": slice, "array": array, "map": mapvalue, "pivalue": &ivalue, "puvalue": &uvalue, "psvalue": &svalue, "pbvalue": &bvalue, "pfvalue": &fvalue, "pnvalue": &nvalue, "pstruct": &structv, "pslice": &slice, "parray": &array, "pmap": &mapvalue, } expected, err := stdjson.Marshal(data) if err != nil { t.Fatal(err) } actual, err := json.Marshal(data) if err != nil { t.Fatal(err) } assertEq(t, "interface{}", string(expected), string(actual)) } func TestIssue263(t *testing.T) { type Foo struct { A []string `json:"a"` B int `json:"b"` } type MyStruct struct { Foo *Foo `json:"foo,omitempty"` } s := MyStruct{ Foo: &Foo{ A: []string{"ls -lah"}, B: 0, }, } expected, err := stdjson.Marshal(s) if err != nil { t.Fatal(err) } actual, err := json.Marshal(s) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, actual) { t.Fatalf("expected:[%s] but got:[%s]", string(expected), string(actual)) } } func TestEmbeddedNotFirstField(t *testing.T) { type Embedded struct { Has bool `json:"has"` } type T struct { X int `json:"is"` Embedded `json:"child"` } p := T{X: 10, Embedded: Embedded{Has: true}} expected, err := stdjson.Marshal(&p) if err != nil { t.Fatal(err) } got, err := json.Marshal(&p) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("failed to encode embedded structure. expected = %q but got %q", expected, got) } } type implementedMethodIface interface { M() } type implementedIfaceType struct { A int B string } func (implementedIfaceType) M() {} func TestImplementedMethodInterfaceType(t *testing.T) { data := []implementedIfaceType{implementedIfaceType{}} expected, err := stdjson.Marshal(data) if err != nil { t.Fatal(err) } got, err := json.Marshal(data) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("failed to encode implemented method interface type. expected:[%q] but got:[%q]", expected, got) } } func TestEmptyStructInterface(t *testing.T) { expected, err := stdjson.Marshal([]interface{}{struct{}{}}) if err != nil { t.Fatal(err) } got, err := json.Marshal([]interface{}{struct{}{}}) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("failed to encode empty struct interface. expected:[%q] but got:[%q]", expected, got) } } func TestIssue290(t *testing.T) { type Issue290 interface { A() } var a struct { A Issue290 } expected, err := stdjson.Marshal(a) if err != nil { t.Fatal(err) } got, err := json.Marshal(a) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("failed to encode non empty interface. expected = %q but got %q", expected, got) } } func TestIssue299(t *testing.T) { t.Run("conflict second field", func(t *testing.T) { type Embedded struct { ID string `json:"id"` Name map[string]string `json:"name"` } type Container struct { Embedded Name string `json:"name"` } c := &Container{ Embedded: Embedded{ ID: "1", Name: map[string]string{"en": "Hello", "es": "Hola"}, }, Name: "Hi", } expected, _ := stdjson.Marshal(c) got, err := json.Marshal(c) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("expected %q but got %q", expected, got) } }) t.Run("conflict map field", func(t *testing.T) { type Embedded struct { Name map[string]string `json:"name"` } type Container struct { Embedded Name string `json:"name"` } c := &Container{ Embedded: Embedded{ Name: map[string]string{"en": "Hello", "es": "Hola"}, }, Name: "Hi", } expected, _ := stdjson.Marshal(c) got, err := json.Marshal(c) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("expected %q but got %q", expected, got) } }) t.Run("conflict slice field", func(t *testing.T) { type Embedded struct { Name []string `json:"name"` } type Container struct { Embedded Name string `json:"name"` } c := &Container{ Embedded: Embedded{ Name: []string{"Hello"}, }, Name: "Hi", } expected, _ := stdjson.Marshal(c) got, err := json.Marshal(c) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("expected %q but got %q", expected, got) } }) } func TestRecursivePtrHead(t *testing.T) { type User struct { Account *string `json:"account"` Password *string `json:"password"` Nickname *string `json:"nickname"` Address *string `json:"address,omitempty"` Friends []*User `json:"friends,omitempty"` } user1Account, user1Password, user1Nickname := "abcdef", "123456", "user1" user1 := &User{ Account: &user1Account, Password: &user1Password, Nickname: &user1Nickname, Address: nil, } user2Account, user2Password, user2Nickname := "ghijkl", "123456", "user2" user2 := &User{ Account: &user2Account, Password: &user2Password, Nickname: &user2Nickname, Address: nil, } user1.Friends = []*User{user2} expected, err := stdjson.Marshal(user1) if err != nil { t.Fatal(err) } got, err := json.Marshal(user1) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("failed to encode. expected %q but got %q", expected, got) } } func TestMarshalIndent(t *testing.T) { v := map[string]map[string]interface{}{ "a": { "b": "1", "c": map[string]interface{}{ "d": "1", }, }, } expected, err := stdjson.MarshalIndent(v, "", " ") if err != nil { t.Fatal(err) } got, err := json.MarshalIndent(v, "", " ") if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("expected: %q but got %q", expected, got) } } type issue318Embedded struct { _ [64]byte } type issue318 struct { issue318Embedded `json:"-"` ID issue318MarshalText `json:"id,omitempty"` } type issue318MarshalText struct { ID string } func (i issue318MarshalText) MarshalText() ([]byte, error) { return []byte(i.ID), nil } func TestIssue318(t *testing.T) { v := issue318{ ID: issue318MarshalText{ID: "1"}, } b, err := json.Marshal(v) if err != nil { t.Fatal(err) } expected := `{"id":"1"}` if string(b) != expected { t.Fatalf("failed to encode. expected %s but got %s", expected, string(b)) } } type emptyStringMarshaler struct { Value stringMarshaler `json:"value,omitempty"` } type stringMarshaler string func (s stringMarshaler) MarshalJSON() ([]byte, error) { return []byte(`"` + s + `"`), nil } func TestEmptyStringMarshaler(t *testing.T) { value := emptyStringMarshaler{} expected, err := stdjson.Marshal(value) assertErr(t, err) got, err := json.Marshal(value) assertErr(t, err) assertEq(t, "struct", string(expected), string(got)) } func TestIssue324(t *testing.T) { type T struct { FieldA *string `json:"fieldA,omitempty"` FieldB *string `json:"fieldB,omitempty"` FieldC *bool `json:"fieldC"` FieldD []string `json:"fieldD,omitempty"` } v := &struct { Code string `json:"code"` *T }{ T: &T{}, } var sv = "Test Field" v.Code = "Test" v.T.FieldB = &sv expected, err := stdjson.Marshal(v) if err != nil { t.Fatal(err) } got, err := json.Marshal(v) if err != nil { t.Fatal(err) } if !bytes.Equal(expected, got) { t.Fatalf("failed to encode. expected %q but got %q", expected, got) } } func TestIssue339(t *testing.T) { type T1 struct { *big.Int } type T2 struct { T1 T1 `json:"T1"` } v := T2{T1{Int: big.NewInt(10000)}} b, err := json.Marshal(&v) assertErr(t, err) got := string(b) expected := `{"T1":10000}` if got != expected { t.Errorf("unexpected result: %v != %v", got, expected) } } func TestIssue376(t *testing.T) { type Container struct { V interface{} `json:"value"` } type MapOnly struct { Map map[string]int64 `json:"map"` } b, err := json.Marshal(Container{MapOnly{}}) if err != nil { t.Fatal(err) } got := string(b) expected := `{"value":{"map":null}}` if got != expected { t.Errorf("unexpected result: %v != %v", got, expected) } } type Issue370 struct { String string Valid bool } func (i *Issue370) MarshalJSON() ([]byte, error) { if !i.Valid { return json.Marshal(nil) } return json.Marshal(i.String) } func TestIssue370(t *testing.T) { v := []struct { V Issue370 }{ {V: Issue370{String: "test", Valid: true}}, } b, err := json.Marshal(v) if err != nil { t.Fatal(err) } got := string(b) expected := `[{"V":"test"}]` if got != expected { t.Errorf("unexpected result: %v != %v", got, expected) } } func TestIssue374(t *testing.T) { r := io.MultiReader(strings.NewReader(strings.Repeat(" ", 505)+`"\u`), strings.NewReader(`0000"`)) var v interface{} if err := json.NewDecoder(r).Decode(&v); err != nil { t.Fatal(err) } got := v.(string) expected := "\u0000" if got != expected { t.Errorf("unexpected result: %q != %q", got, expected) } } func TestIssue381(t *testing.T) { var v struct { Field0 bool Field1 bool Field2 bool Field3 bool Field4 bool Field5 bool Field6 bool Field7 bool Field8 bool Field9 bool Field10 bool Field11 bool Field12 bool Field13 bool Field14 bool Field15 bool Field16 bool Field17 bool Field18 bool Field19 bool Field20 bool Field21 bool Field22 bool Field23 bool Field24 bool Field25 bool Field26 bool Field27 bool Field28 bool Field29 bool Field30 bool Field31 bool Field32 bool Field33 bool Field34 bool Field35 bool Field36 bool Field37 bool Field38 bool Field39 bool Field40 bool Field41 bool Field42 bool Field43 bool Field44 bool Field45 bool Field46 bool Field47 bool Field48 bool Field49 bool Field50 bool Field51 bool Field52 bool Field53 bool Field54 bool Field55 bool Field56 bool Field57 bool Field58 bool Field59 bool Field60 bool Field61 bool Field62 bool Field63 bool Field64 bool Field65 bool Field66 bool Field67 bool Field68 bool Field69 bool Field70 bool Field71 bool Field72 bool Field73 bool Field74 bool Field75 bool Field76 bool Field77 bool Field78 bool Field79 bool Field80 bool Field81 bool Field82 bool Field83 bool Field84 bool Field85 bool Field86 bool Field87 bool Field88 bool Field89 bool Field90 bool Field91 bool Field92 bool Field93 bool Field94 bool Field95 bool Field96 bool Field97 bool Field98 bool Field99 bool } // test encoder cache issue, not related to encoder b, err := json.Marshal(v) if err != nil { t.Errorf("failed to marshal %s", err.Error()) t.FailNow() } std, err := stdjson.Marshal(v) if err != nil { t.Errorf("failed to marshal with encoding/json %s", err.Error()) t.FailNow() } if !bytes.Equal(std, b) { t.Errorf("encoding result not equal to encoding/json") t.FailNow() } } func TestIssue386(t *testing.T) { raw := `{"date": null, "platform": "\u6f2b\u753b", "images": {"small": "https://lain.bgm.tv/pic/cover/s/d2/a1/80048_jp.jpg", "grid": "https://lain.bgm.tv/pic/cover/g/d2/a1/80048_jp.jpg", "large": "https://lain.bgm.tv/pic/cover/l/d2/a1/80048_jp.jpg", "medium": "https://lain.bgm.tv/pic/cover/m/d2/a1/80048_jp.jpg", "common": "https://lain.bgm.tv/pic/cover/c/d2/a1/80048_jp.jpg"}, "summary": "\u5929\u624d\u8a2d\u8a08\u58eb\u30fb\u5929\u5bae\uff08\u3042\u307e\u307f\u3084\uff09\u3092\u62b1\u3048\u308b\u6751\u96e8\u7dcf\u5408\u4f01\u753b\u306f\u3001\u771f\u6c34\u5efa\u8a2d\u3068\u63d0\u643a\u3057\u3066\u300c\u3055\u304d\u305f\u307e\u30a2\u30ea\u30fc\u30ca\u300d\u306e\u30b3\u30f3\u30da\u306b\u512a\u52dd\u3059\u308b\u3053\u3068\u306b\u8ced\u3051\u3066\u3044\u305f\u3002\u3057\u304b\u3057\u3001\u73fe\u77e5\u4e8b\u306e\u6d25\u5730\u7530\uff08\u3064\u3061\u3060\uff09\u306f\u5927\u65e5\u5efa\u8a2d\u306b\u512a\u52dd\u3055\u305b\u3088\u3046\u3068\u6697\u8e8d\u3059\u308b\u3002\u305d\u308c\u306f\u73fe\u77e5\u4e8b\u306e\u6d25\u5730\u7530\u3068\u526f\u77e5\u4e8b\u306e\u592a\u7530\uff08\u304a\u304a\u305f\uff09\u306e\u653f\u6cbb\u751f\u547d\u3092\u5de6\u53f3\u3059\u308b\u4e89\u3044\u3068\u306a\u308a\u2026\u2026!?\u3000\u305d\u3057\u3066\u516c\u5171\u4e8b\u696d\u306b\u6e26\u5dfb\u304f\u6df1\u3044\u95c7\u306b\u842c\u7530\u9280\u6b21\u90ce\uff08\u307e\u3093\u3060\u30fb\u304e\u3093\u3058\u308d\u3046\uff09\u306f\u2026\u2026!?", "name": "\u30df\u30ca\u30df\u306e\u5e1d\u738b (48)"}` var a struct { Date *string `json:"date"` Platform *string `json:"platform"` Summary string `json:"summary"` Name string `json:"name"` } err := json.NewDecoder(strings.NewReader(raw)).Decode(&a) if err != nil { t.Error(err) } } type customMapKey string func (b customMapKey) MarshalJSON() ([]byte, error) { return []byte("[]"), nil } func TestCustomMarshalForMapKey(t *testing.T) { m := map[customMapKey]string{customMapKey("skipcustom"): "test"} expected, err := stdjson.Marshal(m) assertErr(t, err) got, err := json.Marshal(m) assertErr(t, err) assertEq(t, "custom map key", string(expected), string(got)) } func TestIssue391(t *testing.T) { type A struct { X string `json:"x,omitempty"` } type B struct { A } type C struct { X []int `json:"x,omitempty"` } for _, tc := range []struct { name string in interface{} out string }{ {in: struct{ B }{}, out: "{}"}, {in: struct { B Y string `json:"y"` }{}, out: `{"y":""}`}, {in: struct { Y string `json:"y"` B }{}, out: `{"y":""}`}, {in: struct{ C }{}, out: "{}"}, } { t.Run(tc.name, func(t *testing.T) { b, err := json.Marshal(tc.in) assertErr(t, err) assertEq(t, "unexpected result", tc.out, string(b)) }) } } func TestIssue417(t *testing.T) { x := map[string]string{ "b": "b", "a": "a", } b, err := json.MarshalIndentWithOption(x, "", " ", json.UnorderedMap()) assertErr(t, err) var y map[string]string err = json.Unmarshal(b, &y) assertErr(t, err) assertEq(t, "key b", "b", y["b"]) assertEq(t, "key a", "a", y["a"]) } func TestIssue426(t *testing.T) { type I interface { Foo() } type A struct { I Val string } var s A s.Val = "456" b, _ := json.Marshal(s) assertEq(t, "unexpected result", `{"I":null,"Val":"456"}`, string(b)) } func TestIssue441(t *testing.T) { type A struct { Y string `json:"y,omitempty"` } type B struct { X *int `json:"x,omitempty"` A Z int `json:"z,omitempty"` } b, err := json.Marshal(B{}) assertErr(t, err) assertEq(t, "unexpected result", "{}", string(b)) } golang-github-goccy-go-json-0.10.3/error.go000066400000000000000000000030011463555276600204730ustar00rootroot00000000000000package json import ( "github.com/goccy/go-json/internal/errors" ) // Before Go 1.2, an InvalidUTF8Error was returned by Marshal when // attempting to encode a string value with invalid UTF-8 sequences. // As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by // replacing invalid bytes with the Unicode replacement rune U+FFFD. // // Deprecated: No longer used; kept for compatibility. type InvalidUTF8Error = errors.InvalidUTF8Error // An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. // (The argument to Unmarshal must be a non-nil pointer.) type InvalidUnmarshalError = errors.InvalidUnmarshalError // A MarshalerError represents an error from calling a MarshalJSON or MarshalText method. type MarshalerError = errors.MarshalerError // A SyntaxError is a description of a JSON syntax error. type SyntaxError = errors.SyntaxError // An UnmarshalFieldError describes a JSON object key that // led to an unexported (and therefore unwritable) struct field. // // Deprecated: No longer used; kept for compatibility. type UnmarshalFieldError = errors.UnmarshalFieldError // An UnmarshalTypeError describes a JSON value that was // not appropriate for a value of a specific Go type. type UnmarshalTypeError = errors.UnmarshalTypeError // An UnsupportedTypeError is returned by Marshal when attempting // to encode an unsupported value type. type UnsupportedTypeError = errors.UnsupportedTypeError type UnsupportedValueError = errors.UnsupportedValueError type PathError = errors.PathError golang-github-goccy-go-json-0.10.3/export_test.go000066400000000000000000000002351463555276600217300ustar00rootroot00000000000000package json import ( "github.com/goccy/go-json/internal/errors" ) var ( NewSyntaxError = errors.ErrSyntax NewMarshalerError = errors.ErrMarshaler ) golang-github-goccy-go-json-0.10.3/go.mod000066400000000000000000000000511463555276600201230ustar00rootroot00000000000000module github.com/goccy/go-json go 1.19 golang-github-goccy-go-json-0.10.3/go.sum000066400000000000000000000000001463555276600201420ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/helper_test.go000066400000000000000000000010161463555276600216640ustar00rootroot00000000000000package json_test import "testing" func assertErr(t *testing.T, err error) { t.Helper() if err != nil { t.Fatalf("%+v", err) } } func assertEq(t *testing.T, msg string, exp interface{}, act interface{}) { t.Helper() if exp != act { t.Fatalf("failed to test for %s. exp=[%v] but act=[%v]", msg, exp, act) } } func assertNeq(t *testing.T, msg string, exp interface{}, act interface{}) { t.Helper() if exp == act { t.Fatalf("failed to test for %s. expected value is not [%v] but got same value", msg, act) } } golang-github-goccy-go-json-0.10.3/internal/000077500000000000000000000000001463555276600206355ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/cmd/000077500000000000000000000000001463555276600214005ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/cmd/generator/000077500000000000000000000000001463555276600233665ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/cmd/generator/main.go000066400000000000000000000155511463555276600246500ustar00rootroot00000000000000package main import ( "bytes" "fmt" "go/format" "go/parser" "go/printer" "go/token" "os" "path/filepath" "runtime" "strings" "text/template" ) type opType struct { Op string Code string } func createOpType(op, code string) opType { return opType{ Op: op, Code: code, } } func _main() error { tmpl, err := template.New("").Parse(`// Code generated by internal/cmd/generator. DO NOT EDIT! package encoder import ( "strings" ) type CodeType int const ( {{- range $index, $type := .CodeTypes }} Code{{ $type }} CodeType = {{ $index }} {{- end }} ) var opTypeStrings = [{{ .OpLen }}]string{ {{- range $type := .OpTypes }} "{{ $type.Op }}", {{- end }} } type OpType uint16 const ( {{- range $index, $type := .OpTypes }} Op{{ $type.Op }} OpType = {{ $index }} {{- end }} ) func (t OpType) String() string { if int(t) >= {{ .OpLen }} { return "" } return opTypeStrings[int(t)] } func (t OpType) CodeType() CodeType { if strings.Contains(t.String(), "Struct") { if strings.Contains(t.String(), "End") { return CodeStructEnd } return CodeStructField } switch t { case OpArray, OpArrayPtr: return CodeArrayHead case OpArrayElem: return CodeArrayElem case OpSlice, OpSlicePtr: return CodeSliceHead case OpSliceElem: return CodeSliceElem case OpMap, OpMapPtr: return CodeMapHead case OpMapKey: return CodeMapKey case OpMapValue: return CodeMapValue case OpMapEnd: return CodeMapEnd } return CodeOp } func (t OpType) HeadToPtrHead() OpType { if strings.Index(t.String(), "PtrHead") > 0 { return t } idx := strings.Index(t.String(), "Head") if idx == -1 { return t } suffix := "PtrHead"+t.String()[idx+len("Head"):] const toPtrOffset = 2 if strings.Contains(OpType(int(t) + toPtrOffset).String(), suffix) { return OpType(int(t) + toPtrOffset) } return t } func (t OpType) HeadToOmitEmptyHead() OpType { const toOmitEmptyOffset = 1 if strings.Contains(OpType(int(t) + toOmitEmptyOffset).String(), "OmitEmpty") { return OpType(int(t) + toOmitEmptyOffset) } return t } func (t OpType) PtrHeadToHead() OpType { idx := strings.Index(t.String(), "PtrHead") if idx == -1 { return t } suffix := t.String()[idx+len("Ptr"):] const toPtrOffset = 2 if strings.Contains(OpType(int(t) - toPtrOffset).String(), suffix) { return OpType(int(t) - toPtrOffset) } return t } func (t OpType) FieldToEnd() OpType { idx := strings.Index(t.String(), "Field") if idx == -1 { return t } suffix := t.String()[idx+len("Field"):] if suffix == "" || suffix == "OmitEmpty" { return t } const toEndOffset = 2 if strings.Contains(OpType(int(t) + toEndOffset).String(), "End"+suffix) { return OpType(int(t) + toEndOffset) } return t } func (t OpType) FieldToOmitEmptyField() OpType { const toOmitEmptyOffset = 1 if strings.Contains(OpType(int(t) + toOmitEmptyOffset).String(), "OmitEmpty") { return OpType(int(t) + toOmitEmptyOffset) } return t } `) if err != nil { return err } codeTypes := []string{ "Op", "ArrayHead", "ArrayElem", "SliceHead", "SliceElem", "MapHead", "MapKey", "MapValue", "MapEnd", "Recursive", "StructField", "StructEnd", } primitiveTypes := []string{ "int", "uint", "float32", "float64", "bool", "string", "bytes", "number", "array", "map", "slice", "struct", "MarshalJSON", "MarshalText", "intString", "uintString", "float32String", "float64String", "boolString", "stringString", "numberString", "intPtr", "uintPtr", "float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr", "numberPtr", "arrayPtr", "mapPtr", "slicePtr", "marshalJSONPtr", "marshalTextPtr", "interfacePtr", "intPtrString", "uintPtrString", "float32PtrString", "float64PtrString", "boolPtrString", "stringPtrString", "numberPtrString", } primitiveTypesUpper := []string{} for _, typ := range primitiveTypes { primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:]) } opTypes := []opType{ createOpType("End", "Op"), createOpType("Interface", "Op"), createOpType("Ptr", "Op"), createOpType("SliceElem", "SliceElem"), createOpType("SliceEnd", "Op"), createOpType("ArrayElem", "ArrayElem"), createOpType("ArrayEnd", "Op"), createOpType("MapKey", "MapKey"), createOpType("MapValue", "MapValue"), createOpType("MapEnd", "Op"), createOpType("Recursive", "Op"), createOpType("RecursivePtr", "Op"), createOpType("RecursiveEnd", "Op"), createOpType("InterfaceEnd", "Op"), } for _, typ := range primitiveTypesUpper { typ := typ opTypes = append(opTypes, createOpType(typ, "Op")) } for _, typ := range append(primitiveTypesUpper, "") { for _, ptrOrNot := range []string{"", "Ptr"} { for _, opt := range []string{"", "OmitEmpty"} { ptrOrNot := ptrOrNot opt := opt typ := typ op := fmt.Sprintf( "Struct%sHead%s%s", ptrOrNot, opt, typ, ) opTypes = append(opTypes, opType{ Op: op, Code: "StructField", }) } } } for _, typ := range append(primitiveTypesUpper, "") { for _, opt := range []string{"", "OmitEmpty"} { opt := opt typ := typ op := fmt.Sprintf( "StructField%s%s", opt, typ, ) opTypes = append(opTypes, opType{ Op: op, Code: "StructField", }) } for _, opt := range []string{"", "OmitEmpty"} { opt := opt typ := typ op := fmt.Sprintf( "StructEnd%s%s", opt, typ, ) opTypes = append(opTypes, opType{ Op: op, Code: "StructEnd", }) } } var b bytes.Buffer if err := tmpl.Execute(&b, struct { CodeTypes []string OpTypes []opType OpLen int }{ CodeTypes: codeTypes, OpTypes: opTypes, OpLen: len(opTypes), }); err != nil { return err } path := filepath.Join(repoRoot(), "internal", "encoder", "optype.go") buf, err := format.Source(b.Bytes()) if err != nil { return err } return os.WriteFile(path, buf, 0644) } func generateVM() error { file, err := os.ReadFile("vm.go.tmpl") if err != nil { return err } fset := token.NewFileSet() f, err := parser.ParseFile(fset, "", string(file), parser.ParseComments) if err != nil { return err } for _, pkg := range []string{"vm", "vm_indent", "vm_color", "vm_color_indent"} { f.Name.Name = pkg var buf bytes.Buffer printer.Fprint(&buf, fset, f) path := filepath.Join(repoRoot(), "internal", "encoder", pkg, "vm.go") source, err := format.Source(buf.Bytes()) if err != nil { return err } if err := os.WriteFile(path, source, 0644); err != nil { return err } } return nil } func repoRoot() string { _, file, _, _ := runtime.Caller(0) relativePathFromRepoRoot := filepath.Join("internal", "cmd", "generator") return strings.TrimSuffix(filepath.Dir(file), relativePathFromRepoRoot) } //go:generate go run main.go func main() { if err := generateVM(); err != nil { panic(err) } if err := _main(); err != nil { panic(err) } } golang-github-goccy-go-json-0.10.3/internal/cmd/generator/vm.go.tmpl000066400000000000000000004142071463555276600253220ustar00rootroot00000000000000// Code generated by internal/cmd/generator. DO NOT EDIT! package vm import ( "math" "reflect" "sort" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { recursiveLevel := 0 ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode } for { switch code.Op { default: return nil, errUnimplementedOp(code.Op) case encoder.OpPtr: p := load(ctxptr, code.Idx) code = code.Next store(ctxptr, code.Idx, ptrToPtr(p)) case encoder.OpIntPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInt: b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpUintPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpUint: b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpIntString: b = append(b, '"') b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpUintString: b = append(b, '"') b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpFloat32Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat32: b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpFloat64Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat64: v := ptrToFloat64(load(ctxptr, code.Idx)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStringPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpString: b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBoolPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBool: b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBytesPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBytes: b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpNumberPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpNumber: bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpInterfacePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInterface: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if p == seen { return nil, errUnsupportedValue(code, p) } } } ctx.SeenPtr = append(ctx.SeenPtr, p) var ( typ *runtime.Type ifacePtr unsafe.Pointer ) up := ptrToUnsafePtr(p) if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { iface := (*nonEmptyInterface)(up) ifacePtr = iface.ptr if iface.itab != nil { typ = iface.itab.typ } } else { iface := (*emptyInterface)(up) ifacePtr = iface.ptr typ = iface.typ } if ifacePtr == nil { isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) if !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) if err != nil { return nil, err } totalLength := uintptr(code.Length) + 3 nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 var c *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { c = ifaceCodeSet.InterfaceEscapeKeyCode } else { c = ifaceCodeSet.InterfaceNoescapeKeyCode } curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += totalLength * uintptrSize oldBaseIndent := ctx.BaseIndent ctx.BaseIndent += code.Indent newLen := offsetNum + totalLength + nextTotalLength if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr end := ifaceCodeSet.EndCode store(ctxptr, c.Idx, uintptr(ifacePtr)) store(ctxptr, end.Idx, oldOffset) store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpInterfaceEnd: recursiveLevel-- // restore ctxptr offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalText: p := load(ctxptr, code.Idx) if p == 0 { b = append(b, `""`...) b = appendComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpSlicePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpSlice: p := load(ctxptr, code.Idx) slice := ptrToSlice(p) if p == 0 || slice.Data == nil { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(slice.Len)) store(ctxptr, code.Idx, uintptr(slice.Data)) if slice.Len > 0 { b = appendArrayHead(ctx, code, b) code = code.Next store(ctxptr, code.Idx, uintptr(slice.Data)) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpSliceElem: idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ if idx < length { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) data := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, data+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpArrayPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpArray: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } if code.Length > 0 { b = appendArrayHead(ctx, code, b) store(ctxptr, code.ElemIdx, 0) code = code.Next store(ctxptr, code.Idx, p) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpArrayElem: idx := load(ctxptr, code.ElemIdx) idx++ if idx < uintptr(code.Length) { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) p := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, p+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpMapPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpMap: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } uptr := ptrToUnsafePtr(p) mlen := maplen(uptr) if mlen <= 0 { b = appendEmptyObject(ctx, b) code = code.End.Next break } b = appendStructHead(ctx, b) unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 mapCtx := encoder.NewMapContext(mlen, unorderedMap) mapiterinit(code.Type, uptr, &mapCtx.Iter) store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) if unorderedMap { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx.Start = len(b) mapCtx.First = len(b) } key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next case encoder.OpMapKey: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) idx := mapCtx.Idx idx++ if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < mapCtx.Len { b = appendMapKeyIndent(ctx, code, b) mapCtx.Idx = int(idx) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { b = appendObjectEnd(ctx, code, b) encoder.ReleaseMapContext(mapCtx) code = code.End.Next } } else { mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] if idx < mapCtx.Len { mapCtx.Idx = int(idx) mapCtx.Start = len(b) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { code = code.End } } case encoder.OpMapValue: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] mapCtx.Start = len(b) } value := mapitervalue(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(value)) mapiternext(&mapCtx.Iter) code = code.Next case encoder.OpMapEnd: // this operation only used by sorted map. mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) sort.Sort(mapCtx.Slice) buf := mapCtx.Buf for _, item := range mapCtx.Slice.Items { buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) } buf = appendMapEnd(ctx, code, buf) b = b[:mapCtx.First] b = append(b, buf...) mapCtx.Buf = buf encoder.ReleaseMapContext(mapCtx) code = code.Next case encoder.OpRecursivePtr: p := load(ctxptr, code.Idx) if p == 0 { code = code.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpRecursive: ptr := load(ctxptr, code.Idx) if ptr != 0 { if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if ptr == seen { return nil, errUnsupportedValue(code, ptr) } } } } ctx.SeenPtr = append(ctx.SeenPtr, ptr) c := code.Jmp.Code curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += code.Jmp.CurLen * uintptrSize oldBaseIndent := ctx.BaseIndent indentDiffFromTop := c.Indent - 1 ctx.BaseIndent += code.Indent - indentDiffFromTop newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr store(ctxptr, c.Idx, ptr) store(ctxptr, c.End.Next.Idx, oldOffset) store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpRecursiveEnd: recursiveLevel-- // restore ctxptr restoreIndent(ctx, code, ctxptr) offset := load(ctxptr, code.Idx) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpStructPtrHead: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHead: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if len(code.Key) > 0 { if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } } p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) u64 := ptrToUint64(p, code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBytes(p + uintptr(code.Offset)) if len(v) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next } case encoder.OpStructPtrHeadNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructPtrHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyArray: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyArray: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptySlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptySlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } if maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { p = ptrToPtr(p) } } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructField: if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } p := load(ctxptr, code.Idx) + uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmpty: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringString: p := load(ctxptr, code.Idx) s := ptrToString(p + uintptr(code.Offset)) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldMarshalJSON: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalJSONPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldMarshalText: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalText: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalTextPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldArrayPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArrayPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldSlice: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlice: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldSlicePtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlicePtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldMap: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMap: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldMapPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMapPtr: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldStruct: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyStruct: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructEnd: b = appendStructEndSkipLast(ctx, code, b) code = code.Next case encoder.OpStructEndInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendStructEnd(ctx, code, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) s := ptrToString(p + uintptr(code.Offset)) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytesPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) code = code.Next case encoder.OpStructEndOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpEnd: goto END } } END: return b, nil } golang-github-goccy-go-json-0.10.3/internal/decoder/000077500000000000000000000000001463555276600222425ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/decoder/anonymous_field.go000066400000000000000000000022151463555276600257640ustar00rootroot00000000000000package 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)) } func (d *anonymousFieldDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return d.dec.DecodePath(ctx, cursor, depth) } golang-github-goccy-go-json-0.10.3/internal/decoder/array.go000066400000000000000000000076011463555276600237130ustar00rootroot00000000000000package decoder import ( "fmt" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type arrayDecoder struct { elemType *runtime.Type size uintptr valueDecoder Decoder alen int structName string fieldName string zeroValue unsafe.Pointer } func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder { // workaround to avoid checkptr errors. cannot use `*(*unsafe.Pointer)(unsafe_New(elemType))` directly. zeroValuePtr := unsafe_New(elemType) zeroValue := **(**unsafe.Pointer)(unsafe.Pointer(&zeroValuePtr)) return &arrayDecoder{ valueDecoder: dec, elemType: elemType, size: elemType.Size(), alen: alen, structName: structName, fieldName: fieldName, zeroValue: zeroValue, } } func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { depth++ if depth > maxDecodeNestingDepth { return errors.ErrExceededMaxDepth(s.char(), s.cursor) } for { switch s.char() { case ' ', '\n', '\t', '\r': case 'n': if err := nullBytes(s); err != nil { return err } return nil case '[': idx := 0 s.cursor++ if s.skipWhiteSpace() == ']' { for idx < d.alen { *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue idx++ } s.cursor++ return nil } for { if idx < d.alen { if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil { return err } } else { if err := s.skipValue(depth); err != nil { return err } } idx++ switch s.skipWhiteSpace() { case ']': for idx < d.alen { *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue idx++ } s.cursor++ return nil case ',': s.cursor++ continue case nul: if s.read() { s.cursor++ continue } goto ERROR default: goto ERROR } } case nul: if s.read() { continue } goto ERROR default: goto ERROR } s.cursor++ } ERROR: return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset()) } func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf depth++ if depth > maxDecodeNestingDepth { return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } for { switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ continue case 'n': if err := validateNull(buf, cursor); err != nil { return 0, err } cursor += 4 return cursor, nil case '[': idx := 0 cursor++ cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == ']' { for idx < d.alen { *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue idx++ } cursor++ return cursor, nil } for { if idx < d.alen { c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)) if err != nil { return 0, err } cursor = c } else { c, err := skipValue(buf, cursor, depth) if err != nil { return 0, err } cursor = c } idx++ cursor = skipWhiteSpace(buf, cursor) switch buf[cursor] { case ']': for idx < d.alen { *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue idx++ } cursor++ return cursor, nil case ',': cursor++ continue default: return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor) } } default: return 0, errors.ErrUnexpectedEndOfJSON("array", cursor) } } } func (d *arrayDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: array decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/assign.go000066400000000000000000000304151463555276600240600ustar00rootroot00000000000000package decoder import ( "fmt" "reflect" "strconv" ) var ( nilValue = reflect.ValueOf(nil) ) func AssignValue(src, dst reflect.Value) error { if dst.Type().Kind() != reflect.Ptr { return fmt.Errorf("invalid dst type. required pointer type: %T", dst.Type()) } casted, err := castValue(dst.Elem().Type(), src) if err != nil { return err } dst.Elem().Set(casted) return nil } func castValue(t reflect.Type, v reflect.Value) (reflect.Value, error) { switch t.Kind() { case reflect.Int: vv, err := castInt(v) if err != nil { return nilValue, err } return reflect.ValueOf(int(vv.Int())), nil case reflect.Int8: vv, err := castInt(v) if err != nil { return nilValue, err } return reflect.ValueOf(int8(vv.Int())), nil case reflect.Int16: vv, err := castInt(v) if err != nil { return nilValue, err } return reflect.ValueOf(int16(vv.Int())), nil case reflect.Int32: vv, err := castInt(v) if err != nil { return nilValue, err } return reflect.ValueOf(int32(vv.Int())), nil case reflect.Int64: return castInt(v) case reflect.Uint: vv, err := castUint(v) if err != nil { return nilValue, err } return reflect.ValueOf(uint(vv.Uint())), nil case reflect.Uint8: vv, err := castUint(v) if err != nil { return nilValue, err } return reflect.ValueOf(uint8(vv.Uint())), nil case reflect.Uint16: vv, err := castUint(v) if err != nil { return nilValue, err } return reflect.ValueOf(uint16(vv.Uint())), nil case reflect.Uint32: vv, err := castUint(v) if err != nil { return nilValue, err } return reflect.ValueOf(uint32(vv.Uint())), nil case reflect.Uint64: return castUint(v) case reflect.Uintptr: vv, err := castUint(v) if err != nil { return nilValue, err } return reflect.ValueOf(uintptr(vv.Uint())), nil case reflect.String: return castString(v) case reflect.Bool: return castBool(v) case reflect.Float32: vv, err := castFloat(v) if err != nil { return nilValue, err } return reflect.ValueOf(float32(vv.Float())), nil case reflect.Float64: return castFloat(v) case reflect.Array: return castArray(t, v) case reflect.Slice: return castSlice(t, v) case reflect.Map: return castMap(t, v) case reflect.Struct: return castStruct(t, v) } return v, nil } func castInt(v reflect.Value) (reflect.Value, error) { switch v.Type().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v, nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return reflect.ValueOf(int64(v.Uint())), nil case reflect.String: i64, err := strconv.ParseInt(v.String(), 10, 64) if err != nil { return nilValue, err } return reflect.ValueOf(i64), nil case reflect.Bool: if v.Bool() { return reflect.ValueOf(int64(1)), nil } return reflect.ValueOf(int64(0)), nil case reflect.Float32, reflect.Float64: return reflect.ValueOf(int64(v.Float())), nil case reflect.Array: if v.Len() > 0 { return castInt(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to int64 from empty array") case reflect.Slice: if v.Len() > 0 { return castInt(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to int64 from empty slice") case reflect.Interface: return castInt(reflect.ValueOf(v.Interface())) case reflect.Map: return nilValue, fmt.Errorf("failed to cast to int64 from map") case reflect.Struct: return nilValue, fmt.Errorf("failed to cast to int64 from struct") case reflect.Ptr: return castInt(v.Elem()) } return nilValue, fmt.Errorf("failed to cast to int64 from %s", v.Type().Kind()) } func castUint(v reflect.Value) (reflect.Value, error) { switch v.Type().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return reflect.ValueOf(uint64(v.Int())), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v, nil case reflect.String: u64, err := strconv.ParseUint(v.String(), 10, 64) if err != nil { return nilValue, err } return reflect.ValueOf(u64), nil case reflect.Bool: if v.Bool() { return reflect.ValueOf(uint64(1)), nil } return reflect.ValueOf(uint64(0)), nil case reflect.Float32, reflect.Float64: return reflect.ValueOf(uint64(v.Float())), nil case reflect.Array: if v.Len() > 0 { return castUint(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to uint64 from empty array") case reflect.Slice: if v.Len() > 0 { return castUint(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to uint64 from empty slice") case reflect.Interface: return castUint(reflect.ValueOf(v.Interface())) case reflect.Map: return nilValue, fmt.Errorf("failed to cast to uint64 from map") case reflect.Struct: return nilValue, fmt.Errorf("failed to cast to uint64 from struct") case reflect.Ptr: return castUint(v.Elem()) } return nilValue, fmt.Errorf("failed to cast to uint64 from %s", v.Type().Kind()) } func castString(v reflect.Value) (reflect.Value, error) { switch v.Type().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return reflect.ValueOf(fmt.Sprint(v.Int())), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return reflect.ValueOf(fmt.Sprint(v.Uint())), nil case reflect.String: return v, nil case reflect.Bool: if v.Bool() { return reflect.ValueOf("true"), nil } return reflect.ValueOf("false"), nil case reflect.Float32, reflect.Float64: return reflect.ValueOf(fmt.Sprint(v.Float())), nil case reflect.Array: if v.Len() > 0 { return castString(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to string from empty array") case reflect.Slice: if v.Len() > 0 { return castString(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to string from empty slice") case reflect.Interface: return castString(reflect.ValueOf(v.Interface())) case reflect.Map: return nilValue, fmt.Errorf("failed to cast to string from map") case reflect.Struct: return nilValue, fmt.Errorf("failed to cast to string from struct") case reflect.Ptr: return castString(v.Elem()) } return nilValue, fmt.Errorf("failed to cast to string from %s", v.Type().Kind()) } func castBool(v reflect.Value) (reflect.Value, error) { switch v.Type().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch v.Int() { case 0: return reflect.ValueOf(false), nil case 1: return reflect.ValueOf(true), nil } return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Int()) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: switch v.Uint() { case 0: return reflect.ValueOf(false), nil case 1: return reflect.ValueOf(true), nil } return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Uint()) case reflect.String: b, err := strconv.ParseBool(v.String()) if err != nil { return nilValue, err } return reflect.ValueOf(b), nil case reflect.Bool: return v, nil case reflect.Float32, reflect.Float64: switch v.Float() { case 0: return reflect.ValueOf(false), nil case 1: return reflect.ValueOf(true), nil } return nilValue, fmt.Errorf("failed to cast to bool from %f", v.Float()) case reflect.Array: if v.Len() > 0 { return castBool(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to string from empty array") case reflect.Slice: if v.Len() > 0 { return castBool(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to string from empty slice") case reflect.Interface: return castBool(reflect.ValueOf(v.Interface())) case reflect.Map: return nilValue, fmt.Errorf("failed to cast to string from map") case reflect.Struct: return nilValue, fmt.Errorf("failed to cast to string from struct") case reflect.Ptr: return castBool(v.Elem()) } return nilValue, fmt.Errorf("failed to cast to bool from %s", v.Type().Kind()) } func castFloat(v reflect.Value) (reflect.Value, error) { switch v.Type().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return reflect.ValueOf(float64(v.Int())), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return reflect.ValueOf(float64(v.Uint())), nil case reflect.String: f64, err := strconv.ParseFloat(v.String(), 64) if err != nil { return nilValue, err } return reflect.ValueOf(f64), nil case reflect.Bool: if v.Bool() { return reflect.ValueOf(float64(1)), nil } return reflect.ValueOf(float64(0)), nil case reflect.Float32, reflect.Float64: return v, nil case reflect.Array: if v.Len() > 0 { return castFloat(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to float64 from empty array") case reflect.Slice: if v.Len() > 0 { return castFloat(v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to float64 from empty slice") case reflect.Interface: return castFloat(reflect.ValueOf(v.Interface())) case reflect.Map: return nilValue, fmt.Errorf("failed to cast to float64 from map") case reflect.Struct: return nilValue, fmt.Errorf("failed to cast to float64 from struct") case reflect.Ptr: return castFloat(v.Elem()) } return nilValue, fmt.Errorf("failed to cast to float64 from %s", v.Type().Kind()) } func castArray(t reflect.Type, v reflect.Value) (reflect.Value, error) { kind := v.Type().Kind() if kind == reflect.Interface { return castArray(t, reflect.ValueOf(v.Interface())) } if kind != reflect.Slice && kind != reflect.Array { return nilValue, fmt.Errorf("failed to cast to array from %s", kind) } if t.Elem() == v.Type().Elem() { return v, nil } if t.Len() != v.Len() { return nilValue, fmt.Errorf("failed to cast [%d]array from slice of %d length", t.Len(), v.Len()) } ret := reflect.New(t).Elem() for i := 0; i < v.Len(); i++ { vv, err := castValue(t.Elem(), v.Index(i)) if err != nil { return nilValue, err } ret.Index(i).Set(vv) } return ret, nil } func castSlice(t reflect.Type, v reflect.Value) (reflect.Value, error) { kind := v.Type().Kind() if kind == reflect.Interface { return castSlice(t, reflect.ValueOf(v.Interface())) } if kind != reflect.Slice && kind != reflect.Array { return nilValue, fmt.Errorf("failed to cast to slice from %s", kind) } if t.Elem() == v.Type().Elem() { return v, nil } ret := reflect.MakeSlice(t, v.Len(), v.Len()) for i := 0; i < v.Len(); i++ { vv, err := castValue(t.Elem(), v.Index(i)) if err != nil { return nilValue, err } ret.Index(i).Set(vv) } return ret, nil } func castMap(t reflect.Type, v reflect.Value) (reflect.Value, error) { ret := reflect.MakeMap(t) switch v.Type().Kind() { case reflect.Map: iter := v.MapRange() for iter.Next() { key, err := castValue(t.Key(), iter.Key()) if err != nil { return nilValue, err } value, err := castValue(t.Elem(), iter.Value()) if err != nil { return nilValue, err } ret.SetMapIndex(key, value) } return ret, nil case reflect.Interface: return castMap(t, reflect.ValueOf(v.Interface())) case reflect.Slice: if v.Len() > 0 { return castMap(t, v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to map from empty slice") } return nilValue, fmt.Errorf("failed to cast to map from %s", v.Type().Kind()) } func castStruct(t reflect.Type, v reflect.Value) (reflect.Value, error) { ret := reflect.New(t).Elem() switch v.Type().Kind() { case reflect.Map: iter := v.MapRange() for iter.Next() { key := iter.Key() k, err := castString(key) if err != nil { return nilValue, err } fieldName := k.String() field, ok := t.FieldByName(fieldName) if ok { value, err := castValue(field.Type, iter.Value()) if err != nil { return nilValue, err } ret.FieldByName(fieldName).Set(value) } } return ret, nil case reflect.Struct: for i := 0; i < v.Type().NumField(); i++ { name := v.Type().Field(i).Name ret.FieldByName(name).Set(v.FieldByName(name)) } return ret, nil case reflect.Interface: return castStruct(t, reflect.ValueOf(v.Interface())) case reflect.Slice: if v.Len() > 0 { return castStruct(t, v.Index(0)) } return nilValue, fmt.Errorf("failed to cast to struct from empty slice") default: return nilValue, fmt.Errorf("failed to cast to struct from %s", v.Type().Kind()) } } golang-github-goccy-go-json-0.10.3/internal/decoder/bool.go000066400000000000000000000034051463555276600235260ustar00rootroot00000000000000package decoder import ( "fmt" "unsafe" "github.com/goccy/go-json/internal/errors" ) type boolDecoder struct { structName string fieldName string } func newBoolDecoder(structName, fieldName string) *boolDecoder { return &boolDecoder{structName: structName, fieldName: fieldName} } func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { c := s.skipWhiteSpace() for { switch c { case 't': if err := trueBytes(s); err != nil { return err } **(**bool)(unsafe.Pointer(&p)) = true return nil case 'f': if err := falseBytes(s); err != nil { return err } **(**bool)(unsafe.Pointer(&p)) = false return nil case 'n': if err := nullBytes(s); err != nil { return err } return nil case nul: if s.read() { c = s.char() continue } goto ERROR } break } ERROR: return errors.ErrUnexpectedEndOfJSON("bool", s.totalOffset()) } func (d *boolDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf cursor = skipWhiteSpace(buf, cursor) switch buf[cursor] { case 't': if err := validateTrue(buf, cursor); err != nil { return 0, err } cursor += 4 **(**bool)(unsafe.Pointer(&p)) = true return cursor, nil case 'f': if err := validateFalse(buf, cursor); err != nil { return 0, err } cursor += 5 **(**bool)(unsafe.Pointer(&p)) = false return cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return 0, err } cursor += 4 return cursor, nil } return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor) } func (d *boolDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: bool decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/bytes.go000066400000000000000000000062521463555276600237240ustar00rootroot00000000000000package decoder import ( "encoding/base64" "fmt" "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) default: unmarshalDecoder, _ = compileUint8(typ, structName, fieldName) } 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) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: []byte decoder does not support decode path") } 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) } golang-github-goccy-go-json-0.10.3/internal/decoder/compile.go000066400000000000000000000351511463555276600242260ustar00rootroot00000000000000package decoder import ( "encoding/json" "fmt" "reflect" "strings" "sync/atomic" "unicode" "unsafe" "github.com/goccy/go-json/internal/runtime" ) var ( jsonNumberType = reflect.TypeOf(json.Number("")) typeAddr *runtime.TypeAddr cachedDecoderMap unsafe.Pointer // map[uintptr]decoder cachedDecoder []Decoder ) func init() { typeAddr = runtime.AnalyzeTypeAddr() if typeAddr == nil { typeAddr = &runtime.TypeAddr{} } cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift+1) } func loadDecoderMap() map[uintptr]Decoder { p := atomic.LoadPointer(&cachedDecoderMap) return *(*map[uintptr]Decoder)(unsafe.Pointer(&p)) } func storeDecoder(typ uintptr, dec Decoder, m map[uintptr]Decoder) { newDecoderMap := make(map[uintptr]Decoder, len(m)+1) newDecoderMap[typ] = dec for k, v := range m { newDecoderMap[k] = v } atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap))) } func compileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (Decoder, error) { decoderMap := loadDecoderMap() if dec, exists := decoderMap[typeptr]; exists { return dec, nil } dec, err := compileHead(typ, map[uintptr]Decoder{}) if err != nil { return nil, err } storeDecoder(typeptr, dec, decoderMap) return dec, nil } func compileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { switch { case implementsUnmarshalJSONType(runtime.PtrTo(typ)): return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil case runtime.PtrTo(typ).Implements(unmarshalTextType): return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil } return compile(typ.Elem(), "", "", structTypeToDecoder) } func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { switch { case implementsUnmarshalJSONType(runtime.PtrTo(typ)): return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil case runtime.PtrTo(typ).Implements(unmarshalTextType): return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil } switch typ.Kind() { case reflect.Ptr: return compilePtr(typ, structName, fieldName, structTypeToDecoder) case reflect.Struct: return compileStruct(typ, structName, fieldName, structTypeToDecoder) case reflect.Slice: elem := typ.Elem() if elem.Kind() == reflect.Uint8 { return compileBytes(elem, structName, fieldName) } return compileSlice(typ, structName, fieldName, structTypeToDecoder) case reflect.Array: return compileArray(typ, structName, fieldName, structTypeToDecoder) case reflect.Map: return compileMap(typ, structName, fieldName, structTypeToDecoder) case reflect.Interface: return compileInterface(typ, structName, fieldName) case reflect.Uintptr: return compileUint(typ, structName, fieldName) case reflect.Int: return compileInt(typ, structName, fieldName) case reflect.Int8: return compileInt8(typ, structName, fieldName) case reflect.Int16: return compileInt16(typ, structName, fieldName) case reflect.Int32: return compileInt32(typ, structName, fieldName) case reflect.Int64: return compileInt64(typ, structName, fieldName) case reflect.Uint: return compileUint(typ, structName, fieldName) case reflect.Uint8: return compileUint8(typ, structName, fieldName) case reflect.Uint16: return compileUint16(typ, structName, fieldName) case reflect.Uint32: return compileUint32(typ, structName, fieldName) case reflect.Uint64: return compileUint64(typ, structName, fieldName) case reflect.String: return compileString(typ, structName, fieldName) case reflect.Bool: return compileBool(structName, fieldName) case reflect.Float32: return compileFloat32(structName, fieldName) case reflect.Float64: return compileFloat64(structName, fieldName) case reflect.Func: return compileFunc(typ, structName, fieldName) } return newInvalidDecoder(typ, structName, fieldName), nil } func isStringTagSupportedType(typ *runtime.Type) bool { switch { case implementsUnmarshalJSONType(runtime.PtrTo(typ)): return false case runtime.PtrTo(typ).Implements(unmarshalTextType): return false } switch typ.Kind() { case reflect.Map: return false case reflect.Slice: return false case reflect.Array: return false case reflect.Struct: return false case reflect.Interface: return false } return true } func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { if runtime.PtrTo(typ).Implements(unmarshalTextType) { return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil } if typ.Kind() == reflect.String { return newStringDecoder(structName, fieldName), nil } dec, err := compile(typ, structName, fieldName, structTypeToDecoder) if err != nil { return nil, err } for { switch t := dec.(type) { case *stringDecoder, *interfaceDecoder: return dec, nil case *boolDecoder, *intDecoder, *uintDecoder, *numberDecoder: return newWrappedStringDecoder(typ, dec, structName, fieldName), nil case *ptrDecoder: dec = t.dec default: return newInvalidDecoder(typ, structName, fieldName), nil } } } func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { dec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder) if err != nil { return nil, err } return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil } func compileInt(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int)(p) = int(v) }), nil } func compileInt8(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int8)(p) = int8(v) }), nil } func compileInt16(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int16)(p) = int16(v) }), nil } func compileInt32(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int32)(p) = int32(v) }), nil } func compileInt64(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int64)(p) = v }), nil } func compileUint(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint)(p) = uint(v) }), nil } func compileUint8(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint8)(p) = uint8(v) }), nil } func compileUint16(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint16)(p) = uint16(v) }), nil } func compileUint32(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint32)(p) = uint32(v) }), nil } func compileUint64(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint64)(p) = v }), nil } func compileFloat32(structName, fieldName string) (Decoder, error) { return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*float32)(p) = float32(v) }), nil } func compileFloat64(structName, fieldName string) (Decoder, error) { return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*float64)(p) = v }), nil } func compileString(typ *runtime.Type, structName, fieldName string) (Decoder, error) { if typ == runtime.Type2RType(jsonNumberType) { return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) { *(*json.Number)(p) = v }), nil } return newStringDecoder(structName, fieldName), nil } func compileBool(structName, fieldName string) (Decoder, error) { return newBoolDecoder(structName, fieldName), nil } func compileBytes(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newBytesDecoder(typ, structName, fieldName), nil } func compileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { elem := typ.Elem() decoder, err := compile(elem, structName, fieldName, structTypeToDecoder) if err != nil { return nil, err } return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil } func compileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { elem := typ.Elem() decoder, err := compile(elem, structName, fieldName, structTypeToDecoder) if err != nil { return nil, err } return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil } func compileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { keyDec, err := compileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder) if err != nil { return nil, err } valueDec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder) if err != nil { return nil, err } return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil } func compileInterface(typ *runtime.Type, structName, fieldName string) (Decoder, error) { return newInterfaceDecoder(typ, structName, fieldName), nil } func compileFunc(typ *runtime.Type, strutName, fieldName string) (Decoder, error) { return newFuncDecoder(typ, strutName, fieldName), nil } func typeToStructTags(typ *runtime.Type) runtime.StructTags { tags := runtime.StructTags{} fieldNum := typ.NumField() for i := 0; i < fieldNum; i++ { field := typ.Field(i) if runtime.IsIgnoredStructField(field) { continue } tags = append(tags, runtime.StructTagFromField(field)) } return tags } func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { fieldNum := typ.NumField() fieldMap := map[string]*structFieldSet{} typeptr := uintptr(unsafe.Pointer(typ)) if dec, exists := structTypeToDecoder[typeptr]; exists { return dec, nil } structDec := newStructDecoder(structName, fieldName, fieldMap) structTypeToDecoder[typeptr] = structDec structName = typ.Name() tags := typeToStructTags(typ) allFields := []*structFieldSet{} for i := 0; i < fieldNum; i++ { field := typ.Field(i) if runtime.IsIgnoredStructField(field) { continue } isUnexportedField := unicode.IsLower([]rune(field.Name)[0]) tag := runtime.StructTagFromField(field) dec, err := compile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder) if err != nil { return nil, err } if field.Anonymous && !tag.IsTaggedKey { if stDec, ok := dec.(*structDecoder); ok { if runtime.Type2RType(field.Type) == typ { // recursive definition continue } for k, v := range stDec.fieldMap { if tags.ExistsKey(k) { continue } fieldSet := &structFieldSet{ dec: v.dec, offset: field.Offset + v.offset, isTaggedKey: v.isTaggedKey, key: k, keyLen: int64(len(k)), } allFields = append(allFields, fieldSet) } } else if pdec, ok := dec.(*ptrDecoder); ok { contentDec := pdec.contentDecoder() if pdec.typ == typ { // recursive definition continue } var fieldSetErr error if isUnexportedField { fieldSetErr = fmt.Errorf( "json: cannot set embedded pointer to unexported struct: %v", field.Type.Elem(), ) } if dec, ok := contentDec.(*structDecoder); ok { for k, v := range dec.fieldMap { if tags.ExistsKey(k) { continue } fieldSet := &structFieldSet{ dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec), offset: field.Offset, isTaggedKey: v.isTaggedKey, key: k, keyLen: int64(len(k)), err: fieldSetErr, } allFields = append(allFields, fieldSet) } } else { fieldSet := &structFieldSet{ dec: pdec, offset: field.Offset, isTaggedKey: tag.IsTaggedKey, key: field.Name, keyLen: int64(len(field.Name)), } allFields = append(allFields, fieldSet) } } else { fieldSet := &structFieldSet{ dec: dec, offset: field.Offset, isTaggedKey: tag.IsTaggedKey, key: field.Name, keyLen: int64(len(field.Name)), } allFields = append(allFields, fieldSet) } } else { if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) { dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name) } var key string if tag.Key != "" { key = tag.Key } else { key = field.Name } fieldSet := &structFieldSet{ dec: dec, offset: field.Offset, isTaggedKey: tag.IsTaggedKey, key: key, keyLen: int64(len(key)), } allFields = append(allFields, fieldSet) } } for _, set := range filterDuplicatedFields(allFields) { fieldMap[set.key] = set lower := strings.ToLower(set.key) if _, exists := fieldMap[lower]; !exists { // first win fieldMap[lower] = set } } delete(structTypeToDecoder, typeptr) structDec.tryOptimize() return structDec, nil } func filterDuplicatedFields(allFields []*structFieldSet) []*structFieldSet { fieldMap := map[string][]*structFieldSet{} for _, field := range allFields { fieldMap[field.key] = append(fieldMap[field.key], field) } duplicatedFieldMap := map[string]struct{}{} for k, sets := range fieldMap { sets = filterFieldSets(sets) if len(sets) != 1 { duplicatedFieldMap[k] = struct{}{} } } filtered := make([]*structFieldSet, 0, len(allFields)) for _, field := range allFields { if _, exists := duplicatedFieldMap[field.key]; exists { continue } filtered = append(filtered, field) } return filtered } func filterFieldSets(sets []*structFieldSet) []*structFieldSet { if len(sets) == 1 { return sets } filtered := make([]*structFieldSet, 0, len(sets)) for _, set := range sets { if set.isTaggedKey { filtered = append(filtered, set) } } return filtered } func implementsUnmarshalJSONType(typ *runtime.Type) bool { return typ.Implements(unmarshalJSONType) || typ.Implements(unmarshalJSONContextType) } golang-github-goccy-go-json-0.10.3/internal/decoder/compile_norace.go000066400000000000000000000011131463555276600255440ustar00rootroot00000000000000//go:build !race // +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 } golang-github-goccy-go-json-0.10.3/internal/decoder/compile_race.go000066400000000000000000000012711463555276600252140ustar00rootroot00000000000000//go:build race // +build race package decoder import ( "sync" "unsafe" "github.com/goccy/go-json/internal/runtime" ) var decMu sync.RWMutex func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) { typeptr := uintptr(unsafe.Pointer(typ)) if typeptr > typeAddr.MaxTypeAddr { return compileToGetDecoderSlowPath(typeptr, typ) } index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift decMu.RLock() if dec := cachedDecoder[index]; dec != nil { decMu.RUnlock() return dec, nil } decMu.RUnlock() dec, err := compileHead(typ, map[uintptr]Decoder{}) if err != nil { return nil, err } decMu.Lock() cachedDecoder[index] = dec decMu.Unlock() return dec, nil } golang-github-goccy-go-json-0.10.3/internal/decoder/context.go000066400000000000000000000125261463555276600242630ustar00rootroot00000000000000package decoder import ( "sync" "unsafe" "github.com/goccy/go-json/internal/errors" ) type RuntimeContext struct { Buf []byte Option *Option } var ( runtimeContextPool = sync.Pool{ New: func() interface{} { return &RuntimeContext{ Option: &Option{}, } }, } ) func TakeRuntimeContext() *RuntimeContext { return runtimeContextPool.Get().(*RuntimeContext) } func ReleaseRuntimeContext(ctx *RuntimeContext) { runtimeContextPool.Put(ctx) } var ( isWhiteSpace = [256]bool{} ) func init() { isWhiteSpace[' '] = true isWhiteSpace['\n'] = true isWhiteSpace['\t'] = true isWhiteSpace['\r'] = true } func char(ptr unsafe.Pointer, offset int64) byte { return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset))) } func skipWhiteSpace(buf []byte, cursor int64) int64 { for isWhiteSpace[buf[cursor]] { cursor++ } return cursor } func skipObject(buf []byte, cursor, depth int64) (int64, error) { braceCount := 1 for { switch buf[cursor] { case '{': braceCount++ depth++ if depth > maxDecodeNestingDepth { return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } case '}': depth-- braceCount-- if braceCount == 0 { return cursor + 1, nil } case '[': depth++ if depth > maxDecodeNestingDepth { return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } case ']': depth-- case '"': for { cursor++ switch buf[cursor] { case '\\': cursor++ if buf[cursor] == nul { return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) } case '"': goto SWITCH_OUT case nul: return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) } } case nul: return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor) } SWITCH_OUT: cursor++ } } func skipArray(buf []byte, cursor, depth int64) (int64, error) { bracketCount := 1 for { switch buf[cursor] { case '[': bracketCount++ depth++ if depth > maxDecodeNestingDepth { return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } case ']': bracketCount-- depth-- if bracketCount == 0 { return cursor + 1, nil } case '{': depth++ if depth > maxDecodeNestingDepth { return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } case '}': depth-- case '"': for { cursor++ switch buf[cursor] { case '\\': cursor++ if buf[cursor] == nul { return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) } case '"': goto SWITCH_OUT case nul: return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) } } case nul: return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor) } SWITCH_OUT: cursor++ } } func skipValue(buf []byte, cursor, depth int64) (int64, error) { for { switch buf[cursor] { case ' ', '\t', '\n', '\r': cursor++ continue case '{': return skipObject(buf, cursor+1, depth+1) case '[': return skipArray(buf, cursor+1, depth+1) case '"': for { cursor++ switch buf[cursor] { case '\\': cursor++ if buf[cursor] == nul { return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) } case '"': return cursor + 1, nil case nul: return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) } } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': for { cursor++ if floatTable[buf[cursor]] { continue } break } return cursor, nil case 't': if err := validateTrue(buf, cursor); err != nil { return 0, err } cursor += 4 return cursor, nil case 'f': if err := validateFalse(buf, cursor); err != nil { return 0, err } cursor += 5 return cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return 0, err } cursor += 4 return cursor, nil default: return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor) } } } func validateTrue(buf []byte, cursor int64) error { if cursor+3 >= int64(len(buf)) { return errors.ErrUnexpectedEndOfJSON("true", cursor) } if buf[cursor+1] != 'r' { return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor) } if buf[cursor+2] != 'u' { return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor) } if buf[cursor+3] != 'e' { return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor) } return nil } func validateFalse(buf []byte, cursor int64) error { if cursor+4 >= int64(len(buf)) { return errors.ErrUnexpectedEndOfJSON("false", cursor) } if buf[cursor+1] != 'a' { return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor) } if buf[cursor+2] != 'l' { return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor) } if buf[cursor+3] != 's' { return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor) } if buf[cursor+4] != 'e' { return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor) } return nil } func validateNull(buf []byte, cursor int64) error { if cursor+3 >= int64(len(buf)) { return errors.ErrUnexpectedEndOfJSON("null", cursor) } if buf[cursor+1] != 'u' { return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor) } if buf[cursor+2] != 'l' { return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor) } if buf[cursor+3] != 'l' { return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor) } return nil } golang-github-goccy-go-json-0.10.3/internal/decoder/float.go000066400000000000000000000064541463555276600237070ustar00rootroot00000000000000package decoder import ( "strconv" "unsafe" "github.com/goccy/go-json/internal/errors" ) type floatDecoder struct { op func(unsafe.Pointer, float64) structName string fieldName string } func newFloatDecoder(structName, fieldName string, op func(unsafe.Pointer, float64)) *floatDecoder { return &floatDecoder{op: op, structName: structName, fieldName: fieldName} } var ( floatTable = [256]bool{ '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true, '.': true, 'e': true, 'E': true, '+': true, '-': true, } validEndNumberChar = [256]bool{ nul: true, ' ': true, '\t': true, '\r': true, '\n': true, ',': true, ':': true, '}': true, ']': true, } ) func floatBytes(s *Stream) []byte { start := s.cursor for { s.cursor++ if floatTable[s.char()] { continue } else if s.char() == nul { if s.read() { s.cursor-- // for retry current character continue } } break } return s.buf[start:s.cursor] } func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) { for { switch s.char() { case ' ', '\n', '\t', '\r': s.cursor++ continue case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return floatBytes(s), nil case 'n': if err := nullBytes(s); err != nil { return nil, err } return nil, nil case nul: if s.read() { continue } goto ERROR default: goto ERROR } } ERROR: return nil, errors.ErrUnexpectedEndOfJSON("float", s.totalOffset()) } func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { for { switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ continue case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': start := cursor cursor++ for floatTable[buf[cursor]] { cursor++ } num := buf[start:cursor] return num, cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return nil, cursor, nil default: return nil, 0, errors.ErrUnexpectedEndOfJSON("float", cursor) } } } func (d *floatDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { bytes, err := d.decodeStreamByte(s) if err != nil { return err } if bytes == nil { return nil } str := *(*string)(unsafe.Pointer(&bytes)) f64, err := strconv.ParseFloat(str, 64) if err != nil { return errors.ErrSyntax(err.Error(), s.totalOffset()) } d.op(p, f64) return nil } func (d *floatDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf bytes, c, err := d.decodeByte(buf, cursor) if err != nil { return 0, err } if bytes == nil { return c, nil } cursor = c if !validEndNumberChar[buf[cursor]] { return 0, errors.ErrUnexpectedEndOfJSON("float", cursor) } s := *(*string)(unsafe.Pointer(&bytes)) f64, err := strconv.ParseFloat(s, 64) if err != nil { return 0, errors.ErrSyntax(err.Error(), cursor) } d.op(p, f64) return cursor, nil } func (d *floatDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { buf := ctx.Buf bytes, c, err := d.decodeByte(buf, cursor) if err != nil { return nil, 0, err } if bytes == nil { return [][]byte{nullbytes}, c, nil } return [][]byte{bytes}, c, nil } golang-github-goccy-go-json-0.10.3/internal/decoder/func.go000066400000000000000000000067521463555276600235360ustar00rootroot00000000000000package decoder import ( "bytes" "fmt" "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) } func (d *funcDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: func decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/int.go000066400000000000000000000117651463555276600233750ustar00rootroot00000000000000package decoder import ( "fmt" "reflect" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type intDecoder struct { typ *runtime.Type kind reflect.Kind op func(unsafe.Pointer, int64) structName string fieldName string } func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder { return &intDecoder{ typ: typ, kind: typ.Kind(), op: op, structName: structName, fieldName: fieldName, } } func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError { return &errors.UnmarshalTypeError{ Value: fmt.Sprintf("number %s", string(buf)), Type: runtime.RType2Type(d.typ), Struct: d.structName, Field: d.fieldName, Offset: offset, } } var ( pow10i64 = [...]int64{ 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, } pow10i64Len = len(pow10i64) ) func (d *intDecoder) parseInt(b []byte) (int64, error) { isNegative := false if b[0] == '-' { b = b[1:] isNegative = true } maxDigit := len(b) if maxDigit > pow10i64Len { return 0, fmt.Errorf("invalid length of number") } sum := int64(0) for i := 0; i < maxDigit; i++ { c := int64(b[i]) - 48 digitValue := pow10i64[maxDigit-i-1] sum += c * digitValue } if isNegative { return -1 * sum, nil } return sum, nil } var ( numTable = [256]bool{ '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true, } ) var ( numZeroBuf = []byte{'0'} ) func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) { for { switch s.char() { case ' ', '\n', '\t', '\r': s.cursor++ continue case '-': start := s.cursor for { s.cursor++ if numTable[s.char()] { continue } else if s.char() == nul { if s.read() { s.cursor-- // for retry current character continue } } break } num := s.buf[start:s.cursor] if len(num) < 2 { goto ERROR } return num, nil case '0': s.cursor++ return numZeroBuf, nil case '1', '2', '3', '4', '5', '6', '7', '8', '9': start := s.cursor for { s.cursor++ if numTable[s.char()] { continue } else if s.char() == nul { if s.read() { s.cursor-- // for retry current character continue } } break } num := s.buf[start:s.cursor] return num, nil case 'n': if err := nullBytes(s); err != nil { return nil, err } return nil, nil case nul: if s.read() { continue } goto ERROR default: return nil, d.typeError([]byte{s.char()}, s.totalOffset()) } } ERROR: return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset()) } func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { b := (*sliceHeader)(unsafe.Pointer(&buf)).data for { switch char(b, cursor) { case ' ', '\n', '\t', '\r': cursor++ continue case '0': cursor++ return numZeroBuf, cursor, nil case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': start := cursor cursor++ for numTable[char(b, cursor)] { cursor++ } num := buf[start:cursor] return num, cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return nil, cursor, nil default: return nil, 0, d.typeError([]byte{char(b, cursor)}, cursor) } } } func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { bytes, err := d.decodeStreamByte(s) if err != nil { return err } if bytes == nil { return nil } i64, err := d.parseInt(bytes) if err != nil { return d.typeError(bytes, s.totalOffset()) } switch d.kind { case reflect.Int8: if i64 < -1*(1<<7) || (1<<7) <= i64 { return d.typeError(bytes, s.totalOffset()) } case reflect.Int16: if i64 < -1*(1<<15) || (1<<15) <= i64 { return d.typeError(bytes, s.totalOffset()) } case reflect.Int32: if i64 < -1*(1<<31) || (1<<31) <= i64 { return d.typeError(bytes, s.totalOffset()) } } d.op(p, i64) s.reset() return nil } func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { bytes, c, err := d.decodeByte(ctx.Buf, cursor) if err != nil { return 0, err } if bytes == nil { return c, nil } cursor = c i64, err := d.parseInt(bytes) if err != nil { return 0, d.typeError(bytes, cursor) } switch d.kind { case reflect.Int8: if i64 < -1*(1<<7) || (1<<7) <= i64 { return 0, d.typeError(bytes, cursor) } case reflect.Int16: if i64 < -1*(1<<15) || (1<<15) <= i64 { return 0, d.typeError(bytes, cursor) } case reflect.Int32: if i64 < -1*(1<<31) || (1<<31) <= i64 { return 0, d.typeError(bytes, cursor) } } d.op(p, i64) return cursor, nil } func (d *intDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: int decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/interface.go000066400000000000000000000326031463555276600245350ustar00rootroot00000000000000package decoder import ( "bytes" "encoding" "encoding/json" "reflect" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type interfaceDecoder struct { typ *runtime.Type structName string fieldName string sliceDecoder *sliceDecoder mapDecoder *mapDecoder floatDecoder *floatDecoder numberDecoder *numberDecoder stringDecoder *stringDecoder } func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder { ifaceDecoder := &interfaceDecoder{ typ: emptyInterfaceType, structName: structName, fieldName: fieldName, floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*interface{})(p) = v }), numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) { *(*interface{})(p) = v }), stringDecoder: newStringDecoder(structName, fieldName), } ifaceDecoder.sliceDecoder = newSliceDecoder( ifaceDecoder, emptyInterfaceType, emptyInterfaceType.Size(), structName, fieldName, ) ifaceDecoder.mapDecoder = newMapDecoder( interfaceMapType, stringType, ifaceDecoder.stringDecoder, interfaceMapType.Elem(), ifaceDecoder, structName, fieldName, ) return ifaceDecoder } func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder { emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName) stringDecoder := newStringDecoder(structName, fieldName) return &interfaceDecoder{ typ: typ, structName: structName, fieldName: fieldName, sliceDecoder: newSliceDecoder( emptyIfaceDecoder, emptyInterfaceType, emptyInterfaceType.Size(), structName, fieldName, ), mapDecoder: newMapDecoder( interfaceMapType, stringType, stringDecoder, interfaceMapType.Elem(), emptyIfaceDecoder, structName, fieldName, ), floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*interface{})(p) = v }), numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) { *(*interface{})(p) = v }), stringDecoder: stringDecoder, } } func (d *interfaceDecoder) numDecoder(s *Stream) Decoder { if s.UseNumber { return d.numberDecoder } return d.floatDecoder } var ( emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem()) EmptyInterfaceType = emptyInterfaceType interfaceMapType = runtime.Type2RType( reflect.TypeOf((*map[string]interface{})(nil)).Elem(), ) stringType = runtime.Type2RType( reflect.TypeOf(""), ) ) func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error { start := s.cursor if err := s.skipValue(depth); err != nil { return err } src := s.buf[start:s.cursor] dst := make([]byte, len(src)) copy(dst, src) if err := unmarshaler.UnmarshalJSON(dst); err != nil { return err } return nil } func decodeStreamUnmarshalerContext(s *Stream, depth int64, unmarshaler unmarshalerContext) error { start := s.cursor if err := s.skipValue(depth); err != nil { return err } src := s.buf[start:s.cursor] dst := make([]byte, len(src)) copy(dst, src) if err := unmarshaler.UnmarshalJSON(s.Option.Context, dst); err != nil { return err } return nil } func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) { cursor = skipWhiteSpace(buf, cursor) start := cursor end, err := skipValue(buf, cursor, depth) if err != nil { return 0, err } src := buf[start:end] dst := make([]byte, len(src)) copy(dst, src) if err := unmarshaler.UnmarshalJSON(dst); err != nil { return 0, err } return end, nil } func decodeUnmarshalerContext(ctx *RuntimeContext, buf []byte, cursor, depth int64, unmarshaler unmarshalerContext) (int64, error) { cursor = skipWhiteSpace(buf, cursor) start := cursor end, err := skipValue(buf, cursor, depth) if err != nil { return 0, err } src := buf[start:end] dst := make([]byte, len(src)) copy(dst, src) if err := unmarshaler.UnmarshalJSON(ctx.Option.Context, dst); err != nil { return 0, err } return end, nil } func decodeStreamTextUnmarshaler(s *Stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error { start := s.cursor if err := s.skipValue(depth); err != nil { return err } src := s.buf[start:s.cursor] if bytes.Equal(src, nullbytes) { *(*unsafe.Pointer)(p) = nil return nil } dst := make([]byte, len(src)) copy(dst, src) if err := unmarshaler.UnmarshalText(dst); err != nil { return err } return nil } func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) (int64, error) { cursor = skipWhiteSpace(buf, cursor) start := cursor end, err := skipValue(buf, cursor, depth) if err != nil { return 0, err } src := buf[start:end] if bytes.Equal(src, nullbytes) { *(*unsafe.Pointer)(p) = nil return end, nil } if s, ok := unquoteBytes(src); ok { src = s } if err := unmarshaler.UnmarshalText(src); err != nil { return 0, err } return end, nil } func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error { c := s.skipWhiteSpace() for { switch c { case '{': var v map[string]interface{} ptr := unsafe.Pointer(&v) if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil { return err } *(*interface{})(p) = v return nil case '[': var v []interface{} ptr := unsafe.Pointer(&v) if err := d.sliceDecoder.DecodeStream(s, depth, ptr); err != nil { return err } *(*interface{})(p) = v return nil case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return d.numDecoder(s).DecodeStream(s, depth, p) case '"': s.cursor++ start := s.cursor for { switch s.char() { case '\\': if _, err := decodeEscapeString(s, nil); err != nil { return err } case '"': literal := s.buf[start:s.cursor] s.cursor++ *(*interface{})(p) = string(literal) return nil case nul: if s.read() { continue } return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) } s.cursor++ } case 't': if err := trueBytes(s); err != nil { return err } **(**interface{})(unsafe.Pointer(&p)) = true return nil case 'f': if err := falseBytes(s); err != nil { return err } **(**interface{})(unsafe.Pointer(&p)) = false return nil case 'n': if err := nullBytes(s); err != nil { return err } *(*interface{})(p) = nil return nil case nul: if s.read() { c = s.char() continue } } break } return errors.ErrInvalidBeginningOfValue(c, s.totalOffset()) } type emptyInterface struct { typ *runtime.Type ptr unsafe.Pointer } func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) rv := reflect.ValueOf(runtimeInterfaceValue) if rv.NumMethod() > 0 && rv.CanInterface() { if u, ok := rv.Interface().(unmarshalerContext); ok { return decodeStreamUnmarshalerContext(s, depth, u) } if u, ok := rv.Interface().(json.Unmarshaler); ok { return decodeStreamUnmarshaler(s, depth, u) } if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok { return decodeStreamTextUnmarshaler(s, depth, u, p) } if s.skipWhiteSpace() == 'n' { if err := nullBytes(s); err != nil { return err } *(*interface{})(p) = nil return nil } return d.errUnmarshalType(rv.Type(), s.totalOffset()) } iface := rv.Interface() ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface)) typ := ifaceHeader.typ if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { // concrete type is empty interface return d.decodeStreamEmptyInterface(s, depth, p) } if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr { return d.decodeStreamEmptyInterface(s, depth, p) } if s.skipWhiteSpace() == 'n' { if err := nullBytes(s); err != nil { return err } *(*interface{})(p) = nil return nil } decoder, err := CompileToGetDecoder(typ) if err != nil { return err } return decoder.DecodeStream(s, depth, ifaceHeader.ptr) } func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError { return &errors.UnmarshalTypeError{ Value: typ.String(), Type: typ, Offset: offset, Struct: d.structName, Field: d.fieldName, } } func (d *interfaceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) rv := reflect.ValueOf(runtimeInterfaceValue) if rv.NumMethod() > 0 && rv.CanInterface() { if u, ok := rv.Interface().(unmarshalerContext); ok { return decodeUnmarshalerContext(ctx, buf, cursor, depth, u) } if u, ok := rv.Interface().(json.Unmarshaler); ok { return decodeUnmarshaler(buf, cursor, depth, u) } if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok { return decodeTextUnmarshaler(buf, cursor, depth, u, p) } cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == 'n' { if err := validateNull(buf, cursor); err != nil { return 0, err } cursor += 4 **(**interface{})(unsafe.Pointer(&p)) = nil return cursor, nil } return 0, d.errUnmarshalType(rv.Type(), cursor) } iface := rv.Interface() ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface)) typ := ifaceHeader.typ if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { // concrete type is empty interface return d.decodeEmptyInterface(ctx, cursor, depth, p) } if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr { return d.decodeEmptyInterface(ctx, cursor, depth, p) } cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == 'n' { if err := validateNull(buf, cursor); err != nil { return 0, err } cursor += 4 **(**interface{})(unsafe.Pointer(&p)) = nil return cursor, nil } decoder, err := CompileToGetDecoder(typ) if err != nil { return 0, err } return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr) } func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf cursor = skipWhiteSpace(buf, cursor) switch buf[cursor] { case '{': var v map[string]interface{} ptr := unsafe.Pointer(&v) cursor, err := d.mapDecoder.Decode(ctx, cursor, depth, ptr) if err != nil { return 0, err } **(**interface{})(unsafe.Pointer(&p)) = v return cursor, nil case '[': var v []interface{} ptr := unsafe.Pointer(&v) cursor, err := d.sliceDecoder.Decode(ctx, cursor, depth, ptr) if err != nil { return 0, err } **(**interface{})(unsafe.Pointer(&p)) = v return cursor, nil case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return d.floatDecoder.Decode(ctx, cursor, depth, p) case '"': var v string ptr := unsafe.Pointer(&v) cursor, err := d.stringDecoder.Decode(ctx, cursor, depth, ptr) if err != nil { return 0, err } **(**interface{})(unsafe.Pointer(&p)) = v return cursor, nil case 't': if err := validateTrue(buf, cursor); err != nil { return 0, err } cursor += 4 **(**interface{})(unsafe.Pointer(&p)) = true return cursor, nil case 'f': if err := validateFalse(buf, cursor); err != nil { return 0, err } cursor += 5 **(**interface{})(unsafe.Pointer(&p)) = false return cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return 0, err } cursor += 4 **(**interface{})(unsafe.Pointer(&p)) = nil return cursor, nil } return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) } func NewPathDecoder() Decoder { ifaceDecoder := &interfaceDecoder{ typ: emptyInterfaceType, structName: "", fieldName: "", floatDecoder: newFloatDecoder("", "", func(p unsafe.Pointer, v float64) { *(*interface{})(p) = v }), numberDecoder: newNumberDecoder("", "", func(p unsafe.Pointer, v json.Number) { *(*interface{})(p) = v }), stringDecoder: newStringDecoder("", ""), } ifaceDecoder.sliceDecoder = newSliceDecoder( ifaceDecoder, emptyInterfaceType, emptyInterfaceType.Size(), "", "", ) ifaceDecoder.mapDecoder = newMapDecoder( interfaceMapType, stringType, ifaceDecoder.stringDecoder, interfaceMapType.Elem(), ifaceDecoder, "", "", ) return ifaceDecoder } var ( truebytes = []byte("true") falsebytes = []byte("false") ) func (d *interfaceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { buf := ctx.Buf cursor = skipWhiteSpace(buf, cursor) switch buf[cursor] { case '{': return d.mapDecoder.DecodePath(ctx, cursor, depth) case '[': return d.sliceDecoder.DecodePath(ctx, cursor, depth) case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return d.floatDecoder.DecodePath(ctx, cursor, depth) case '"': return d.stringDecoder.DecodePath(ctx, cursor, depth) case 't': if err := validateTrue(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return [][]byte{truebytes}, cursor, nil case 'f': if err := validateFalse(buf, cursor); err != nil { return nil, 0, err } cursor += 5 return [][]byte{falsebytes}, cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return [][]byte{nullbytes}, cursor, nil } return nil, cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) } golang-github-goccy-go-json-0.10.3/internal/decoder/invalid.go000066400000000000000000000024131463555276600242170ustar00rootroot00000000000000package decoder import ( "reflect" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type invalidDecoder struct { typ *runtime.Type kind reflect.Kind structName string fieldName string } func newInvalidDecoder(typ *runtime.Type, structName, fieldName string) *invalidDecoder { return &invalidDecoder{ typ: typ, kind: typ.Kind(), structName: structName, fieldName: fieldName, } } func (d *invalidDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { return &errors.UnmarshalTypeError{ Value: "object", Type: runtime.RType2Type(d.typ), Offset: s.totalOffset(), Struct: d.structName, Field: d.fieldName, } } func (d *invalidDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { return 0, &errors.UnmarshalTypeError{ Value: "object", Type: runtime.RType2Type(d.typ), Offset: cursor, Struct: d.structName, Field: d.fieldName, } } func (d *invalidDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, &errors.UnmarshalTypeError{ Value: "object", Type: runtime.RType2Type(d.typ), Offset: cursor, Struct: d.structName, Field: d.fieldName, } } golang-github-goccy-go-json-0.10.3/internal/decoder/map.go000066400000000000000000000156101463555276600233510ustar00rootroot00000000000000package 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) } s.cursor++ if s.skipWhiteSpace() == '}' { *(*unsafe.Pointer)(p) = mapValue s.cursor++ return nil } for { 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()) } s.cursor++ } } 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++ } } func (d *mapDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { buf := ctx.Buf depth++ if depth > maxDecodeNestingDepth { return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } cursor = skipWhiteSpace(buf, cursor) buflen := int64(len(buf)) if buflen < 2 { return nil, 0, errors.ErrExpected("{} for map", cursor) } switch buf[cursor] { case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return [][]byte{nullbytes}, cursor, nil case '{': default: return nil, 0, errors.ErrExpected("{ character for map value", cursor) } cursor++ cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == '}' { cursor++ return nil, cursor, nil } keyDecoder, ok := d.keyDecoder.(*stringDecoder) if !ok { return nil, 0, &errors.UnmarshalTypeError{ Value: "string", Type: reflect.TypeOf(""), Offset: cursor, Struct: d.structName, Field: d.fieldName, } } ret := [][]byte{} for { key, keyCursor, err := keyDecoder.decodeByte(buf, cursor) if err != nil { return nil, 0, err } cursor = skipWhiteSpace(buf, keyCursor) if buf[cursor] != ':' { return nil, 0, errors.ErrExpected("colon after object key", cursor) } cursor++ child, found, err := ctx.Option.Path.Field(string(key)) if err != nil { return nil, 0, err } if found { if child != nil { oldPath := ctx.Option.Path.node ctx.Option.Path.node = child paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth) if err != nil { return nil, 0, err } ctx.Option.Path.node = oldPath ret = append(ret, paths...) cursor = c } else { start := cursor end, err := skipValue(buf, cursor, depth) if err != nil { return nil, 0, err } ret = append(ret, buf[start:end]) cursor = end } } else { c, err := skipValue(buf, cursor, depth) if err != nil { return nil, 0, err } cursor = c } cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == '}' { cursor++ return ret, cursor, nil } if buf[cursor] != ',' { return nil, 0, errors.ErrExpected("comma after object value", cursor) } cursor++ } } golang-github-goccy-go-json-0.10.3/internal/decoder/number.go000066400000000000000000000056361463555276600240730ustar00rootroot00000000000000package decoder import ( "encoding/json" "strconv" "unsafe" "github.com/goccy/go-json/internal/errors" ) type numberDecoder struct { stringDecoder *stringDecoder op func(unsafe.Pointer, json.Number) structName string fieldName string } func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder { return &numberDecoder{ stringDecoder: newStringDecoder(structName, fieldName), op: op, structName: structName, fieldName: fieldName, } } func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { bytes, err := d.decodeStreamByte(s) if err != nil { return err } if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { return errors.ErrSyntax(err.Error(), s.totalOffset()) } d.op(p, json.Number(string(bytes))) s.reset() return nil } func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { bytes, c, err := d.decodeByte(ctx.Buf, cursor) if err != nil { return 0, err } if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { return 0, errors.ErrSyntax(err.Error(), c) } cursor = c s := *(*string)(unsafe.Pointer(&bytes)) d.op(p, json.Number(s)) return cursor, nil } func (d *numberDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { bytes, c, err := d.decodeByte(ctx.Buf, cursor) if err != nil { return nil, 0, err } if bytes == nil { return [][]byte{nullbytes}, c, nil } return [][]byte{bytes}, c, nil } func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) { start := s.cursor for { switch s.char() { case ' ', '\n', '\t', '\r': s.cursor++ continue case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return floatBytes(s), nil case 'n': if err := nullBytes(s); err != nil { return nil, err } return nil, nil case '"': return d.stringDecoder.decodeStreamByte(s) case nul: if s.read() { continue } goto ERROR default: goto ERROR } } ERROR: if s.cursor == start { return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset()) } return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset()) } func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { for { switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ continue case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': start := cursor cursor++ for floatTable[buf[cursor]] { cursor++ } num := buf[start:cursor] return num, cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return nil, cursor, nil case '"': return d.stringDecoder.decodeByte(buf, cursor) default: return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor) } } } golang-github-goccy-go-json-0.10.3/internal/decoder/option.go000066400000000000000000000003351463555276600241020ustar00rootroot00000000000000package decoder import "context" type OptionFlags uint8 const ( FirstWinOption OptionFlags = 1 << iota ContextOption PathOption ) type Option struct { Flags OptionFlags Context context.Context Path *Path } golang-github-goccy-go-json-0.10.3/internal/decoder/path.go000066400000000000000000000401051463555276600235250ustar00rootroot00000000000000package decoder import ( "fmt" "reflect" "strconv" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type PathString string func (s PathString) Build() (*Path, error) { builder := new(PathBuilder) return builder.Build([]rune(s)) } type PathBuilder struct { root PathNode node PathNode singleQuotePathSelector bool doubleQuotePathSelector bool } func (b *PathBuilder) Build(buf []rune) (*Path, error) { node, err := b.build(buf) if err != nil { return nil, err } return &Path{ node: node, RootSelectorOnly: node == nil, SingleQuotePathSelector: b.singleQuotePathSelector, DoubleQuotePathSelector: b.doubleQuotePathSelector, }, nil } func (b *PathBuilder) build(buf []rune) (PathNode, error) { if len(buf) == 0 { return nil, errors.ErrEmptyPath() } if buf[0] != '$' { return nil, errors.ErrInvalidPath("JSON Path must start with a $ character") } if len(buf) == 1 { return nil, nil } buf = buf[1:] offset, err := b.buildNext(buf) if err != nil { return nil, err } if len(buf) > offset { return nil, errors.ErrInvalidPath("remain invalid path %q", buf[offset:]) } return b.root, nil } func (b *PathBuilder) buildNextCharIfExists(buf []rune, cursor int) (int, error) { if len(buf) > cursor { offset, err := b.buildNext(buf[cursor:]) if err != nil { return 0, err } return cursor + 1 + offset, nil } return cursor, nil } func (b *PathBuilder) buildNext(buf []rune) (int, error) { switch buf[0] { case '.': if len(buf) == 1 { return 0, errors.ErrInvalidPath("JSON Path ends with dot character") } offset, err := b.buildSelector(buf[1:]) if err != nil { return 0, err } return offset + 1, nil case '[': if len(buf) == 1 { return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character") } offset, err := b.buildIndex(buf[1:]) if err != nil { return 0, err } return offset + 1, nil default: return 0, errors.ErrInvalidPath("expect dot or left bracket character. but found %c character", buf[0]) } } func (b *PathBuilder) buildSelector(buf []rune) (int, error) { switch buf[0] { case '.': if len(buf) == 1 { return 0, errors.ErrInvalidPath("JSON Path ends with double dot character") } offset, err := b.buildPathRecursive(buf[1:]) if err != nil { return 0, err } return 1 + offset, nil case '[', ']', '$', '*': return 0, errors.ErrInvalidPath("found invalid path character %c after dot", buf[0]) } for cursor := 0; cursor < len(buf); cursor++ { switch buf[cursor] { case '$', '*', ']': return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor]) case '.': if cursor+1 >= len(buf) { return 0, errors.ErrInvalidPath("JSON Path ends with dot character") } selector := buf[:cursor] b.addSelectorNode(string(selector)) offset, err := b.buildSelector(buf[cursor+1:]) if err != nil { return 0, err } return cursor + 1 + offset, nil case '[': if cursor+1 >= len(buf) { return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character") } selector := buf[:cursor] b.addSelectorNode(string(selector)) offset, err := b.buildIndex(buf[cursor+1:]) if err != nil { return 0, err } return cursor + 1 + offset, nil case '"': if cursor+1 >= len(buf) { return 0, errors.ErrInvalidPath("JSON Path ends with double quote character") } offset, err := b.buildQuoteSelector(buf[cursor+1:], DoubleQuotePathSelector) if err != nil { return 0, err } return cursor + 1 + offset, nil } } b.addSelectorNode(string(buf)) return len(buf), nil } func (b *PathBuilder) buildQuoteSelector(buf []rune, sel QuotePathSelector) (int, error) { switch buf[0] { case '[', ']', '$', '.', '*', '\'', '"': return 0, errors.ErrInvalidPath("found invalid path character %c after quote", buf[0]) } for cursor := 0; cursor < len(buf); cursor++ { switch buf[cursor] { case '\'': if sel != SingleQuotePathSelector { return 0, errors.ErrInvalidPath("found double quote character in field selector with single quote context") } if len(buf) <= cursor+1 { return 0, errors.ErrInvalidPath("JSON Path ends with single quote character in field selector context") } if buf[cursor+1] != ']' { return 0, errors.ErrInvalidPath("expect right bracket for field selector with single quote but found %c", buf[cursor+1]) } selector := buf[:cursor] b.addSelectorNode(string(selector)) b.singleQuotePathSelector = true return b.buildNextCharIfExists(buf, cursor+2) case '"': if sel != DoubleQuotePathSelector { return 0, errors.ErrInvalidPath("found single quote character in field selector with double quote context") } selector := buf[:cursor] b.addSelectorNode(string(selector)) b.doubleQuotePathSelector = true return b.buildNextCharIfExists(buf, cursor+1) } } return 0, errors.ErrInvalidPath("couldn't find quote character in selector quote path context") } func (b *PathBuilder) buildPathRecursive(buf []rune) (int, error) { switch buf[0] { case '.', '[', ']', '$', '*': return 0, errors.ErrInvalidPath("found invalid path character %c after double dot", buf[0]) } for cursor := 0; cursor < len(buf); cursor++ { switch buf[cursor] { case '$', '*', ']': return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor]) case '.': if cursor+1 >= len(buf) { return 0, errors.ErrInvalidPath("JSON Path ends with dot character") } selector := buf[:cursor] b.addRecursiveNode(string(selector)) offset, err := b.buildSelector(buf[cursor+1:]) if err != nil { return 0, err } return cursor + 1 + offset, nil case '[': if cursor+1 >= len(buf) { return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character") } selector := buf[:cursor] b.addRecursiveNode(string(selector)) offset, err := b.buildIndex(buf[cursor+1:]) if err != nil { return 0, err } return cursor + 1 + offset, nil } } b.addRecursiveNode(string(buf)) return len(buf), nil } func (b *PathBuilder) buildIndex(buf []rune) (int, error) { switch buf[0] { case '.', '[', ']', '$': return 0, errors.ErrInvalidPath("found invalid path character %c after left bracket", buf[0]) case '\'': if len(buf) == 1 { return 0, errors.ErrInvalidPath("JSON Path ends with single quote character") } offset, err := b.buildQuoteSelector(buf[1:], SingleQuotePathSelector) if err != nil { return 0, err } return 1 + offset, nil case '*': if len(buf) == 1 { return 0, errors.ErrInvalidPath("JSON Path ends with star character") } if buf[1] != ']' { return 0, errors.ErrInvalidPath("expect right bracket character for index all path but found %c character", buf[1]) } b.addIndexAllNode() offset := len("*]") if len(buf) > 2 { buildOffset, err := b.buildNext(buf[2:]) if err != nil { return 0, err } return offset + buildOffset, nil } return offset, nil } for cursor := 0; cursor < len(buf); cursor++ { switch buf[cursor] { case ']': index, err := strconv.ParseInt(string(buf[:cursor]), 10, 64) if err != nil { return 0, errors.ErrInvalidPath("%q is unexpected index path", buf[:cursor]) } b.addIndexNode(int(index)) return b.buildNextCharIfExists(buf, cursor+1) } } return 0, errors.ErrInvalidPath("couldn't find right bracket character in index path context") } func (b *PathBuilder) addIndexAllNode() { node := newPathIndexAllNode() if b.root == nil { b.root = node b.node = node } else { b.node = b.node.chain(node) } } func (b *PathBuilder) addRecursiveNode(selector string) { node := newPathRecursiveNode(selector) if b.root == nil { b.root = node b.node = node } else { b.node = b.node.chain(node) } } func (b *PathBuilder) addSelectorNode(name string) { node := newPathSelectorNode(name) if b.root == nil { b.root = node b.node = node } else { b.node = b.node.chain(node) } } func (b *PathBuilder) addIndexNode(idx int) { node := newPathIndexNode(idx) if b.root == nil { b.root = node b.node = node } else { b.node = b.node.chain(node) } } type QuotePathSelector int const ( SingleQuotePathSelector QuotePathSelector = 1 DoubleQuotePathSelector QuotePathSelector = 2 ) type Path struct { node PathNode RootSelectorOnly bool SingleQuotePathSelector bool DoubleQuotePathSelector bool } func (p *Path) Field(sel string) (PathNode, bool, error) { if p.node == nil { return nil, false, nil } return p.node.Field(sel) } func (p *Path) Get(src, dst reflect.Value) error { if p.node == nil { return nil } return p.node.Get(src, dst) } func (p *Path) String() string { if p.node == nil { return "$" } return p.node.String() } type PathNode interface { fmt.Stringer Index(idx int) (PathNode, bool, error) Field(fieldName string) (PathNode, bool, error) Get(src, dst reflect.Value) error chain(PathNode) PathNode target() bool single() bool } type BasePathNode struct { child PathNode } func (n *BasePathNode) chain(node PathNode) PathNode { n.child = node return node } func (n *BasePathNode) target() bool { return n.child == nil } func (n *BasePathNode) single() bool { return true } type PathSelectorNode struct { *BasePathNode selector string } func newPathSelectorNode(selector string) *PathSelectorNode { return &PathSelectorNode{ BasePathNode: &BasePathNode{}, selector: selector, } } func (n *PathSelectorNode) Index(idx int) (PathNode, bool, error) { return nil, false, &errors.PathError{} } func (n *PathSelectorNode) Field(fieldName string) (PathNode, bool, error) { if n.selector == fieldName { return n.child, true, nil } return nil, false, nil } func (n *PathSelectorNode) Get(src, dst reflect.Value) error { switch src.Type().Kind() { case reflect.Map: iter := src.MapRange() for iter.Next() { key, ok := iter.Key().Interface().(string) if !ok { return fmt.Errorf("invalid map key type %T", src.Type().Key()) } child, found, err := n.Field(key) if err != nil { return err } if found { if child != nil { return child.Get(iter.Value(), dst) } return AssignValue(iter.Value(), dst) } } case reflect.Struct: typ := src.Type() for i := 0; i < typ.Len(); i++ { tag := runtime.StructTagFromField(typ.Field(i)) child, found, err := n.Field(tag.Key) if err != nil { return err } if found { if child != nil { return child.Get(src.Field(i), dst) } return AssignValue(src.Field(i), dst) } } case reflect.Ptr: return n.Get(src.Elem(), dst) case reflect.Interface: return n.Get(reflect.ValueOf(src.Interface()), dst) case reflect.Float64, reflect.String, reflect.Bool: return AssignValue(src, dst) } return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type()) } func (n *PathSelectorNode) String() string { s := fmt.Sprintf(".%s", n.selector) if n.child != nil { s += n.child.String() } return s } type PathIndexNode struct { *BasePathNode selector int } func newPathIndexNode(selector int) *PathIndexNode { return &PathIndexNode{ BasePathNode: &BasePathNode{}, selector: selector, } } func (n *PathIndexNode) Index(idx int) (PathNode, bool, error) { if n.selector == idx { return n.child, true, nil } return nil, false, nil } func (n *PathIndexNode) Field(fieldName string) (PathNode, bool, error) { return nil, false, &errors.PathError{} } func (n *PathIndexNode) Get(src, dst reflect.Value) error { switch src.Type().Kind() { case reflect.Array, reflect.Slice: if src.Len() > n.selector { if n.child != nil { return n.child.Get(src.Index(n.selector), dst) } return AssignValue(src.Index(n.selector), dst) } case reflect.Ptr: return n.Get(src.Elem(), dst) case reflect.Interface: return n.Get(reflect.ValueOf(src.Interface()), dst) } return fmt.Errorf("failed to get [%d] value from %s", n.selector, src.Type()) } func (n *PathIndexNode) String() string { s := fmt.Sprintf("[%d]", n.selector) if n.child != nil { s += n.child.String() } return s } type PathIndexAllNode struct { *BasePathNode } func newPathIndexAllNode() *PathIndexAllNode { return &PathIndexAllNode{ BasePathNode: &BasePathNode{}, } } func (n *PathIndexAllNode) Index(idx int) (PathNode, bool, error) { return n.child, true, nil } func (n *PathIndexAllNode) Field(fieldName string) (PathNode, bool, error) { return nil, false, &errors.PathError{} } func (n *PathIndexAllNode) Get(src, dst reflect.Value) error { switch src.Type().Kind() { case reflect.Array, reflect.Slice: var arr []interface{} for i := 0; i < src.Len(); i++ { var v interface{} rv := reflect.ValueOf(&v) if n.child != nil { if err := n.child.Get(src.Index(i), rv); err != nil { return err } } else { if err := AssignValue(src.Index(i), rv); err != nil { return err } } arr = append(arr, v) } if err := AssignValue(reflect.ValueOf(arr), dst); err != nil { return err } return nil case reflect.Ptr: return n.Get(src.Elem(), dst) case reflect.Interface: return n.Get(reflect.ValueOf(src.Interface()), dst) } return fmt.Errorf("failed to get all value from %s", src.Type()) } func (n *PathIndexAllNode) String() string { s := "[*]" if n.child != nil { s += n.child.String() } return s } type PathRecursiveNode struct { *BasePathNode selector string } func newPathRecursiveNode(selector string) *PathRecursiveNode { node := newPathSelectorNode(selector) return &PathRecursiveNode{ BasePathNode: &BasePathNode{ child: node, }, selector: selector, } } func (n *PathRecursiveNode) Field(fieldName string) (PathNode, bool, error) { if n.selector == fieldName { return n.child, true, nil } return nil, false, nil } func (n *PathRecursiveNode) Index(_ int) (PathNode, bool, error) { return n, true, nil } func valueToSliceValue(v interface{}) []interface{} { rv := reflect.ValueOf(v) ret := []interface{}{} if rv.Type().Kind() == reflect.Slice || rv.Type().Kind() == reflect.Array { for i := 0; i < rv.Len(); i++ { ret = append(ret, rv.Index(i).Interface()) } return ret } return []interface{}{v} } func (n *PathRecursiveNode) Get(src, dst reflect.Value) error { if n.child == nil { return fmt.Errorf("failed to get by recursive path ..%s", n.selector) } var arr []interface{} switch src.Type().Kind() { case reflect.Map: iter := src.MapRange() for iter.Next() { key, ok := iter.Key().Interface().(string) if !ok { return fmt.Errorf("invalid map key type %T", src.Type().Key()) } child, found, err := n.Field(key) if err != nil { return err } if found { var v interface{} rv := reflect.ValueOf(&v) _ = child.Get(iter.Value(), rv) arr = append(arr, valueToSliceValue(v)...) } else { var v interface{} rv := reflect.ValueOf(&v) _ = n.Get(iter.Value(), rv) if v != nil { arr = append(arr, valueToSliceValue(v)...) } } } _ = AssignValue(reflect.ValueOf(arr), dst) return nil case reflect.Struct: typ := src.Type() for i := 0; i < typ.Len(); i++ { tag := runtime.StructTagFromField(typ.Field(i)) child, found, err := n.Field(tag.Key) if err != nil { return err } if found { var v interface{} rv := reflect.ValueOf(&v) _ = child.Get(src.Field(i), rv) arr = append(arr, valueToSliceValue(v)...) } else { var v interface{} rv := reflect.ValueOf(&v) _ = n.Get(src.Field(i), rv) if v != nil { arr = append(arr, valueToSliceValue(v)...) } } } _ = AssignValue(reflect.ValueOf(arr), dst) return nil case reflect.Array, reflect.Slice: for i := 0; i < src.Len(); i++ { var v interface{} rv := reflect.ValueOf(&v) _ = n.Get(src.Index(i), rv) if v != nil { arr = append(arr, valueToSliceValue(v)...) } } _ = AssignValue(reflect.ValueOf(arr), dst) return nil case reflect.Ptr: return n.Get(src.Elem(), dst) case reflect.Interface: return n.Get(reflect.ValueOf(src.Interface()), dst) } return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type()) } func (n *PathRecursiveNode) String() string { s := fmt.Sprintf("..%s", n.selector) if n.child != nil { s += n.child.String() } return s } golang-github-goccy-go-json-0.10.3/internal/decoder/ptr.go000066400000000000000000000040671463555276600234050ustar00rootroot00000000000000package decoder import ( "fmt" "unsafe" "github.com/goccy/go-json/internal/runtime" ) type ptrDecoder struct { dec Decoder typ *runtime.Type structName string fieldName string } func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder { return &ptrDecoder{ dec: dec, typ: typ, structName: structName, fieldName: fieldName, } } func (d *ptrDecoder) contentDecoder() Decoder { dec, ok := d.dec.(*ptrDecoder) if !ok { return d.dec } return dec.contentDecoder() } //nolint:golint //go:linkname unsafe_New reflect.unsafe_New func unsafe_New(*runtime.Type) unsafe.Pointer func UnsafeNew(t *runtime.Type) unsafe.Pointer { return unsafe_New(t) } func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { if s.skipWhiteSpace() == nul { s.read() } if s.char() == 'n' { if err := nullBytes(s); err != nil { return err } *(*unsafe.Pointer)(p) = nil return nil } var newptr unsafe.Pointer if *(*unsafe.Pointer)(p) == nil { newptr = unsafe_New(d.typ) *(*unsafe.Pointer)(p) = newptr } else { newptr = *(*unsafe.Pointer)(p) } if err := d.dec.DecodeStream(s, depth, newptr); err != nil { return err } return nil } func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == 'n' { if err := validateNull(buf, cursor); err != nil { return 0, err } if p != nil { *(*unsafe.Pointer)(p) = nil } cursor += 4 return cursor, nil } var newptr unsafe.Pointer if *(*unsafe.Pointer)(p) == nil { newptr = unsafe_New(d.typ) *(*unsafe.Pointer)(p) = newptr } else { newptr = *(*unsafe.Pointer)(p) } c, err := d.dec.Decode(ctx, cursor, depth, newptr) if err != nil { *(*unsafe.Pointer)(p) = nil return 0, err } cursor = c return cursor, nil } func (d *ptrDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: ptr decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/slice.go000066400000000000000000000217411463555276600236750ustar00rootroot00000000000000package decoder import ( "reflect" "sync" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) var ( sliceType = runtime.Type2RType( reflect.TypeOf((*sliceHeader)(nil)).Elem(), ) nilSlice = unsafe.Pointer(&sliceHeader{}) ) type sliceDecoder struct { elemType *runtime.Type isElemPointerType bool valueDecoder Decoder size uintptr arrayPool sync.Pool structName string fieldName string } // If use reflect.SliceHeader, data type is uintptr. // In this case, Go compiler cannot trace reference created by newArray(). // So, define using unsafe.Pointer as data type type sliceHeader struct { data unsafe.Pointer len int cap int } const ( defaultSliceCapacity = 2 ) func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder { return &sliceDecoder{ valueDecoder: dec, elemType: elemType, isElemPointerType: elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map, size: size, arrayPool: sync.Pool{ New: func() interface{} { return &sliceHeader{ data: newArray(elemType, defaultSliceCapacity), len: 0, cap: defaultSliceCapacity, } }, }, structName: structName, fieldName: fieldName, } } func (d *sliceDecoder) newSlice(src *sliceHeader) *sliceHeader { slice := d.arrayPool.Get().(*sliceHeader) if src.len > 0 { // copy original elem if slice.cap < src.cap { data := newArray(d.elemType, src.cap) slice = &sliceHeader{data: data, len: src.len, cap: src.cap} } else { slice.len = src.len } copySlice(d.elemType, *slice, *src) } else { slice.len = 0 } return slice } func (d *sliceDecoder) releaseSlice(p *sliceHeader) { d.arrayPool.Put(p) } //go:linkname copySlice reflect.typedslicecopy func copySlice(elemType *runtime.Type, dst, src sliceHeader) int //go:linkname newArray reflect.unsafe_NewArray func newArray(*runtime.Type, int) unsafe.Pointer //go:linkname typedmemmove reflect.typedmemmove func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer) func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError { return &errors.UnmarshalTypeError{ Value: "number", Type: reflect.SliceOf(runtime.RType2Type(d.elemType)), Struct: d.structName, Field: d.fieldName, Offset: offset, } } func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { depth++ if depth > maxDecodeNestingDepth { return errors.ErrExceededMaxDepth(s.char(), s.cursor) } for { switch s.char() { case ' ', '\n', '\t', '\r': s.cursor++ continue case 'n': if err := nullBytes(s); err != nil { return err } typedmemmove(sliceType, p, nilSlice) return nil case '[': s.cursor++ if s.skipWhiteSpace() == ']' { dst := (*sliceHeader)(p) if dst.data == nil { dst.data = newArray(d.elemType, 0) } else { dst.len = 0 } s.cursor++ return nil } idx := 0 slice := d.newSlice((*sliceHeader)(p)) srcLen := slice.len capacity := slice.cap data := slice.data for { if capacity <= idx { src := sliceHeader{data: data, len: idx, cap: capacity} capacity *= 2 data = newArray(d.elemType, capacity) dst := sliceHeader{data: data, len: idx, cap: capacity} copySlice(d.elemType, dst, src) } ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size) // if srcLen is greater than idx, keep the original reference if srcLen <= idx { if d.isElemPointerType { **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer } else { // assign new element to the slice typedmemmove(d.elemType, ep, unsafe_New(d.elemType)) } } if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil { return err } s.skipWhiteSpace() RETRY: switch s.char() { case ']': slice.cap = capacity slice.len = idx + 1 slice.data = data dst := (*sliceHeader)(p) dst.len = idx + 1 if dst.len > dst.cap { dst.data = newArray(d.elemType, dst.len) dst.cap = dst.len } copySlice(d.elemType, *dst, *slice) d.releaseSlice(slice) s.cursor++ return nil case ',': idx++ case nul: if s.read() { goto RETRY } slice.cap = capacity slice.data = data d.releaseSlice(slice) goto ERROR default: slice.cap = capacity slice.data = data d.releaseSlice(slice) goto ERROR } s.cursor++ } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return d.errNumber(s.totalOffset()) case nul: if s.read() { continue } goto ERROR default: goto ERROR } } ERROR: return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset()) } func (d *sliceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf depth++ if depth > maxDecodeNestingDepth { return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } for { switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ continue case 'n': if err := validateNull(buf, cursor); err != nil { return 0, err } cursor += 4 typedmemmove(sliceType, p, nilSlice) return cursor, nil case '[': cursor++ cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == ']' { dst := (*sliceHeader)(p) if dst.data == nil { dst.data = newArray(d.elemType, 0) } else { dst.len = 0 } cursor++ return cursor, nil } idx := 0 slice := d.newSlice((*sliceHeader)(p)) srcLen := slice.len capacity := slice.cap data := slice.data for { if capacity <= idx { src := sliceHeader{data: data, len: idx, cap: capacity} capacity *= 2 data = newArray(d.elemType, capacity) dst := sliceHeader{data: data, len: idx, cap: capacity} copySlice(d.elemType, dst, src) } ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size) // if srcLen is greater than idx, keep the original reference if srcLen <= idx { if d.isElemPointerType { **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer } else { // assign new element to the slice typedmemmove(d.elemType, ep, unsafe_New(d.elemType)) } } c, err := d.valueDecoder.Decode(ctx, cursor, depth, ep) if err != nil { return 0, err } cursor = c cursor = skipWhiteSpace(buf, cursor) switch buf[cursor] { case ']': slice.cap = capacity slice.len = idx + 1 slice.data = data dst := (*sliceHeader)(p) dst.len = idx + 1 if dst.len > dst.cap { dst.data = newArray(d.elemType, dst.len) dst.cap = dst.len } copySlice(d.elemType, *dst, *slice) d.releaseSlice(slice) cursor++ return cursor, nil case ',': idx++ default: slice.cap = capacity slice.data = data d.releaseSlice(slice) return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor) } cursor++ } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return 0, d.errNumber(cursor) default: return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor) } } } func (d *sliceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { buf := ctx.Buf depth++ if depth > maxDecodeNestingDepth { return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) } ret := [][]byte{} for { switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ continue case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return [][]byte{nullbytes}, cursor, nil case '[': cursor++ cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == ']' { cursor++ return ret, cursor, nil } idx := 0 for { child, found, err := ctx.Option.Path.node.Index(idx) if err != nil { return nil, 0, err } if found { if child != nil { oldPath := ctx.Option.Path.node ctx.Option.Path.node = child paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth) if err != nil { return nil, 0, err } ctx.Option.Path.node = oldPath ret = append(ret, paths...) cursor = c } else { start := cursor end, err := skipValue(buf, cursor, depth) if err != nil { return nil, 0, err } ret = append(ret, buf[start:end]) cursor = end } } else { c, err := skipValue(buf, cursor, depth) if err != nil { return nil, 0, err } cursor = c } cursor = skipWhiteSpace(buf, cursor) switch buf[cursor] { case ']': cursor++ return ret, cursor, nil case ',': idx++ default: return nil, 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor) } cursor++ } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return nil, 0, d.errNumber(cursor) default: return nil, 0, errors.ErrUnexpectedEndOfJSON("slice", cursor) } } } golang-github-goccy-go-json-0.10.3/internal/decoder/stream.go000066400000000000000000000243441463555276600240730ustar00rootroot00000000000000package decoder import ( "bytes" "encoding/json" "io" "strconv" "unsafe" "github.com/goccy/go-json/internal/errors" ) const ( initBufSize = 512 ) type Stream struct { buf []byte bufSize int64 length int64 r io.Reader offset int64 cursor int64 filledBuffer bool allRead bool UseNumber bool DisallowUnknownFields bool Option *Option } func NewStream(r io.Reader) *Stream { return &Stream{ r: r, bufSize: initBufSize, buf: make([]byte, initBufSize), Option: &Option{}, } } func (s *Stream) TotalOffset() int64 { return s.totalOffset() } func (s *Stream) Buffered() io.Reader { buflen := int64(len(s.buf)) for i := s.cursor; i < buflen; i++ { if s.buf[i] == nul { return bytes.NewReader(s.buf[s.cursor:i]) } } return bytes.NewReader(s.buf[s.cursor:]) } func (s *Stream) PrepareForDecode() error { for { switch s.char() { case ' ', '\t', '\r', '\n': s.cursor++ continue case ',', ':': s.cursor++ return nil case nul: if s.read() { continue } return io.EOF } break } return nil } func (s *Stream) totalOffset() int64 { return s.offset + s.cursor } func (s *Stream) char() byte { return s.buf[s.cursor] } func (s *Stream) equalChar(c byte) bool { cur := s.buf[s.cursor] if cur == nul { s.read() cur = s.buf[s.cursor] } return cur == c } func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) { return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data } func (s *Stream) bufptr() unsafe.Pointer { return (*sliceHeader)(unsafe.Pointer(&s.buf)).data } func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) { s.cursor-- // for retry ( because caller progress cursor position in each loop ) return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data } func (s *Stream) Reset() { s.reset() s.bufSize = int64(len(s.buf)) } 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) str := *(*string)(unsafe.Pointer(&bytes)) if s.UseNumber { return json.Number(str), nil } f64, err := strconv.ParseFloat(str, 64) if err != nil { return nil, err } return f64, nil case '"': bytes, err := stringBytes(s) if err != nil { return nil, err } return string(bytes), nil case 't': if err := trueBytes(s); err != nil { return nil, err } return true, nil case 'f': if err := falseBytes(s); err != nil { return nil, err } return false, nil case 'n': if err := nullBytes(s); err != nil { return nil, err } return nil, nil case nul: if s.read() { continue } goto END default: return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset()) } } END: return nil, io.EOF } func (s *Stream) reset() { s.offset += s.cursor s.buf = s.buf[s.cursor:] s.length -= s.cursor s.cursor = 0 } func (s *Stream) readBuf() []byte { if s.filledBuffer { s.bufSize *= 2 remainBuf := s.buf s.buf = make([]byte, s.bufSize) copy(s.buf, remainBuf) } remainLen := s.length - s.cursor remainNotNulCharNum := int64(0) for i := int64(0); i < remainLen; i++ { if s.buf[s.cursor+i] == nul { break } remainNotNulCharNum++ } s.length = s.cursor + remainNotNulCharNum return s.buf[s.cursor+remainNotNulCharNum:] } func (s *Stream) read() bool { if s.allRead { return false } buf := s.readBuf() last := len(buf) - 1 buf[last] = nul n, err := s.r.Read(buf[:last]) s.length += int64(n) if n == last { s.filledBuffer = true } else { s.filledBuffer = false } if err == io.EOF { s.allRead = true } else if err != nil { return false } return true } func (s *Stream) skipWhiteSpace() byte { p := s.bufptr() LOOP: c := char(p, s.cursor) switch c { case ' ', '\n', '\t', '\r': s.cursor++ goto LOOP case nul: if s.read() { p = s.bufptr() goto LOOP } } return c } func (s *Stream) skipObject(depth int64) error { braceCount := 1 _, cursor, p := s.stat() for { switch char(p, cursor) { case '{': braceCount++ depth++ if depth > maxDecodeNestingDepth { return errors.ErrExceededMaxDepth(s.char(), s.cursor) } case '}': braceCount-- depth-- if braceCount == 0 { s.cursor = cursor + 1 return nil } case '[': depth++ if depth > maxDecodeNestingDepth { return errors.ErrExceededMaxDepth(s.char(), s.cursor) } case ']': depth-- case '"': for { cursor++ switch char(p, cursor) { case '\\': cursor++ if char(p, cursor) == nul { s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } return errors.ErrUnexpectedEndOfJSON("string of object", cursor) } case '"': goto SWITCH_OUT case nul: s.cursor = cursor if s.read() { _, cursor, p = s.statForRetry() continue } return errors.ErrUnexpectedEndOfJSON("string of object", cursor) } } case nul: s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } return errors.ErrUnexpectedEndOfJSON("object of object", cursor) } SWITCH_OUT: cursor++ } } func (s *Stream) skipArray(depth int64) error { bracketCount := 1 _, cursor, p := s.stat() for { switch char(p, cursor) { case '[': bracketCount++ depth++ if depth > maxDecodeNestingDepth { return errors.ErrExceededMaxDepth(s.char(), s.cursor) } case ']': bracketCount-- depth-- if bracketCount == 0 { s.cursor = cursor + 1 return nil } case '{': depth++ if depth > maxDecodeNestingDepth { return errors.ErrExceededMaxDepth(s.char(), s.cursor) } case '}': depth-- case '"': for { cursor++ switch char(p, cursor) { case '\\': cursor++ if char(p, cursor) == nul { s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } return errors.ErrUnexpectedEndOfJSON("string of object", cursor) } case '"': goto SWITCH_OUT case nul: s.cursor = cursor if s.read() { _, cursor, p = s.statForRetry() continue } return errors.ErrUnexpectedEndOfJSON("string of object", cursor) } } case nul: s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } return errors.ErrUnexpectedEndOfJSON("array of object", cursor) } SWITCH_OUT: cursor++ } } func (s *Stream) skipValue(depth int64) error { _, cursor, p := s.stat() for { switch char(p, cursor) { case ' ', '\n', '\t', '\r': cursor++ continue case nul: s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset()) case '{': s.cursor = cursor + 1 return s.skipObject(depth + 1) case '[': s.cursor = cursor + 1 return s.skipArray(depth + 1) case '"': for { cursor++ switch char(p, cursor) { case '\\': cursor++ if char(p, cursor) == nul { s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset()) } case '"': s.cursor = cursor + 1 return nil case nul: s.cursor = cursor if s.read() { _, cursor, p = s.statForRetry() continue } return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset()) } } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': for { cursor++ c := char(p, cursor) if floatTable[c] { continue } else if c == nul { if s.read() { _, cursor, p = s.stat() continue } } s.cursor = cursor return nil } case 't': s.cursor = cursor if err := trueBytes(s); err != nil { return err } return nil case 'f': s.cursor = cursor if err := falseBytes(s); err != nil { return err } return nil case 'n': s.cursor = cursor if err := nullBytes(s); err != nil { return err } return nil } cursor++ } } func nullBytes(s *Stream) error { // current cursor's character is 'n' s.cursor++ if s.char() != 'u' { if err := retryReadNull(s); err != nil { return err } } s.cursor++ if s.char() != 'l' { if err := retryReadNull(s); err != nil { return err } } s.cursor++ if s.char() != 'l' { if err := retryReadNull(s); err != nil { return err } } s.cursor++ return nil } func retryReadNull(s *Stream) error { if s.char() == nul && s.read() { return nil } return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset()) } func trueBytes(s *Stream) error { // current cursor's character is 't' s.cursor++ if s.char() != 'r' { if err := retryReadTrue(s); err != nil { return err } } s.cursor++ if s.char() != 'u' { if err := retryReadTrue(s); err != nil { return err } } s.cursor++ if s.char() != 'e' { if err := retryReadTrue(s); err != nil { return err } } s.cursor++ return nil } func retryReadTrue(s *Stream) error { if s.char() == nul && s.read() { return nil } return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset()) } func falseBytes(s *Stream) error { // current cursor's character is 'f' s.cursor++ if s.char() != 'a' { if err := retryReadFalse(s); err != nil { return err } } s.cursor++ if s.char() != 'l' { if err := retryReadFalse(s); err != nil { return err } } s.cursor++ if s.char() != 's' { if err := retryReadFalse(s); err != nil { return err } } s.cursor++ if s.char() != 'e' { if err := retryReadFalse(s); err != nil { return err } } s.cursor++ return nil } func retryReadFalse(s *Stream) error { if s.char() == nul && s.read() { return nil } return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset()) } golang-github-goccy-go-json-0.10.3/internal/decoder/string.go000066400000000000000000000271511463555276600241050ustar00rootroot00000000000000package decoder import ( "bytes" "fmt" "reflect" "unicode" "unicode/utf16" "unicode/utf8" "unsafe" "github.com/goccy/go-json/internal/errors" ) type stringDecoder struct { structName string fieldName string } func newStringDecoder(structName, fieldName string) *stringDecoder { return &stringDecoder{ structName: structName, fieldName: fieldName, } } func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError { return &errors.UnmarshalTypeError{ Value: typeName, Type: reflect.TypeOf(""), Offset: offset, Struct: d.structName, Field: d.fieldName, } } func (d *stringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { bytes, err := d.decodeStreamByte(s) if err != nil { return err } if bytes == nil { return nil } **(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes)) s.reset() return nil } func (d *stringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { bytes, c, err := d.decodeByte(ctx.Buf, cursor) if err != nil { return 0, err } if bytes == nil { return c, nil } cursor = c **(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes)) return cursor, nil } func (d *stringDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { bytes, c, err := d.decodeByte(ctx.Buf, cursor) if err != nil { return nil, 0, err } if bytes == nil { return [][]byte{nullbytes}, c, nil } return [][]byte{bytes}, c, nil } var ( hexToInt = [256]int{ '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15, 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15, } ) func unicodeToRune(code []byte) rune { var r rune for i := 0; i < len(code); i++ { r = r*16 + rune(hexToInt[code[i]]) } return r } func readAtLeast(s *Stream, n int64, p *unsafe.Pointer) bool { for s.cursor+n >= s.length { if !s.read() { return false } *p = s.bufptr() } return true } func decodeUnicodeRune(s *Stream, p unsafe.Pointer) (rune, int64, unsafe.Pointer, error) { const defaultOffset = 5 const surrogateOffset = 11 if !readAtLeast(s, defaultOffset, &p) { return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset()) } r := unicodeToRune(s.buf[s.cursor+1 : s.cursor+defaultOffset]) if utf16.IsSurrogate(r) { if !readAtLeast(s, surrogateOffset, &p) { return unicode.ReplacementChar, defaultOffset, p, nil } if s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' { return unicode.ReplacementChar, defaultOffset, p, nil } r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset]) if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar { return r, surrogateOffset, p, nil } } return r, defaultOffset, p, nil } func decodeUnicode(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) { const backSlashAndULen = 2 // length of \u r, offset, pp, err := decodeUnicodeRune(s, p) if err != nil { return nil, err } unicode := []byte(string(r)) unicodeLen := int64(len(unicode)) s.buf = append(append(s.buf[:s.cursor-1], unicode...), s.buf[s.cursor+offset:]...) unicodeOrgLen := offset - 1 s.length = s.length - (backSlashAndULen + (unicodeOrgLen - unicodeLen)) s.cursor = s.cursor - backSlashAndULen + unicodeLen return pp, nil } func decodeEscapeString(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) { s.cursor++ RETRY: switch s.buf[s.cursor] { case '"': s.buf[s.cursor] = '"' case '\\': s.buf[s.cursor] = '\\' case '/': s.buf[s.cursor] = '/' case 'b': s.buf[s.cursor] = '\b' case 'f': s.buf[s.cursor] = '\f' case 'n': s.buf[s.cursor] = '\n' case 'r': s.buf[s.cursor] = '\r' case 't': s.buf[s.cursor] = '\t' case 'u': return decodeUnicode(s, p) case nul: if !s.read() { return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset()) } p = s.bufptr() goto RETRY default: return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) } s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...) s.length-- s.cursor-- p = s.bufptr() return p, nil } var ( runeErrBytes = []byte(string(utf8.RuneError)) runeErrBytesLen = int64(len(runeErrBytes)) ) func stringBytes(s *Stream) ([]byte, error) { _, cursor, p := s.stat() cursor++ // skip double quote char start := cursor for { switch char(p, cursor) { case '\\': s.cursor = cursor pp, err := decodeEscapeString(s, p) if err != nil { return nil, err } p = pp cursor = s.cursor case '"': literal := s.buf[start:cursor] cursor++ s.cursor = cursor return literal, nil case // 0x00 is nul, 0x5c is '\\', 0x22 is '"' . 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 0x00-0x0F 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // 0x10-0x1F 0x20, 0x21 /*0x22,*/, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // 0x20-0x2F 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, // 0x30-0x3F 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, // 0x40-0x4F 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B /*0x5C,*/, 0x5D, 0x5E, 0x5F, // 0x50-0x5F 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, // 0x60-0x6F 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F: // 0x70-0x7F // character is ASCII. skip to next char case 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, // 0x80-0x8F 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, // 0x90-0x9F 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, // 0xA0-0xAF 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, // 0xB0-0xBF 0xC0, 0xC1, // 0xC0-0xC1 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF: // 0xF5-0xFE // character is invalid s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...) _, _, p = s.stat() cursor += runeErrBytesLen s.length += runeErrBytesLen continue case nul: s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } goto ERROR case 0xEF: // RuneError is {0xEF, 0xBF, 0xBD} if s.buf[cursor+1] == 0xBF && s.buf[cursor+2] == 0xBD { // found RuneError: skip cursor += 2 break } fallthrough default: // multi bytes character if !utf8.FullRune(s.buf[cursor : len(s.buf)-1]) { s.cursor = cursor if s.read() { _, cursor, p = s.stat() continue } goto ERROR } r, size := utf8.DecodeRune(s.buf[cursor:]) if r == utf8.RuneError { s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...) cursor += runeErrBytesLen s.length += runeErrBytesLen _, _, p = s.stat() } else { cursor += int64(size) } continue } cursor++ } ERROR: return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) } func (d *stringDecoder) decodeStreamByte(s *Stream) ([]byte, error) { for { switch s.char() { case ' ', '\n', '\t', '\r': s.cursor++ continue case '[': return nil, d.errUnmarshalType("array", s.totalOffset()) case '{': return nil, d.errUnmarshalType("object", s.totalOffset()) case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return nil, d.errUnmarshalType("number", s.totalOffset()) case '"': return stringBytes(s) case 'n': if err := nullBytes(s); err != nil { return nil, err } return nil, nil case nul: if s.read() { continue } } break } return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset()) } func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { for { switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ case '[': return nil, 0, d.errUnmarshalType("array", cursor) case '{': return nil, 0, d.errUnmarshalType("object", cursor) case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return nil, 0, d.errUnmarshalType("number", cursor) case '"': cursor++ start := cursor b := (*sliceHeader)(unsafe.Pointer(&buf)).data escaped := 0 for { switch char(b, cursor) { case '\\': escaped++ cursor++ switch char(b, cursor) { case '"', '\\', '/', 'b', 'f', 'n', 'r', 't': cursor++ case 'u': buflen := int64(len(buf)) if cursor+5 >= buflen { return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor) } for i := int64(1); i <= 4; i++ { c := char(b, cursor+i) if !(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) { return nil, 0, errors.ErrSyntax(fmt.Sprintf("json: invalid character %c in \\u hexadecimal character escape", c), cursor+i) } } cursor += 5 default: return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor) } continue case '"': literal := buf[start:cursor] if escaped > 0 { literal = literal[:unescapeString(literal)] } cursor++ return literal, cursor, nil case nul: return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor) } cursor++ } case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return nil, cursor, nil default: return nil, 0, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) } } } var unescapeMap = [256]byte{ '"': '"', '\\': '\\', '/': '/', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', } func unsafeAdd(ptr unsafe.Pointer, offset int) unsafe.Pointer { return unsafe.Pointer(uintptr(ptr) + uintptr(offset)) } func unescapeString(buf []byte) int { p := (*sliceHeader)(unsafe.Pointer(&buf)).data end := unsafeAdd(p, len(buf)) src := unsafeAdd(p, bytes.IndexByte(buf, '\\')) dst := src for src != end { c := char(src, 0) if c == '\\' { escapeChar := char(src, 1) if escapeChar != 'u' { *(*byte)(dst) = unescapeMap[escapeChar] src = unsafeAdd(src, 2) dst = unsafeAdd(dst, 1) } else { v1 := hexToInt[char(src, 2)] v2 := hexToInt[char(src, 3)] v3 := hexToInt[char(src, 4)] v4 := hexToInt[char(src, 5)] code := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4) if code >= 0xd800 && code < 0xdc00 && uintptr(unsafeAdd(src, 11)) < uintptr(end) { if char(src, 6) == '\\' && char(src, 7) == 'u' { v1 := hexToInt[char(src, 8)] v2 := hexToInt[char(src, 9)] v3 := hexToInt[char(src, 10)] v4 := hexToInt[char(src, 11)] lo := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4) if lo >= 0xdc00 && lo < 0xe000 { code = (code-0xd800)<<10 | (lo - 0xdc00) + 0x10000 src = unsafeAdd(src, 6) } } } var b [utf8.UTFMax]byte n := utf8.EncodeRune(b[:], code) switch n { case 4: *(*byte)(unsafeAdd(dst, 3)) = b[3] fallthrough case 3: *(*byte)(unsafeAdd(dst, 2)) = b[2] fallthrough case 2: *(*byte)(unsafeAdd(dst, 1)) = b[1] fallthrough case 1: *(*byte)(unsafeAdd(dst, 0)) = b[0] } src = unsafeAdd(src, 6) dst = unsafeAdd(dst, n) } } else { *(*byte)(dst) = c src = unsafeAdd(src, 1) dst = unsafeAdd(dst, 1) } } return int(uintptr(dst) - uintptr(p)) } golang-github-goccy-go-json-0.10.3/internal/decoder/struct.go000066400000000000000000000477051463555276600241320ustar00rootroot00000000000000package 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 toASCIILower(s string) string { b := []byte(s) for i := range b { b[i] = largeToSmallTable[b[i]] } return string(b) } 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 { if key != toASCIILower(k) { d.isTriedOptimize = true return } // 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, error) { const defaultOffset = 4 const surrogateOffset = 6 if cursor+defaultOffset >= int64(len(buf)) { return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor) } 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, nil } cursor += 2 r2 := unicodeToRune(buf[cursor : cursor+defaultOffset]) if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar { return []byte(string(r)), cursor + defaultOffset - 1, nil } } return []byte(string(r)), cursor + defaultOffset - 1, nil } func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64, error) { c := buf[cursor] cursor++ switch c { case '"': return []byte{'"'}, cursor, nil case '\\': return []byte{'\\'}, cursor, nil case '/': return []byte{'/'}, cursor, nil case 'b': return []byte{'\b'}, cursor, nil case 'f': return []byte{'\f'}, cursor, nil case 'n': return []byte{'\n'}, cursor, nil case 'r': return []byte{'\r'}, cursor, nil case 't': return []byte{'\t'}, cursor, nil case 'u': return decodeKeyCharByUnicodeRune(buf, cursor) } return nil, cursor, nil } 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, err := decodeKeyCharByEscapedChar(buf, cursor) if err != nil { return 0, nil, err } 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, err := decodeKeyCharByEscapedChar(buf, cursor) if err != nil { return 0, nil, err } 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++ } } func (d *structDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: struct decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/type.go000066400000000000000000000013111463555276600235460ustar00rootroot00000000000000package decoder import ( "context" "encoding" "encoding/json" "reflect" "unsafe" ) type Decoder interface { Decode(*RuntimeContext, int64, int64, unsafe.Pointer) (int64, error) DecodePath(*RuntimeContext, int64, int64) ([][]byte, 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() ) golang-github-goccy-go-json-0.10.3/internal/decoder/uint.go000066400000000000000000000102421463555276600235470ustar00rootroot00000000000000package decoder import ( "fmt" "reflect" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type uintDecoder struct { typ *runtime.Type kind reflect.Kind op func(unsafe.Pointer, uint64) structName string fieldName string } func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder { return &uintDecoder{ typ: typ, kind: typ.Kind(), op: op, structName: structName, fieldName: fieldName, } } func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError { return &errors.UnmarshalTypeError{ Value: fmt.Sprintf("number %s", string(buf)), Type: runtime.RType2Type(d.typ), Offset: offset, } } var ( pow10u64 = [...]uint64{ 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, } pow10u64Len = len(pow10u64) ) func (d *uintDecoder) parseUint(b []byte) (uint64, error) { maxDigit := len(b) if maxDigit > pow10u64Len { return 0, fmt.Errorf("invalid length of number") } sum := uint64(0) for i := 0; i < maxDigit; i++ { c := uint64(b[i]) - 48 digitValue := pow10u64[maxDigit-i-1] sum += c * digitValue } return sum, nil } func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) { for { switch s.char() { case ' ', '\n', '\t', '\r': s.cursor++ continue case '0': s.cursor++ return numZeroBuf, nil case '1', '2', '3', '4', '5', '6', '7', '8', '9': start := s.cursor for { s.cursor++ if numTable[s.char()] { continue } else if s.char() == nul { if s.read() { s.cursor-- // for retry current character continue } } break } num := s.buf[start:s.cursor] return num, nil case 'n': if err := nullBytes(s); err != nil { return nil, err } return nil, nil case nul: if s.read() { continue } default: return nil, d.typeError([]byte{s.char()}, s.totalOffset()) } break } return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset()) } func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { for { switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ continue case '0': cursor++ return numZeroBuf, cursor, nil case '1', '2', '3', '4', '5', '6', '7', '8', '9': start := cursor cursor++ for numTable[buf[cursor]] { cursor++ } num := buf[start:cursor] return num, cursor, nil case 'n': if err := validateNull(buf, cursor); err != nil { return nil, 0, err } cursor += 4 return nil, cursor, nil default: return nil, 0, d.typeError([]byte{buf[cursor]}, cursor) } } } func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { bytes, err := d.decodeStreamByte(s) if err != nil { return err } if bytes == nil { return nil } u64, err := d.parseUint(bytes) if err != nil { return d.typeError(bytes, s.totalOffset()) } switch d.kind { case reflect.Uint8: if (1 << 8) <= u64 { return d.typeError(bytes, s.totalOffset()) } case reflect.Uint16: if (1 << 16) <= u64 { return d.typeError(bytes, s.totalOffset()) } case reflect.Uint32: if (1 << 32) <= u64 { return d.typeError(bytes, s.totalOffset()) } } d.op(p, u64) return nil } func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { bytes, c, err := d.decodeByte(ctx.Buf, cursor) if err != nil { return 0, err } if bytes == nil { return c, nil } cursor = c u64, err := d.parseUint(bytes) if err != nil { return 0, d.typeError(bytes, cursor) } switch d.kind { case reflect.Uint8: if (1 << 8) <= u64 { return 0, d.typeError(bytes, cursor) } case reflect.Uint16: if (1 << 16) <= u64 { return 0, d.typeError(bytes, cursor) } case reflect.Uint32: if (1 << 32) <= u64 { return 0, d.typeError(bytes, cursor) } } d.op(p, u64) return cursor, nil } func (d *uintDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: uint decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/unmarshal_json.go000066400000000000000000000046341463555276600256230ustar00rootroot00000000000000package decoder import ( "context" "encoding/json" "fmt" "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, })) switch v := v.(type) { case unmarshalerContext: var ctx context.Context if (s.Option.Flags & ContextOption) != 0 { ctx = s.Option.Context } else { ctx = context.Background() } if err := v.UnmarshalJSON(ctx, dst); err != nil { d.annotateError(s.cursor, err) return err } case json.Unmarshaler: if err := v.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 } func (d *unmarshalJSONDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: unmarshal json decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/decoder/unmarshal_text.go000066400000000000000000000132761463555276600256400ustar00rootroot00000000000000package decoder import ( "bytes" "encoding" "fmt" "unicode" "unicode/utf16" "unicode/utf8" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type unmarshalTextDecoder struct { typ *runtime.Type structName string fieldName string } func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder { return &unmarshalTextDecoder{ typ: typ, structName: structName, fieldName: fieldName, } } func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) { switch e := err.(type) { case *errors.UnmarshalTypeError: e.Struct = d.structName e.Field = d.fieldName case *errors.SyntaxError: e.Offset = cursor } } var ( nullbytes = []byte(`null`) ) func (d *unmarshalTextDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { s.skipWhiteSpace() start := s.cursor if err := s.skipValue(depth); err != nil { return err } src := s.buf[start:s.cursor] if len(src) > 0 { switch src[0] { case '[': return &errors.UnmarshalTypeError{ Value: "array", Type: runtime.RType2Type(d.typ), Offset: s.totalOffset(), } case '{': return &errors.UnmarshalTypeError{ Value: "object", Type: runtime.RType2Type(d.typ), Offset: s.totalOffset(), } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return &errors.UnmarshalTypeError{ Value: "number", Type: runtime.RType2Type(d.typ), Offset: s.totalOffset(), } case 'n': if bytes.Equal(src, nullbytes) { *(*unsafe.Pointer)(p) = nil return nil } } } dst := make([]byte, len(src)) copy(dst, src) if b, ok := unquoteBytes(dst); ok { dst = b } v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) if err := v.(encoding.TextUnmarshaler).UnmarshalText(dst); err != nil { d.annotateError(s.cursor, err) return err } return nil } func (d *unmarshalTextDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { buf := ctx.Buf cursor = skipWhiteSpace(buf, cursor) start := cursor end, err := skipValue(buf, cursor, depth) if err != nil { return 0, err } src := buf[start:end] if len(src) > 0 { switch src[0] { case '[': return 0, &errors.UnmarshalTypeError{ Value: "array", Type: runtime.RType2Type(d.typ), Offset: start, } case '{': return 0, &errors.UnmarshalTypeError{ Value: "object", Type: runtime.RType2Type(d.typ), Offset: start, } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return 0, &errors.UnmarshalTypeError{ Value: "number", Type: runtime.RType2Type(d.typ), Offset: start, } case 'n': if bytes.Equal(src, nullbytes) { *(*unsafe.Pointer)(p) = nil return end, nil } } } if s, ok := unquoteBytes(src); ok { src = s } v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) if err := v.(encoding.TextUnmarshaler).UnmarshalText(src); err != nil { d.annotateError(cursor, err) return 0, err } return end, nil } func (d *unmarshalTextDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path") } func unquoteBytes(s []byte) (t []byte, ok bool) { //nolint: nonamedreturns length := len(s) if length < 2 || s[0] != '"' || s[length-1] != '"' { return } s = s[1 : length-1] length -= 2 // Check for unusual characters. If there are none, // then no unquoting is needed, so return a slice of the // original bytes. r := 0 for r < length { c := s[r] if c == '\\' || c == '"' || c < ' ' { break } if c < utf8.RuneSelf { r++ continue } rr, size := utf8.DecodeRune(s[r:]) if rr == utf8.RuneError && size == 1 { break } r += size } if r == length { return s, true } b := make([]byte, length+2*utf8.UTFMax) w := copy(b, s[0:r]) for r < length { // Out of room? Can only happen if s is full of // malformed UTF-8 and we're replacing each // byte with RuneError. if w >= len(b)-2*utf8.UTFMax { nb := make([]byte, (len(b)+utf8.UTFMax)*2) copy(nb, b[0:w]) b = nb } switch c := s[r]; { case c == '\\': r++ if r >= length { return } switch s[r] { default: return case '"', '\\', '/', '\'': b[w] = s[r] r++ w++ case 'b': b[w] = '\b' r++ w++ case 'f': b[w] = '\f' r++ w++ case 'n': b[w] = '\n' r++ w++ case 'r': b[w] = '\r' r++ w++ case 't': b[w] = '\t' r++ w++ case 'u': r-- rr := getu4(s[r:]) if rr < 0 { return } r += 6 if utf16.IsSurrogate(rr) { rr1 := getu4(s[r:]) if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { // A valid pair; consume. r += 6 w += utf8.EncodeRune(b[w:], dec) break } // Invalid surrogate; fall back to replacement rune. rr = unicode.ReplacementChar } w += utf8.EncodeRune(b[w:], rr) } // Quote, control characters are invalid. case c == '"', c < ' ': return // ASCII case c < utf8.RuneSelf: b[w] = c r++ w++ // Coerce to well-formed UTF-8. default: rr, size := utf8.DecodeRune(s[r:]) r += size w += utf8.EncodeRune(b[w:], rr) } } return b[0:w], true } func getu4(s []byte) rune { if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { return -1 } var r rune for _, c := range s[2:6] { switch { case '0' <= c && c <= '9': c = c - '0' case 'a' <= c && c <= 'f': c = c - 'a' + 10 case 'A' <= c && c <= 'F': c = c - 'A' + 10 default: return -1 } r = r*16 + rune(c) } return r } golang-github-goccy-go-json-0.10.3/internal/decoder/wrapped_string.go000066400000000000000000000033301463555276600256200ustar00rootroot00000000000000package decoder import ( "fmt" "reflect" "unsafe" "github.com/goccy/go-json/internal/runtime" ) type wrappedStringDecoder struct { typ *runtime.Type dec Decoder stringDecoder *stringDecoder structName string fieldName string isPtrType bool } func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) *wrappedStringDecoder { return &wrappedStringDecoder{ typ: typ, dec: dec, stringDecoder: newStringDecoder(structName, fieldName), structName: structName, fieldName: fieldName, isPtrType: typ.Kind() == reflect.Ptr, } } func (d *wrappedStringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { bytes, err := d.stringDecoder.decodeStreamByte(s) if err != nil { return err } if bytes == nil { if d.isPtrType { *(*unsafe.Pointer)(p) = nil } return nil } b := make([]byte, len(bytes)+1) copy(b, bytes) if _, err := d.dec.Decode(&RuntimeContext{Buf: b}, 0, depth, p); err != nil { return err } return nil } func (d *wrappedStringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { bytes, c, err := d.stringDecoder.decodeByte(ctx.Buf, cursor) if err != nil { return 0, err } if bytes == nil { if d.isPtrType { *(*unsafe.Pointer)(p) = nil } return c, nil } bytes = append(bytes, nul) oldBuf := ctx.Buf ctx.Buf = bytes if _, err := d.dec.Decode(ctx, 0, depth, p); err != nil { return 0, err } ctx.Buf = oldBuf return c, nil } func (d *wrappedStringDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { return nil, 0, fmt.Errorf("json: wrapped string decoder does not support decode path") } golang-github-goccy-go-json-0.10.3/internal/encoder/000077500000000000000000000000001463555276600222545ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/encoder/code.go000066400000000000000000000537631463555276600235330ustar00rootroot00000000000000package encoder import ( "fmt" "reflect" "unsafe" "github.com/goccy/go-json/internal/runtime" ) type Code interface { Kind() CodeKind ToOpcode(*compileContext) Opcodes Filter(*FieldQuery) Code } type AnonymousCode interface { ToAnonymousOpcode(*compileContext) Opcodes } type Opcodes []*Opcode func (o Opcodes) First() *Opcode { if len(o) == 0 { return nil } return o[0] } func (o Opcodes) Last() *Opcode { if len(o) == 0 { return nil } return o[len(o)-1] } func (o Opcodes) Add(codes ...*Opcode) Opcodes { return append(o, codes...) } type CodeKind int const ( CodeKindInterface CodeKind = iota CodeKindPtr CodeKindInt CodeKindUint CodeKindFloat CodeKindString CodeKindBool CodeKindStruct CodeKindMap CodeKindSlice CodeKindArray CodeKindBytes CodeKindMarshalJSON CodeKindMarshalText CodeKindRecursive ) type IntCode struct { typ *runtime.Type bitSize uint8 isString bool isPtr bool } func (c *IntCode) Kind() CodeKind { return CodeKindInt } func (c *IntCode) ToOpcode(ctx *compileContext) Opcodes { var code *Opcode switch { case c.isPtr: code = newOpCode(ctx, c.typ, OpIntPtr) case c.isString: code = newOpCode(ctx, c.typ, OpIntString) default: code = newOpCode(ctx, c.typ, OpInt) } code.NumBitSize = c.bitSize ctx.incIndex() return Opcodes{code} } func (c *IntCode) Filter(_ *FieldQuery) Code { return c } type UintCode struct { typ *runtime.Type bitSize uint8 isString bool isPtr bool } func (c *UintCode) Kind() CodeKind { return CodeKindUint } func (c *UintCode) ToOpcode(ctx *compileContext) Opcodes { var code *Opcode switch { case c.isPtr: code = newOpCode(ctx, c.typ, OpUintPtr) case c.isString: code = newOpCode(ctx, c.typ, OpUintString) default: code = newOpCode(ctx, c.typ, OpUint) } code.NumBitSize = c.bitSize ctx.incIndex() return Opcodes{code} } func (c *UintCode) Filter(_ *FieldQuery) Code { return c } type FloatCode struct { typ *runtime.Type bitSize uint8 isPtr bool } func (c *FloatCode) Kind() CodeKind { return CodeKindFloat } func (c *FloatCode) ToOpcode(ctx *compileContext) Opcodes { var code *Opcode switch { case c.isPtr: switch c.bitSize { case 32: code = newOpCode(ctx, c.typ, OpFloat32Ptr) default: code = newOpCode(ctx, c.typ, OpFloat64Ptr) } default: switch c.bitSize { case 32: code = newOpCode(ctx, c.typ, OpFloat32) default: code = newOpCode(ctx, c.typ, OpFloat64) } } ctx.incIndex() return Opcodes{code} } func (c *FloatCode) Filter(_ *FieldQuery) Code { return c } type StringCode struct { typ *runtime.Type isPtr bool } func (c *StringCode) Kind() CodeKind { return CodeKindString } func (c *StringCode) ToOpcode(ctx *compileContext) Opcodes { isJSONNumberType := c.typ == runtime.Type2RType(jsonNumberType) var code *Opcode if c.isPtr { if isJSONNumberType { code = newOpCode(ctx, c.typ, OpNumberPtr) } else { code = newOpCode(ctx, c.typ, OpStringPtr) } } else { if isJSONNumberType { code = newOpCode(ctx, c.typ, OpNumber) } else { code = newOpCode(ctx, c.typ, OpString) } } ctx.incIndex() return Opcodes{code} } func (c *StringCode) Filter(_ *FieldQuery) Code { return c } type BoolCode struct { typ *runtime.Type isPtr bool } func (c *BoolCode) Kind() CodeKind { return CodeKindBool } func (c *BoolCode) ToOpcode(ctx *compileContext) Opcodes { var code *Opcode switch { case c.isPtr: code = newOpCode(ctx, c.typ, OpBoolPtr) default: code = newOpCode(ctx, c.typ, OpBool) } ctx.incIndex() return Opcodes{code} } func (c *BoolCode) Filter(_ *FieldQuery) Code { return c } type BytesCode struct { typ *runtime.Type isPtr bool } func (c *BytesCode) Kind() CodeKind { return CodeKindBytes } func (c *BytesCode) ToOpcode(ctx *compileContext) Opcodes { var code *Opcode switch { case c.isPtr: code = newOpCode(ctx, c.typ, OpBytesPtr) default: code = newOpCode(ctx, c.typ, OpBytes) } ctx.incIndex() return Opcodes{code} } func (c *BytesCode) Filter(_ *FieldQuery) Code { return c } type SliceCode struct { typ *runtime.Type value Code } func (c *SliceCode) Kind() CodeKind { return CodeKindSlice } func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes { // header => opcode => elem => end // ^ | // |________| size := c.typ.Elem().Size() header := newSliceHeaderCode(ctx, c.typ) ctx.incIndex() ctx.incIndent() codes := c.value.ToOpcode(ctx) ctx.decIndent() codes.First().Flags |= IndirectFlags elemCode := newSliceElemCode(ctx, c.typ.Elem(), header, size) ctx.incIndex() end := newOpCode(ctx, c.typ, OpSliceEnd) ctx.incIndex() header.End = end header.Next = codes.First() codes.Last().Next = elemCode elemCode.Next = codes.First() elemCode.End = end return Opcodes{header}.Add(codes...).Add(elemCode).Add(end) } func (c *SliceCode) Filter(_ *FieldQuery) Code { return c } type ArrayCode struct { typ *runtime.Type value Code } func (c *ArrayCode) Kind() CodeKind { return CodeKindArray } func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes { // header => opcode => elem => end // ^ | // |________| elem := c.typ.Elem() alen := c.typ.Len() size := elem.Size() header := newArrayHeaderCode(ctx, c.typ, alen) ctx.incIndex() ctx.incIndent() codes := c.value.ToOpcode(ctx) ctx.decIndent() codes.First().Flags |= IndirectFlags elemCode := newArrayElemCode(ctx, elem, header, alen, size) ctx.incIndex() end := newOpCode(ctx, c.typ, OpArrayEnd) ctx.incIndex() header.End = end header.Next = codes.First() codes.Last().Next = elemCode elemCode.Next = codes.First() elemCode.End = end return Opcodes{header}.Add(codes...).Add(elemCode).Add(end) } func (c *ArrayCode) Filter(_ *FieldQuery) Code { return c } type MapCode struct { typ *runtime.Type key Code value Code } func (c *MapCode) Kind() CodeKind { return CodeKindMap } func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes { // header => code => value => code => key => code => value => code => end // ^ | // |_______________________| header := newMapHeaderCode(ctx, c.typ) ctx.incIndex() keyCodes := c.key.ToOpcode(ctx) value := newMapValueCode(ctx, c.typ.Elem(), header) ctx.incIndex() ctx.incIndent() valueCodes := c.value.ToOpcode(ctx) ctx.decIndent() valueCodes.First().Flags |= IndirectFlags key := newMapKeyCode(ctx, c.typ.Key(), header) ctx.incIndex() end := newMapEndCode(ctx, c.typ, header) ctx.incIndex() header.Next = keyCodes.First() keyCodes.Last().Next = value value.Next = valueCodes.First() valueCodes.Last().Next = key key.Next = keyCodes.First() header.End = end key.End = end value.End = end return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end) } func (c *MapCode) Filter(_ *FieldQuery) Code { return c } type StructCode struct { typ *runtime.Type fields []*StructFieldCode isPtr bool disableIndirectConversion bool isIndirect bool isRecursive bool } func (c *StructCode) Kind() CodeKind { return CodeKindStruct } func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode { if isEmbeddedStruct(field) { return c.lastAnonymousFieldCode(firstField) } lastField := firstField for lastField.NextField != nil { lastField = lastField.NextField } return lastField } func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode { // firstField is special StructHead operation for anonymous structure. // So, StructHead's next operation is truly struct head operation. for firstField.Op == OpStructHead || firstField.Op == OpStructField { firstField = firstField.Next } lastField := firstField for lastField.NextField != nil { lastField = lastField.NextField } return lastField } func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes { // header => code => structField => code => end // ^ | // |__________| if c.isRecursive { recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{}) recursive.Type = c.typ ctx.incIndex() *ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive) return Opcodes{recursive} } codes := Opcodes{} var prevField *Opcode ctx.incIndent() for idx, field := range c.fields { isFirstField := idx == 0 isEndField := idx == len(c.fields)-1 fieldCodes := field.ToOpcode(ctx, isFirstField, isEndField) for _, code := range fieldCodes { if c.isIndirect { code.Flags |= IndirectFlags } } firstField := fieldCodes.First() if len(codes) > 0 { codes.Last().Next = firstField firstField.Idx = codes.First().Idx } if prevField != nil { prevField.NextField = firstField } if isEndField { endField := fieldCodes.Last() if len(codes) > 0 { codes.First().End = endField } else { firstField.End = endField } codes = codes.Add(fieldCodes...) break } prevField = c.lastFieldCode(field, firstField) codes = codes.Add(fieldCodes...) } if len(codes) == 0 { head := &Opcode{ Op: OpStructHead, Idx: opcodeOffset(ctx.ptrIndex), Type: c.typ, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, } ctx.incOpcodeIndex() end := &Opcode{ Op: OpStructEnd, Idx: opcodeOffset(ctx.ptrIndex), DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, } head.NextField = end head.Next = end head.End = end codes = codes.Add(head, end) ctx.incIndex() } ctx.decIndent() ctx.structTypeToCodes[uintptr(unsafe.Pointer(c.typ))] = codes return codes } func (c *StructCode) ToAnonymousOpcode(ctx *compileContext) Opcodes { // header => code => structField => code => end // ^ | // |__________| if c.isRecursive { recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{}) recursive.Type = c.typ ctx.incIndex() *ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive) return Opcodes{recursive} } codes := Opcodes{} var prevField *Opcode for idx, field := range c.fields { isFirstField := idx == 0 isEndField := idx == len(c.fields)-1 fieldCodes := field.ToAnonymousOpcode(ctx, isFirstField, isEndField) for _, code := range fieldCodes { if c.isIndirect { code.Flags |= IndirectFlags } } firstField := fieldCodes.First() if len(codes) > 0 { codes.Last().Next = firstField firstField.Idx = codes.First().Idx } if prevField != nil { prevField.NextField = firstField } if isEndField { lastField := fieldCodes.Last() if len(codes) > 0 { codes.First().End = lastField } else { firstField.End = lastField } } prevField = firstField codes = codes.Add(fieldCodes...) } return codes } func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) { fields := make([]*StructFieldCode, 0, len(c.fields)) for _, field := range c.fields { if field.isAnonymous { structCode := field.getAnonymousStruct() if structCode != nil && !structCode.isRecursive { structCode.removeFieldsByTags(tags) if len(structCode.fields) > 0 { fields = append(fields, field) } continue } } if tags.ExistsKey(field.key) { continue } fields = append(fields, field) } c.fields = fields } func (c *StructCode) enableIndirect() { if c.isIndirect { return } c.isIndirect = true if len(c.fields) == 0 { return } structCode := c.fields[0].getStruct() if structCode == nil { return } structCode.enableIndirect() } func (c *StructCode) Filter(query *FieldQuery) Code { fieldMap := map[string]*FieldQuery{} for _, field := range query.Fields { fieldMap[field.Name] = field } fields := make([]*StructFieldCode, 0, len(c.fields)) for _, field := range c.fields { query, exists := fieldMap[field.key] if !exists { continue } fieldCode := &StructFieldCode{ typ: field.typ, key: field.key, tag: field.tag, value: field.value, offset: field.offset, isAnonymous: field.isAnonymous, isTaggedKey: field.isTaggedKey, isNilableType: field.isNilableType, isNilCheck: field.isNilCheck, isAddrForMarshaler: field.isAddrForMarshaler, isNextOpPtrType: field.isNextOpPtrType, } if len(query.Fields) > 0 { fieldCode.value = fieldCode.value.Filter(query) } fields = append(fields, fieldCode) } return &StructCode{ typ: c.typ, fields: fields, isPtr: c.isPtr, disableIndirectConversion: c.disableIndirectConversion, isIndirect: c.isIndirect, isRecursive: c.isRecursive, } } type StructFieldCode struct { typ *runtime.Type key string tag *runtime.StructTag value Code offset uintptr isAnonymous bool isTaggedKey bool isNilableType bool isNilCheck bool isAddrForMarshaler bool isNextOpPtrType bool isMarshalerContext bool } func (c *StructFieldCode) getStruct() *StructCode { value := c.value ptr, ok := value.(*PtrCode) if ok { value = ptr.value } structCode, ok := value.(*StructCode) if ok { return structCode } return nil } func (c *StructFieldCode) getAnonymousStruct() *StructCode { if !c.isAnonymous { return nil } return c.getStruct() } func optimizeStructHeader(code *Opcode, tag *runtime.StructTag) OpType { headType := code.ToHeaderType(tag.IsString) if tag.IsOmitEmpty { headType = headType.HeadToOmitEmptyHead() } return headType } func optimizeStructField(code *Opcode, tag *runtime.StructTag) OpType { fieldType := code.ToFieldType(tag.IsString) if tag.IsOmitEmpty { fieldType = fieldType.FieldToOmitEmptyField() } return fieldType } func (c *StructFieldCode) headerOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes { value := valueCodes.First() op := optimizeStructHeader(value, c.tag) field.Op = op if value.Flags&MarshalerContextFlags != 0 { field.Flags |= MarshalerContextFlags } field.NumBitSize = value.NumBitSize field.PtrNum = value.PtrNum field.FieldQuery = value.FieldQuery fieldCodes := Opcodes{field} if op.IsMultipleOpHead() { field.Next = value fieldCodes = fieldCodes.Add(valueCodes...) } else { ctx.decIndex() } return fieldCodes } func (c *StructFieldCode) fieldOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes { value := valueCodes.First() op := optimizeStructField(value, c.tag) field.Op = op if value.Flags&MarshalerContextFlags != 0 { field.Flags |= MarshalerContextFlags } field.NumBitSize = value.NumBitSize field.PtrNum = value.PtrNum field.FieldQuery = value.FieldQuery fieldCodes := Opcodes{field} if op.IsMultipleOpField() { field.Next = value fieldCodes = fieldCodes.Add(valueCodes...) } else { ctx.decIndex() } return fieldCodes } func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) Opcodes { end := &Opcode{ Op: OpStructEnd, Idx: opcodeOffset(ctx.ptrIndex), DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, } codes.Last().Next = end code := codes.First() for code.Op == OpStructField || code.Op == OpStructHead { code = code.Next } for code.NextField != nil { code = code.NextField } code.NextField = end codes = codes.Add(end) ctx.incOpcodeIndex() return codes } func (c *StructFieldCode) structKey(ctx *compileContext) string { if ctx.escapeKey { rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}} return fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key))) } return fmt.Sprintf(`"%s":`, c.key) } func (c *StructFieldCode) flags() OpFlags { var flags OpFlags if c.isTaggedKey { flags |= IsTaggedKeyFlags } if c.isNilableType { flags |= IsNilableTypeFlags } if c.isNilCheck { flags |= NilCheckFlags } if c.isAddrForMarshaler { flags |= AddrForMarshalerFlags } if c.isNextOpPtrType { flags |= IsNextOpPtrTypeFlags } if c.isAnonymous { flags |= AnonymousKeyFlags } if c.isMarshalerContext { flags |= MarshalerContextFlags } return flags } func (c *StructFieldCode) toValueOpcodes(ctx *compileContext) Opcodes { if c.isAnonymous { anonymCode, ok := c.value.(AnonymousCode) if ok { return anonymCode.ToAnonymousOpcode(ctx) } } return c.value.ToOpcode(ctx) } func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes { field := &Opcode{ Idx: opcodeOffset(ctx.ptrIndex), Flags: c.flags(), Key: c.structKey(ctx), Offset: uint32(c.offset), Type: c.typ, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, DisplayKey: c.key, } ctx.incIndex() valueCodes := c.toValueOpcodes(ctx) if isFirstField { codes := c.headerOpcodes(ctx, field, valueCodes) if isEndField { codes = c.addStructEndCode(ctx, codes) } return codes } codes := c.fieldOpcodes(ctx, field, valueCodes) if isEndField { if isEnableStructEndOptimization(c.value) { field.Op = field.Op.FieldToEnd() } else { codes = c.addStructEndCode(ctx, codes) } } return codes } func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes { field := &Opcode{ Idx: opcodeOffset(ctx.ptrIndex), Flags: c.flags() | AnonymousHeadFlags, Key: c.structKey(ctx), Offset: uint32(c.offset), Type: c.typ, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, DisplayKey: c.key, } ctx.incIndex() valueCodes := c.toValueOpcodes(ctx) if isFirstField { return c.headerOpcodes(ctx, field, valueCodes) } return c.fieldOpcodes(ctx, field, valueCodes) } func isEnableStructEndOptimization(value Code) bool { switch value.Kind() { case CodeKindInt, CodeKindUint, CodeKindFloat, CodeKindString, CodeKindBool, CodeKindBytes: return true case CodeKindPtr: return isEnableStructEndOptimization(value.(*PtrCode).value) default: return false } } type InterfaceCode struct { typ *runtime.Type fieldQuery *FieldQuery isPtr bool } func (c *InterfaceCode) Kind() CodeKind { return CodeKindInterface } func (c *InterfaceCode) ToOpcode(ctx *compileContext) Opcodes { var code *Opcode switch { case c.isPtr: code = newOpCode(ctx, c.typ, OpInterfacePtr) default: code = newOpCode(ctx, c.typ, OpInterface) } code.FieldQuery = c.fieldQuery if c.typ.NumMethod() > 0 { code.Flags |= NonEmptyInterfaceFlags } ctx.incIndex() return Opcodes{code} } func (c *InterfaceCode) Filter(query *FieldQuery) Code { return &InterfaceCode{ typ: c.typ, fieldQuery: query, isPtr: c.isPtr, } } type MarshalJSONCode struct { typ *runtime.Type fieldQuery *FieldQuery isAddrForMarshaler bool isNilableType bool isMarshalerContext bool } func (c *MarshalJSONCode) Kind() CodeKind { return CodeKindMarshalJSON } func (c *MarshalJSONCode) ToOpcode(ctx *compileContext) Opcodes { code := newOpCode(ctx, c.typ, OpMarshalJSON) code.FieldQuery = c.fieldQuery if c.isAddrForMarshaler { code.Flags |= AddrForMarshalerFlags } if c.isMarshalerContext { code.Flags |= MarshalerContextFlags } if c.isNilableType { code.Flags |= IsNilableTypeFlags } else { code.Flags &= ^IsNilableTypeFlags } ctx.incIndex() return Opcodes{code} } func (c *MarshalJSONCode) Filter(query *FieldQuery) Code { return &MarshalJSONCode{ typ: c.typ, fieldQuery: query, isAddrForMarshaler: c.isAddrForMarshaler, isNilableType: c.isNilableType, isMarshalerContext: c.isMarshalerContext, } } type MarshalTextCode struct { typ *runtime.Type fieldQuery *FieldQuery isAddrForMarshaler bool isNilableType bool } func (c *MarshalTextCode) Kind() CodeKind { return CodeKindMarshalText } func (c *MarshalTextCode) ToOpcode(ctx *compileContext) Opcodes { code := newOpCode(ctx, c.typ, OpMarshalText) code.FieldQuery = c.fieldQuery if c.isAddrForMarshaler { code.Flags |= AddrForMarshalerFlags } if c.isNilableType { code.Flags |= IsNilableTypeFlags } else { code.Flags &= ^IsNilableTypeFlags } ctx.incIndex() return Opcodes{code} } func (c *MarshalTextCode) Filter(query *FieldQuery) Code { return &MarshalTextCode{ typ: c.typ, fieldQuery: query, isAddrForMarshaler: c.isAddrForMarshaler, isNilableType: c.isNilableType, } } type PtrCode struct { typ *runtime.Type value Code ptrNum uint8 } func (c *PtrCode) Kind() CodeKind { return CodeKindPtr } func (c *PtrCode) ToOpcode(ctx *compileContext) Opcodes { codes := c.value.ToOpcode(ctx) codes.First().Op = convertPtrOp(codes.First()) codes.First().PtrNum = c.ptrNum return codes } func (c *PtrCode) ToAnonymousOpcode(ctx *compileContext) Opcodes { var codes Opcodes anonymCode, ok := c.value.(AnonymousCode) if ok { codes = anonymCode.ToAnonymousOpcode(ctx) } else { codes = c.value.ToOpcode(ctx) } codes.First().Op = convertPtrOp(codes.First()) codes.First().PtrNum = c.ptrNum return codes } func (c *PtrCode) Filter(query *FieldQuery) Code { return &PtrCode{ typ: c.typ, value: c.value.Filter(query), ptrNum: c.ptrNum, } } func convertPtrOp(code *Opcode) OpType { ptrHeadOp := code.Op.HeadToPtrHead() if code.Op != ptrHeadOp { if code.PtrNum > 0 { // ptr field and ptr head code.PtrNum-- } return ptrHeadOp } switch code.Op { case OpInt: return OpIntPtr case OpUint: return OpUintPtr case OpFloat32: return OpFloat32Ptr case OpFloat64: return OpFloat64Ptr case OpString: return OpStringPtr case OpBool: return OpBoolPtr case OpBytes: return OpBytesPtr case OpNumber: return OpNumberPtr case OpArray: return OpArrayPtr case OpSlice: return OpSlicePtr case OpMap: return OpMapPtr case OpMarshalJSON: return OpMarshalJSONPtr case OpMarshalText: return OpMarshalTextPtr case OpInterface: return OpInterfacePtr case OpRecursive: return OpRecursivePtr } return code.Op } func isEmbeddedStruct(field *StructFieldCode) bool { if !field.isAnonymous { return false } t := field.typ if t.Kind() == reflect.Ptr { t = t.Elem() } return t.Kind() == reflect.Struct } golang-github-goccy-go-json-0.10.3/internal/encoder/compact.go000066400000000000000000000154211463555276600242340ustar00rootroot00000000000000package encoder import ( "bytes" "fmt" "strconv" "unsafe" "github.com/goccy/go-json/internal/errors" ) var ( isWhiteSpace = [256]bool{ ' ': true, '\n': true, '\t': true, '\r': true, } isHTMLEscapeChar = [256]bool{ '<': true, '>': true, '&': true, } nul = byte('\000') ) func Compact(buf *bytes.Buffer, src []byte, escape bool) error { if len(src) == 0 { return errors.ErrUnexpectedEndOfJSON("", 0) } buf.Grow(len(src)) dst := buf.Bytes() ctx := TakeRuntimeContext() ctxBuf := ctx.Buf[:0] ctxBuf = append(append(ctxBuf, src...), nul) ctx.Buf = ctxBuf if err := compactAndWrite(buf, dst, ctxBuf, escape); err != nil { ReleaseRuntimeContext(ctx) return err } ReleaseRuntimeContext(ctx) return nil } func compactAndWrite(buf *bytes.Buffer, dst []byte, src []byte, escape bool) error { dst, err := compact(dst, src, escape) if err != nil { return err } if _, err := buf.Write(dst); err != nil { return err } return nil } func compact(dst, src []byte, escape bool) ([]byte, error) { buf, cursor, err := compactValue(dst, src, 0, escape) if err != nil { return nil, err } if err := validateEndBuf(src, cursor); err != nil { return nil, err } return buf, nil } func validateEndBuf(src []byte, cursor int64) error { for { switch src[cursor] { case ' ', '\t', '\n', '\r': cursor++ continue case nul: return nil } return errors.ErrSyntax( fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]), cursor+1, ) } } func skipWhiteSpace(buf []byte, cursor int64) int64 { LOOP: if isWhiteSpace[buf[cursor]] { cursor++ goto LOOP } return cursor } func compactValue(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { for { switch src[cursor] { case ' ', '\t', '\n', '\r': cursor++ continue case '{': return compactObject(dst, src, cursor, escape) case '}': return nil, 0, errors.ErrSyntax("unexpected character '}'", cursor) case '[': return compactArray(dst, src, cursor, escape) case ']': return nil, 0, errors.ErrSyntax("unexpected character ']'", cursor) case '"': return compactString(dst, src, cursor, escape) case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return compactNumber(dst, src, cursor) case 't': return compactTrue(dst, src, cursor) case 'f': return compactFalse(dst, src, cursor) case 'n': return compactNull(dst, src, cursor) default: return nil, 0, errors.ErrSyntax(fmt.Sprintf("unexpected character '%c'", src[cursor]), cursor) } } } func compactObject(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { if src[cursor] == '{' { dst = append(dst, '{') } else { return nil, 0, errors.ErrExpected("expected { character for object value", cursor) } cursor = skipWhiteSpace(src, cursor+1) if src[cursor] == '}' { dst = append(dst, '}') return dst, cursor + 1, nil } var err error for { cursor = skipWhiteSpace(src, cursor) dst, cursor, err = compactString(dst, src, cursor, escape) if err != nil { return nil, 0, err } cursor = skipWhiteSpace(src, cursor) if src[cursor] != ':' { return nil, 0, errors.ErrExpected("colon after object key", cursor) } dst = append(dst, ':') dst, cursor, err = compactValue(dst, src, cursor+1, escape) if err != nil { return nil, 0, err } cursor = skipWhiteSpace(src, cursor) switch src[cursor] { case '}': dst = append(dst, '}') cursor++ return dst, cursor, nil case ',': dst = append(dst, ',') default: return nil, 0, errors.ErrExpected("comma after object value", cursor) } cursor++ } } func compactArray(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { if src[cursor] == '[' { dst = append(dst, '[') } else { return nil, 0, errors.ErrExpected("expected [ character for array value", cursor) } cursor = skipWhiteSpace(src, cursor+1) if src[cursor] == ']' { dst = append(dst, ']') return dst, cursor + 1, nil } var err error for { dst, cursor, err = compactValue(dst, src, cursor, escape) if err != nil { return nil, 0, err } cursor = skipWhiteSpace(src, cursor) switch src[cursor] { case ']': dst = append(dst, ']') cursor++ return dst, cursor, nil case ',': dst = append(dst, ',') default: return nil, 0, errors.ErrExpected("comma after array value", cursor) } cursor++ } } func compactString(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { if src[cursor] != '"' { return nil, 0, errors.ErrInvalidCharacter(src[cursor], "string", cursor) } start := cursor for { cursor++ c := src[cursor] if escape { if isHTMLEscapeChar[c] { dst = append(dst, src[start:cursor]...) dst = append(dst, `\u00`...) dst = append(dst, hex[c>>4], hex[c&0xF]) start = cursor + 1 } else if c == 0xE2 && cursor+2 < int64(len(src)) && src[cursor+1] == 0x80 && src[cursor+2]&^1 == 0xA8 { dst = append(dst, src[start:cursor]...) dst = append(dst, `\u202`...) dst = append(dst, hex[src[cursor+2]&0xF]) start = cursor + 3 cursor += 2 } } switch c { case '\\': cursor++ if src[cursor] == nul { return nil, 0, errors.ErrUnexpectedEndOfJSON("string", int64(len(src))) } case '"': cursor++ return append(dst, src[start:cursor]...), cursor, nil case nul: return nil, 0, errors.ErrUnexpectedEndOfJSON("string", int64(len(src))) } } } func compactNumber(dst, src []byte, cursor int64) ([]byte, int64, error) { start := cursor for { cursor++ if floatTable[src[cursor]] { continue } break } num := src[start:cursor] if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&num)), 64); err != nil { return nil, 0, err } dst = append(dst, num...) return dst, cursor, nil } func compactTrue(dst, src []byte, cursor int64) ([]byte, int64, error) { if cursor+3 >= int64(len(src)) { return nil, 0, errors.ErrUnexpectedEndOfJSON("true", cursor) } if !bytes.Equal(src[cursor:cursor+4], []byte(`true`)) { return nil, 0, errors.ErrInvalidCharacter(src[cursor], "true", cursor) } dst = append(dst, "true"...) cursor += 4 return dst, cursor, nil } func compactFalse(dst, src []byte, cursor int64) ([]byte, int64, error) { if cursor+4 >= int64(len(src)) { return nil, 0, errors.ErrUnexpectedEndOfJSON("false", cursor) } if !bytes.Equal(src[cursor:cursor+5], []byte(`false`)) { return nil, 0, errors.ErrInvalidCharacter(src[cursor], "false", cursor) } dst = append(dst, "false"...) cursor += 5 return dst, cursor, nil } func compactNull(dst, src []byte, cursor int64) ([]byte, int64, error) { if cursor+3 >= int64(len(src)) { return nil, 0, errors.ErrUnexpectedEndOfJSON("null", cursor) } if !bytes.Equal(src[cursor:cursor+4], []byte(`null`)) { return nil, 0, errors.ErrInvalidCharacter(src[cursor], "null", cursor) } dst = append(dst, "null"...) cursor += 4 return dst, cursor, nil } golang-github-goccy-go-json-0.10.3/internal/encoder/compiler.go000066400000000000000000000644441463555276600244310ustar00rootroot00000000000000package encoder import ( "context" "encoding" "encoding/json" "reflect" "sync/atomic" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) type marshalerContext interface { MarshalJSON(context.Context) ([]byte, error) } var ( 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() { typeAddr = runtime.AnalyzeTypeAddr() if typeAddr == nil { typeAddr = &runtime.TypeAddr{} } cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift+1) } func loadOpcodeMap() map[uintptr]*OpcodeSet { p := atomic.LoadPointer(&cachedOpcodeMap) return *(*map[uintptr]*OpcodeSet)(unsafe.Pointer(&p)) } func storeOpcodeSet(typ uintptr, set *OpcodeSet, m map[uintptr]*OpcodeSet) { newOpcodeMap := make(map[uintptr]*OpcodeSet, len(m)+1) newOpcodeMap[typ] = set for k, v := range m { newOpcodeMap[k] = v } atomic.StorePointer(&cachedOpcodeMap, *(*unsafe.Pointer)(unsafe.Pointer(&newOpcodeMap))) } func compileToGetCodeSetSlowPath(typeptr uintptr) (*OpcodeSet, error) { opcodeMap := loadOpcodeMap() if codeSet, exists := opcodeMap[typeptr]; exists { return codeSet, nil } codeSet, err := newCompiler().compile(typeptr) if err != nil { return nil, err } storeOpcodeSet(typeptr, codeSet, opcodeMap) return codeSet, nil } func getFilteredCodeSetIfNeeded(ctx *RuntimeContext, codeSet *OpcodeSet) (*OpcodeSet, error) { if (ctx.Option.Flag & ContextOption) == 0 { return codeSet, nil } query := FieldQueryFromContext(ctx.Option.Context) if query == nil { return codeSet, nil } ctx.Option.Flag |= FieldQueryOption cacheCodeSet := codeSet.getQueryCache(query.Hash()) if cacheCodeSet != nil { return cacheCodeSet, nil } queryCodeSet, err := newCompiler().codeToOpcodeSet(codeSet.Type, codeSet.Code.Filter(query)) if err != nil { return nil, err } codeSet.setQueryCache(query.Hash(), queryCodeSet) return queryCodeSet, nil } type Compiler struct { structTypeToCode map[uintptr]*StructCode } func newCompiler() *Compiler { return &Compiler{ structTypeToCode: map[uintptr]*StructCode{}, } } func (c *Compiler) compile(typeptr uintptr) (*OpcodeSet, error) { // noescape trick for header.typ ( reflect.*rtype ) typ := *(**runtime.Type)(unsafe.Pointer(&typeptr)) code, err := c.typeToCode(typ) if err != nil { return nil, err } return c.codeToOpcodeSet(typ, code) } func (c *Compiler) codeToOpcodeSet(typ *runtime.Type, code Code) (*OpcodeSet, error) { noescapeKeyCode := c.codeToOpcode(&compileContext{ structTypeToCodes: map[uintptr]Opcodes{}, recursiveCodes: &Opcodes{}, }, typ, code) if err := noescapeKeyCode.Validate(); err != nil { return nil, err } escapeKeyCode := c.codeToOpcode(&compileContext{ structTypeToCodes: map[uintptr]Opcodes{}, recursiveCodes: &Opcodes{}, escapeKey: true, }, typ, code) noescapeKeyCode = copyOpcode(noescapeKeyCode) escapeKeyCode = copyOpcode(escapeKeyCode) setTotalLengthToInterfaceOp(noescapeKeyCode) setTotalLengthToInterfaceOp(escapeKeyCode) interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode) interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode) codeLength := noescapeKeyCode.TotalLength() return &OpcodeSet{ Type: typ, NoescapeKeyCode: noescapeKeyCode, EscapeKeyCode: escapeKeyCode, InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode, InterfaceEscapeKeyCode: interfaceEscapeKeyCode, CodeLength: codeLength, EndCode: ToEndCode(interfaceNoescapeKeyCode), Code: code, QueryCache: map[string]*OpcodeSet{}, }, nil } func (c *Compiler) typeToCode(typ *runtime.Type) (Code, error) { switch { case c.implementsMarshalJSON(typ): return c.marshalJSONCode(typ) case c.implementsMarshalText(typ): return c.marshalTextCode(typ) } isPtr := false orgType := typ if typ.Kind() == reflect.Ptr { typ = typ.Elem() isPtr = true } switch { case c.implementsMarshalJSON(typ): return c.marshalJSONCode(orgType) case c.implementsMarshalText(typ): return c.marshalTextCode(orgType) } switch typ.Kind() { case reflect.Slice: elem := typ.Elem() if elem.Kind() == reflect.Uint8 { p := runtime.PtrTo(elem) if !c.implementsMarshalJSONType(p) && !p.Implements(marshalTextType) { return c.bytesCode(typ, isPtr) } } return c.sliceCode(typ) case reflect.Map: if isPtr { return c.ptrCode(runtime.PtrTo(typ)) } return c.mapCode(typ) case reflect.Struct: return c.structCode(typ, isPtr) case reflect.Int: return c.intCode(typ, isPtr) case reflect.Int8: return c.int8Code(typ, isPtr) case reflect.Int16: return c.int16Code(typ, isPtr) case reflect.Int32: return c.int32Code(typ, isPtr) case reflect.Int64: return c.int64Code(typ, isPtr) case reflect.Uint, reflect.Uintptr: return c.uintCode(typ, isPtr) case reflect.Uint8: return c.uint8Code(typ, isPtr) case reflect.Uint16: return c.uint16Code(typ, isPtr) case reflect.Uint32: return c.uint32Code(typ, isPtr) case reflect.Uint64: return c.uint64Code(typ, isPtr) case reflect.Float32: return c.float32Code(typ, isPtr) case reflect.Float64: return c.float64Code(typ, isPtr) case reflect.String: return c.stringCode(typ, isPtr) case reflect.Bool: return c.boolCode(typ, isPtr) case reflect.Interface: return c.interfaceCode(typ, isPtr) default: if isPtr && typ.Implements(marshalTextType) { typ = orgType } return c.typeToCodeWithPtr(typ, isPtr) } } func (c *Compiler) typeToCodeWithPtr(typ *runtime.Type, isPtr bool) (Code, error) { switch { case c.implementsMarshalJSON(typ): return c.marshalJSONCode(typ) case c.implementsMarshalText(typ): return c.marshalTextCode(typ) } switch typ.Kind() { case reflect.Ptr: return c.ptrCode(typ) case reflect.Slice: elem := typ.Elem() if elem.Kind() == reflect.Uint8 { p := runtime.PtrTo(elem) if !c.implementsMarshalJSONType(p) && !p.Implements(marshalTextType) { return c.bytesCode(typ, false) } } return c.sliceCode(typ) case reflect.Array: return c.arrayCode(typ) case reflect.Map: return c.mapCode(typ) case reflect.Struct: return c.structCode(typ, isPtr) case reflect.Interface: return c.interfaceCode(typ, false) case reflect.Int: return c.intCode(typ, false) case reflect.Int8: return c.int8Code(typ, false) case reflect.Int16: return c.int16Code(typ, false) case reflect.Int32: return c.int32Code(typ, false) case reflect.Int64: return c.int64Code(typ, false) case reflect.Uint: return c.uintCode(typ, false) case reflect.Uint8: return c.uint8Code(typ, false) case reflect.Uint16: return c.uint16Code(typ, false) case reflect.Uint32: return c.uint32Code(typ, false) case reflect.Uint64: return c.uint64Code(typ, false) case reflect.Uintptr: return c.uintCode(typ, false) case reflect.Float32: return c.float32Code(typ, false) case reflect.Float64: return c.float64Code(typ, false) case reflect.String: return c.stringCode(typ, false) case reflect.Bool: return c.boolCode(typ, false) } return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type(typ)} } const intSize = 32 << (^uint(0) >> 63) //nolint:unparam func (c *Compiler) intCode(typ *runtime.Type, isPtr bool) (*IntCode, error) { return &IntCode{typ: typ, bitSize: intSize, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) int8Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 8, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) int16Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 16, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) int32Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) int64Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) uintCode(typ *runtime.Type, isPtr bool) (*UintCode, error) { return &UintCode{typ: typ, bitSize: intSize, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) uint8Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 8, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) uint16Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 16, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) uint32Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) uint64Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) float32Code(typ *runtime.Type, isPtr bool) (*FloatCode, error) { return &FloatCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) float64Code(typ *runtime.Type, isPtr bool) (*FloatCode, error) { return &FloatCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) stringCode(typ *runtime.Type, isPtr bool) (*StringCode, error) { return &StringCode{typ: typ, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) boolCode(typ *runtime.Type, isPtr bool) (*BoolCode, error) { return &BoolCode{typ: typ, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) intStringCode(typ *runtime.Type) (*IntCode, error) { return &IntCode{typ: typ, bitSize: intSize, isString: true}, nil } //nolint:unparam func (c *Compiler) int8StringCode(typ *runtime.Type) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 8, isString: true}, nil } //nolint:unparam func (c *Compiler) int16StringCode(typ *runtime.Type) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 16, isString: true}, nil } //nolint:unparam func (c *Compiler) int32StringCode(typ *runtime.Type) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 32, isString: true}, nil } //nolint:unparam func (c *Compiler) int64StringCode(typ *runtime.Type) (*IntCode, error) { return &IntCode{typ: typ, bitSize: 64, isString: true}, nil } //nolint:unparam func (c *Compiler) uintStringCode(typ *runtime.Type) (*UintCode, error) { return &UintCode{typ: typ, bitSize: intSize, isString: true}, nil } //nolint:unparam func (c *Compiler) uint8StringCode(typ *runtime.Type) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 8, isString: true}, nil } //nolint:unparam func (c *Compiler) uint16StringCode(typ *runtime.Type) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 16, isString: true}, nil } //nolint:unparam func (c *Compiler) uint32StringCode(typ *runtime.Type) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 32, isString: true}, nil } //nolint:unparam func (c *Compiler) uint64StringCode(typ *runtime.Type) (*UintCode, error) { return &UintCode{typ: typ, bitSize: 64, isString: true}, nil } //nolint:unparam func (c *Compiler) bytesCode(typ *runtime.Type, isPtr bool) (*BytesCode, error) { return &BytesCode{typ: typ, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) interfaceCode(typ *runtime.Type, isPtr bool) (*InterfaceCode, error) { return &InterfaceCode{typ: typ, isPtr: isPtr}, nil } //nolint:unparam func (c *Compiler) marshalJSONCode(typ *runtime.Type) (*MarshalJSONCode, error) { return &MarshalJSONCode{ typ: typ, isAddrForMarshaler: c.isPtrMarshalJSONType(typ), isNilableType: c.isNilableType(typ), isMarshalerContext: typ.Implements(marshalJSONContextType) || runtime.PtrTo(typ).Implements(marshalJSONContextType), }, nil } //nolint:unparam func (c *Compiler) marshalTextCode(typ *runtime.Type) (*MarshalTextCode, error) { return &MarshalTextCode{ typ: typ, isAddrForMarshaler: c.isPtrMarshalTextType(typ), isNilableType: c.isNilableType(typ), }, nil } func (c *Compiler) ptrCode(typ *runtime.Type) (*PtrCode, error) { code, err := c.typeToCodeWithPtr(typ.Elem(), true) if err != nil { return nil, err } ptr, ok := code.(*PtrCode) if ok { return &PtrCode{typ: typ, value: ptr.value, ptrNum: ptr.ptrNum + 1}, nil } return &PtrCode{typ: typ, value: code, ptrNum: 1}, nil } func (c *Compiler) sliceCode(typ *runtime.Type) (*SliceCode, error) { elem := typ.Elem() code, err := c.listElemCode(elem) if err != nil { return nil, err } if code.Kind() == CodeKindStruct { structCode := code.(*StructCode) structCode.enableIndirect() } return &SliceCode{typ: typ, value: code}, nil } func (c *Compiler) arrayCode(typ *runtime.Type) (*ArrayCode, error) { elem := typ.Elem() code, err := c.listElemCode(elem) if err != nil { return nil, err } if code.Kind() == CodeKindStruct { structCode := code.(*StructCode) structCode.enableIndirect() } return &ArrayCode{typ: typ, value: code}, nil } func (c *Compiler) mapCode(typ *runtime.Type) (*MapCode, error) { keyCode, err := c.mapKeyCode(typ.Key()) if err != nil { return nil, err } valueCode, err := c.mapValueCode(typ.Elem()) if err != nil { return nil, err } if valueCode.Kind() == CodeKindStruct { structCode := valueCode.(*StructCode) structCode.enableIndirect() } return &MapCode{typ: typ, key: keyCode, value: valueCode}, nil } func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) { switch { case c.implementsMarshalJSONType(typ) || c.implementsMarshalJSONType(runtime.PtrTo(typ)): return c.marshalJSONCode(typ) case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType): return c.marshalTextCode(typ) case typ.Kind() == reflect.Map: return c.ptrCode(runtime.PtrTo(typ)) default: // isPtr was originally used to indicate whether the type of top level is pointer. // However, since the slice/array element is a specification that can get the pointer address, explicitly set isPtr to true. // See here for related issues: https://github.com/goccy/go-json/issues/370 code, err := c.typeToCodeWithPtr(typ, true) if err != nil { return nil, err } ptr, ok := code.(*PtrCode) if ok { if ptr.value.Kind() == CodeKindMap { ptr.ptrNum++ } } return code, nil } } func (c *Compiler) mapKeyCode(typ *runtime.Type) (Code, error) { switch { case c.implementsMarshalText(typ): return c.marshalTextCode(typ) } switch typ.Kind() { case reflect.Ptr: return c.ptrCode(typ) case reflect.String: return c.stringCode(typ, false) case reflect.Int: return c.intStringCode(typ) case reflect.Int8: return c.int8StringCode(typ) case reflect.Int16: return c.int16StringCode(typ) case reflect.Int32: return c.int32StringCode(typ) case reflect.Int64: return c.int64StringCode(typ) case reflect.Uint: return c.uintStringCode(typ) case reflect.Uint8: return c.uint8StringCode(typ) case reflect.Uint16: return c.uint16StringCode(typ) case reflect.Uint32: return c.uint32StringCode(typ) case reflect.Uint64: return c.uint64StringCode(typ) case reflect.Uintptr: return c.uintStringCode(typ) } return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type(typ)} } func (c *Compiler) mapValueCode(typ *runtime.Type) (Code, error) { switch typ.Kind() { case reflect.Map: return c.ptrCode(runtime.PtrTo(typ)) default: code, err := c.typeToCodeWithPtr(typ, false) if err != nil { return nil, err } ptr, ok := code.(*PtrCode) if ok { if ptr.value.Kind() == CodeKindMap { ptr.ptrNum++ } } return code, nil } } func (c *Compiler) structCode(typ *runtime.Type, isPtr bool) (*StructCode, error) { typeptr := uintptr(unsafe.Pointer(typ)) if code, exists := c.structTypeToCode[typeptr]; exists { derefCode := *code derefCode.isRecursive = true return &derefCode, nil } indirect := runtime.IfaceIndir(typ) code := &StructCode{typ: typ, isPtr: isPtr, isIndirect: indirect} c.structTypeToCode[typeptr] = code fieldNum := typ.NumField() tags := c.typeToStructTags(typ) fields := []*StructFieldCode{} for i, tag := range tags { isOnlyOneFirstField := i == 0 && fieldNum == 1 field, err := c.structFieldCode(code, tag, isPtr, isOnlyOneFirstField) if err != nil { return nil, err } if field.isAnonymous { structCode := field.getAnonymousStruct() if structCode != nil { structCode.removeFieldsByTags(tags) if c.isAssignableIndirect(field, isPtr) { if indirect { structCode.isIndirect = true } else { structCode.isIndirect = false } } } } else { structCode := field.getStruct() if structCode != nil { if indirect { // if parent is indirect type, set child indirect property to true structCode.isIndirect = true } else { // 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. structCode.isIndirect = false } } } fields = append(fields, field) } fieldMap := c.getFieldMap(fields) duplicatedFieldMap := c.getDuplicatedFieldMap(fieldMap) code.fields = c.filteredDuplicatedFields(fields, duplicatedFieldMap) if !code.disableIndirectConversion && !indirect && isPtr { code.enableIndirect() } delete(c.structTypeToCode, typeptr) return code, nil } func toElemType(t *runtime.Type) *runtime.Type { for t.Kind() == reflect.Ptr { t = t.Elem() } return t } func (c *Compiler) structFieldCode(structCode *StructCode, tag *runtime.StructTag, isPtr, isOnlyOneFirstField bool) (*StructFieldCode, error) { field := tag.Field fieldType := runtime.Type2RType(field.Type) isIndirectSpecialCase := isPtr && isOnlyOneFirstField fieldCode := &StructFieldCode{ typ: fieldType, key: tag.Key, tag: tag, offset: field.Offset, isAnonymous: field.Anonymous && !tag.IsTaggedKey && toElemType(fieldType).Kind() == reflect.Struct, isTaggedKey: tag.IsTaggedKey, isNilableType: c.isNilableType(fieldType), isNilCheck: true, } switch { case c.isMovePointerPositionFromHeadToFirstMarshalJSONFieldCase(fieldType, isIndirectSpecialCase): code, err := c.marshalJSONCode(fieldType) if err != nil { return nil, err } fieldCode.value = code fieldCode.isAddrForMarshaler = true fieldCode.isNilCheck = false structCode.isIndirect = false structCode.disableIndirectConversion = true case c.isMovePointerPositionFromHeadToFirstMarshalTextFieldCase(fieldType, isIndirectSpecialCase): code, err := c.marshalTextCode(fieldType) if err != nil { return nil, err } fieldCode.value = code fieldCode.isAddrForMarshaler = true fieldCode.isNilCheck = false structCode.isIndirect = false structCode.disableIndirectConversion = true case isPtr && c.isPtrMarshalJSONType(fieldType): // *struct{ field T } // func (*T) MarshalJSON() ([]byte, error) code, err := c.marshalJSONCode(fieldType) if err != nil { return nil, err } fieldCode.value = code fieldCode.isAddrForMarshaler = true fieldCode.isNilCheck = false case isPtr && c.isPtrMarshalTextType(fieldType): // *struct{ field T } // func (*T) MarshalText() ([]byte, error) code, err := c.marshalTextCode(fieldType) if err != nil { return nil, err } fieldCode.value = code fieldCode.isAddrForMarshaler = true fieldCode.isNilCheck = false default: code, err := c.typeToCodeWithPtr(fieldType, isPtr) if err != nil { return nil, err } switch code.Kind() { case CodeKindPtr, CodeKindInterface: fieldCode.isNextOpPtrType = true } fieldCode.value = code } return fieldCode, nil } func (c *Compiler) isAssignableIndirect(fieldCode *StructFieldCode, isPtr bool) bool { if isPtr { return false } codeType := fieldCode.value.Kind() if codeType == CodeKindMarshalJSON { return false } if codeType == CodeKindMarshalText { return false } return true } func (c *Compiler) getFieldMap(fields []*StructFieldCode) map[string][]*StructFieldCode { fieldMap := map[string][]*StructFieldCode{} for _, field := range fields { if field.isAnonymous { for k, v := range c.getAnonymousFieldMap(field) { fieldMap[k] = append(fieldMap[k], v...) } continue } fieldMap[field.key] = append(fieldMap[field.key], field) } return fieldMap } func (c *Compiler) getAnonymousFieldMap(field *StructFieldCode) map[string][]*StructFieldCode { fieldMap := map[string][]*StructFieldCode{} structCode := field.getAnonymousStruct() if structCode == nil || structCode.isRecursive { fieldMap[field.key] = append(fieldMap[field.key], field) return fieldMap } for k, v := range c.getFieldMapFromAnonymousParent(structCode.fields) { fieldMap[k] = append(fieldMap[k], v...) } return fieldMap } func (c *Compiler) getFieldMapFromAnonymousParent(fields []*StructFieldCode) map[string][]*StructFieldCode { fieldMap := map[string][]*StructFieldCode{} for _, field := range fields { if field.isAnonymous { for k, v := range c.getAnonymousFieldMap(field) { // Do not handle tagged key when embedding more than once for _, vv := range v { vv.isTaggedKey = false } fieldMap[k] = append(fieldMap[k], v...) } continue } fieldMap[field.key] = append(fieldMap[field.key], field) } return fieldMap } func (c *Compiler) getDuplicatedFieldMap(fieldMap map[string][]*StructFieldCode) map[*StructFieldCode]struct{} { duplicatedFieldMap := map[*StructFieldCode]struct{}{} for _, fields := range fieldMap { if len(fields) == 1 { continue } if c.isTaggedKeyOnly(fields) { for _, field := range fields { if field.isTaggedKey { continue } duplicatedFieldMap[field] = struct{}{} } } else { for _, field := range fields { duplicatedFieldMap[field] = struct{}{} } } } return duplicatedFieldMap } func (c *Compiler) filteredDuplicatedFields(fields []*StructFieldCode, duplicatedFieldMap map[*StructFieldCode]struct{}) []*StructFieldCode { filteredFields := make([]*StructFieldCode, 0, len(fields)) for _, field := range fields { if field.isAnonymous { structCode := field.getAnonymousStruct() if structCode != nil && !structCode.isRecursive { structCode.fields = c.filteredDuplicatedFields(structCode.fields, duplicatedFieldMap) if len(structCode.fields) > 0 { filteredFields = append(filteredFields, field) } continue } } if _, exists := duplicatedFieldMap[field]; exists { continue } filteredFields = append(filteredFields, field) } return filteredFields } func (c *Compiler) isTaggedKeyOnly(fields []*StructFieldCode) bool { var taggedKeyFieldCount int for _, field := range fields { if field.isTaggedKey { taggedKeyFieldCount++ } } return taggedKeyFieldCount == 1 } func (c *Compiler) typeToStructTags(typ *runtime.Type) runtime.StructTags { tags := runtime.StructTags{} fieldNum := typ.NumField() for i := 0; i < fieldNum; i++ { field := typ.Field(i) if runtime.IsIgnoredStructField(field) { continue } tags = append(tags, runtime.StructTagFromField(field)) } return tags } // *struct{ field T } => struct { field *T } // func (*T) MarshalJSON() ([]byte, error) func (c *Compiler) isMovePointerPositionFromHeadToFirstMarshalJSONFieldCase(typ *runtime.Type, isIndirectSpecialCase bool) bool { return isIndirectSpecialCase && !c.isNilableType(typ) && c.isPtrMarshalJSONType(typ) } // *struct{ field T } => struct { field *T } // func (*T) MarshalText() ([]byte, error) func (c *Compiler) isMovePointerPositionFromHeadToFirstMarshalTextFieldCase(typ *runtime.Type, isIndirectSpecialCase bool) bool { return isIndirectSpecialCase && !c.isNilableType(typ) && c.isPtrMarshalTextType(typ) } func (c *Compiler) implementsMarshalJSON(typ *runtime.Type) bool { if !c.implementsMarshalJSONType(typ) { return false } if typ.Kind() != reflect.Ptr { return true } // type kind is reflect.Ptr if !c.implementsMarshalJSONType(typ.Elem()) { return true } // needs to dereference return false } func (c *Compiler) implementsMarshalText(typ *runtime.Type) bool { if !typ.Implements(marshalTextType) { return false } if typ.Kind() != reflect.Ptr { return true } // type kind is reflect.Ptr if !typ.Elem().Implements(marshalTextType) { return true } // needs to dereference return false } func (c *Compiler) isNilableType(typ *runtime.Type) bool { if !runtime.IfaceIndir(typ) { return true } switch typ.Kind() { case reflect.Ptr: return true case reflect.Map: return true case reflect.Func: return true default: return false } } func (c *Compiler) implementsMarshalJSONType(typ *runtime.Type) bool { return typ.Implements(marshalJSONType) || typ.Implements(marshalJSONContextType) } func (c *Compiler) isPtrMarshalJSONType(typ *runtime.Type) bool { return !c.implementsMarshalJSONType(typ) && c.implementsMarshalJSONType(runtime.PtrTo(typ)) } func (c *Compiler) isPtrMarshalTextType(typ *runtime.Type) bool { return !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) } func (c *Compiler) codeToOpcode(ctx *compileContext, typ *runtime.Type, code Code) *Opcode { codes := code.ToOpcode(ctx) codes.Last().Next = newEndOp(ctx, typ) c.linkRecursiveCode(ctx) return codes.First() } func (c *Compiler) linkRecursiveCode(ctx *compileContext) { recursiveCodes := map[uintptr]*CompiledCode{} for _, recursive := range *ctx.recursiveCodes { typeptr := uintptr(unsafe.Pointer(recursive.Type)) codes := ctx.structTypeToCodes[typeptr] if recursiveCode, ok := recursiveCodes[typeptr]; ok { *recursive.Jmp = *recursiveCode continue } code := copyOpcode(codes.First()) code.Op = code.Op.PtrHeadToHead() lastCode := newEndOp(&compileContext{}, recursive.Type) lastCode.Op = OpRecursiveEnd // OpRecursiveEnd must set before call TotalLength code.End.Next = lastCode totalLength := code.TotalLength() // Idx, ElemIdx, Length must set after call TotalLength lastCode.Idx = uint32((totalLength + 1) * uintptrSize) lastCode.ElemIdx = lastCode.Idx + uintptrSize lastCode.Length = lastCode.Idx + 2*uintptrSize // extend length to alloc slot for elemIdx + length curTotalLength := uintptr(recursive.TotalLength()) + 3 nextTotalLength := uintptr(totalLength) + 3 compiled := recursive.Jmp compiled.Code = code compiled.CurLen = curTotalLength compiled.NextLen = nextTotalLength compiled.Linked = true recursiveCodes[typeptr] = compiled } } golang-github-goccy-go-json-0.10.3/internal/encoder/compiler_norace.go000066400000000000000000000015211463555276600257430ustar00rootroot00000000000000//go:build !race // +build !race package encoder func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) { if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr { codeSet, err := compileToGetCodeSetSlowPath(typeptr) if err != nil { return nil, err } return getFilteredCodeSetIfNeeded(ctx, codeSet) } index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift if codeSet := cachedOpcodeSets[index]; codeSet != nil { filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) if err != nil { return nil, err } return filtered, nil } codeSet, err := newCompiler().compile(typeptr) if err != nil { return nil, err } filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) if err != nil { return nil, err } cachedOpcodeSets[index] = codeSet return filtered, nil } golang-github-goccy-go-json-0.10.3/internal/encoder/compiler_race.go000066400000000000000000000017461463555276600254170ustar00rootroot00000000000000//go:build race // +build race package encoder import ( "sync" ) var setsMu sync.RWMutex func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) { if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr { codeSet, err := compileToGetCodeSetSlowPath(typeptr) if err != nil { return nil, err } return getFilteredCodeSetIfNeeded(ctx, codeSet) } index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift setsMu.RLock() if codeSet := cachedOpcodeSets[index]; codeSet != nil { filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) if err != nil { setsMu.RUnlock() return nil, err } setsMu.RUnlock() return filtered, nil } setsMu.RUnlock() codeSet, err := newCompiler().compile(typeptr) if err != nil { return nil, err } filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) if err != nil { return nil, err } setsMu.Lock() cachedOpcodeSets[index] = codeSet setsMu.Unlock() return filtered, nil } golang-github-goccy-go-json-0.10.3/internal/encoder/context.go000066400000000000000000000035121463555276600242700ustar00rootroot00000000000000package encoder import ( "context" "sync" "unsafe" "github.com/goccy/go-json/internal/runtime" ) type compileContext struct { opcodeIndex uint32 ptrIndex int indent uint32 escapeKey bool structTypeToCodes map[uintptr]Opcodes recursiveCodes *Opcodes } func (c *compileContext) incIndent() { c.indent++ } func (c *compileContext) decIndent() { c.indent-- } func (c *compileContext) incIndex() { c.incOpcodeIndex() c.incPtrIndex() } func (c *compileContext) decIndex() { c.decOpcodeIndex() c.decPtrIndex() } func (c *compileContext) incOpcodeIndex() { c.opcodeIndex++ } func (c *compileContext) decOpcodeIndex() { c.opcodeIndex-- } func (c *compileContext) incPtrIndex() { c.ptrIndex++ } func (c *compileContext) decPtrIndex() { c.ptrIndex-- } const ( bufSize = 1024 ) var ( runtimeContextPool = sync.Pool{ New: func() interface{} { return &RuntimeContext{ 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 uint32 Prefix []byte IndentStr []byte Option *Option } func (c *RuntimeContext) Init(p uintptr, codelen int) { if len(c.Ptrs) < codelen { c.Ptrs = make([]uintptr, codelen) } c.Ptrs[0] = p c.KeepRefs = c.KeepRefs[:0] c.SeenPtr = c.SeenPtr[:0] c.BaseIndent = 0 } func (c *RuntimeContext) Ptr() uintptr { header := (*runtime.SliceHeader)(unsafe.Pointer(&c.Ptrs)) return uintptr(header.Data) } func TakeRuntimeContext() *RuntimeContext { return runtimeContextPool.Get().(*RuntimeContext) } func ReleaseRuntimeContext(ctx *RuntimeContext) { runtimeContextPool.Put(ctx) } golang-github-goccy-go-json-0.10.3/internal/encoder/decode_rune.go000066400000000000000000000072671463555276600250730ustar00rootroot00000000000000package encoder import "unicode/utf8" const ( // The default lowest and highest continuation byte. locb = 128 //0b10000000 hicb = 191 //0b10111111 // These names of these constants are chosen to give nice alignment in the // table below. The first nibble is an index into acceptRanges or F for // special one-byte cases. The second nibble is the Rune length or the // Status for the special one-byte case. xx = 0xF1 // invalid: size 1 as = 0xF0 // ASCII: size 1 s1 = 0x02 // accept 0, size 2 s2 = 0x13 // accept 1, size 3 s3 = 0x03 // accept 0, size 3 s4 = 0x23 // accept 2, size 3 s5 = 0x34 // accept 3, size 4 s6 = 0x04 // accept 0, size 4 s7 = 0x44 // accept 4, size 4 ) // first is information about the first byte in a UTF-8 sequence. var first = [256]uint8{ // 1 2 3 4 5 6 7 8 9 A B C D E F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F // 1 2 3 4 5 6 7 8 9 A B C D E F xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF } const ( lineSep = byte(168) //'\u2028' paragraphSep = byte(169) //'\u2029' ) type decodeRuneState int const ( validUTF8State decodeRuneState = iota runeErrorState lineSepState paragraphSepState ) func decodeRuneInString(s string) (decodeRuneState, int) { n := len(s) s0 := s[0] x := first[s0] if x >= as { // The following code simulates an additional check for x == xx and // handling the ASCII and invalid cases accordingly. This mask-and-or // approach prevents an additional branch. mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF. if rune(s[0])&^mask|utf8.RuneError&mask == utf8.RuneError { return runeErrorState, 1 } return validUTF8State, 1 } sz := int(x & 7) if n < sz { return runeErrorState, 1 } s1 := s[1] switch x >> 4 { case 0: if s1 < locb || hicb < s1 { return runeErrorState, 1 } case 1: if s1 < 0xA0 || hicb < s1 { return runeErrorState, 1 } case 2: if s1 < locb || 0x9F < s1 { return runeErrorState, 1 } case 3: if s1 < 0x90 || hicb < s1 { return runeErrorState, 1 } case 4: if s1 < locb || 0x8F < s1 { return runeErrorState, 1 } } if sz <= 2 { return validUTF8State, 2 } s2 := s[2] if s2 < locb || hicb < s2 { return runeErrorState, 1 } if sz <= 3 { // separator character prefixes: [2]byte{226, 128} if s0 == 226 && s1 == 128 { switch s2 { case lineSep: return lineSepState, 3 case paragraphSep: return paragraphSepState, 3 } } return validUTF8State, 3 } s3 := s[3] if s3 < locb || hicb < s3 { return runeErrorState, 1 } return validUTF8State, 4 } golang-github-goccy-go-json-0.10.3/internal/encoder/encode_opcode_test.go000066400000000000000000000006171463555276600264340ustar00rootroot00000000000000package encoder import ( "testing" "unsafe" ) func TestDumpOpcode(t *testing.T) { ctx := TakeRuntimeContext() defer ReleaseRuntimeContext(ctx) var v interface{} = 1 header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) codeSet, err := CompileToGetCodeSet(ctx, typeptr) if err != nil { t.Fatal(err) } codeSet.EscapeKeyCode.Dump() } golang-github-goccy-go-json-0.10.3/internal/encoder/encoder.go000066400000000000000000000341031463555276600242230ustar00rootroot00000000000000package encoder import ( "bytes" "encoding" "encoding/base64" "encoding/json" "fmt" "math" "reflect" "strconv" "strings" "sync" "unsafe" "github.com/goccy/go-json/internal/errors" "github.com/goccy/go-json/internal/runtime" ) func (t OpType) IsMultipleOpHead() bool { switch t { case OpStructHead: return true case OpStructHeadSlice: return true case OpStructHeadArray: return true case OpStructHeadMap: return true case OpStructHeadStruct: return true case OpStructHeadOmitEmpty: return true case OpStructHeadOmitEmptySlice: return true case OpStructHeadOmitEmptyArray: return true case OpStructHeadOmitEmptyMap: return true case OpStructHeadOmitEmptyStruct: return true case OpStructHeadSlicePtr: return true case OpStructHeadOmitEmptySlicePtr: return true case OpStructHeadArrayPtr: return true case OpStructHeadOmitEmptyArrayPtr: return true case OpStructHeadMapPtr: return true case OpStructHeadOmitEmptyMapPtr: return true } return false } func (t OpType) IsMultipleOpField() bool { switch t { case OpStructField: return true case OpStructFieldSlice: return true case OpStructFieldArray: return true case OpStructFieldMap: return true case OpStructFieldStruct: return true case OpStructFieldOmitEmpty: return true case OpStructFieldOmitEmptySlice: return true case OpStructFieldOmitEmptyArray: return true case OpStructFieldOmitEmptyMap: return true case OpStructFieldOmitEmptyStruct: return true case OpStructFieldSlicePtr: return true case OpStructFieldOmitEmptySlicePtr: return true case OpStructFieldArrayPtr: return true case OpStructFieldOmitEmptyArrayPtr: return true case OpStructFieldMapPtr: return true case OpStructFieldOmitEmptyMapPtr: return true } return false } type OpcodeSet struct { Type *runtime.Type NoescapeKeyCode *Opcode EscapeKeyCode *Opcode InterfaceNoescapeKeyCode *Opcode InterfaceEscapeKeyCode *Opcode CodeLength int EndCode *Opcode Code Code QueryCache map[string]*OpcodeSet cacheMu sync.RWMutex } func (s *OpcodeSet) getQueryCache(hash string) *OpcodeSet { s.cacheMu.RLock() codeSet := s.QueryCache[hash] s.cacheMu.RUnlock() return codeSet } func (s *OpcodeSet) setQueryCache(hash string, codeSet *OpcodeSet) { s.cacheMu.Lock() s.QueryCache[hash] = codeSet s.cacheMu.Unlock() } type CompiledCode struct { Code *Opcode Linked bool // whether recursive code already have linked CurLen uintptr NextLen uintptr } const StartDetectingCyclesAfter = 1000 func Load(base uintptr, idx uintptr) uintptr { addr := base + idx return **(**uintptr)(unsafe.Pointer(&addr)) } func Store(base uintptr, idx uintptr, p uintptr) { addr := base + idx **(**uintptr)(unsafe.Pointer(&addr)) = p } func LoadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { addr := base + idx p := **(**uintptr)(unsafe.Pointer(&addr)) if p == 0 { return 0 } return PtrToPtr(p) /* for i := 0; i < ptrNum; i++ { if p == 0 { return p } p = PtrToPtr(p) } return p */ } func PtrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } func PtrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func PtrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func PtrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func PtrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } func PtrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } func PtrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } func PtrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } 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++ { if p == 0 { return 0 } p = PtrToPtr(p) } return p } func PtrToUnsafePtr(p uintptr) unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&p)) } func PtrToInterface(code *Opcode, p uintptr) interface{} { return *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.Type, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) } func ErrUnsupportedValue(code *Opcode, ptr uintptr) *errors.UnsupportedValueError { v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.Type, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&ptr)), })) return &errors.UnsupportedValueError{ Value: reflect.ValueOf(v), Str: fmt.Sprintf("encountered a cycle via %s", code.Type), } } func ErrUnsupportedFloat(v float64) *errors.UnsupportedValueError { return &errors.UnsupportedValueError{ Value: reflect.ValueOf(v), Str: strconv.FormatFloat(v, 'g', -1, 64), } } func ErrMarshalerWithCode(code *Opcode, err error) *errors.MarshalerError { return &errors.MarshalerError{ Type: runtime.RType2Type(code.Type), Err: err, } } type emptyInterface struct { typ *runtime.Type ptr unsafe.Pointer } type MapItem struct { Key []byte Value []byte } type Mapslice struct { Items []MapItem } func (m *Mapslice) Len() int { return len(m.Items) } func (m *Mapslice) Less(i, j int) bool { return bytes.Compare(m.Items[i].Key, m.Items[j].Key) < 0 } func (m *Mapslice) Swap(i, j int) { m.Items[i], m.Items[j] = m.Items[j], m.Items[i] } //nolint:structcheck,unused type mapIter struct { key unsafe.Pointer elem unsafe.Pointer t unsafe.Pointer h unsafe.Pointer buckets unsafe.Pointer bptr unsafe.Pointer overflow unsafe.Pointer oldoverflow unsafe.Pointer startBucket uintptr offset uint8 wrapped bool B uint8 i uint8 bucket uintptr checkBucket uintptr } type MapContext struct { Start int First int Idx int Slice *Mapslice Buf []byte Len int Iter mapIter } var mapContextPool = sync.Pool{ New: func() interface{} { return &MapContext{ Slice: &Mapslice{}, } }, } func NewMapContext(mapLen int, unorderedMap bool) *MapContext { ctx := mapContextPool.Get().(*MapContext) if !unorderedMap { if len(ctx.Slice.Items) < mapLen { ctx.Slice.Items = make([]MapItem, mapLen) } else { ctx.Slice.Items = ctx.Slice.Items[:mapLen] } } ctx.Buf = ctx.Buf[:0] ctx.Iter = mapIter{} ctx.Idx = 0 ctx.Len = mapLen return ctx } func ReleaseMapContext(c *MapContext) { mapContextPool.Put(c) } //go:linkname MapIterInit runtime.mapiterinit //go:noescape func MapIterInit(mapType *runtime.Type, m unsafe.Pointer, it *mapIter) //go:linkname MapIterKey reflect.mapiterkey //go:noescape func MapIterKey(it *mapIter) unsafe.Pointer //go:linkname MapIterNext reflect.mapiternext //go:noescape func MapIterNext(it *mapIter) //go:linkname MapLen reflect.maplen //go:noescape func MapLen(m unsafe.Pointer) int func AppendByteSlice(_ *RuntimeContext, b []byte, src []byte) []byte { if src == nil { return append(b, `null`...) } encodedLen := base64.StdEncoding.EncodedLen(len(src)) b = append(b, '"') pos := len(b) remainLen := cap(b[pos:]) var buf []byte if remainLen > encodedLen { buf = b[pos : pos+encodedLen] } else { buf = make([]byte, encodedLen) } base64.StdEncoding.Encode(buf, src) return append(append(b, buf...), '"') } func AppendFloat32(_ *RuntimeContext, b []byte, v float32) []byte { f64 := float64(v) abs := math.Abs(f64) fmt := byte('f') // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. if abs != 0 { f32 := float32(abs) if f32 < 1e-6 || f32 >= 1e21 { fmt = 'e' } } return strconv.AppendFloat(b, f64, fmt, -1, 32) } 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. if abs != 0 { if abs < 1e-6 || abs >= 1e21 { fmt = 'e' } } return strconv.AppendFloat(b, v, fmt, -1, 64) } func AppendBool(_ *RuntimeContext, b []byte, v bool) []byte { if v { return append(b, "true"...) } return append(b, "false"...) } var ( floatTable = [256]bool{ '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true, '.': true, 'e': true, 'E': true, '+': true, '-': true, } ) func AppendNumber(_ *RuntimeContext, b []byte, n json.Number) ([]byte, error) { if len(n) == 0 { return append(b, '0'), nil } for i := 0; i < len(n); i++ { if !floatTable[n[i]] { return nil, fmt.Errorf("json: invalid number literal %q", n) } } b = append(b, n...) return b, nil } func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { rv := reflect.ValueOf(v) // convert by dynamic interface type if (code.Flags & AddrForMarshalerFlags) != 0 { if rv.CanAddr() { rv = rv.Addr() } else { newV := reflect.New(rv.Type()) newV.Elem().Set(rv) rv = newV } } v = rv.Interface() var bb []byte if (code.Flags & MarshalerContextFlags) != 0 { marshaler, ok := v.(marshalerContext) if !ok { return AppendNull(ctx, b), nil } stdctx := ctx.Option.Context if ctx.Option.Flag&FieldQueryOption != 0 { stdctx = SetFieldQueryToContext(stdctx, code.FieldQuery) } b, err := marshaler.MarshalJSON(stdctx) 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, (ctx.Option.Flag&HTMLEscapeOption) != 0) if err != nil { return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} } ctx.MarshalBuf = marshalBuf return compactedBuf, nil } func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { rv := reflect.ValueOf(v) // convert by dynamic interface type if (code.Flags & AddrForMarshalerFlags) != 0 { if rv.CanAddr() { rv = rv.Addr() } else { newV := reflect.New(rv.Type()) newV.Elem().Set(rv) rv = newV } } v = rv.Interface() 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), int(ctx.BaseIndent+code.Indent)), string(ctx.IndentStr), (ctx.Option.Flag&HTMLEscapeOption) != 0, ) if err != nil { return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} } ctx.MarshalBuf = marshalBuf return indentedBuf, nil } func AppendMarshalText(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { rv := reflect.ValueOf(v) // convert by dynamic interface type if (code.Flags & AddrForMarshalerFlags) != 0 { if rv.CanAddr() { rv = rv.Addr() } else { newV := reflect.New(rv.Type()) newV.Elem().Set(rv) rv = newV } } v = rv.Interface() marshaler, ok := v.(encoding.TextMarshaler) if !ok { return AppendNull(ctx, b), nil } bytes, err := marshaler.MarshalText() if err != nil { return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} } return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil } func AppendMarshalTextIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { rv := reflect.ValueOf(v) // convert by dynamic interface type if (code.Flags & AddrForMarshalerFlags) != 0 { if rv.CanAddr() { rv = rv.Addr() } else { newV := reflect.New(rv.Type()) newV.Elem().Set(rv) rv = newV } } v = rv.Interface() marshaler, ok := v.(encoding.TextMarshaler) if !ok { return AppendNull(ctx, b), nil } bytes, err := marshaler.MarshalText() if err != nil { return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} } return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil } func AppendNull(_ *RuntimeContext, b []byte) []byte { return append(b, "null"...) } func AppendComma(_ *RuntimeContext, b []byte) []byte { return append(b, ',') } func AppendCommaIndent(_ *RuntimeContext, b []byte) []byte { return append(b, ',', '\n') } func AppendStructEnd(_ *RuntimeContext, b []byte) []byte { return append(b, '}', ',') } 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 := uint32(0); i < indentNum; i++ { b = append(b, ctx.IndentStr...) } return append(b, '}', ',', '\n') } func AppendIndent(ctx *RuntimeContext, b []byte, indent uint32) []byte { b = append(b, ctx.Prefix...) indentNum := ctx.BaseIndent + indent for i := uint32(0); i < indentNum; i++ { b = append(b, ctx.IndentStr...) } return b } func IsNilForMarshaler(v interface{}) bool { rv := reflect.ValueOf(v) switch rv.Kind() { case reflect.Bool: return !rv.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return rv.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return rv.Uint() == 0 case reflect.Float32, reflect.Float64: return math.Float64bits(rv.Float()) == 0 case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Func: return rv.IsNil() case reflect.Slice: return rv.IsNil() || rv.Len() == 0 case reflect.String: return rv.Len() == 0 } return false } golang-github-goccy-go-json-0.10.3/internal/encoder/indent.go000066400000000000000000000120541463555276600240660ustar00rootroot00000000000000package encoder import ( "bytes" "fmt" "github.com/goccy/go-json/internal/errors" ) func takeIndentSrcRuntimeContext(src []byte) (*RuntimeContext, []byte) { ctx := TakeRuntimeContext() buf := ctx.Buf[:0] buf = append(append(buf, src...), nul) ctx.Buf = buf return ctx, buf } func Indent(buf *bytes.Buffer, src []byte, prefix, indentStr string) error { if len(src) == 0 { return errors.ErrUnexpectedEndOfJSON("", 0) } srcCtx, srcBuf := takeIndentSrcRuntimeContext(src) dstCtx := TakeRuntimeContext() dst := dstCtx.Buf[:0] dst, err := indentAndWrite(buf, dst, srcBuf, prefix, indentStr) if err != nil { ReleaseRuntimeContext(srcCtx) ReleaseRuntimeContext(dstCtx) return err } dstCtx.Buf = dst ReleaseRuntimeContext(srcCtx) ReleaseRuntimeContext(dstCtx) return nil } func indentAndWrite(buf *bytes.Buffer, dst []byte, src []byte, prefix, indentStr string) ([]byte, error) { dst, err := doIndent(dst, src, prefix, indentStr, false) if err != nil { return nil, err } if _, err := buf.Write(dst); err != nil { return nil, err } return dst, nil } func doIndent(dst, src []byte, prefix, indentStr string, escape bool) ([]byte, error) { buf, cursor, err := indentValue(dst, src, 0, 0, []byte(prefix), []byte(indentStr), escape) if err != nil { return nil, err } if err := validateEndBuf(src, cursor); err != nil { return nil, err } return buf, nil } func indentValue( dst []byte, src []byte, indentNum int, cursor int64, prefix []byte, indentBytes []byte, escape bool) ([]byte, int64, error) { for { switch src[cursor] { case ' ', '\t', '\n', '\r': cursor++ continue case '{': return indentObject(dst, src, indentNum, cursor, prefix, indentBytes, escape) case '}': return nil, 0, errors.ErrSyntax("unexpected character '}'", cursor) case '[': return indentArray(dst, src, indentNum, cursor, prefix, indentBytes, escape) case ']': return nil, 0, errors.ErrSyntax("unexpected character ']'", cursor) case '"': return compactString(dst, src, cursor, escape) case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return compactNumber(dst, src, cursor) case 't': return compactTrue(dst, src, cursor) case 'f': return compactFalse(dst, src, cursor) case 'n': return compactNull(dst, src, cursor) default: return nil, 0, errors.ErrSyntax(fmt.Sprintf("unexpected character '%c'", src[cursor]), cursor) } } } func indentObject( dst []byte, src []byte, indentNum int, cursor int64, prefix []byte, indentBytes []byte, escape bool) ([]byte, int64, error) { if src[cursor] == '{' { dst = append(dst, '{') } else { return nil, 0, errors.ErrExpected("expected { character for object value", cursor) } cursor = skipWhiteSpace(src, cursor+1) if src[cursor] == '}' { dst = append(dst, '}') return dst, cursor + 1, nil } indentNum++ var err error for { dst = append(append(dst, '\n'), prefix...) for i := 0; i < indentNum; i++ { dst = append(dst, indentBytes...) } cursor = skipWhiteSpace(src, cursor) dst, cursor, err = compactString(dst, src, cursor, escape) if err != nil { return nil, 0, err } cursor = skipWhiteSpace(src, cursor) if src[cursor] != ':' { return nil, 0, errors.ErrSyntax( fmt.Sprintf("invalid character '%c' after object key", src[cursor]), cursor+1, ) } dst = append(dst, ':', ' ') dst, cursor, err = indentValue(dst, src, indentNum, cursor+1, prefix, indentBytes, escape) if err != nil { return nil, 0, err } cursor = skipWhiteSpace(src, cursor) switch src[cursor] { case '}': dst = append(append(dst, '\n'), prefix...) for i := 0; i < indentNum-1; i++ { dst = append(dst, indentBytes...) } dst = append(dst, '}') cursor++ return dst, cursor, nil case ',': dst = append(dst, ',') default: return nil, 0, errors.ErrSyntax( fmt.Sprintf("invalid character '%c' after object key:value pair", src[cursor]), cursor+1, ) } cursor++ } } func indentArray( dst []byte, src []byte, indentNum int, cursor int64, prefix []byte, indentBytes []byte, escape bool) ([]byte, int64, error) { if src[cursor] == '[' { dst = append(dst, '[') } else { return nil, 0, errors.ErrExpected("expected [ character for array value", cursor) } cursor = skipWhiteSpace(src, cursor+1) if src[cursor] == ']' { dst = append(dst, ']') return dst, cursor + 1, nil } indentNum++ var err error for { dst = append(append(dst, '\n'), prefix...) for i := 0; i < indentNum; i++ { dst = append(dst, indentBytes...) } dst, cursor, err = indentValue(dst, src, indentNum, cursor, prefix, indentBytes, escape) if err != nil { return nil, 0, err } cursor = skipWhiteSpace(src, cursor) switch src[cursor] { case ']': dst = append(append(dst, '\n'), prefix...) for i := 0; i < indentNum-1; i++ { dst = append(dst, indentBytes...) } dst = append(dst, ']') cursor++ return dst, cursor, nil case ',': dst = append(dst, ',') default: return nil, 0, errors.ErrSyntax( fmt.Sprintf("invalid character '%c' after array value", src[cursor]), cursor+1, ) } cursor++ } } golang-github-goccy-go-json-0.10.3/internal/encoder/int.go000066400000000000000000000121711463555276600233770ustar00rootroot00000000000000// This files's processing codes are inspired by https://github.com/segmentio/encoding. // The license notation is as follows. // // # MIT License // // Copyright (c) 2019 Segment.io, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. package encoder import ( "unsafe" ) var endianness int func init() { var b [2]byte *(*uint16)(unsafe.Pointer(&b)) = uint16(0xABCD) switch b[0] { case 0xCD: endianness = 0 // LE case 0xAB: endianness = 1 // BE default: panic("could not determine endianness") } } // "00010203...96979899" cast to []uint16 var intLELookup = [100]uint16{ 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 0x3630, 0x3730, 0x3830, 0x3930, 0x3031, 0x3131, 0x3231, 0x3331, 0x3431, 0x3531, 0x3631, 0x3731, 0x3831, 0x3931, 0x3032, 0x3132, 0x3232, 0x3332, 0x3432, 0x3532, 0x3632, 0x3732, 0x3832, 0x3932, 0x3033, 0x3133, 0x3233, 0x3333, 0x3433, 0x3533, 0x3633, 0x3733, 0x3833, 0x3933, 0x3034, 0x3134, 0x3234, 0x3334, 0x3434, 0x3534, 0x3634, 0x3734, 0x3834, 0x3934, 0x3035, 0x3135, 0x3235, 0x3335, 0x3435, 0x3535, 0x3635, 0x3735, 0x3835, 0x3935, 0x3036, 0x3136, 0x3236, 0x3336, 0x3436, 0x3536, 0x3636, 0x3736, 0x3836, 0x3936, 0x3037, 0x3137, 0x3237, 0x3337, 0x3437, 0x3537, 0x3637, 0x3737, 0x3837, 0x3937, 0x3038, 0x3138, 0x3238, 0x3338, 0x3438, 0x3538, 0x3638, 0x3738, 0x3838, 0x3938, 0x3039, 0x3139, 0x3239, 0x3339, 0x3439, 0x3539, 0x3639, 0x3739, 0x3839, 0x3939, } var intBELookup = [100]uint16{ 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x3130, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, 0x3239, 0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, 0x3336, 0x3337, 0x3338, 0x3339, 0x3430, 0x3431, 0x3432, 0x3433, 0x3434, 0x3435, 0x3436, 0x3437, 0x3438, 0x3439, 0x3530, 0x3531, 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, 0x3537, 0x3538, 0x3539, 0x3630, 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x3830, 0x3831, 0x3832, 0x3833, 0x3834, 0x3835, 0x3836, 0x3837, 0x3838, 0x3839, 0x3930, 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, 0x3938, 0x3939, } var intLookup = [2]*[100]uint16{&intLELookup, &intBELookup} func numMask(numBitSize uint8) uint64 { return 1<>(code.NumBitSize-1))&1 == 1 if !negative { if n < 10 { return append(out, byte(n+'0')) } else if n < 100 { u := intLELookup[n] return append(out, byte(u), byte(u>>8)) } } else { n = -n & mask } lookup := intLookup[endianness] var b [22]byte u := (*[11]uint16)(unsafe.Pointer(&b)) i := 11 for n >= 100 { j := n % 100 n /= 100 i-- u[i] = lookup[j] } i-- u[i] = lookup[n] i *= 2 // convert to byte index if n < 10 { i++ // remove leading zero } if negative { i-- b[i] = '-' } return append(out, b[i:]...) } func AppendUint(_ *RuntimeContext, out []byte, p uintptr, code *Opcode) []byte { var u64 uint64 switch code.NumBitSize { case 8: u64 = (uint64)(**(**uint8)(unsafe.Pointer(&p))) case 16: u64 = (uint64)(**(**uint16)(unsafe.Pointer(&p))) case 32: u64 = (uint64)(**(**uint32)(unsafe.Pointer(&p))) case 64: u64 = **(**uint64)(unsafe.Pointer(&p)) } mask := numMask(code.NumBitSize) n := u64 & mask if n < 10 { return append(out, byte(n+'0')) } else if n < 100 { u := intLELookup[n] return append(out, byte(u), byte(u>>8)) } lookup := intLookup[endianness] var b [22]byte u := (*[11]uint16)(unsafe.Pointer(&b)) i := 11 for n >= 100 { j := n % 100 n /= 100 i-- u[i] = lookup[j] } i-- u[i] = lookup[n] i *= 2 // convert to byte index if n < 10 { i++ // remove leading zero } return append(out, b[i:]...) } golang-github-goccy-go-json-0.10.3/internal/encoder/map112.go000066400000000000000000000002461463555276600236060ustar00rootroot00000000000000//go:build !go1.13 // +build !go1.13 package encoder import "unsafe" //go:linkname MapIterValue reflect.mapitervalue func MapIterValue(it *mapIter) unsafe.Pointer golang-github-goccy-go-json-0.10.3/internal/encoder/map113.go000066400000000000000000000002431463555276600236040ustar00rootroot00000000000000//go:build go1.13 // +build go1.13 package encoder import "unsafe" //go:linkname MapIterValue reflect.mapiterelem func MapIterValue(it *mapIter) unsafe.Pointer golang-github-goccy-go-json-0.10.3/internal/encoder/opcode.go000066400000000000000000000407371463555276600240670ustar00rootroot00000000000000package encoder import ( "bytes" "fmt" "sort" "strings" "unsafe" "github.com/goccy/go-json/internal/runtime" ) 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 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 Type *runtime.Type // go type Jmp *CompiledCode // for recursive call FieldQuery *FieldQuery // field query for Interface / MarshalJSON / MarshalText ElemIdx uint32 // offset to access array/slice elem Length uint32 // offset to access slice length or array length Indent uint32 // indent number Size uint32 // array/slice elem size DisplayIdx uint32 // opcode index DisplayKey string // key text to display } func (c *Opcode) Validate() error { var prevIdx uint32 for code := c; !code.IsEnd(); { if prevIdx != 0 { if code.DisplayIdx != prevIdx+1 { return fmt.Errorf( "invalid index. previous display index is %d but next is %d. dump = %s", prevIdx, code.DisplayIdx, c.Dump(), ) } } prevIdx = code.DisplayIdx code = code.IterNext() } return nil } func (c *Opcode) IterNext() *Opcode { if c == nil { return nil } switch c.Op.CodeType() { case CodeArrayElem, CodeSliceElem, CodeMapKey: return c.End default: return c.Next } } func (c *Opcode) IsEnd() bool { if c == nil { return true } return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd } func (c *Opcode) MaxIdx() uint32 { max := uint32(0) for _, value := range []uint32{ c.Idx, c.ElemIdx, c.Length, c.Size, } { if max < value { max = value } } return max } func (c *Opcode) ToHeaderType(isString bool) OpType { switch c.Op { case OpInt: if isString { return OpStructHeadIntString } return OpStructHeadInt case OpIntPtr: if isString { return OpStructHeadIntPtrString } return OpStructHeadIntPtr case OpUint: if isString { return OpStructHeadUintString } return OpStructHeadUint case OpUintPtr: if isString { return OpStructHeadUintPtrString } return OpStructHeadUintPtr case OpFloat32: if isString { return OpStructHeadFloat32String } return OpStructHeadFloat32 case OpFloat32Ptr: if isString { return OpStructHeadFloat32PtrString } return OpStructHeadFloat32Ptr case OpFloat64: if isString { return OpStructHeadFloat64String } return OpStructHeadFloat64 case OpFloat64Ptr: if isString { return OpStructHeadFloat64PtrString } return OpStructHeadFloat64Ptr case OpString: if isString { return OpStructHeadStringString } return OpStructHeadString case OpStringPtr: if isString { return OpStructHeadStringPtrString } return OpStructHeadStringPtr case OpNumber: if isString { return OpStructHeadNumberString } return OpStructHeadNumber case OpNumberPtr: if isString { return OpStructHeadNumberPtrString } return OpStructHeadNumberPtr case OpBool: if isString { return OpStructHeadBoolString } return OpStructHeadBool case OpBoolPtr: if isString { return OpStructHeadBoolPtrString } return OpStructHeadBoolPtr case OpBytes: return OpStructHeadBytes case OpBytesPtr: return OpStructHeadBytesPtr case OpMap: return OpStructHeadMap case OpMapPtr: c.Op = OpMap return OpStructHeadMapPtr case OpArray: return OpStructHeadArray case OpArrayPtr: c.Op = OpArray return OpStructHeadArrayPtr case OpSlice: return OpStructHeadSlice case OpSlicePtr: c.Op = OpSlice return OpStructHeadSlicePtr case OpMarshalJSON: return OpStructHeadMarshalJSON case OpMarshalJSONPtr: return OpStructHeadMarshalJSONPtr case OpMarshalText: return OpStructHeadMarshalText case OpMarshalTextPtr: return OpStructHeadMarshalTextPtr } return OpStructHead } func (c *Opcode) ToFieldType(isString bool) OpType { switch c.Op { case OpInt: if isString { return OpStructFieldIntString } return OpStructFieldInt case OpIntPtr: if isString { return OpStructFieldIntPtrString } return OpStructFieldIntPtr case OpUint: if isString { return OpStructFieldUintString } return OpStructFieldUint case OpUintPtr: if isString { return OpStructFieldUintPtrString } return OpStructFieldUintPtr case OpFloat32: if isString { return OpStructFieldFloat32String } return OpStructFieldFloat32 case OpFloat32Ptr: if isString { return OpStructFieldFloat32PtrString } return OpStructFieldFloat32Ptr case OpFloat64: if isString { return OpStructFieldFloat64String } return OpStructFieldFloat64 case OpFloat64Ptr: if isString { return OpStructFieldFloat64PtrString } return OpStructFieldFloat64Ptr case OpString: if isString { return OpStructFieldStringString } return OpStructFieldString case OpStringPtr: if isString { return OpStructFieldStringPtrString } return OpStructFieldStringPtr case OpNumber: if isString { return OpStructFieldNumberString } return OpStructFieldNumber case OpNumberPtr: if isString { return OpStructFieldNumberPtrString } return OpStructFieldNumberPtr case OpBool: if isString { return OpStructFieldBoolString } return OpStructFieldBool case OpBoolPtr: if isString { return OpStructFieldBoolPtrString } return OpStructFieldBoolPtr case OpBytes: return OpStructFieldBytes case OpBytesPtr: return OpStructFieldBytesPtr case OpMap: return OpStructFieldMap case OpMapPtr: c.Op = OpMap return OpStructFieldMapPtr case OpArray: return OpStructFieldArray case OpArrayPtr: c.Op = OpArray return OpStructFieldArrayPtr case OpSlice: return OpStructFieldSlice case OpSlicePtr: c.Op = OpSlice return OpStructFieldSlicePtr case OpMarshalJSON: return OpStructFieldMarshalJSON case OpMarshalJSONPtr: return OpStructFieldMarshalJSONPtr case OpMarshalText: return OpStructFieldMarshalText case OpMarshalTextPtr: return OpStructFieldMarshalTextPtr } return OpStructField } func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode { return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ)) } func opcodeOffset(idx int) uint32 { return uint32(idx) * uintptrSize } func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode { addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{}) return *(**Opcode)(unsafe.Pointer(&addr)) } func copyOpcode(code *Opcode) *Opcode { codeNum := ToEndCode(code).DisplayIdx + 1 codeSlice := make([]Opcode, codeNum) head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data) ptr := head c := code for { *ptr = Opcode{ Op: c.Op, Key: c.Key, PtrNum: c.PtrNum, NumBitSize: c.NumBitSize, Flags: c.Flags, Idx: c.Idx, Offset: c.Offset, Type: c.Type, FieldQuery: c.FieldQuery, DisplayIdx: c.DisplayIdx, DisplayKey: c.DisplayKey, ElemIdx: c.ElemIdx, Length: c.Length, Size: c.Size, Indent: c.Indent, Jmp: c.Jmp, } if c.End != nil { ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx) } if c.NextField != nil { ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx) } if c.Next != nil { ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx) } if c.IsEnd() { break } ptr = getCodeAddrByIdx(head, c.DisplayIdx+1) c = c.IterNext() } return head } func setTotalLengthToInterfaceOp(code *Opcode) { for c := code; !c.IsEnd(); { if c.Op == OpInterface || c.Op == OpInterfacePtr { c.Length = uint32(code.TotalLength()) } c = c.IterNext() } } func ToEndCode(code *Opcode) *Opcode { c := code for !c.IsEnd() { c = c.IterNext() } 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, typ *runtime.Type, op OpType, next *Opcode) *Opcode { return &Opcode{ Op: op, Idx: opcodeOffset(ctx.ptrIndex), Next: next, Type: typ, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, } } func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode { return newOpCodeWithNext(ctx, typ, OpEnd, nil) } func (c *Opcode) TotalLength() int { var idx int code := c for !code.IsEnd() { maxIdx := int(code.MaxIdx() / uintptrSize) if idx < maxIdx { idx = maxIdx } if code.Op == OpRecursiveEnd { break } code = code.IterNext() } maxIdx := int(code.MaxIdx() / uintptrSize) if idx < maxIdx { idx = maxIdx } return idx + 1 } func (c *Opcode) dumpHead(code *Opcode) string { var length uint32 if code.Op.CodeType() == CodeArrayHead { length = code.Length } else { length = code.Length / uintptrSize } return fmt.Sprintf( `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`, code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, code.ElemIdx/uintptrSize, length, ) } func (c *Opcode) dumpMapHead(code *Opcode) string { return fmt.Sprintf( `[%03d]%s%s ([idx:%d])`, code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, ) } func (c *Opcode) dumpMapEnd(code *Opcode) string { return fmt.Sprintf( `[%03d]%s%s ([idx:%d])`, code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, ) } func (c *Opcode) dumpElem(code *Opcode) string { var length uint32 if code.Op.CodeType() == CodeArrayElem { length = code.Length } else { length = code.Length / uintptrSize } return fmt.Sprintf( `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`, code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, code.ElemIdx/uintptrSize, length, code.Size, ) } func (c *Opcode) dumpField(code *Opcode) string { return fmt.Sprintf( `[%03d]%s%s ([idx:%d][key:%s][offset:%d])`, code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, code.DisplayKey, code.Offset, ) } func (c *Opcode) dumpKey(code *Opcode) string { return fmt.Sprintf( `[%03d]%s%s ([idx:%d])`, code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, ) } func (c *Opcode) dumpValue(code *Opcode) string { return fmt.Sprintf( `[%03d]%s%s ([idx:%d])`, code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, ) } func (c *Opcode) Dump() string { codes := []string{} for code := c; !code.IsEnd(); { switch code.Op.CodeType() { case CodeSliceHead: codes = append(codes, c.dumpHead(code)) code = code.Next case CodeMapHead: codes = append(codes, c.dumpMapHead(code)) code = code.Next case CodeArrayElem, CodeSliceElem: codes = append(codes, c.dumpElem(code)) code = code.End case CodeMapKey: codes = append(codes, c.dumpKey(code)) code = code.End case CodeMapValue: codes = append(codes, c.dumpValue(code)) code = code.Next case CodeMapEnd: codes = append(codes, c.dumpMapEnd(code)) code = code.Next case CodeStructField: codes = append(codes, c.dumpField(code)) code = code.Next case CodeStructEnd: codes = append(codes, c.dumpField(code)) code = code.Next default: codes = append(codes, fmt.Sprintf( "[%03d]%s%s ([idx:%d])", code.DisplayIdx, strings.Repeat("-", int(code.Indent)), code.Op, code.Idx/uintptrSize, )) code = code.Next } } return strings.Join(codes, "\n") } func (c *Opcode) DumpDOT() string { type edge struct { from, to *Opcode label string weight int } var edges []edge b := &bytes.Buffer{} fmt.Fprintf(b, "digraph \"%p\" {\n", c.Type) fmt.Fprintln(b, "mclimit=1.5;\nrankdir=TD;\nordering=out;\nnode[shape=box];") for code := c; !code.IsEnd(); { label := code.Op.String() fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, label) if p := code.Next; p != nil { edges = append(edges, edge{ from: code, to: p, label: "Next", weight: 10, }) } if p := code.NextField; p != nil { edges = append(edges, edge{ from: code, to: p, label: "NextField", weight: 2, }) } if p := code.End; p != nil { edges = append(edges, edge{ from: code, to: p, label: "End", weight: 1, }) } if p := code.Jmp; p != nil { edges = append(edges, edge{ from: code, to: p.Code, label: "Jmp", weight: 1, }) } switch code.Op.CodeType() { case CodeSliceHead: code = code.Next case CodeMapHead: code = code.Next case CodeArrayElem, CodeSliceElem: code = code.End case CodeMapKey: code = code.End case CodeMapValue: code = code.Next case CodeMapEnd: code = code.Next case CodeStructField: code = code.Next case CodeStructEnd: code = code.Next default: code = code.Next } if code.IsEnd() { fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, code.Op.String()) } } sort.Slice(edges, func(i, j int) bool { return edges[i].to.DisplayIdx < edges[j].to.DisplayIdx }) for _, e := range edges { fmt.Fprintf(b, "\"%p\" -> \"%p\" [label=%q][weight=%d];\n", e.from, e.to, e.label, e.weight) } fmt.Fprint(b, "}") return b.String() } func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode { idx := opcodeOffset(ctx.ptrIndex) ctx.incPtrIndex() elemIdx := opcodeOffset(ctx.ptrIndex) ctx.incPtrIndex() length := opcodeOffset(ctx.ptrIndex) return &Opcode{ Op: OpSlice, Type: typ, Idx: idx, DisplayIdx: ctx.opcodeIndex, ElemIdx: elemIdx, Length: length, Indent: ctx.indent, } } func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode { return &Opcode{ Op: OpSliceElem, Type: typ, Idx: head.Idx, DisplayIdx: ctx.opcodeIndex, ElemIdx: head.ElemIdx, Length: head.Length, Indent: ctx.indent, Size: uint32(size), } } func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode { idx := opcodeOffset(ctx.ptrIndex) ctx.incPtrIndex() elemIdx := opcodeOffset(ctx.ptrIndex) return &Opcode{ Op: OpArray, Type: typ, Idx: idx, DisplayIdx: ctx.opcodeIndex, ElemIdx: elemIdx, Indent: ctx.indent, Length: uint32(alen), } } func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode { return &Opcode{ Op: OpArrayElem, Type: typ, Idx: head.Idx, DisplayIdx: ctx.opcodeIndex, ElemIdx: head.ElemIdx, Length: uint32(length), Indent: ctx.indent, Size: uint32(size), } } func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode { idx := opcodeOffset(ctx.ptrIndex) ctx.incPtrIndex() return &Opcode{ Op: OpMap, Type: typ, Idx: idx, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, } } func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { return &Opcode{ Op: OpMapKey, Type: typ, Idx: head.Idx, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, } } func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { return &Opcode{ Op: OpMapValue, Type: typ, Idx: head.Idx, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, } } func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { return &Opcode{ Op: OpMapEnd, Type: typ, Idx: head.Idx, DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, Next: newEndOp(ctx, typ), } } func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode { return &Opcode{ Op: OpRecursive, Type: typ, Idx: opcodeOffset(ctx.ptrIndex), Next: newEndOp(ctx, typ), DisplayIdx: ctx.opcodeIndex, Indent: ctx.indent, Jmp: jmp, } } golang-github-goccy-go-json-0.10.3/internal/encoder/option.go000066400000000000000000000013571463555276600241210ustar00rootroot00000000000000package encoder import ( "context" "io" ) type OptionFlag uint8 const ( HTMLEscapeOption OptionFlag = 1 << iota IndentOption UnorderedMapOption DebugOption ColorizeOption ContextOption NormalizeUTF8Option FieldQueryOption ) type Option struct { Flag OptionFlag ColorScheme *ColorScheme Context context.Context DebugOut io.Writer DebugDOTOut io.WriteCloser } 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 ) golang-github-goccy-go-json-0.10.3/internal/encoder/optype.go000066400000000000000000001051621463555276600241300ustar00rootroot00000000000000// Code generated by internal/cmd/generator. DO NOT EDIT! package encoder import ( "strings" ) type CodeType int const ( CodeOp CodeType = 0 CodeArrayHead CodeType = 1 CodeArrayElem CodeType = 2 CodeSliceHead CodeType = 3 CodeSliceElem CodeType = 4 CodeMapHead CodeType = 5 CodeMapKey CodeType = 6 CodeMapValue CodeType = 7 CodeMapEnd CodeType = 8 CodeRecursive CodeType = 9 CodeStructField CodeType = 10 CodeStructEnd CodeType = 11 ) var opTypeStrings = [400]string{ "End", "Interface", "Ptr", "SliceElem", "SliceEnd", "ArrayElem", "ArrayEnd", "MapKey", "MapValue", "MapEnd", "Recursive", "RecursivePtr", "RecursiveEnd", "InterfaceEnd", "Int", "Uint", "Float32", "Float64", "Bool", "String", "Bytes", "Number", "Array", "Map", "Slice", "Struct", "MarshalJSON", "MarshalText", "IntString", "UintString", "Float32String", "Float64String", "BoolString", "StringString", "NumberString", "IntPtr", "UintPtr", "Float32Ptr", "Float64Ptr", "BoolPtr", "StringPtr", "BytesPtr", "NumberPtr", "ArrayPtr", "MapPtr", "SlicePtr", "MarshalJSONPtr", "MarshalTextPtr", "InterfacePtr", "IntPtrString", "UintPtrString", "Float32PtrString", "Float64PtrString", "BoolPtrString", "StringPtrString", "NumberPtrString", "StructHeadInt", "StructHeadOmitEmptyInt", "StructPtrHeadInt", "StructPtrHeadOmitEmptyInt", "StructHeadUint", "StructHeadOmitEmptyUint", "StructPtrHeadUint", "StructPtrHeadOmitEmptyUint", "StructHeadFloat32", "StructHeadOmitEmptyFloat32", "StructPtrHeadFloat32", "StructPtrHeadOmitEmptyFloat32", "StructHeadFloat64", "StructHeadOmitEmptyFloat64", "StructPtrHeadFloat64", "StructPtrHeadOmitEmptyFloat64", "StructHeadBool", "StructHeadOmitEmptyBool", "StructPtrHeadBool", "StructPtrHeadOmitEmptyBool", "StructHeadString", "StructHeadOmitEmptyString", "StructPtrHeadString", "StructPtrHeadOmitEmptyString", "StructHeadBytes", "StructHeadOmitEmptyBytes", "StructPtrHeadBytes", "StructPtrHeadOmitEmptyBytes", "StructHeadNumber", "StructHeadOmitEmptyNumber", "StructPtrHeadNumber", "StructPtrHeadOmitEmptyNumber", "StructHeadArray", "StructHeadOmitEmptyArray", "StructPtrHeadArray", "StructPtrHeadOmitEmptyArray", "StructHeadMap", "StructHeadOmitEmptyMap", "StructPtrHeadMap", "StructPtrHeadOmitEmptyMap", "StructHeadSlice", "StructHeadOmitEmptySlice", "StructPtrHeadSlice", "StructPtrHeadOmitEmptySlice", "StructHeadStruct", "StructHeadOmitEmptyStruct", "StructPtrHeadStruct", "StructPtrHeadOmitEmptyStruct", "StructHeadMarshalJSON", "StructHeadOmitEmptyMarshalJSON", "StructPtrHeadMarshalJSON", "StructPtrHeadOmitEmptyMarshalJSON", "StructHeadMarshalText", "StructHeadOmitEmptyMarshalText", "StructPtrHeadMarshalText", "StructPtrHeadOmitEmptyMarshalText", "StructHeadIntString", "StructHeadOmitEmptyIntString", "StructPtrHeadIntString", "StructPtrHeadOmitEmptyIntString", "StructHeadUintString", "StructHeadOmitEmptyUintString", "StructPtrHeadUintString", "StructPtrHeadOmitEmptyUintString", "StructHeadFloat32String", "StructHeadOmitEmptyFloat32String", "StructPtrHeadFloat32String", "StructPtrHeadOmitEmptyFloat32String", "StructHeadFloat64String", "StructHeadOmitEmptyFloat64String", "StructPtrHeadFloat64String", "StructPtrHeadOmitEmptyFloat64String", "StructHeadBoolString", "StructHeadOmitEmptyBoolString", "StructPtrHeadBoolString", "StructPtrHeadOmitEmptyBoolString", "StructHeadStringString", "StructHeadOmitEmptyStringString", "StructPtrHeadStringString", "StructPtrHeadOmitEmptyStringString", "StructHeadNumberString", "StructHeadOmitEmptyNumberString", "StructPtrHeadNumberString", "StructPtrHeadOmitEmptyNumberString", "StructHeadIntPtr", "StructHeadOmitEmptyIntPtr", "StructPtrHeadIntPtr", "StructPtrHeadOmitEmptyIntPtr", "StructHeadUintPtr", "StructHeadOmitEmptyUintPtr", "StructPtrHeadUintPtr", "StructPtrHeadOmitEmptyUintPtr", "StructHeadFloat32Ptr", "StructHeadOmitEmptyFloat32Ptr", "StructPtrHeadFloat32Ptr", "StructPtrHeadOmitEmptyFloat32Ptr", "StructHeadFloat64Ptr", "StructHeadOmitEmptyFloat64Ptr", "StructPtrHeadFloat64Ptr", "StructPtrHeadOmitEmptyFloat64Ptr", "StructHeadBoolPtr", "StructHeadOmitEmptyBoolPtr", "StructPtrHeadBoolPtr", "StructPtrHeadOmitEmptyBoolPtr", "StructHeadStringPtr", "StructHeadOmitEmptyStringPtr", "StructPtrHeadStringPtr", "StructPtrHeadOmitEmptyStringPtr", "StructHeadBytesPtr", "StructHeadOmitEmptyBytesPtr", "StructPtrHeadBytesPtr", "StructPtrHeadOmitEmptyBytesPtr", "StructHeadNumberPtr", "StructHeadOmitEmptyNumberPtr", "StructPtrHeadNumberPtr", "StructPtrHeadOmitEmptyNumberPtr", "StructHeadArrayPtr", "StructHeadOmitEmptyArrayPtr", "StructPtrHeadArrayPtr", "StructPtrHeadOmitEmptyArrayPtr", "StructHeadMapPtr", "StructHeadOmitEmptyMapPtr", "StructPtrHeadMapPtr", "StructPtrHeadOmitEmptyMapPtr", "StructHeadSlicePtr", "StructHeadOmitEmptySlicePtr", "StructPtrHeadSlicePtr", "StructPtrHeadOmitEmptySlicePtr", "StructHeadMarshalJSONPtr", "StructHeadOmitEmptyMarshalJSONPtr", "StructPtrHeadMarshalJSONPtr", "StructPtrHeadOmitEmptyMarshalJSONPtr", "StructHeadMarshalTextPtr", "StructHeadOmitEmptyMarshalTextPtr", "StructPtrHeadMarshalTextPtr", "StructPtrHeadOmitEmptyMarshalTextPtr", "StructHeadInterfacePtr", "StructHeadOmitEmptyInterfacePtr", "StructPtrHeadInterfacePtr", "StructPtrHeadOmitEmptyInterfacePtr", "StructHeadIntPtrString", "StructHeadOmitEmptyIntPtrString", "StructPtrHeadIntPtrString", "StructPtrHeadOmitEmptyIntPtrString", "StructHeadUintPtrString", "StructHeadOmitEmptyUintPtrString", "StructPtrHeadUintPtrString", "StructPtrHeadOmitEmptyUintPtrString", "StructHeadFloat32PtrString", "StructHeadOmitEmptyFloat32PtrString", "StructPtrHeadFloat32PtrString", "StructPtrHeadOmitEmptyFloat32PtrString", "StructHeadFloat64PtrString", "StructHeadOmitEmptyFloat64PtrString", "StructPtrHeadFloat64PtrString", "StructPtrHeadOmitEmptyFloat64PtrString", "StructHeadBoolPtrString", "StructHeadOmitEmptyBoolPtrString", "StructPtrHeadBoolPtrString", "StructPtrHeadOmitEmptyBoolPtrString", "StructHeadStringPtrString", "StructHeadOmitEmptyStringPtrString", "StructPtrHeadStringPtrString", "StructPtrHeadOmitEmptyStringPtrString", "StructHeadNumberPtrString", "StructHeadOmitEmptyNumberPtrString", "StructPtrHeadNumberPtrString", "StructPtrHeadOmitEmptyNumberPtrString", "StructHead", "StructHeadOmitEmpty", "StructPtrHead", "StructPtrHeadOmitEmpty", "StructFieldInt", "StructFieldOmitEmptyInt", "StructEndInt", "StructEndOmitEmptyInt", "StructFieldUint", "StructFieldOmitEmptyUint", "StructEndUint", "StructEndOmitEmptyUint", "StructFieldFloat32", "StructFieldOmitEmptyFloat32", "StructEndFloat32", "StructEndOmitEmptyFloat32", "StructFieldFloat64", "StructFieldOmitEmptyFloat64", "StructEndFloat64", "StructEndOmitEmptyFloat64", "StructFieldBool", "StructFieldOmitEmptyBool", "StructEndBool", "StructEndOmitEmptyBool", "StructFieldString", "StructFieldOmitEmptyString", "StructEndString", "StructEndOmitEmptyString", "StructFieldBytes", "StructFieldOmitEmptyBytes", "StructEndBytes", "StructEndOmitEmptyBytes", "StructFieldNumber", "StructFieldOmitEmptyNumber", "StructEndNumber", "StructEndOmitEmptyNumber", "StructFieldArray", "StructFieldOmitEmptyArray", "StructEndArray", "StructEndOmitEmptyArray", "StructFieldMap", "StructFieldOmitEmptyMap", "StructEndMap", "StructEndOmitEmptyMap", "StructFieldSlice", "StructFieldOmitEmptySlice", "StructEndSlice", "StructEndOmitEmptySlice", "StructFieldStruct", "StructFieldOmitEmptyStruct", "StructEndStruct", "StructEndOmitEmptyStruct", "StructFieldMarshalJSON", "StructFieldOmitEmptyMarshalJSON", "StructEndMarshalJSON", "StructEndOmitEmptyMarshalJSON", "StructFieldMarshalText", "StructFieldOmitEmptyMarshalText", "StructEndMarshalText", "StructEndOmitEmptyMarshalText", "StructFieldIntString", "StructFieldOmitEmptyIntString", "StructEndIntString", "StructEndOmitEmptyIntString", "StructFieldUintString", "StructFieldOmitEmptyUintString", "StructEndUintString", "StructEndOmitEmptyUintString", "StructFieldFloat32String", "StructFieldOmitEmptyFloat32String", "StructEndFloat32String", "StructEndOmitEmptyFloat32String", "StructFieldFloat64String", "StructFieldOmitEmptyFloat64String", "StructEndFloat64String", "StructEndOmitEmptyFloat64String", "StructFieldBoolString", "StructFieldOmitEmptyBoolString", "StructEndBoolString", "StructEndOmitEmptyBoolString", "StructFieldStringString", "StructFieldOmitEmptyStringString", "StructEndStringString", "StructEndOmitEmptyStringString", "StructFieldNumberString", "StructFieldOmitEmptyNumberString", "StructEndNumberString", "StructEndOmitEmptyNumberString", "StructFieldIntPtr", "StructFieldOmitEmptyIntPtr", "StructEndIntPtr", "StructEndOmitEmptyIntPtr", "StructFieldUintPtr", "StructFieldOmitEmptyUintPtr", "StructEndUintPtr", "StructEndOmitEmptyUintPtr", "StructFieldFloat32Ptr", "StructFieldOmitEmptyFloat32Ptr", "StructEndFloat32Ptr", "StructEndOmitEmptyFloat32Ptr", "StructFieldFloat64Ptr", "StructFieldOmitEmptyFloat64Ptr", "StructEndFloat64Ptr", "StructEndOmitEmptyFloat64Ptr", "StructFieldBoolPtr", "StructFieldOmitEmptyBoolPtr", "StructEndBoolPtr", "StructEndOmitEmptyBoolPtr", "StructFieldStringPtr", "StructFieldOmitEmptyStringPtr", "StructEndStringPtr", "StructEndOmitEmptyStringPtr", "StructFieldBytesPtr", "StructFieldOmitEmptyBytesPtr", "StructEndBytesPtr", "StructEndOmitEmptyBytesPtr", "StructFieldNumberPtr", "StructFieldOmitEmptyNumberPtr", "StructEndNumberPtr", "StructEndOmitEmptyNumberPtr", "StructFieldArrayPtr", "StructFieldOmitEmptyArrayPtr", "StructEndArrayPtr", "StructEndOmitEmptyArrayPtr", "StructFieldMapPtr", "StructFieldOmitEmptyMapPtr", "StructEndMapPtr", "StructEndOmitEmptyMapPtr", "StructFieldSlicePtr", "StructFieldOmitEmptySlicePtr", "StructEndSlicePtr", "StructEndOmitEmptySlicePtr", "StructFieldMarshalJSONPtr", "StructFieldOmitEmptyMarshalJSONPtr", "StructEndMarshalJSONPtr", "StructEndOmitEmptyMarshalJSONPtr", "StructFieldMarshalTextPtr", "StructFieldOmitEmptyMarshalTextPtr", "StructEndMarshalTextPtr", "StructEndOmitEmptyMarshalTextPtr", "StructFieldInterfacePtr", "StructFieldOmitEmptyInterfacePtr", "StructEndInterfacePtr", "StructEndOmitEmptyInterfacePtr", "StructFieldIntPtrString", "StructFieldOmitEmptyIntPtrString", "StructEndIntPtrString", "StructEndOmitEmptyIntPtrString", "StructFieldUintPtrString", "StructFieldOmitEmptyUintPtrString", "StructEndUintPtrString", "StructEndOmitEmptyUintPtrString", "StructFieldFloat32PtrString", "StructFieldOmitEmptyFloat32PtrString", "StructEndFloat32PtrString", "StructEndOmitEmptyFloat32PtrString", "StructFieldFloat64PtrString", "StructFieldOmitEmptyFloat64PtrString", "StructEndFloat64PtrString", "StructEndOmitEmptyFloat64PtrString", "StructFieldBoolPtrString", "StructFieldOmitEmptyBoolPtrString", "StructEndBoolPtrString", "StructEndOmitEmptyBoolPtrString", "StructFieldStringPtrString", "StructFieldOmitEmptyStringPtrString", "StructEndStringPtrString", "StructEndOmitEmptyStringPtrString", "StructFieldNumberPtrString", "StructFieldOmitEmptyNumberPtrString", "StructEndNumberPtrString", "StructEndOmitEmptyNumberPtrString", "StructField", "StructFieldOmitEmpty", "StructEnd", "StructEndOmitEmpty", } type OpType uint16 const ( OpEnd OpType = 0 OpInterface OpType = 1 OpPtr OpType = 2 OpSliceElem OpType = 3 OpSliceEnd OpType = 4 OpArrayElem OpType = 5 OpArrayEnd OpType = 6 OpMapKey OpType = 7 OpMapValue OpType = 8 OpMapEnd OpType = 9 OpRecursive OpType = 10 OpRecursivePtr OpType = 11 OpRecursiveEnd OpType = 12 OpInterfaceEnd 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 ) func (t OpType) String() string { if int(t) >= 400 { return "" } return opTypeStrings[int(t)] } func (t OpType) CodeType() CodeType { if strings.Contains(t.String(), "Struct") { if strings.Contains(t.String(), "End") { return CodeStructEnd } return CodeStructField } switch t { case OpArray, OpArrayPtr: return CodeArrayHead case OpArrayElem: return CodeArrayElem case OpSlice, OpSlicePtr: return CodeSliceHead case OpSliceElem: return CodeSliceElem case OpMap, OpMapPtr: return CodeMapHead case OpMapKey: return CodeMapKey case OpMapValue: return CodeMapValue case OpMapEnd: return CodeMapEnd } return CodeOp } func (t OpType) HeadToPtrHead() OpType { if strings.Index(t.String(), "PtrHead") > 0 { return t } idx := strings.Index(t.String(), "Head") if idx == -1 { return t } suffix := "PtrHead" + t.String()[idx+len("Head"):] const toPtrOffset = 2 if strings.Contains(OpType(int(t)+toPtrOffset).String(), suffix) { return OpType(int(t) + toPtrOffset) } return t } func (t OpType) HeadToOmitEmptyHead() OpType { const toOmitEmptyOffset = 1 if strings.Contains(OpType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") { return OpType(int(t) + toOmitEmptyOffset) } return t } func (t OpType) PtrHeadToHead() OpType { idx := strings.Index(t.String(), "PtrHead") if idx == -1 { return t } suffix := t.String()[idx+len("Ptr"):] const toPtrOffset = 2 if strings.Contains(OpType(int(t)-toPtrOffset).String(), suffix) { return OpType(int(t) - toPtrOffset) } return t } func (t OpType) FieldToEnd() OpType { idx := strings.Index(t.String(), "Field") if idx == -1 { return t } suffix := t.String()[idx+len("Field"):] if suffix == "" || suffix == "OmitEmpty" { return t } const toEndOffset = 2 if strings.Contains(OpType(int(t)+toEndOffset).String(), "End"+suffix) { return OpType(int(t) + toEndOffset) } return t } func (t OpType) FieldToOmitEmptyField() OpType { const toOmitEmptyOffset = 1 if strings.Contains(OpType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") { return OpType(int(t) + toOmitEmptyOffset) } return t } golang-github-goccy-go-json-0.10.3/internal/encoder/query.go000066400000000000000000000055211463555276600237530ustar00rootroot00000000000000package encoder import ( "context" "fmt" "reflect" ) var ( Marshal func(interface{}) ([]byte, error) Unmarshal func([]byte, interface{}) error ) type FieldQuery struct { Name string Fields []*FieldQuery hash string } func (q *FieldQuery) Hash() string { if q.hash != "" { return q.hash } b, _ := Marshal(q) q.hash = string(b) return q.hash } func (q *FieldQuery) MarshalJSON() ([]byte, error) { if q.Name != "" { if len(q.Fields) > 0 { return Marshal(map[string][]*FieldQuery{q.Name: q.Fields}) } return Marshal(q.Name) } return Marshal(q.Fields) } func (q *FieldQuery) QueryString() (FieldQueryString, error) { b, err := Marshal(q) if err != nil { return "", err } return FieldQueryString(b), nil } type FieldQueryString string func (s FieldQueryString) Build() (*FieldQuery, error) { var query interface{} if err := Unmarshal([]byte(s), &query); err != nil { return nil, err } return s.build(reflect.ValueOf(query)) } func (s FieldQueryString) build(v reflect.Value) (*FieldQuery, error) { switch v.Type().Kind() { case reflect.String: return s.buildString(v) case reflect.Map: return s.buildMap(v) case reflect.Slice: return s.buildSlice(v) case reflect.Interface: return s.build(reflect.ValueOf(v.Interface())) } return nil, fmt.Errorf("failed to build field query") } func (s FieldQueryString) buildString(v reflect.Value) (*FieldQuery, error) { b := []byte(v.String()) switch b[0] { case '[', '{': var query interface{} if err := Unmarshal(b, &query); err != nil { return nil, err } if str, ok := query.(string); ok { return &FieldQuery{Name: str}, nil } return s.build(reflect.ValueOf(query)) } return &FieldQuery{Name: string(b)}, nil } func (s FieldQueryString) buildSlice(v reflect.Value) (*FieldQuery, error) { fields := make([]*FieldQuery, 0, v.Len()) for i := 0; i < v.Len(); i++ { def, err := s.build(v.Index(i)) if err != nil { return nil, err } fields = append(fields, def) } return &FieldQuery{Fields: fields}, nil } func (s FieldQueryString) buildMap(v reflect.Value) (*FieldQuery, error) { keys := v.MapKeys() if len(keys) != 1 { return nil, fmt.Errorf("failed to build field query object") } key := keys[0] if key.Type().Kind() != reflect.String { return nil, fmt.Errorf("failed to build field query. invalid object key type") } name := key.String() def, err := s.build(v.MapIndex(key)) if err != nil { return nil, err } return &FieldQuery{ Name: name, Fields: def.Fields, }, nil } type queryKey struct{} func FieldQueryFromContext(ctx context.Context) *FieldQuery { query := ctx.Value(queryKey{}) if query == nil { return nil } q, ok := query.(*FieldQuery) if !ok { return nil } return q } func SetFieldQueryToContext(ctx context.Context, query *FieldQuery) context.Context { return context.WithValue(ctx, queryKey{}, query) } golang-github-goccy-go-json-0.10.3/internal/encoder/string.go000066400000000000000000000271401463555276600241150ustar00rootroot00000000000000// This files's string processing codes are inspired by https://github.com/segmentio/encoding. // The license notation is as follows. // // # MIT License // // Copyright (c) 2019 Segment.io, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. package encoder import ( "math/bits" "reflect" "unsafe" ) const ( lsb = 0x0101010101010101 msb = 0x8080808080808080 ) var hex = "0123456789abcdef" //nolint:govet func stringToUint64Slice(s string) []uint64 { return *(*[]uint64)(unsafe.Pointer(&reflect.SliceHeader{ Data: ((*reflect.StringHeader)(unsafe.Pointer(&s))).Data, Len: len(s) / 8, Cap: len(s) / 8, })) } func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte { if ctx.Option.Flag&HTMLEscapeOption != 0 { if ctx.Option.Flag&NormalizeUTF8Option != 0 { return appendNormalizedHTMLString(buf, s) } return appendHTMLString(buf, s) } if ctx.Option.Flag&NormalizeUTF8Option != 0 { return appendNormalizedString(buf, s) } return appendString(buf, s) } func appendNormalizedHTMLString(buf []byte, s string) []byte { valLen := len(s) if valLen == 0 { return append(buf, `""`...) } buf = append(buf, '"') var ( i, j int ) if valLen >= 8 { chunks := stringToUint64Slice(s) for _, n := range chunks { // combine masks before checking for the MSB of each byte. We include // `n` in the mask to check whether any of the *input* byte MSBs were // set (i.e. the byte was outside the ASCII range). mask := n | (n - (lsb * 0x20)) | ((n ^ (lsb * '"')) - lsb) | ((n ^ (lsb * '\\')) - lsb) | ((n ^ (lsb * '<')) - lsb) | ((n ^ (lsb * '>')) - lsb) | ((n ^ (lsb * '&')) - lsb) if (mask & msb) != 0 { j = bits.TrailingZeros64(mask&msb) / 8 goto ESCAPE_END } } for i := len(chunks) * 8; i < valLen; i++ { if needEscapeHTMLNormalizeUTF8[s[i]] { j = i goto ESCAPE_END } } // no found any escape characters. return append(append(buf, s...), '"') } ESCAPE_END: for j < valLen { c := s[j] if !needEscapeHTMLNormalizeUTF8[c] { // fast path: most of the time, printable ascii characters are used j++ continue } switch c { case '\\', '"': buf = append(buf, s[i:j]...) buf = append(buf, '\\', c) i = j + 1 j = j + 1 continue case '\n': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'n') i = j + 1 j = j + 1 continue case '\r': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'r') i = j + 1 j = j + 1 continue case '\t': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 't') i = j + 1 j = j + 1 continue case '<', '>', '&': buf = append(buf, s[i:j]...) buf = append(buf, `\u00`...) buf = append(buf, hex[c>>4], hex[c&0xF]) i = j + 1 j = j + 1 continue case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F buf = append(buf, s[i:j]...) buf = append(buf, `\u00`...) buf = append(buf, hex[c>>4], hex[c&0xF]) i = j + 1 j = j + 1 continue } state, size := decodeRuneInString(s[j:]) switch state { case runeErrorState: buf = append(buf, s[i:j]...) buf = append(buf, `\ufffd`...) i = j + 1 j = j + 1 continue // U+2028 is LINE SEPARATOR. // U+2029 is PARAGRAPH SEPARATOR. // They are both technically valid characters in JSON strings, // but don't work in JSONP, which has to be evaluated as JavaScript, // and can lead to security holes there. It is valid JSON to // escape them, so we do so unconditionally. // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. case lineSepState: buf = append(buf, s[i:j]...) buf = append(buf, `\u2028`...) i = j + 3 j = j + 3 continue case paragraphSepState: buf = append(buf, s[i:j]...) buf = append(buf, `\u2029`...) i = j + 3 j = j + 3 continue } j += size } return append(append(buf, s[i:]...), '"') } func appendHTMLString(buf []byte, s string) []byte { valLen := len(s) if valLen == 0 { return append(buf, `""`...) } buf = append(buf, '"') var ( i, j int ) if valLen >= 8 { chunks := stringToUint64Slice(s) for _, n := range chunks { // combine masks before checking for the MSB of each byte. We include // `n` in the mask to check whether any of the *input* byte MSBs were // set (i.e. the byte was outside the ASCII range). mask := n | (n - (lsb * 0x20)) | ((n ^ (lsb * '"')) - lsb) | ((n ^ (lsb * '\\')) - lsb) | ((n ^ (lsb * '<')) - lsb) | ((n ^ (lsb * '>')) - lsb) | ((n ^ (lsb * '&')) - lsb) if (mask & msb) != 0 { j = bits.TrailingZeros64(mask&msb) / 8 goto ESCAPE_END } } for i := len(chunks) * 8; i < valLen; i++ { if needEscapeHTML[s[i]] { j = i goto ESCAPE_END } } // no found any escape characters. return append(append(buf, s...), '"') } ESCAPE_END: for j < valLen { c := s[j] if !needEscapeHTML[c] { // fast path: most of the time, printable ascii characters are used j++ continue } switch c { case '\\', '"': buf = append(buf, s[i:j]...) buf = append(buf, '\\', c) i = j + 1 j = j + 1 continue case '\n': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'n') i = j + 1 j = j + 1 continue case '\r': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'r') i = j + 1 j = j + 1 continue case '\t': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 't') i = j + 1 j = j + 1 continue case '<', '>', '&': buf = append(buf, s[i:j]...) buf = append(buf, `\u00`...) buf = append(buf, hex[c>>4], hex[c&0xF]) i = j + 1 j = j + 1 continue case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F buf = append(buf, s[i:j]...) buf = append(buf, `\u00`...) buf = append(buf, hex[c>>4], hex[c&0xF]) i = j + 1 j = j + 1 continue } j++ } return append(append(buf, s[i:]...), '"') } func appendNormalizedString(buf []byte, s string) []byte { valLen := len(s) if valLen == 0 { return append(buf, `""`...) } buf = append(buf, '"') var ( i, j int ) if valLen >= 8 { chunks := stringToUint64Slice(s) for _, n := range chunks { // combine masks before checking for the MSB of each byte. We include // `n` in the mask to check whether any of the *input* byte MSBs were // set (i.e. the byte was outside the ASCII range). mask := n | (n - (lsb * 0x20)) | ((n ^ (lsb * '"')) - lsb) | ((n ^ (lsb * '\\')) - lsb) if (mask & msb) != 0 { j = bits.TrailingZeros64(mask&msb) / 8 goto ESCAPE_END } } valLen := len(s) for i := len(chunks) * 8; i < valLen; i++ { if needEscapeNormalizeUTF8[s[i]] { j = i goto ESCAPE_END } } return append(append(buf, s...), '"') } ESCAPE_END: for j < valLen { c := s[j] if !needEscapeNormalizeUTF8[c] { // fast path: most of the time, printable ascii characters are used j++ continue } switch c { case '\\', '"': buf = append(buf, s[i:j]...) buf = append(buf, '\\', c) i = j + 1 j = j + 1 continue case '\n': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'n') i = j + 1 j = j + 1 continue case '\r': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'r') i = j + 1 j = j + 1 continue case '\t': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 't') i = j + 1 j = j + 1 continue case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F buf = append(buf, s[i:j]...) buf = append(buf, `\u00`...) buf = append(buf, hex[c>>4], hex[c&0xF]) i = j + 1 j = j + 1 continue } state, size := decodeRuneInString(s[j:]) switch state { case runeErrorState: buf = append(buf, s[i:j]...) buf = append(buf, `\ufffd`...) i = j + 1 j = j + 1 continue // U+2028 is LINE SEPARATOR. // U+2029 is PARAGRAPH SEPARATOR. // They are both technically valid characters in JSON strings, // but don't work in JSONP, which has to be evaluated as JavaScript, // and can lead to security holes there. It is valid JSON to // escape them, so we do so unconditionally. // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. case lineSepState: buf = append(buf, s[i:j]...) buf = append(buf, `\u2028`...) i = j + 3 j = j + 3 continue case paragraphSepState: buf = append(buf, s[i:j]...) buf = append(buf, `\u2029`...) i = j + 3 j = j + 3 continue } j += size } return append(append(buf, s[i:]...), '"') } func appendString(buf []byte, s string) []byte { valLen := len(s) if valLen == 0 { return append(buf, `""`...) } buf = append(buf, '"') var ( i, j int ) if valLen >= 8 { chunks := stringToUint64Slice(s) for _, n := range chunks { // combine masks before checking for the MSB of each byte. We include // `n` in the mask to check whether any of the *input* byte MSBs were // set (i.e. the byte was outside the ASCII range). mask := n | (n - (lsb * 0x20)) | ((n ^ (lsb * '"')) - lsb) | ((n ^ (lsb * '\\')) - lsb) if (mask & msb) != 0 { j = bits.TrailingZeros64(mask&msb) / 8 goto ESCAPE_END } } valLen := len(s) for i := len(chunks) * 8; i < valLen; i++ { if needEscape[s[i]] { j = i goto ESCAPE_END } } return append(append(buf, s...), '"') } ESCAPE_END: for j < valLen { c := s[j] if !needEscape[c] { // fast path: most of the time, printable ascii characters are used j++ continue } switch c { case '\\', '"': buf = append(buf, s[i:j]...) buf = append(buf, '\\', c) i = j + 1 j = j + 1 continue case '\n': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'n') i = j + 1 j = j + 1 continue case '\r': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 'r') i = j + 1 j = j + 1 continue case '\t': buf = append(buf, s[i:j]...) buf = append(buf, '\\', 't') i = j + 1 j = j + 1 continue case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F buf = append(buf, s[i:j]...) buf = append(buf, `\u00`...) buf = append(buf, hex[c>>4], hex[c&0xF]) i = j + 1 j = j + 1 continue } j++ } return append(append(buf, s[i:]...), '"') } golang-github-goccy-go-json-0.10.3/internal/encoder/string_table.go000066400000000000000000000124601463555276600252630ustar00rootroot00000000000000package encoder var needEscapeHTMLNormalizeUTF8 = [256]bool{ '"': true, '&': true, '<': true, '>': true, '\\': true, 0x00: true, 0x01: true, 0x02: true, 0x03: true, 0x04: true, 0x05: true, 0x06: true, 0x07: true, 0x08: true, 0x09: true, 0x0a: true, 0x0b: true, 0x0c: true, 0x0d: true, 0x0e: true, 0x0f: true, 0x10: true, 0x11: true, 0x12: true, 0x13: true, 0x14: true, 0x15: true, 0x16: true, 0x17: true, 0x18: true, 0x19: true, 0x1a: true, 0x1b: true, 0x1c: true, 0x1d: true, 0x1e: true, 0x1f: true, /* 0x20 - 0x7f */ 0x80: true, 0x81: true, 0x82: true, 0x83: true, 0x84: true, 0x85: true, 0x86: true, 0x87: true, 0x88: true, 0x89: true, 0x8a: true, 0x8b: true, 0x8c: true, 0x8d: true, 0x8e: true, 0x8f: true, 0x90: true, 0x91: true, 0x92: true, 0x93: true, 0x94: true, 0x95: true, 0x96: true, 0x97: true, 0x98: true, 0x99: true, 0x9a: true, 0x9b: true, 0x9c: true, 0x9d: true, 0x9e: true, 0x9f: true, 0xa0: true, 0xa1: true, 0xa2: true, 0xa3: true, 0xa4: true, 0xa5: true, 0xa6: true, 0xa7: true, 0xa8: true, 0xa9: true, 0xaa: true, 0xab: true, 0xac: true, 0xad: true, 0xae: true, 0xaf: true, 0xb0: true, 0xb1: true, 0xb2: true, 0xb3: true, 0xb4: true, 0xb5: true, 0xb6: true, 0xb7: true, 0xb8: true, 0xb9: true, 0xba: true, 0xbb: true, 0xbc: true, 0xbd: true, 0xbe: true, 0xbf: true, 0xc0: true, 0xc1: true, 0xc2: true, 0xc3: true, 0xc4: true, 0xc5: true, 0xc6: true, 0xc7: true, 0xc8: true, 0xc9: true, 0xca: true, 0xcb: true, 0xcc: true, 0xcd: true, 0xce: true, 0xcf: true, 0xd0: true, 0xd1: true, 0xd2: true, 0xd3: true, 0xd4: true, 0xd5: true, 0xd6: true, 0xd7: true, 0xd8: true, 0xd9: true, 0xda: true, 0xdb: true, 0xdc: true, 0xdd: true, 0xde: true, 0xdf: true, 0xe0: true, 0xe1: true, 0xe2: true, 0xe3: true, 0xe4: true, 0xe5: true, 0xe6: true, 0xe7: true, 0xe8: true, 0xe9: true, 0xea: true, 0xeb: true, 0xec: true, 0xed: true, 0xee: true, 0xef: true, 0xf0: true, 0xf1: true, 0xf2: true, 0xf3: true, 0xf4: true, 0xf5: true, 0xf6: true, 0xf7: true, 0xf8: true, 0xf9: true, 0xfa: true, 0xfb: true, 0xfc: true, 0xfd: true, 0xfe: true, 0xff: true, } var needEscapeNormalizeUTF8 = [256]bool{ '"': true, '\\': true, 0x00: true, 0x01: true, 0x02: true, 0x03: true, 0x04: true, 0x05: true, 0x06: true, 0x07: true, 0x08: true, 0x09: true, 0x0a: true, 0x0b: true, 0x0c: true, 0x0d: true, 0x0e: true, 0x0f: true, 0x10: true, 0x11: true, 0x12: true, 0x13: true, 0x14: true, 0x15: true, 0x16: true, 0x17: true, 0x18: true, 0x19: true, 0x1a: true, 0x1b: true, 0x1c: true, 0x1d: true, 0x1e: true, 0x1f: true, /* 0x20 - 0x7f */ 0x80: true, 0x81: true, 0x82: true, 0x83: true, 0x84: true, 0x85: true, 0x86: true, 0x87: true, 0x88: true, 0x89: true, 0x8a: true, 0x8b: true, 0x8c: true, 0x8d: true, 0x8e: true, 0x8f: true, 0x90: true, 0x91: true, 0x92: true, 0x93: true, 0x94: true, 0x95: true, 0x96: true, 0x97: true, 0x98: true, 0x99: true, 0x9a: true, 0x9b: true, 0x9c: true, 0x9d: true, 0x9e: true, 0x9f: true, 0xa0: true, 0xa1: true, 0xa2: true, 0xa3: true, 0xa4: true, 0xa5: true, 0xa6: true, 0xa7: true, 0xa8: true, 0xa9: true, 0xaa: true, 0xab: true, 0xac: true, 0xad: true, 0xae: true, 0xaf: true, 0xb0: true, 0xb1: true, 0xb2: true, 0xb3: true, 0xb4: true, 0xb5: true, 0xb6: true, 0xb7: true, 0xb8: true, 0xb9: true, 0xba: true, 0xbb: true, 0xbc: true, 0xbd: true, 0xbe: true, 0xbf: true, 0xc0: true, 0xc1: true, 0xc2: true, 0xc3: true, 0xc4: true, 0xc5: true, 0xc6: true, 0xc7: true, 0xc8: true, 0xc9: true, 0xca: true, 0xcb: true, 0xcc: true, 0xcd: true, 0xce: true, 0xcf: true, 0xd0: true, 0xd1: true, 0xd2: true, 0xd3: true, 0xd4: true, 0xd5: true, 0xd6: true, 0xd7: true, 0xd8: true, 0xd9: true, 0xda: true, 0xdb: true, 0xdc: true, 0xdd: true, 0xde: true, 0xdf: true, 0xe0: true, 0xe1: true, 0xe2: true, 0xe3: true, 0xe4: true, 0xe5: true, 0xe6: true, 0xe7: true, 0xe8: true, 0xe9: true, 0xea: true, 0xeb: true, 0xec: true, 0xed: true, 0xee: true, 0xef: true, 0xf0: true, 0xf1: true, 0xf2: true, 0xf3: true, 0xf4: true, 0xf5: true, 0xf6: true, 0xf7: true, 0xf8: true, 0xf9: true, 0xfa: true, 0xfb: true, 0xfc: true, 0xfd: true, 0xfe: true, 0xff: true, } var needEscapeHTML = [256]bool{ '"': true, '&': true, '<': true, '>': true, '\\': true, 0x00: true, 0x01: true, 0x02: true, 0x03: true, 0x04: true, 0x05: true, 0x06: true, 0x07: true, 0x08: true, 0x09: true, 0x0a: true, 0x0b: true, 0x0c: true, 0x0d: true, 0x0e: true, 0x0f: true, 0x10: true, 0x11: true, 0x12: true, 0x13: true, 0x14: true, 0x15: true, 0x16: true, 0x17: true, 0x18: true, 0x19: true, 0x1a: true, 0x1b: true, 0x1c: true, 0x1d: true, 0x1e: true, 0x1f: true, /* 0x20 - 0xff */ } var needEscape = [256]bool{ '"': true, '\\': true, 0x00: true, 0x01: true, 0x02: true, 0x03: true, 0x04: true, 0x05: true, 0x06: true, 0x07: true, 0x08: true, 0x09: true, 0x0a: true, 0x0b: true, 0x0c: true, 0x0d: true, 0x0e: true, 0x0f: true, 0x10: true, 0x11: true, 0x12: true, 0x13: true, 0x14: true, 0x15: true, 0x16: true, 0x17: true, 0x18: true, 0x19: true, 0x1a: true, 0x1b: true, 0x1c: true, 0x1d: true, 0x1e: true, 0x1f: true, /* 0x20 - 0xff */ } golang-github-goccy-go-json-0.10.3/internal/encoder/vm/000077500000000000000000000000001463555276600226765ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/encoder/vm/debug_vm.go000066400000000000000000000017341463555276600250220ustar00rootroot00000000000000package vm import ( "fmt" "io" "github.com/goccy/go-json/internal/encoder" ) 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 wc := ctx.Option.DebugDOTOut; wc != nil { _, _ = io.WriteString(wc, code.DumpDOT()) wc.Close() ctx.Option.DebugDOTOut = nil } if err := recover(); err != nil { w := ctx.Option.DebugOut fmt.Fprintln(w, "=============[DEBUG]===============") fmt.Fprintln(w, "* [TYPE]") fmt.Fprintln(w, codeSet.Type) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [ALL OPCODE]") fmt.Fprintln(w, code.Dump()) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [CONTEXT]") fmt.Fprintf(w, "%+v\n", ctx) fmt.Fprintln(w, "===================================") panic(err) } }() return Run(ctx, b, codeSet) } golang-github-goccy-go-json-0.10.3/internal/encoder/vm/hack.go000066400000000000000000000005211463555276600241310ustar00rootroot00000000000000package vm 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_indent" ) golang-github-goccy-go-json-0.10.3/internal/encoder/vm/util.go000066400000000000000000000135231463555276600242060ustar00rootroot00000000000000package vm import ( "encoding/json" "fmt" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) 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 errUnsupportedValue = encoder.ErrUnsupportedValue errUnsupportedFloat = encoder.ErrUnsupportedFloat mapiterinit = encoder.MapIterInit mapiterkey = encoder.MapIterKey mapitervalue = encoder.MapIterValue mapiternext = encoder.MapIterNext maplen = encoder.MapLen ) type emptyInterface struct { typ *runtime.Type 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 uint32) uintptr { addr := base + uintptr(idx) return **(**uintptr)(unsafe.Pointer(&addr)) } func store(base uintptr, idx uint32, p uintptr) { addr := base + uintptr(idx) **(**uintptr)(unsafe.Pointer(&addr)) = p } func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { addr := base + uintptr(idx) p := **(**uintptr)(unsafe.Pointer(&addr)) for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUint64(p uintptr, bitSize uint8) uint64 { switch bitSize { case 8: return (uint64)(**(**uint8)(unsafe.Pointer(&p))) case 16: return (uint64)(**(**uint16)(unsafe.Pointer(&p))) case 32: return (uint64)(**(**uint32)(unsafe.Pointer(&p))) case 64: return **(**uint64)(unsafe.Pointer(&p)) } return 0 } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } func ptrToPtr(p uintptr) uintptr { return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) } func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUnsafePtr(p uintptr) unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&p)) } func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { return *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.Type, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) } func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte { if v { return append(b, "true"...) } return append(b, "false"...) } func appendNull(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, "null"...) } func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, ',') } func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, "null,"...) } 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] = ':' return append(b, value...) } func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { b[len(b)-1] = '}' b = append(b, ',') return b } func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { return encoder.AppendMarshalJSON(ctx, code, b, v) } 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 { return append(b, '[') } func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { last := len(b) - 1 b[last] = ']' return append(b, ',') } func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '[', ']', ',') } func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '{', '}', ',') } func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { last := len(b) - 1 b[last] = '}' return append(b, ',') } func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '{') } func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { return append(b, code.Key...) } func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return append(b, '}', ',') } func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { last := len(b) - 1 if b[last] == ',' { b[last] = '}' return appendComma(ctx, b) } return appendStructEnd(ctx, code, b) } func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {} func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {} func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } golang-github-goccy-go-json-0.10.3/internal/encoder/vm/vm.go000066400000000000000000004142071463555276600236570ustar00rootroot00000000000000// Code generated by internal/cmd/generator. DO NOT EDIT! package vm import ( "math" "reflect" "sort" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { recursiveLevel := 0 ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode } for { switch code.Op { default: return nil, errUnimplementedOp(code.Op) case encoder.OpPtr: p := load(ctxptr, code.Idx) code = code.Next store(ctxptr, code.Idx, ptrToPtr(p)) case encoder.OpIntPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInt: b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpUintPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpUint: b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpIntString: b = append(b, '"') b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpUintString: b = append(b, '"') b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpFloat32Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat32: b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpFloat64Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat64: v := ptrToFloat64(load(ctxptr, code.Idx)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStringPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpString: b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBoolPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBool: b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBytesPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBytes: b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpNumberPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpNumber: bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpInterfacePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInterface: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if p == seen { return nil, errUnsupportedValue(code, p) } } } ctx.SeenPtr = append(ctx.SeenPtr, p) var ( typ *runtime.Type ifacePtr unsafe.Pointer ) up := ptrToUnsafePtr(p) if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { iface := (*nonEmptyInterface)(up) ifacePtr = iface.ptr if iface.itab != nil { typ = iface.itab.typ } } else { iface := (*emptyInterface)(up) ifacePtr = iface.ptr typ = iface.typ } if ifacePtr == nil { isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) if !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) if err != nil { return nil, err } totalLength := uintptr(code.Length) + 3 nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 var c *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { c = ifaceCodeSet.InterfaceEscapeKeyCode } else { c = ifaceCodeSet.InterfaceNoescapeKeyCode } curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += totalLength * uintptrSize oldBaseIndent := ctx.BaseIndent ctx.BaseIndent += code.Indent newLen := offsetNum + totalLength + nextTotalLength if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr end := ifaceCodeSet.EndCode store(ctxptr, c.Idx, uintptr(ifacePtr)) store(ctxptr, end.Idx, oldOffset) store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpInterfaceEnd: recursiveLevel-- // restore ctxptr offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalText: p := load(ctxptr, code.Idx) if p == 0 { b = append(b, `""`...) b = appendComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpSlicePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpSlice: p := load(ctxptr, code.Idx) slice := ptrToSlice(p) if p == 0 || slice.Data == nil { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(slice.Len)) store(ctxptr, code.Idx, uintptr(slice.Data)) if slice.Len > 0 { b = appendArrayHead(ctx, code, b) code = code.Next store(ctxptr, code.Idx, uintptr(slice.Data)) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpSliceElem: idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ if idx < length { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) data := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, data+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpArrayPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpArray: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } if code.Length > 0 { b = appendArrayHead(ctx, code, b) store(ctxptr, code.ElemIdx, 0) code = code.Next store(ctxptr, code.Idx, p) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpArrayElem: idx := load(ctxptr, code.ElemIdx) idx++ if idx < uintptr(code.Length) { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) p := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, p+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpMapPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpMap: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } uptr := ptrToUnsafePtr(p) mlen := maplen(uptr) if mlen <= 0 { b = appendEmptyObject(ctx, b) code = code.End.Next break } b = appendStructHead(ctx, b) unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 mapCtx := encoder.NewMapContext(mlen, unorderedMap) mapiterinit(code.Type, uptr, &mapCtx.Iter) store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) if unorderedMap { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx.Start = len(b) mapCtx.First = len(b) } key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next case encoder.OpMapKey: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) idx := mapCtx.Idx idx++ if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < mapCtx.Len { b = appendMapKeyIndent(ctx, code, b) mapCtx.Idx = int(idx) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { b = appendObjectEnd(ctx, code, b) encoder.ReleaseMapContext(mapCtx) code = code.End.Next } } else { mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] if idx < mapCtx.Len { mapCtx.Idx = int(idx) mapCtx.Start = len(b) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { code = code.End } } case encoder.OpMapValue: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] mapCtx.Start = len(b) } value := mapitervalue(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(value)) mapiternext(&mapCtx.Iter) code = code.Next case encoder.OpMapEnd: // this operation only used by sorted map. mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) sort.Sort(mapCtx.Slice) buf := mapCtx.Buf for _, item := range mapCtx.Slice.Items { buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) } buf = appendMapEnd(ctx, code, buf) b = b[:mapCtx.First] b = append(b, buf...) mapCtx.Buf = buf encoder.ReleaseMapContext(mapCtx) code = code.Next case encoder.OpRecursivePtr: p := load(ctxptr, code.Idx) if p == 0 { code = code.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpRecursive: ptr := load(ctxptr, code.Idx) if ptr != 0 { if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if ptr == seen { return nil, errUnsupportedValue(code, ptr) } } } } ctx.SeenPtr = append(ctx.SeenPtr, ptr) c := code.Jmp.Code curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += code.Jmp.CurLen * uintptrSize oldBaseIndent := ctx.BaseIndent indentDiffFromTop := c.Indent - 1 ctx.BaseIndent += code.Indent - indentDiffFromTop newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr store(ctxptr, c.Idx, ptr) store(ctxptr, c.End.Next.Idx, oldOffset) store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpRecursiveEnd: recursiveLevel-- // restore ctxptr restoreIndent(ctx, code, ctxptr) offset := load(ctxptr, code.Idx) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpStructPtrHead: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHead: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if len(code.Key) > 0 { if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } } p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) u64 := ptrToUint64(p, code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBytes(p + uintptr(code.Offset)) if len(v) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next } case encoder.OpStructPtrHeadNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructPtrHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyArray: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyArray: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptySlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptySlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } if maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { p = ptrToPtr(p) } } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructField: if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } p := load(ctxptr, code.Idx) + uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmpty: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringString: p := load(ctxptr, code.Idx) s := ptrToString(p + uintptr(code.Offset)) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldMarshalJSON: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalJSONPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldMarshalText: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalText: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalTextPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldArrayPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArrayPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldSlice: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlice: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldSlicePtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlicePtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldMap: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMap: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldMapPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMapPtr: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldStruct: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyStruct: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructEnd: b = appendStructEndSkipLast(ctx, code, b) code = code.Next case encoder.OpStructEndInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendStructEnd(ctx, code, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) s := ptrToString(p + uintptr(code.Offset)) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytesPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) code = code.Next case encoder.OpStructEndOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpEnd: goto END } } END: return b, nil } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color/000077500000000000000000000000001463555276600240745ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color/debug_vm.go000066400000000000000000000015101463555276600262100ustar00rootroot00000000000000package vm_color import ( "fmt" "github.com/goccy/go-json/internal/encoder" ) 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 { w := ctx.Option.DebugOut fmt.Fprintln(w, "=============[DEBUG]===============") fmt.Fprintln(w, "* [TYPE]") fmt.Fprintln(w, codeSet.Type) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [ALL OPCODE]") fmt.Fprintln(w, code.Dump()) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [CONTEXT]") fmt.Fprintf(w, "%+v\n", ctx) fmt.Fprintln(w, "===================================") panic(err) } }() return Run(ctx, b, codeSet) } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color/hack.go000066400000000000000000000005351463555276600253340ustar00rootroot00000000000000package 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" ) golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color/util.go000066400000000000000000000175621463555276600254130ustar00rootroot00000000000000package vm_color import ( "encoding/json" "fmt" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) const uintptrSize = 4 << (^uintptr(0) >> 63) var ( errUnsupportedValue = encoder.ErrUnsupportedValue errUnsupportedFloat = encoder.ErrUnsupportedFloat mapiterinit = encoder.MapIterInit mapiterkey = encoder.MapIterKey mapitervalue = encoder.MapIterValue mapiternext = encoder.MapIterNext maplen = encoder.MapLen ) type emptyInterface struct { typ *runtime.Type 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 uint32) uintptr { addr := base + uintptr(idx) return **(**uintptr)(unsafe.Pointer(&addr)) } func store(base uintptr, idx uint32, p uintptr) { addr := base + uintptr(idx) **(**uintptr)(unsafe.Pointer(&addr)) = p } func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { addr := base + uintptr(idx) p := **(**uintptr)(unsafe.Pointer(&addr)) for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUint64(p uintptr, bitSize uint8) uint64 { switch bitSize { case 8: return (uint64)(**(**uint8)(unsafe.Pointer(&p))) case 16: return (uint64)(**(**uint16)(unsafe.Pointer(&p))) case 32: return (uint64)(**(**uint32)(unsafe.Pointer(&p))) case 64: return **(**uint64)(unsafe.Pointer(&p)) } return 0 } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } func ptrToPtr(p uintptr) uintptr { return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) } func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUnsafePtr(p uintptr) unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&p)) } func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { return *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.Type, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) } func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { format := ctx.Option.ColorScheme.Int b = append(b, format.Header...) b = encoder.AppendInt(ctx, b, p, code) return append(b, format.Footer...) } func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { format := ctx.Option.ColorScheme.Uint b = append(b, format.Header...) b = encoder.AppendUint(ctx, b, p, 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(bb, format.Footer...), nil } 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 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 appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte { format := ctx.Option.ColorScheme.Null b = append(b, format.Header...) b = append(b, "null"...) return append(append(b, format.Footer...), ',') } 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[:len(key)-1]...) b = append(b, ':') return append(b, value...) } func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { last := len(b) - 1 b[last] = '}' b = append(b, ',') return b } func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { return encoder.AppendMarshalJSON(ctx, code, b, v) } 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 { return append(b, '[') } func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { last := len(b) - 1 b[last] = ']' return append(b, ',') } func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '[', ']', ',') } func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '{', '}', ',') } func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { last := len(b) - 1 b[last] = '}' return append(b, ',') } func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '{') } 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 { return append(b, '}', ',') } func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { last := len(b) - 1 if b[last] == ',' { b[last] = '}' return appendComma(ctx, b) } return appendStructEnd(ctx, code, b) } func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {} func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {} func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color/vm.go000066400000000000000000004142151463555276600250540ustar00rootroot00000000000000// Code generated by internal/cmd/generator. DO NOT EDIT! package vm_color import ( "math" "reflect" "sort" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { recursiveLevel := 0 ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode } for { switch code.Op { default: return nil, errUnimplementedOp(code.Op) case encoder.OpPtr: p := load(ctxptr, code.Idx) code = code.Next store(ctxptr, code.Idx, ptrToPtr(p)) case encoder.OpIntPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInt: b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpUintPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpUint: b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpIntString: b = append(b, '"') b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpUintString: b = append(b, '"') b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpFloat32Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat32: b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpFloat64Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat64: v := ptrToFloat64(load(ctxptr, code.Idx)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStringPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpString: b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBoolPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBool: b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBytesPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBytes: b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpNumberPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpNumber: bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpInterfacePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInterface: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if p == seen { return nil, errUnsupportedValue(code, p) } } } ctx.SeenPtr = append(ctx.SeenPtr, p) var ( typ *runtime.Type ifacePtr unsafe.Pointer ) up := ptrToUnsafePtr(p) if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { iface := (*nonEmptyInterface)(up) ifacePtr = iface.ptr if iface.itab != nil { typ = iface.itab.typ } } else { iface := (*emptyInterface)(up) ifacePtr = iface.ptr typ = iface.typ } if ifacePtr == nil { isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) if !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) if err != nil { return nil, err } totalLength := uintptr(code.Length) + 3 nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 var c *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { c = ifaceCodeSet.InterfaceEscapeKeyCode } else { c = ifaceCodeSet.InterfaceNoescapeKeyCode } curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += totalLength * uintptrSize oldBaseIndent := ctx.BaseIndent ctx.BaseIndent += code.Indent newLen := offsetNum + totalLength + nextTotalLength if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr end := ifaceCodeSet.EndCode store(ctxptr, c.Idx, uintptr(ifacePtr)) store(ctxptr, end.Idx, oldOffset) store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpInterfaceEnd: recursiveLevel-- // restore ctxptr offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalText: p := load(ctxptr, code.Idx) if p == 0 { b = append(b, `""`...) b = appendComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpSlicePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpSlice: p := load(ctxptr, code.Idx) slice := ptrToSlice(p) if p == 0 || slice.Data == nil { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(slice.Len)) store(ctxptr, code.Idx, uintptr(slice.Data)) if slice.Len > 0 { b = appendArrayHead(ctx, code, b) code = code.Next store(ctxptr, code.Idx, uintptr(slice.Data)) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpSliceElem: idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ if idx < length { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) data := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, data+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpArrayPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpArray: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } if code.Length > 0 { b = appendArrayHead(ctx, code, b) store(ctxptr, code.ElemIdx, 0) code = code.Next store(ctxptr, code.Idx, p) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpArrayElem: idx := load(ctxptr, code.ElemIdx) idx++ if idx < uintptr(code.Length) { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) p := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, p+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpMapPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpMap: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } uptr := ptrToUnsafePtr(p) mlen := maplen(uptr) if mlen <= 0 { b = appendEmptyObject(ctx, b) code = code.End.Next break } b = appendStructHead(ctx, b) unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 mapCtx := encoder.NewMapContext(mlen, unorderedMap) mapiterinit(code.Type, uptr, &mapCtx.Iter) store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) if unorderedMap { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx.Start = len(b) mapCtx.First = len(b) } key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next case encoder.OpMapKey: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) idx := mapCtx.Idx idx++ if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < mapCtx.Len { b = appendMapKeyIndent(ctx, code, b) mapCtx.Idx = int(idx) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { b = appendObjectEnd(ctx, code, b) encoder.ReleaseMapContext(mapCtx) code = code.End.Next } } else { mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] if idx < mapCtx.Len { mapCtx.Idx = int(idx) mapCtx.Start = len(b) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { code = code.End } } case encoder.OpMapValue: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] mapCtx.Start = len(b) } value := mapitervalue(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(value)) mapiternext(&mapCtx.Iter) code = code.Next case encoder.OpMapEnd: // this operation only used by sorted map. mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) sort.Sort(mapCtx.Slice) buf := mapCtx.Buf for _, item := range mapCtx.Slice.Items { buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) } buf = appendMapEnd(ctx, code, buf) b = b[:mapCtx.First] b = append(b, buf...) mapCtx.Buf = buf encoder.ReleaseMapContext(mapCtx) code = code.Next case encoder.OpRecursivePtr: p := load(ctxptr, code.Idx) if p == 0 { code = code.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpRecursive: ptr := load(ctxptr, code.Idx) if ptr != 0 { if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if ptr == seen { return nil, errUnsupportedValue(code, ptr) } } } } ctx.SeenPtr = append(ctx.SeenPtr, ptr) c := code.Jmp.Code curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += code.Jmp.CurLen * uintptrSize oldBaseIndent := ctx.BaseIndent indentDiffFromTop := c.Indent - 1 ctx.BaseIndent += code.Indent - indentDiffFromTop newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr store(ctxptr, c.Idx, ptr) store(ctxptr, c.End.Next.Idx, oldOffset) store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpRecursiveEnd: recursiveLevel-- // restore ctxptr restoreIndent(ctx, code, ctxptr) offset := load(ctxptr, code.Idx) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpStructPtrHead: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHead: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if len(code.Key) > 0 { if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } } p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) u64 := ptrToUint64(p, code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBytes(p + uintptr(code.Offset)) if len(v) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next } case encoder.OpStructPtrHeadNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructPtrHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyArray: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyArray: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptySlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptySlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } if maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { p = ptrToPtr(p) } } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructField: if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } p := load(ctxptr, code.Idx) + uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmpty: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringString: p := load(ctxptr, code.Idx) s := ptrToString(p + uintptr(code.Offset)) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldMarshalJSON: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalJSONPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldMarshalText: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalText: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalTextPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldArrayPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArrayPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldSlice: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlice: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldSlicePtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlicePtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldMap: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMap: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldMapPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMapPtr: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldStruct: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyStruct: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructEnd: b = appendStructEndSkipLast(ctx, code, b) code = code.Next case encoder.OpStructEndInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendStructEnd(ctx, code, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) s := ptrToString(p + uintptr(code.Offset)) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytesPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) code = code.Next case encoder.OpStructEndOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpEnd: goto END } } END: return b, nil } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color_indent/000077500000000000000000000000001463555276600254355ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color_indent/debug_vm.go000066400000000000000000000015171463555276600275600ustar00rootroot00000000000000package vm_color_indent import ( "fmt" "github.com/goccy/go-json/internal/encoder" ) 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 { w := ctx.Option.DebugOut fmt.Fprintln(w, "=============[DEBUG]===============") fmt.Fprintln(w, "* [TYPE]") fmt.Fprintln(w, codeSet.Type) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [ALL OPCODE]") fmt.Fprintln(w, code.Dump()) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [CONTEXT]") fmt.Fprintf(w, "%+v\n", ctx) fmt.Fprintln(w, "===================================") panic(err) } }() return Run(ctx, b, codeSet) } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color_indent/util.go000066400000000000000000000210261463555276600267420ustar00rootroot00000000000000package vm_color_indent import ( "encoding/json" "fmt" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) const uintptrSize = 4 << (^uintptr(0) >> 63) var ( appendIndent = encoder.AppendIndent appendStructEnd = encoder.AppendStructEndIndent errUnsupportedValue = encoder.ErrUnsupportedValue errUnsupportedFloat = encoder.ErrUnsupportedFloat mapiterinit = encoder.MapIterInit mapiterkey = encoder.MapIterKey mapitervalue = encoder.MapIterValue mapiternext = encoder.MapIterNext maplen = encoder.MapLen ) type emptyInterface struct { typ *runtime.Type 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 uint32) uintptr { addr := base + uintptr(idx) return **(**uintptr)(unsafe.Pointer(&addr)) } func store(base uintptr, idx uint32, p uintptr) { addr := base + uintptr(idx) **(**uintptr)(unsafe.Pointer(&addr)) = p } func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { addr := base + uintptr(idx) p := **(**uintptr)(unsafe.Pointer(&addr)) for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUint64(p uintptr, bitSize uint8) uint64 { switch bitSize { case 8: return (uint64)(**(**uint8)(unsafe.Pointer(&p))) case 16: return (uint64)(**(**uint16)(unsafe.Pointer(&p))) case 32: return (uint64)(**(**uint32)(unsafe.Pointer(&p))) case 64: return **(**uint64)(unsafe.Pointer(&p)) } return 0 } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } func ptrToPtr(p uintptr) uintptr { return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) } func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUnsafePtr(p uintptr) unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&p)) } func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { return *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.Type, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) } func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { format := ctx.Option.ColorScheme.Int b = append(b, format.Header...) b = encoder.AppendInt(ctx, b, p, code) return append(b, format.Footer...) } func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { format := ctx.Option.ColorScheme.Uint b = append(b, format.Header...) b = encoder.AppendUint(ctx, b, p, 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(bb, format.Footer...), nil } 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 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 appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte { format := ctx.Option.ColorScheme.Null b = append(b, format.Header...) b = append(b, "null"...) return append(append(b, format.Footer...), ',', '\n') } func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { return append(b[:len(b)-2], ':', ' ') } func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte { b = appendIndent(ctx, b, code.Indent+1) b = append(b, key...) b[len(b)-2] = ':' b[len(b)-1] = ' ' return append(b, value...) } func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { b = b[:len(b)-2] b = append(b, '\n') b = appendIndent(ctx, b, code.Indent) return append(b, '}', ',', '\n') } func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { b = append(b, '[', '\n') return appendIndent(ctx, b, code.Indent+1) } func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { b = b[:len(b)-2] b = append(b, '\n') b = appendIndent(ctx, b, code.Indent) return append(b, ']', ',', '\n') } func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '[', ']', ',', '\n') } func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '{', '}', ',', '\n') } func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { last := len(b) - 1 // replace comma to newline b[last-1] = '\n' b = appendIndent(ctx, b[:last], code.Indent) return append(b, '}', ',', '\n') } func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { return encoder.AppendMarshalJSONIndent(ctx, code, b, v) } 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(_ *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) 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 { last := len(b) - 1 if b[last-1] == '{' { b[last] = '}' } else { if b[last] == '\n' { // to remove ',' and '\n' characters b = b[:len(b)-2] } b = append(b, '\n') b = appendIndent(ctx, b, code.Indent-1) b = append(b, '}') } return appendComma(ctx, b) } func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) { ctx.BaseIndent = uint32(load(ctxptr, code.Length)) } func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) { store(ctxptr, code.Length, indent) } func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { return appendIndent(ctx, b, code.Indent+1) } func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { return appendIndent(ctx, b, code.Indent) } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_color_indent/vm.go000066400000000000000000004142241463555276600264150ustar00rootroot00000000000000// Code generated by internal/cmd/generator. DO NOT EDIT! package vm_color_indent import ( "math" "reflect" "sort" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { recursiveLevel := 0 ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode } for { switch code.Op { default: return nil, errUnimplementedOp(code.Op) case encoder.OpPtr: p := load(ctxptr, code.Idx) code = code.Next store(ctxptr, code.Idx, ptrToPtr(p)) case encoder.OpIntPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInt: b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpUintPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpUint: b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpIntString: b = append(b, '"') b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpUintString: b = append(b, '"') b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpFloat32Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat32: b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpFloat64Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat64: v := ptrToFloat64(load(ctxptr, code.Idx)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStringPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpString: b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBoolPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBool: b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBytesPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBytes: b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpNumberPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpNumber: bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpInterfacePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInterface: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if p == seen { return nil, errUnsupportedValue(code, p) } } } ctx.SeenPtr = append(ctx.SeenPtr, p) var ( typ *runtime.Type ifacePtr unsafe.Pointer ) up := ptrToUnsafePtr(p) if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { iface := (*nonEmptyInterface)(up) ifacePtr = iface.ptr if iface.itab != nil { typ = iface.itab.typ } } else { iface := (*emptyInterface)(up) ifacePtr = iface.ptr typ = iface.typ } if ifacePtr == nil { isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) if !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) if err != nil { return nil, err } totalLength := uintptr(code.Length) + 3 nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 var c *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { c = ifaceCodeSet.InterfaceEscapeKeyCode } else { c = ifaceCodeSet.InterfaceNoescapeKeyCode } curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += totalLength * uintptrSize oldBaseIndent := ctx.BaseIndent ctx.BaseIndent += code.Indent newLen := offsetNum + totalLength + nextTotalLength if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr end := ifaceCodeSet.EndCode store(ctxptr, c.Idx, uintptr(ifacePtr)) store(ctxptr, end.Idx, oldOffset) store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpInterfaceEnd: recursiveLevel-- // restore ctxptr offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalText: p := load(ctxptr, code.Idx) if p == 0 { b = append(b, `""`...) b = appendComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpSlicePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpSlice: p := load(ctxptr, code.Idx) slice := ptrToSlice(p) if p == 0 || slice.Data == nil { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(slice.Len)) store(ctxptr, code.Idx, uintptr(slice.Data)) if slice.Len > 0 { b = appendArrayHead(ctx, code, b) code = code.Next store(ctxptr, code.Idx, uintptr(slice.Data)) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpSliceElem: idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ if idx < length { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) data := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, data+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpArrayPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpArray: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } if code.Length > 0 { b = appendArrayHead(ctx, code, b) store(ctxptr, code.ElemIdx, 0) code = code.Next store(ctxptr, code.Idx, p) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpArrayElem: idx := load(ctxptr, code.ElemIdx) idx++ if idx < uintptr(code.Length) { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) p := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, p+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpMapPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpMap: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } uptr := ptrToUnsafePtr(p) mlen := maplen(uptr) if mlen <= 0 { b = appendEmptyObject(ctx, b) code = code.End.Next break } b = appendStructHead(ctx, b) unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 mapCtx := encoder.NewMapContext(mlen, unorderedMap) mapiterinit(code.Type, uptr, &mapCtx.Iter) store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) if unorderedMap { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx.Start = len(b) mapCtx.First = len(b) } key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next case encoder.OpMapKey: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) idx := mapCtx.Idx idx++ if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < mapCtx.Len { b = appendMapKeyIndent(ctx, code, b) mapCtx.Idx = int(idx) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { b = appendObjectEnd(ctx, code, b) encoder.ReleaseMapContext(mapCtx) code = code.End.Next } } else { mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] if idx < mapCtx.Len { mapCtx.Idx = int(idx) mapCtx.Start = len(b) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { code = code.End } } case encoder.OpMapValue: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] mapCtx.Start = len(b) } value := mapitervalue(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(value)) mapiternext(&mapCtx.Iter) code = code.Next case encoder.OpMapEnd: // this operation only used by sorted map. mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) sort.Sort(mapCtx.Slice) buf := mapCtx.Buf for _, item := range mapCtx.Slice.Items { buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) } buf = appendMapEnd(ctx, code, buf) b = b[:mapCtx.First] b = append(b, buf...) mapCtx.Buf = buf encoder.ReleaseMapContext(mapCtx) code = code.Next case encoder.OpRecursivePtr: p := load(ctxptr, code.Idx) if p == 0 { code = code.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpRecursive: ptr := load(ctxptr, code.Idx) if ptr != 0 { if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if ptr == seen { return nil, errUnsupportedValue(code, ptr) } } } } ctx.SeenPtr = append(ctx.SeenPtr, ptr) c := code.Jmp.Code curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += code.Jmp.CurLen * uintptrSize oldBaseIndent := ctx.BaseIndent indentDiffFromTop := c.Indent - 1 ctx.BaseIndent += code.Indent - indentDiffFromTop newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr store(ctxptr, c.Idx, ptr) store(ctxptr, c.End.Next.Idx, oldOffset) store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpRecursiveEnd: recursiveLevel-- // restore ctxptr restoreIndent(ctx, code, ctxptr) offset := load(ctxptr, code.Idx) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpStructPtrHead: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHead: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if len(code.Key) > 0 { if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } } p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) u64 := ptrToUint64(p, code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBytes(p + uintptr(code.Offset)) if len(v) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next } case encoder.OpStructPtrHeadNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructPtrHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyArray: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyArray: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptySlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptySlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } if maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { p = ptrToPtr(p) } } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructField: if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } p := load(ctxptr, code.Idx) + uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmpty: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringString: p := load(ctxptr, code.Idx) s := ptrToString(p + uintptr(code.Offset)) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldMarshalJSON: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalJSONPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldMarshalText: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalText: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalTextPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldArrayPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArrayPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldSlice: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlice: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldSlicePtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlicePtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldMap: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMap: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldMapPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMapPtr: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldStruct: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyStruct: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructEnd: b = appendStructEndSkipLast(ctx, code, b) code = code.Next case encoder.OpStructEndInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendStructEnd(ctx, code, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) s := ptrToString(p + uintptr(code.Offset)) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytesPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) code = code.Next case encoder.OpStructEndOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpEnd: goto END } } END: return b, nil } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_indent/000077500000000000000000000000001463555276600242375ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/encoder/vm_indent/debug_vm.go000066400000000000000000000015111463555276600263540ustar00rootroot00000000000000package vm_indent import ( "fmt" "github.com/goccy/go-json/internal/encoder" ) 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 { w := ctx.Option.DebugOut fmt.Fprintln(w, "=============[DEBUG]===============") fmt.Fprintln(w, "* [TYPE]") fmt.Fprintln(w, codeSet.Type) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [ALL OPCODE]") fmt.Fprintln(w, code.Dump()) fmt.Fprintf(w, "\n") fmt.Fprintln(w, "* [CONTEXT]") fmt.Fprintf(w, "%+v\n", ctx) fmt.Fprintln(w, "===================================") panic(err) } }() return Run(ctx, b, codeSet) } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_indent/hack.go000066400000000000000000000005271463555276600255000ustar00rootroot00000000000000package vm_indent 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" ) golang-github-goccy-go-json-0.10.3/internal/encoder/vm_indent/util.go000066400000000000000000000150401463555276600255430ustar00rootroot00000000000000package vm_indent import ( "encoding/json" "fmt" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) 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 errUnsupportedValue = encoder.ErrUnsupportedValue errUnsupportedFloat = encoder.ErrUnsupportedFloat mapiterinit = encoder.MapIterInit mapiterkey = encoder.MapIterKey mapitervalue = encoder.MapIterValue mapiternext = encoder.MapIterNext maplen = encoder.MapLen ) type emptyInterface struct { typ *runtime.Type 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 uint32) uintptr { addr := base + uintptr(idx) return **(**uintptr)(unsafe.Pointer(&addr)) } func store(base uintptr, idx uint32, p uintptr) { addr := base + uintptr(idx) **(**uintptr)(unsafe.Pointer(&addr)) = p } func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { addr := base + uintptr(idx) p := **(**uintptr)(unsafe.Pointer(&addr)) for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUint64(p uintptr, bitSize uint8) uint64 { switch bitSize { case 8: return (uint64)(**(**uint8)(unsafe.Pointer(&p))) case 16: return (uint64)(**(**uint16)(unsafe.Pointer(&p))) case 32: return (uint64)(**(**uint32)(unsafe.Pointer(&p))) case 64: return **(**uint64)(unsafe.Pointer(&p)) } return 0 } func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } func ptrToPtr(p uintptr) uintptr { return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) } func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { for i := uint8(0); i < ptrNum; i++ { if p == 0 { return 0 } p = ptrToPtr(p) } return p } func ptrToUnsafePtr(p uintptr) unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&p)) } func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { return *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.Type, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) } func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte { if v { return append(b, "true"...) } return append(b, "false"...) } func appendNull(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, "null"...) } func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, ',', '\n') } func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, "null,\n"...) } func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { return append(b[:len(b)-2], ':', ' ') } func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte { b = appendIndent(ctx, b, code.Indent+1) b = append(b, key...) b[len(b)-2] = ':' b[len(b)-1] = ' ' return append(b, value...) } func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { b = b[:len(b)-2] b = append(b, '\n') b = appendIndent(ctx, b, code.Indent) return append(b, '}', ',', '\n') } func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { b = append(b, '[', '\n') return appendIndent(ctx, b, code.Indent+1) } func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { b = b[:len(b)-2] b = append(b, '\n') b = appendIndent(ctx, b, code.Indent) return append(b, ']', ',', '\n') } func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '[', ']', ',', '\n') } func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '{', '}', ',', '\n') } func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { last := len(b) - 1 // replace comma to newline b[last-1] = '\n' b = appendIndent(ctx, b[:last], code.Indent) return append(b, '}', ',', '\n') } func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { return encoder.AppendMarshalJSONIndent(ctx, code, b, v) } func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { return encoder.AppendMarshalTextIndent(ctx, code, b, v) } 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.Key...) return append(b, ' ') } func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { last := len(b) - 1 if b[last-1] == '{' { b[last] = '}' } else { if b[last] == '\n' { // to remove ',' and '\n' characters b = b[:len(b)-2] } b = append(b, '\n') b = appendIndent(ctx, b, code.Indent-1) b = append(b, '}') } return appendComma(ctx, b) } func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) { ctx.BaseIndent = uint32(load(ctxptr, code.Length)) } func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) { store(ctxptr, code.Length, indent) } func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { return appendIndent(ctx, b, code.Indent+1) } func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { return appendIndent(ctx, b, code.Indent) } golang-github-goccy-go-json-0.10.3/internal/encoder/vm_indent/vm.go000066400000000000000000004142161463555276600252200ustar00rootroot00000000000000// Code generated by internal/cmd/generator. DO NOT EDIT! package vm_indent import ( "math" "reflect" "sort" "unsafe" "github.com/goccy/go-json/internal/encoder" "github.com/goccy/go-json/internal/runtime" ) func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { recursiveLevel := 0 ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode } for { switch code.Op { default: return nil, errUnimplementedOp(code.Op) case encoder.OpPtr: p := load(ctxptr, code.Idx) code = code.Next store(ctxptr, code.Idx, ptrToPtr(p)) case encoder.OpIntPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInt: b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpUintPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpUint: b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = appendComma(ctx, b) code = code.Next case encoder.OpIntString: b = append(b, '"') b = appendInt(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpUintString: b = append(b, '"') b = appendUint(ctx, b, load(ctxptr, code.Idx), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpFloat32Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat32: b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpFloat64Ptr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpFloat64: v := ptrToFloat64(load(ctxptr, code.Idx)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStringPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpString: b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBoolPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBool: b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpBytesPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpBytes: b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) b = appendComma(ctx, b) code = code.Next case encoder.OpNumberPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpNumber: bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpInterfacePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpInterface: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if p == seen { return nil, errUnsupportedValue(code, p) } } } ctx.SeenPtr = append(ctx.SeenPtr, p) var ( typ *runtime.Type ifacePtr unsafe.Pointer ) up := ptrToUnsafePtr(p) if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { iface := (*nonEmptyInterface)(up) ifacePtr = iface.ptr if iface.itab != nil { typ = iface.itab.typ } } else { iface := (*emptyInterface)(up) ifacePtr = iface.ptr typ = iface.typ } if ifacePtr == nil { isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) if !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) if err != nil { return nil, err } totalLength := uintptr(code.Length) + 3 nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 var c *encoder.Opcode if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { c = ifaceCodeSet.InterfaceEscapeKeyCode } else { c = ifaceCodeSet.InterfaceNoescapeKeyCode } curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += totalLength * uintptrSize oldBaseIndent := ctx.BaseIndent ctx.BaseIndent += code.Indent newLen := offsetNum + totalLength + nextTotalLength if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr end := ifaceCodeSet.EndCode store(ctxptr, c.Idx, uintptr(ifacePtr)) store(ctxptr, end.Idx, oldOffset) store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpInterfaceEnd: recursiveLevel-- // restore ctxptr offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } store(ctxptr, code.Idx, ptrToPtr(p)) fallthrough case encoder.OpMarshalText: p := load(ctxptr, code.Idx) if p == 0 { b = append(b, `""`...) b = appendComma(ctx, b) code = code.Next break } if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p) } bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpSlicePtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpSlice: p := load(ctxptr, code.Idx) slice := ptrToSlice(p) if p == 0 || slice.Data == nil { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(slice.Len)) store(ctxptr, code.Idx, uintptr(slice.Data)) if slice.Len > 0 { b = appendArrayHead(ctx, code, b) code = code.Next store(ctxptr, code.Idx, uintptr(slice.Data)) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpSliceElem: idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ if idx < length { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) data := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, data+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpArrayPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpArray: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } if code.Length > 0 { b = appendArrayHead(ctx, code, b) store(ctxptr, code.ElemIdx, 0) code = code.Next store(ctxptr, code.Idx, p) } else { b = appendEmptyArray(ctx, b) code = code.End.Next } case encoder.OpArrayElem: idx := load(ctxptr, code.ElemIdx) idx++ if idx < uintptr(code.Length) { b = appendArrayElemIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) p := load(ctxptr, code.Idx) size := uintptr(code.Size) code = code.Next store(ctxptr, code.Idx, p+idx*size) } else { b = appendArrayEnd(ctx, code, b) code = code.End.Next } case encoder.OpMapPtr: p := loadNPtr(ctxptr, code.Idx, code.PtrNum) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } store(ctxptr, code.Idx, p) fallthrough case encoder.OpMap: p := load(ctxptr, code.Idx) if p == 0 { b = appendNullComma(ctx, b) code = code.End.Next break } uptr := ptrToUnsafePtr(p) mlen := maplen(uptr) if mlen <= 0 { b = appendEmptyObject(ctx, b) code = code.End.Next break } b = appendStructHead(ctx, b) unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 mapCtx := encoder.NewMapContext(mlen, unorderedMap) mapiterinit(code.Type, uptr, &mapCtx.Iter) store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) if unorderedMap { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx.Start = len(b) mapCtx.First = len(b) } key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next case encoder.OpMapKey: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) idx := mapCtx.Idx idx++ if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < mapCtx.Len { b = appendMapKeyIndent(ctx, code, b) mapCtx.Idx = int(idx) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { b = appendObjectEnd(ctx, code, b) encoder.ReleaseMapContext(mapCtx) code = code.End.Next } } else { mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] if idx < mapCtx.Len { mapCtx.Idx = int(idx) mapCtx.Start = len(b) key := mapiterkey(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(key)) code = code.Next } else { code = code.End } } case encoder.OpMapValue: mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] mapCtx.Start = len(b) } value := mapitervalue(&mapCtx.Iter) store(ctxptr, code.Next.Idx, uintptr(value)) mapiternext(&mapCtx.Iter) code = code.Next case encoder.OpMapEnd: // this operation only used by sorted map. mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) sort.Sort(mapCtx.Slice) buf := mapCtx.Buf for _, item := range mapCtx.Slice.Items { buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) } buf = appendMapEnd(ctx, code, buf) b = b[:mapCtx.First] b = append(b, buf...) mapCtx.Buf = buf encoder.ReleaseMapContext(mapCtx) code = code.Next case encoder.OpRecursivePtr: p := load(ctxptr, code.Idx) if p == 0 { code = code.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpRecursive: ptr := load(ctxptr, code.Idx) if ptr != 0 { if recursiveLevel > encoder.StartDetectingCyclesAfter { for _, seen := range ctx.SeenPtr { if ptr == seen { return nil, errUnsupportedValue(code, ptr) } } } } ctx.SeenPtr = append(ctx.SeenPtr, ptr) c := code.Jmp.Code curlen := uintptr(len(ctx.Ptrs)) offsetNum := ptrOffset / uintptrSize oldOffset := ptrOffset ptrOffset += code.Jmp.CurLen * uintptrSize oldBaseIndent := ctx.BaseIndent indentDiffFromTop := c.Indent - 1 ctx.BaseIndent += code.Indent - indentDiffFromTop newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen if curlen < newLen { ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) } ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr store(ctxptr, c.Idx, ptr) store(ctxptr, c.End.Next.Idx, oldOffset) store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) code = c recursiveLevel++ case encoder.OpRecursiveEnd: recursiveLevel-- // restore ctxptr restoreIndent(ctx, code, ctxptr) offset := load(ctxptr, code.Idx) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] codePtr := load(ctxptr, code.ElemIdx) code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) ctxptr = ctx.Ptr() + offset ptrOffset = offset case encoder.OpStructPtrHead: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHead: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if len(code.Key) > 0 { if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } } p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmpty: p := load(ctxptr, code.Idx) if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyInt: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyInt: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyIntString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) u64 := ptrToUint64(p, code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUint: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUint: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyUintString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat32String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat32(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64String: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyFloat64String: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToFloat64(p + uintptr(code.Offset)) if v == 0 { code = code.NextField } else { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNull(ctx, b) b = appendComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyStringString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToString(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBool: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBool: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBoolString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next } else { code = code.NextField } case encoder.OpStructPtrHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytes: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyBytes: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToBytes(p + uintptr(code.Offset)) if len(v) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumber: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumber: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next } case encoder.OpStructPtrHeadNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberString: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyNumberString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } v := ptrToNumber(p + uintptr(code.Offset)) if v == "" { code = code.NextField } else { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructPtrHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyArray: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyArray: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptySlice: if (code.Flags & encoder.IndirectFlags) != 0 { p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptySlice: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructPtrHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMap: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { p = ptrToPtr(p + uintptr(code.Offset)) } if maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { b = appendNullComma(ctx, b) code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMapPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField break } p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 { code = code.NextField } else { if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p, code.PtrNum) } b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructPtrHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { p = ptrToPtr(p) } } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) } fallthrough case encoder.OpStructHeadOmitEmptyMarshalText: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { p = ptrToPtr(p) } } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructPtrHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } b = appendStructKey(ctx, code, b) if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) fallthrough case encoder.OpStructHeadOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendNullComma(ctx, b) } code = code.End.Next break } if (code.Flags & encoder.IndirectFlags) != 0 { p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) } if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } if p == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb b = appendComma(ctx, b) code = code.Next } case encoder.OpStructField: if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { b = appendStructKey(ctx, code, b) } p := load(ctxptr, code.Idx) + uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmpty: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNullComma(ctx, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringString: p := load(ctxptr, code.Idx) s := ptrToString(p + uintptr(code.Offset)) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) b = appendStructKey(ctx, code, b) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendComma(ctx, b) } code = code.Next case encoder.OpStructFieldMarshalJSON: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSON: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } iface := ptrToInterface(code, p) if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, iface) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalJSONPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldMarshalText: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalText: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if (code.Flags & encoder.IsNilableTypeFlags) != 0 { p = ptrToPtr(p) } if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { code = code.NextField break } b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) code = code.Next case encoder.OpStructFieldMarshalTextPtr: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = bb } b = appendComma(ctx, b) code = code.Next case encoder.OpStructFieldOmitEmptyMarshalTextPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) if err != nil { return nil, err } b = appendComma(ctx, bb) } code = code.Next case encoder.OpStructFieldArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArray: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldArrayPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyArrayPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldSlice: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlice: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) slice := ptrToSlice(p) if slice.Len == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldSlicePtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptySlicePtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldMap: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMap: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructFieldMapPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyMapPtr: p := load(ctxptr, code.Idx) p = ptrToPtr(p + uintptr(code.Offset)) if p != 0 { p = ptrToNPtr(p, code.PtrNum) } if p != 0 { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } else { code = code.NextField } case encoder.OpStructFieldStruct: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p += uintptr(code.Offset) code = code.Next store(ctxptr, code.Idx, p) case encoder.OpStructFieldOmitEmptyStruct: p := load(ctxptr, code.Idx) p += uintptr(code.Offset) if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { code = code.NextField } else { b = appendStructKey(ctx, code, b) code = code.Next store(ctxptr, code.Idx, p) } case encoder.OpStructEnd: b = appendStructEndSkipLast(ctx, code, b) code = code.Next case encoder.OpStructEndInt: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyInt: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendInt(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendInt(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndIntPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyIntPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendInt(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUint: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintString: p := load(ctxptr, code.Idx) u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) v := u64 & ((1 << code.NumBitSize) - 1) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p+uintptr(code.Offset), code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendUint(ctx, b, p, code) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendUint(ctx, b, p, code) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndUintPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyUintPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendUint(ctx, b, p, code) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32String: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32String: p := load(ctxptr, code.Idx) v := ptrToFloat32(p + uintptr(code.Offset)) if v != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendFloat32(ctx, b, ptrToFloat32(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendFloat32(ctx, b, ptrToFloat32(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat32PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat32PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat32(ctx, b, ptrToFloat32(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64String: p := load(ctxptr, code.Idx) v := ptrToFloat64(p + uintptr(code.Offset)) if v != 0 { if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64Ptr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) b = appendStructEnd(ctx, code, b) code = code.Next break } v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64Ptr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndFloat64PtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = appendFloat64(ctx, b, v) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyFloat64PtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) v := ptrToFloat64(p) if math.IsInf(v, 0) || math.IsNaN(v) { return nil, errUnsupportedFloat(v) } b = append(b, '"') b = appendFloat64(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) s := ptrToString(p + uintptr(code.Offset)) b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringString: p := load(ctxptr, code.Idx) v := ptrToString(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, ptrToString(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, ptrToString(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndStringPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyStringPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBool: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) b = append(b, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolString: p := load(ctxptr, code.Idx) v := ptrToBool(p + uintptr(code.Offset)) if v { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, v) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendBool(ctx, b, ptrToBool(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendBool(ctx, b, ptrToBool(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBoolPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBoolPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') b = appendBool(ctx, b, ptrToBool(p)) b = append(b, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytes: p := load(ctxptr, code.Idx) v := ptrToBytes(p + uintptr(code.Offset)) if len(v) > 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, v) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndBytesPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = appendByteSlice(ctx, b, ptrToBytes(p)) } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyBytesPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = appendByteSlice(ctx, b, ptrToBytes(p)) b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumber: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) code = code.Next case encoder.OpStructEndOmitEmptyNumber: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberString: p := load(ctxptr, code.Idx) b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberString: p := load(ctxptr, code.Idx) v := ptrToNumber(p + uintptr(code.Offset)) if v != "" { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, v) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtr: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = bb } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtr: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = appendStructEnd(ctx, code, bb) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpStructEndNumberPtrString: b = appendStructKey(ctx, code, b) p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p == 0 { b = appendNull(ctx, b) } else { b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') } b = appendStructEnd(ctx, code, b) code = code.Next case encoder.OpStructEndOmitEmptyNumberPtrString: p := load(ctxptr, code.Idx) p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) if p != 0 { b = appendStructKey(ctx, code, b) b = append(b, '"') bb, err := appendNumber(ctx, b, ptrToNumber(p)) if err != nil { return nil, err } b = append(bb, '"') b = appendStructEnd(ctx, code, b) } else { b = appendStructEndSkipLast(ctx, code, b) } code = code.Next case encoder.OpEnd: goto END } } END: return b, nil } golang-github-goccy-go-json-0.10.3/internal/errors/000077500000000000000000000000001463555276600221515ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/errors/error.go000066400000000000000000000114371463555276600236370ustar00rootroot00000000000000package errors import ( "fmt" "reflect" "strconv" ) type InvalidUTF8Error struct { S string // the whole string value that caused the error } func (e *InvalidUTF8Error) Error() string { return fmt.Sprintf("json: invalid UTF-8 in string: %s", strconv.Quote(e.S)) } type InvalidUnmarshalError struct { Type reflect.Type } func (e *InvalidUnmarshalError) Error() string { if e.Type == nil { return "json: Unmarshal(nil)" } if e.Type.Kind() != reflect.Ptr { return fmt.Sprintf("json: Unmarshal(non-pointer %s)", e.Type) } return fmt.Sprintf("json: Unmarshal(nil %s)", e.Type) } // A MarshalerError represents an error from calling a MarshalJSON or MarshalText method. type MarshalerError struct { Type reflect.Type Err error sourceFunc string } func (e *MarshalerError) Error() string { srcFunc := e.sourceFunc if srcFunc == "" { srcFunc = "MarshalJSON" } return fmt.Sprintf("json: error calling %s for type %s: %s", srcFunc, e.Type, e.Err.Error()) } // Unwrap returns the underlying error. func (e *MarshalerError) Unwrap() error { return e.Err } // A SyntaxError is a description of a JSON syntax error. type SyntaxError struct { msg string // description of error Offset int64 // error occurred after reading Offset bytes } func (e *SyntaxError) Error() string { return e.msg } // An UnmarshalFieldError describes a JSON object key that // led to an unexported (and therefore unwritable) struct field. // // Deprecated: No longer used; kept for compatibility. type UnmarshalFieldError struct { Key string Type reflect.Type Field reflect.StructField } func (e *UnmarshalFieldError) Error() string { return fmt.Sprintf("json: cannot unmarshal object key %s into unexported field %s of type %s", strconv.Quote(e.Key), e.Field.Name, e.Type.String(), ) } // An UnmarshalTypeError describes a JSON value that was // not appropriate for a value of a specific Go type. type UnmarshalTypeError struct { Value string // description of JSON value - "bool", "array", "number -5" Type reflect.Type // type of Go value it could not be assigned to Offset int64 // error occurred after reading Offset bytes Struct string // name of the struct type containing the field Field string // the full path from root node to the field } func (e *UnmarshalTypeError) Error() string { if e.Struct != "" || e.Field != "" { return fmt.Sprintf("json: cannot unmarshal %s into Go struct field %s.%s of type %s", e.Value, e.Struct, e.Field, e.Type, ) } return fmt.Sprintf("json: cannot unmarshal %s into Go value of type %s", e.Value, e.Type) } // An UnsupportedTypeError is returned by Marshal when attempting // to encode an unsupported value type. type UnsupportedTypeError struct { Type reflect.Type } func (e *UnsupportedTypeError) Error() string { return fmt.Sprintf("json: unsupported type: %s", e.Type) } type UnsupportedValueError struct { Value reflect.Value Str string } func (e *UnsupportedValueError) Error() string { return fmt.Sprintf("json: unsupported value: %s", e.Str) } func ErrSyntax(msg string, offset int64) *SyntaxError { return &SyntaxError{msg: msg, Offset: offset} } func ErrMarshaler(typ reflect.Type, err error, msg string) *MarshalerError { return &MarshalerError{ Type: typ, Err: err, sourceFunc: msg, } } func ErrExceededMaxDepth(c byte, cursor int64) *SyntaxError { return &SyntaxError{ msg: fmt.Sprintf(`invalid character "%c" exceeded max depth`, c), Offset: cursor, } } func ErrNotAtBeginningOfValue(cursor int64) *SyntaxError { return &SyntaxError{msg: "not at beginning of value", Offset: cursor} } func ErrUnexpectedEndOfJSON(msg string, cursor int64) *SyntaxError { return &SyntaxError{ msg: fmt.Sprintf("json: %s unexpected end of JSON input", msg), Offset: cursor, } } func ErrExpected(msg string, cursor int64) *SyntaxError { return &SyntaxError{msg: fmt.Sprintf("expected %s", msg), Offset: cursor} } func ErrInvalidCharacter(c byte, context string, cursor int64) *SyntaxError { if c == 0 { return &SyntaxError{ msg: fmt.Sprintf("json: invalid character as %s", context), Offset: cursor, } } return &SyntaxError{ msg: fmt.Sprintf("json: invalid character %c as %s", c, context), 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, } } type PathError struct { msg string } func (e *PathError) Error() string { return fmt.Sprintf("json: invalid path format: %s", e.msg) } func ErrInvalidPath(msg string, args ...interface{}) *PathError { if len(args) != 0 { return &PathError{msg: fmt.Sprintf(msg, args...)} } return &PathError{msg: msg} } func ErrEmptyPath() *PathError { return &PathError{msg: "path is empty"} } golang-github-goccy-go-json-0.10.3/internal/runtime/000077500000000000000000000000001463555276600223205ustar00rootroot00000000000000golang-github-goccy-go-json-0.10.3/internal/runtime/rtype.go000066400000000000000000000132331463555276600240140ustar00rootroot00000000000000package runtime import ( "reflect" "unsafe" ) // Type representing reflect.rtype for noescape trick type Type struct{} //go:linkname rtype_Align reflect.(*rtype).Align //go:noescape func rtype_Align(*Type) int func (t *Type) Align() int { return rtype_Align(t) } //go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign //go:noescape func rtype_FieldAlign(*Type) int func (t *Type) FieldAlign() int { return rtype_FieldAlign(t) } //go:linkname rtype_Method reflect.(*rtype).Method //go:noescape func rtype_Method(*Type, int) reflect.Method func (t *Type) Method(a0 int) reflect.Method { return rtype_Method(t, a0) } //go:linkname rtype_MethodByName reflect.(*rtype).MethodByName //go:noescape func rtype_MethodByName(*Type, string) (reflect.Method, bool) func (t *Type) MethodByName(a0 string) (reflect.Method, bool) { return rtype_MethodByName(t, a0) } //go:linkname rtype_NumMethod reflect.(*rtype).NumMethod //go:noescape func rtype_NumMethod(*Type) int func (t *Type) NumMethod() int { return rtype_NumMethod(t) } //go:linkname rtype_Name reflect.(*rtype).Name //go:noescape func rtype_Name(*Type) string func (t *Type) Name() string { return rtype_Name(t) } //go:linkname rtype_PkgPath reflect.(*rtype).PkgPath //go:noescape func rtype_PkgPath(*Type) string func (t *Type) PkgPath() string { return rtype_PkgPath(t) } //go:linkname rtype_Size reflect.(*rtype).Size //go:noescape func rtype_Size(*Type) uintptr func (t *Type) Size() uintptr { return rtype_Size(t) } //go:linkname rtype_String reflect.(*rtype).String //go:noescape func rtype_String(*Type) string func (t *Type) String() string { return rtype_String(t) } //go:linkname rtype_Kind reflect.(*rtype).Kind //go:noescape func rtype_Kind(*Type) reflect.Kind func (t *Type) Kind() reflect.Kind { return rtype_Kind(t) } //go:linkname rtype_Implements reflect.(*rtype).Implements //go:noescape func rtype_Implements(*Type, reflect.Type) bool func (t *Type) Implements(u reflect.Type) bool { return rtype_Implements(t, u) } //go:linkname rtype_AssignableTo reflect.(*rtype).AssignableTo //go:noescape func rtype_AssignableTo(*Type, reflect.Type) bool func (t *Type) AssignableTo(u reflect.Type) bool { return rtype_AssignableTo(t, u) } //go:linkname rtype_ConvertibleTo reflect.(*rtype).ConvertibleTo //go:noescape func rtype_ConvertibleTo(*Type, reflect.Type) bool func (t *Type) ConvertibleTo(u reflect.Type) bool { return rtype_ConvertibleTo(t, u) } //go:linkname rtype_Comparable reflect.(*rtype).Comparable //go:noescape func rtype_Comparable(*Type) bool func (t *Type) Comparable() bool { return rtype_Comparable(t) } //go:linkname rtype_Bits reflect.(*rtype).Bits //go:noescape func rtype_Bits(*Type) int func (t *Type) Bits() int { return rtype_Bits(t) } //go:linkname rtype_ChanDir reflect.(*rtype).ChanDir //go:noescape func rtype_ChanDir(*Type) reflect.ChanDir func (t *Type) ChanDir() reflect.ChanDir { return rtype_ChanDir(t) } //go:linkname rtype_IsVariadic reflect.(*rtype).IsVariadic //go:noescape func rtype_IsVariadic(*Type) bool func (t *Type) IsVariadic() bool { return rtype_IsVariadic(t) } //go:linkname rtype_Elem reflect.(*rtype).Elem //go:noescape func rtype_Elem(*Type) reflect.Type func (t *Type) Elem() *Type { return Type2RType(rtype_Elem(t)) } //go:linkname rtype_Field reflect.(*rtype).Field //go:noescape func rtype_Field(*Type, int) reflect.StructField func (t *Type) Field(i int) reflect.StructField { return rtype_Field(t, i) } //go:linkname rtype_FieldByIndex reflect.(*rtype).FieldByIndex //go:noescape func rtype_FieldByIndex(*Type, []int) reflect.StructField func (t *Type) FieldByIndex(index []int) reflect.StructField { return rtype_FieldByIndex(t, index) } //go:linkname rtype_FieldByName reflect.(*rtype).FieldByName //go:noescape func rtype_FieldByName(*Type, string) (reflect.StructField, bool) func (t *Type) FieldByName(name string) (reflect.StructField, bool) { return rtype_FieldByName(t, name) } //go:linkname rtype_FieldByNameFunc reflect.(*rtype).FieldByNameFunc //go:noescape func rtype_FieldByNameFunc(*Type, func(string) bool) (reflect.StructField, bool) func (t *Type) FieldByNameFunc(match func(string) bool) (reflect.StructField, bool) { return rtype_FieldByNameFunc(t, match) } //go:linkname rtype_In reflect.(*rtype).In //go:noescape func rtype_In(*Type, int) reflect.Type func (t *Type) In(i int) reflect.Type { return rtype_In(t, i) } //go:linkname rtype_Key reflect.(*rtype).Key //go:noescape func rtype_Key(*Type) reflect.Type func (t *Type) Key() *Type { return Type2RType(rtype_Key(t)) } //go:linkname rtype_Len reflect.(*rtype).Len //go:noescape func rtype_Len(*Type) int func (t *Type) Len() int { return rtype_Len(t) } //go:linkname rtype_NumField reflect.(*rtype).NumField //go:noescape func rtype_NumField(*Type) int func (t *Type) NumField() int { return rtype_NumField(t) } //go:linkname rtype_NumIn reflect.(*rtype).NumIn //go:noescape func rtype_NumIn(*Type) int func (t *Type) NumIn() int { return rtype_NumIn(t) } //go:linkname rtype_NumOut reflect.(*rtype).NumOut //go:noescape func rtype_NumOut(*Type) int func (t *Type) NumOut() int { return rtype_NumOut(t) } //go:linkname rtype_Out reflect.(*rtype).Out //go:noescape func rtype_Out(*Type, int) reflect.Type //go:linkname PtrTo reflect.(*rtype).ptrTo //go:noescape func PtrTo(*Type) *Type func (t *Type) Out(i int) reflect.Type { return rtype_Out(t, i) } //go:linkname IfaceIndir reflect.ifaceIndir //go:noescape func IfaceIndir(*Type) bool //go:linkname RType2Type reflect.toType //go:noescape func RType2Type(t *Type) reflect.Type type emptyInterface struct { _ *Type ptr unsafe.Pointer } func Type2RType(t reflect.Type) *Type { return (*Type)(((*emptyInterface)(unsafe.Pointer(&t))).ptr) } golang-github-goccy-go-json-0.10.3/internal/runtime/struct_field.go000066400000000000000000000031501463555276600253350ustar00rootroot00000000000000package runtime import ( "reflect" "strings" "unicode" ) func getTag(field reflect.StructField) string { return field.Tag.Get("json") } func IsIgnoredStructField(field reflect.StructField) bool { if field.PkgPath != "" { if field.Anonymous { t := field.Type if t.Kind() == reflect.Ptr { t = t.Elem() } if t.Kind() != reflect.Struct { return true } } else { // private field return true } } tag := getTag(field) return tag == "-" } type StructTag struct { Key string IsTaggedKey bool IsOmitEmpty bool IsString bool Field reflect.StructField } type StructTags []*StructTag func (t StructTags) ExistsKey(key string) bool { for _, tt := range t { if tt.Key == key { return true } } return false } func isValidTag(s string) bool { if s == "" { return false } for _, c := range s { switch { case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): // Backslash and quote chars are reserved, but // otherwise any punctuation chars are allowed // in a tag name. case !unicode.IsLetter(c) && !unicode.IsDigit(c): return false } } return true } func StructTagFromField(field reflect.StructField) *StructTag { keyName := field.Name tag := getTag(field) st := &StructTag{Field: field} opts := strings.Split(tag, ",") if len(opts) > 0 { if opts[0] != "" && isValidTag(opts[0]) { keyName = opts[0] st.IsTaggedKey = true } } st.Key = keyName if len(opts) > 1 { for _, opt := range opts[1:] { switch opt { case "omitempty": st.IsOmitEmpty = true case "string": st.IsString = true } } } return st } golang-github-goccy-go-json-0.10.3/internal/runtime/type.go000066400000000000000000000034351463555276600236350ustar00rootroot00000000000000package runtime import ( "reflect" "unsafe" ) type SliceHeader struct { Data unsafe.Pointer Len int Cap int } const ( maxAcceptableTypeAddrRange = 1024 * 1024 * 2 // 2 Mib ) type TypeAddr struct { BaseTypeAddr uintptr MaxTypeAddr uintptr AddrRange uintptr AddrShift uintptr } var ( typeAddr *TypeAddr alreadyAnalyzed bool ) //go:linkname typelinks reflect.typelinks func typelinks() ([]unsafe.Pointer, [][]int32) //go:linkname rtypeOff reflect.rtypeOff func rtypeOff(unsafe.Pointer, int32) unsafe.Pointer func AnalyzeTypeAddr() *TypeAddr { defer func() { alreadyAnalyzed = true }() if alreadyAnalyzed { return typeAddr } sections, offsets := typelinks() if len(sections) != 1 { return nil } if len(offsets) != 1 { return nil } 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 := (*Type)(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 } } isAligned64 = isAligned64 && (addr-min)&63 == 0 isAligned32 = isAligned32 && (addr-min)&31 == 0 } addrRange := max - min if addrRange == 0 { return nil } var addrShift uintptr if isAligned64 { addrShift = 6 } else if isAligned32 { addrShift = 5 } cacheSize := addrRange >> addrShift if cacheSize > maxAcceptableTypeAddrRange { return nil } typeAddr = &TypeAddr{ BaseTypeAddr: min, MaxTypeAddr: max, AddrRange: addrRange, AddrShift: addrShift, } return typeAddr } golang-github-goccy-go-json-0.10.3/json.go000066400000000000000000000356101463555276600203260ustar00rootroot00000000000000package json import ( "bytes" "context" "encoding/json" "github.com/goccy/go-json/internal/encoder" ) // Marshaler is the interface implemented by types that // can marshal themselves into valid JSON. 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 // a JSON value. UnmarshalJSON must copy the JSON data // if it wishes to retain the data after returning. // // By convention, to approximate the behavior of Unmarshal itself, // Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. 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. // If an encountered value implements the Marshaler interface // and is not a nil pointer, Marshal calls its MarshalJSON method // to produce JSON. If no MarshalJSON method is present but the // value implements encoding.TextMarshaler instead, Marshal calls // its MarshalText method and encodes the result as a JSON string. // The nil pointer exception is not strictly necessary // but mimics a similar, necessary exception in the behavior of // UnmarshalJSON. // // Otherwise, Marshal uses the following type-dependent default encodings: // // Boolean values encode as JSON booleans. // // Floating point, integer, and Number values encode as JSON numbers. // // String values encode as JSON strings coerced to valid UTF-8, // replacing invalid bytes with the Unicode replacement rune. // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" // to keep some browsers from misinterpreting JSON output as HTML. // Ampersand "&" is also escaped to "\u0026" for the same reason. // This escaping can be disabled using an Encoder that had SetEscapeHTML(false) // called on it. // // Array and slice values encode as JSON arrays, except that // []byte encodes as a base64-encoded string, and a nil slice // encodes as the null JSON value. // // Struct values encode as JSON objects. // Each exported struct field becomes a member of the object, using the // field name as the object key, unless the field is omitted for one of the // reasons given below. // // The encoding of each struct field can be customized by the format string // stored under the "json" key in the struct field's tag. // The format string gives the name of the field, possibly followed by a // comma-separated list of options. The name may be empty in order to // specify options without overriding the default field name. // // The "omitempty" option specifies that the field should be omitted // from the encoding if the field has an empty value, defined as // false, 0, a nil pointer, a nil interface value, and any empty array, // slice, map, or string. // // As a special case, if the field tag is "-", the field is always omitted. // Note that a field with name "-" can still be generated using the tag "-,". // // Examples of struct field tags and their meanings: // // // Field appears in JSON as key "myName". // Field int `json:"myName"` // // // Field appears in JSON as key "myName" and // // the field is omitted from the object if its value is empty, // // as defined above. // Field int `json:"myName,omitempty"` // // // Field appears in JSON as key "Field" (the default), but // // the field is skipped if empty. // // Note the leading comma. // Field int `json:",omitempty"` // // // Field is ignored by this package. // Field int `json:"-"` // // // Field appears in JSON as key "-". // Field int `json:"-,"` // // The "string" option signals that a field is stored as JSON inside a // JSON-encoded string. It applies only to fields of string, floating point, // integer, or boolean types. This extra level of encoding is sometimes used // when communicating with JavaScript programs: // // Int64String int64 `json:",string"` // // The key name will be used if it's a non-empty string consisting of // only Unicode letters, digits, and ASCII punctuation except quotation // marks, backslash, and comma. // // Anonymous struct fields are usually marshaled as if their inner exported fields // were fields in the outer struct, subject to the usual Go visibility rules amended // as described in the next paragraph. // An anonymous struct field with a name given in its JSON tag is treated as // having that name, rather than being anonymous. // An anonymous struct field of interface type is treated the same as having // that type as its name, rather than being anonymous. // // The Go visibility rules for struct fields are amended for JSON when // deciding which field to marshal or unmarshal. If there are // multiple fields at the same level, and that level is the least // nested (and would therefore be the nesting level selected by the // usual Go rules), the following extra rules apply: // // 1) Of those fields, if any are JSON-tagged, only tagged fields are considered, // even if there are multiple untagged fields that would otherwise conflict. // // 2) If there is exactly one field (tagged or not according to the first rule), that is selected. // // 3) Otherwise there are multiple fields, and all are ignored; no error occurs. // // Handling of anonymous struct fields is new in Go 1.1. // Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of // an anonymous struct field in both current and earlier versions, give the field // a JSON tag of "-". // // Map values encode as JSON objects. The map's key type must either be a // string, an integer type, or implement encoding.TextMarshaler. The map keys // are sorted and used as JSON object keys by applying the following rules, // subject to the UTF-8 coercion described for string values above: // - string keys are used directly // - encoding.TextMarshalers are marshaled // - integer keys are converted to strings // // Pointer values encode as the value pointed to. // A nil pointer encodes as the null JSON value. // // Interface values encode as the value contained in the interface. // A nil interface value encodes as the null JSON value. // // Channel, complex, and function values cannot be encoded in JSON. // Attempting to encode such a value causes Marshal to return // an UnsupportedTypeError. // // JSON cannot represent cyclic data structures and Marshal does not // handle them. Passing cyclic structures to Marshal will result in // an infinite recursion. func Marshal(v interface{}) ([]byte, error) { return MarshalWithOption(v) } // MarshalNoEscape returns the JSON encoding of v and doesn't escape v. func MarshalNoEscape(v interface{}) ([]byte, error) { 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) { return marshal(v, optFuncs...) } // MarshalIndent is like Marshal but applies Indent to format the output. // Each JSON element in the output will begin on a new line beginning with prefix // followed by one or more copies of indent according to the indentation nesting. func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { return MarshalIndentWithOption(v, prefix, indent) } // MarshalIndentWithOption is like Marshal but applies Indent to format the output with EncodeOption. func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) { return marshalIndent(v, prefix, indent, optFuncs...) } // Unmarshal parses the JSON-encoded data and stores the result // in the value pointed to by v. If v is nil or not a pointer, // Unmarshal returns an InvalidUnmarshalError. // // Unmarshal uses the inverse of the encodings that // Marshal uses, allocating maps, slices, and pointers as necessary, // with the following additional rules: // // To unmarshal JSON into a pointer, Unmarshal first handles the case of // the JSON being the JSON literal null. In that case, Unmarshal sets // the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into // the value pointed at by the pointer. If the pointer is nil, Unmarshal // allocates a new value for it to point to. // // To unmarshal JSON into a value implementing the Unmarshaler interface, // Unmarshal calls that value's UnmarshalJSON method, including // when the input is a JSON null. // Otherwise, if the value implements encoding.TextUnmarshaler // and the input is a JSON quoted string, Unmarshal calls that value's // UnmarshalText method with the unquoted form of the string. // // To unmarshal JSON into a struct, Unmarshal matches incoming object // keys to the keys used by Marshal (either the struct field name or its tag), // preferring an exact match but also accepting a case-insensitive match. By // default, object keys which don't have a corresponding struct field are // ignored (see Decoder.DisallowUnknownFields for an alternative). // // To unmarshal JSON into an interface value, // Unmarshal stores one of these in the interface value: // // bool, for JSON booleans // float64, for JSON numbers // string, for JSON strings // []interface{}, for JSON arrays // map[string]interface{}, for JSON objects // nil for JSON null // // To unmarshal a JSON array into a slice, Unmarshal resets the slice length // to zero and then appends each element to the slice. // As a special case, to unmarshal an empty JSON array into a slice, // Unmarshal replaces the slice with a new empty slice. // // To unmarshal a JSON array into a Go array, Unmarshal decodes // JSON array elements into corresponding Go array elements. // If the Go array is smaller than the JSON array, // the additional JSON array elements are discarded. // If the JSON array is smaller than the Go array, // the additional Go array elements are set to zero values. // // To unmarshal a JSON object into a map, Unmarshal first establishes a map to // use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal // reuses the existing map, keeping existing entries. Unmarshal then stores // key-value pairs from the JSON object into the map. The map's key type must // either be any string type, an integer, implement json.Unmarshaler, or // implement encoding.TextUnmarshaler. // // If a JSON value is not appropriate for a given target type, // or if a JSON number overflows the target type, Unmarshal // skips that field and completes the unmarshaling as best it can. // If no more serious errors are encountered, Unmarshal returns // an UnmarshalTypeError describing the earliest such error. In any // case, it's not guaranteed that all the remaining fields following // the problematic one will be unmarshaled into the target object. // // The JSON null value unmarshals into an interface, map, pointer, or slice // by setting that Go value to nil. Because null is often used in JSON to mean // “not present,” unmarshaling a JSON null into any other Go type has no effect // on the value and produces no error. // // When unmarshaling quoted strings, invalid UTF-8 or // invalid UTF-16 surrogate pairs are not treated as an error. // Instead, they are replaced by the Unicode replacement // character U+FFFD. func Unmarshal(data []byte, v interface{}) error { return unmarshal(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: // // Delim, for the four JSON delimiters [ ] { } // bool, for JSON booleans // float64, for JSON numbers // Number, for JSON numbers // string, for JSON string literals // nil, for JSON null type Token = json.Token // A Number represents a JSON number literal. type Number = json.Number // RawMessage is a raw encoded JSON value. // It implements Marshaler and Unmarshaler and can // be used to delay JSON decoding or precompute a JSON encoding. type RawMessage = json.RawMessage // A Delim is a JSON array or object delimiter, one of [ ] { or }. type Delim = json.Delim // Compact appends to dst the JSON-encoded src with // insignificant space characters elided. func Compact(dst *bytes.Buffer, src []byte) error { return encoder.Compact(dst, src, false) } // Indent appends to dst an indented form of the JSON-encoded src. // Each element in a JSON object or array begins on a new, // indented line beginning with prefix followed by one or more // copies of indent according to the indentation nesting. // The data appended to dst does not begin with the prefix nor // any indentation, to make it easier to embed inside other formatted JSON data. // Although leading space characters (space, tab, carriage return, newline) // at the beginning of src are dropped, trailing space characters // at the end of src are preserved and copied to dst. // For example, if src has no trailing spaces, neither will dst; // if src ends in a trailing newline, so will dst. func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { return encoder.Indent(dst, src, prefix, indent) } // HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029 // characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029 // so that the JSON will be safe to embed inside HTML