Compare commits

...

10 commits

Author SHA1 Message Date
DataHoarder 60d2daca40
Replace go.mod package with git.gammaspectra.live/P2Pool/go-json 2024-04-14 10:03:12 +02:00
DataHoarder 2410a4c5e9
fix custom array type with omitempty 2024-04-14 09:55:53 +02:00
Muhammad Noor Misyuari df897aec9d
fix: decode struct with pointer must be nil (#473) 2023-10-19 16:13:09 +09:00
Masaaki Goshima 3d5ab28ab3
add license for encoding int processing 2023-10-13 12:44:19 +09:00
Masaaki Goshima 9b91208837
Add license for string processing (#476)
* add license for string processing

* update golangci-lint
2023-10-13 12:33:43 +09:00
Masaaki Goshima 8e8cdeacf2
Update CHANGELOG 2023-03-20 05:01:20 +09:00
Nao Yonashiro 5e6fe10846
fix: fixed a problem with NextField being wrong when combining structure embedding and omitempty (#442)
fix #441
2023-03-20 04:54:48 +09:00
Nao Yonashiro 4d199a4b2c
feat: added the option to output opcodes as dot (#440) 2023-03-20 04:53:43 +09:00
Masaaki Goshima 098041a708
Update CI (#439) 2023-03-13 21:24:58 +09:00
Masaaki Goshima fbd4feeb60
Update CHANGELOG 2023-03-13 21:04:33 +09:00
111 changed files with 464 additions and 206 deletions

View file

@ -10,23 +10,24 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: build - name: build
run: docker-compose run go-json run: docker-compose run go-json
test: test:
name: Test name: Test
strategy: strategy:
matrix: matrix:
os: [ "ubuntu-latest", "macos-latest", "windows-latest" ] os: [ "ubuntu-latest", "macos-latest", "windows-latest" ]
go-version: [ "1.16", "1.17", "1.18" ] go-version: [ "1.19", "1.20", "1.21" ]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: setup Go ${{ matrix.go-version }} - name: setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v2 uses: actions/setup-go@v3
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: simple test - name: simple test
run: go test -v ./... -count=1 run: go test -v ./... -count=1
- name: test with GC pressure - name: test with GC pressure
@ -35,41 +36,56 @@ jobs:
GOGC: 1 GOGC: 1
- name: test with race detector - name: test with race detector
run: go test -v -race ./... -count=1 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: bench:
name: Benchmark name: Benchmark
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: setup Go - name: setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: '1.21'
- name: checkout ( feature ) - name: checkout ( feature )
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: run benchmark ( feature ) - name: run benchmark ( feature )
run: cd benchmarks && go test -bench GoJson | tee $HOME/new.txt run: cd benchmarks && go test -bench GoJson | tee $HOME/new.txt
- name: install benchstat - name: install benchstat
run: go install golang.org/x/perf/cmd/benchstat@latest run: go install golang.org/x/perf/cmd/benchstat@latest
- name: checkout ( master ) - name: checkout ( master )
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
ref: master ref: master
- name: run benchmark ( master ) - name: run benchmark ( master )
run: cd benchmarks && go test -bench GoJson | tee $HOME/old.txt run: cd benchmarks && go test -bench GoJson | tee $HOME/old.txt
- name: compare benchmark results - name: compare benchmark results
run: benchstat $HOME/old.txt $HOME/new.txt run: benchstat $HOME/old.txt $HOME/new.txt
coverage: coverage:
name: Coverage name: Coverage
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: setup Go
uses: actions/setup-go@v2
with:
go-version: 1.18
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: setup Go
uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: measure coverage - name: measure coverage
run: make cover run: make cover
- uses: codecov/codecov-action@v2 - uses: codecov/codecov-action@v3
with: with:
fail_ci_if_error: true fail_ci_if_error: true
verbose: true verbose: true

View file

@ -1,16 +0,0 @@
name: lint
on:
push:
branches:
- master
pull_request:
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: golangci/golangci-lint-action@v3
with:
version: v1.45.2
args: --timeout=5m

View file

@ -56,6 +56,9 @@ linters:
- cyclop - cyclop
- containedctx - containedctx
- revive - revive
- nosnakecase
- exhaustruct
- depguard
issues: issues:
exclude-rules: exclude-rules:

View file

@ -1,3 +1,25 @@
# 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 # v0.10.0 - 2022/11/29
### New features ### New features

View file

@ -1,4 +1,4 @@
PKG := github.com/goccy/go-json PKG := git.gammaspectra.live/P2Pool/go-json
BIN_DIR := $(CURDIR)/bin BIN_DIR := $(CURDIR)/bin
PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test) PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test)
@ -30,7 +30,7 @@ golangci-lint: | $(BIN_DIR)
GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \ GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
cd $$GOLANGCI_LINT_TMP_DIR; \ cd $$GOLANGCI_LINT_TMP_DIR; \
go mod init tmp; \ go mod init tmp; \
GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.48.0; \ GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2; \
rm -rf $$GOLANGCI_LINT_TMP_DIR; \ rm -rf $$GOLANGCI_LINT_TMP_DIR; \
} }

View file

@ -1,7 +1,7 @@
# go-json # go-json
![Go](https://github.com/goccy/go-json/workflows/Go/badge.svg) ![Go](https://git.gammaspectra.live/P2Pool/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) [![GoDoc](https://godoc.org/git.gammaspectra.live/P2Pool/go-json?status.svg)](https://pkg.go.dev/git.gammaspectra.live/P2Pool/go-json?tab=doc)
[![codecov](https://codecov.io/gh/goccy/go-json/branch/master/graph/badge.svg)](https://codecov.io/gh/goccy/go-json) [![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 Fast JSON encoder/decoder compatible with encoding/json for Go
@ -22,12 +22,12 @@ Fast JSON encoder/decoder compatible with encoding/json for Go
``` ```
We are accepting requests for features that will be implemented between v0.9.0 and v.1.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). If you have the API you need, please submit your issue [here](https://git.gammaspectra.live/P2Pool/go-json/issues).
# Features # Features
- Drop-in replacement of `encoding/json` - Drop-in replacement of `encoding/json`
- Fast ( See [Benchmark section](https://github.com/goccy/go-json#benchmarks) ) - Fast ( See [Benchmark section](https://git.gammaspectra.live/P2Pool/go-json#benchmarks) )
- Flexible customization with options - Flexible customization with options
- Coloring the encoded string - Coloring the encoded string
- Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON` - Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON`
@ -36,16 +36,16 @@ If you have the API you need, please submit your issue [here](https://github.com
# Installation # Installation
``` ```
go get github.com/goccy/go-json go get git.gammaspectra.live/P2Pool/go-json
``` ```
# How to use # How to use
Replace import statement from `encoding/json` to `github.com/goccy/go-json` Replace import statement from `encoding/json` to `git.gammaspectra.live/P2Pool/go-json`
``` ```
-import "encoding/json" -import "encoding/json"
+import "github.com/goccy/go-json" +import "git.gammaspectra.live/P2Pool/go-json"
``` ```
# JSON library comparison # JSON library comparison
@ -98,8 +98,8 @@ $ go test -bench .
# Fuzzing # Fuzzing
[go-json-fuzz](https://github.com/goccy/go-json-fuzz) is the repository for fuzzing tests. [go-json-fuzz](https://git.gammaspectra.live/P2Pool/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). 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://git.gammaspectra.live/P2Pool/go-json/issues).
# How it works # How it works
@ -192,7 +192,7 @@ For this reason, to date `reflect.Type` is the same as `*reflect.rtype`.
Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`. 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) The technique for working with `*reflect.rtype` directly from `go-json` is implemented at [rtype.go](https://git.gammaspectra.live/P2Pool/go-json/blob/master/internal/runtime/rtype.go)
Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect ) Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect )
@ -353,7 +353,7 @@ However, if there is too much type information, it will use a lot of memory, so
If this approach is not available, it will fall back to the `atomic` based process described above. If 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) If you want to know more, please refer to the implementation [here](https://git.gammaspectra.live/P2Pool/go-json/blob/master/internal/runtime/type.go#L36-L100)
## Decoder ## Decoder

View file

@ -22,7 +22,7 @@ import (
stdjson "encoding/json" stdjson "encoding/json"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
segmentiojson "github.com/segmentio/encoding/json" segmentiojson "github.com/segmentio/encoding/json"
"github.com/wI2L/jettison" "github.com/wI2L/jettison"

View file

@ -5,8 +5,8 @@ import (
"encoding/json" "encoding/json"
"testing" "testing"
gojson "git.gammaspectra.live/P2Pool/go-json"
gojay "github.com/francoispqt/gojay" gojay "github.com/francoispqt/gojay"
gojson "github.com/goccy/go-json"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
segmentiojson "github.com/segmentio/encoding/json" segmentiojson "github.com/segmentio/encoding/json"
fastjson "github.com/valyala/fastjson" fastjson "github.com/valyala/fastjson"

View file

@ -6,8 +6,8 @@ import (
"encoding/json" "encoding/json"
"testing" "testing"
gojson "git.gammaspectra.live/P2Pool/go-json"
gojay "github.com/francoispqt/gojay" gojay "github.com/francoispqt/gojay"
gojson "github.com/goccy/go-json"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
"github.com/pquerna/ffjson/ffjson" "github.com/pquerna/ffjson/ffjson"
segmentiojson "github.com/segmentio/encoding/json" segmentiojson "github.com/segmentio/encoding/json"

View file

@ -4,7 +4,7 @@ go 1.12
require ( require (
github.com/francoispqt/gojay v1.2.13 github.com/francoispqt/gojay v1.2.13
github.com/goccy/go-json v0.0.0-00010101000000-000000000000 git.gammaspectra.live/P2Pool/go-json v0.0.0-00010101000000-000000000000
github.com/json-iterator/go v1.1.10 github.com/json-iterator/go v1.1.10
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7
@ -14,4 +14,4 @@ require (
github.com/wI2L/jettison v0.7.1 github.com/wI2L/jettison v0.7.1
) )
replace github.com/goccy/go-json => ../ replace git.gammaspectra.live/P2Pool/go-json => ../

View file

@ -3,7 +3,7 @@ package benchmark
import ( import (
"testing" "testing"
gojson "github.com/goccy/go-json" gojson "git.gammaspectra.live/P2Pool/go-json"
) )
func Benchmark_Decode_SmallStruct_UnmarshalPath_GoJson(b *testing.B) { func Benchmark_Decode_SmallStruct_UnmarshalPath_GoJson(b *testing.B) {

View file

@ -7,7 +7,7 @@ import (
"reflect" "reflect"
"testing" "testing"
gojson "github.com/goccy/go-json" gojson "git.gammaspectra.live/P2Pool/go-json"
) )
// Benchmark decoding from a slow io.Reader that never fills the buffer completely // Benchmark decoding from a slow io.Reader that never fills the buffer completely

View file

@ -3,7 +3,7 @@ package json
import ( import (
"fmt" "fmt"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
type ( type (

View file

@ -3,7 +3,7 @@ package json_test
import ( import (
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestColorize(t *testing.T) { func TestColorize(t *testing.T) {

View file

@ -7,9 +7,9 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/decoder" "git.gammaspectra.live/P2Pool/go-json/internal/decoder"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type Decoder struct { type Decoder struct {

View file

@ -18,7 +18,7 @@ import (
"time" "time"
"unsafe" "unsafe"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func Test_Decoder(t *testing.T) { func Test_Decoder(t *testing.T) {
@ -123,7 +123,7 @@ func Test_Decoder(t *testing.T) {
assertEq(t, "map.c", v["c"], 3) assertEq(t, "map.c", v["c"], 3)
assertEq(t, "map.d", v["d"], 4) assertEq(t, "map.d", v["d"], 4)
t.Run("nested map", func(t *testing.T) { t.Run("nested map", func(t *testing.T) {
// https://github.com/goccy/go-json/issues/8 // https://git.gammaspectra.live/P2Pool/go-json/issues/8
content := ` content := `
{ {
"a": { "a": {
@ -197,6 +197,13 @@ func Test_Decoder(t *testing.T) {
assertEq(t, "interface{}", v.F, nil) assertEq(t, "interface{}", v.F, nil)
assertEq(t, "nilfunc", true, v.G == 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("interface", func(t *testing.T) {
t.Run("number", func(t *testing.T) { t.Run("number", func(t *testing.T) {

View file

@ -6,11 +6,11 @@ import (
"os" "os"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/encoder/vm" "git.gammaspectra.live/P2Pool/go-json/internal/encoder/vm"
"github.com/goccy/go-json/internal/encoder/vm_color" "git.gammaspectra.live/P2Pool/go-json/internal/encoder/vm_color"
"github.com/goccy/go-json/internal/encoder/vm_color_indent" "git.gammaspectra.live/P2Pool/go-json/internal/encoder/vm_color_indent"
"github.com/goccy/go-json/internal/encoder/vm_indent" "git.gammaspectra.live/P2Pool/go-json/internal/encoder/vm_indent"
) )
// An Encoder writes JSON values to an output stream. // An Encoder writes JSON values to an output stream.
@ -52,7 +52,7 @@ func (e *Encoder) EncodeContext(ctx context.Context, v interface{}, optFuncs ...
rctx.Option.Flag |= encoder.ContextOption rctx.Option.Flag |= encoder.ContextOption
rctx.Option.Context = ctx rctx.Option.Context = ctx
err := e.encodeWithOption(rctx, v, optFuncs...) err := e.encodeWithOption(rctx, v, optFuncs...) //nolint: contextcheck
encoder.ReleaseRuntimeContext(rctx) encoder.ReleaseRuntimeContext(rctx)
return err return err
@ -120,7 +120,7 @@ func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOption
optFunc(rctx.Option) optFunc(rctx.Option)
} }
buf, err := encode(rctx, v) buf, err := encode(rctx, v) //nolint: contextcheck
if err != nil { if err != nil {
encoder.ReleaseRuntimeContext(rctx) encoder.ReleaseRuntimeContext(rctx)
return nil, err return nil, err

View file

@ -18,7 +18,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type recursiveT struct { type recursiveT struct {
@ -2694,3 +2694,19 @@ func TestIssue426(t *testing.T) {
b, _ := json.Marshal(s) b, _ := json.Marshal(s)
assertEq(t, "unexpected result", `{"I":null,"Val":"456"}`, string(b)) 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))
}

View file

@ -1,7 +1,7 @@
package json package json
import ( import (
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
// Before Go 1.2, an InvalidUTF8Error was returned by Marshal when // Before Go 1.2, an InvalidUTF8Error was returned by Marshal when

View file

@ -1,7 +1,7 @@
package json package json
import ( import (
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
var ( var (

4
go.mod
View file

@ -1,3 +1,3 @@
module github.com/goccy/go-json module git.gammaspectra.live/P2Pool/go-json
go 1.12 go 1.19

View file

@ -7,7 +7,7 @@ import (
"go/parser" "go/parser"
"go/printer" "go/printer"
"go/token" "go/token"
"io/ioutil" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
@ -273,11 +273,11 @@ func (t OpType) FieldToOmitEmptyField() OpType {
if err != nil { if err != nil {
return err return err
} }
return ioutil.WriteFile(path, buf, 0644) return os.WriteFile(path, buf, 0644)
} }
func generateVM() error { func generateVM() error {
file, err := ioutil.ReadFile("vm.go.tmpl") file, err := os.ReadFile("vm.go.tmpl")
if err != nil { if err != nil {
return err return err
} }
@ -295,7 +295,7 @@ func generateVM() error {
if err != nil { if err != nil {
return err return err
} }
if err := ioutil.WriteFile(path, source, 0644); err != nil { if err := os.WriteFile(path, source, 0644); err != nil {
return err return err
} }
} }

View file

@ -7,8 +7,8 @@ import (
"sort" "sort"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -3,7 +3,7 @@ package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type anonymousFieldDecoder struct { type anonymousFieldDecoder struct {

View file

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type arrayDecoder struct { type arrayDecoder struct {

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
type boolDecoder struct { type boolDecoder struct {

View file

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type bytesDecoder struct { type bytesDecoder struct {

View file

@ -9,7 +9,7 @@ import (
"unicode" "unicode"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
var ( var (

View file

@ -6,7 +6,7 @@ package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) { func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {

View file

@ -7,7 +7,7 @@ import (
"sync" "sync"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
var decMu sync.RWMutex var decMu sync.RWMutex

View file

@ -4,7 +4,7 @@ import (
"sync" "sync"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
type RuntimeContext struct { type RuntimeContext struct {

View file

@ -4,7 +4,7 @@ import (
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
type floatDecoder struct { type floatDecoder struct {

View file

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type funcDecoder struct { type funcDecoder struct {

View file

@ -5,8 +5,8 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type intDecoder struct { type intDecoder struct {

View file

@ -7,8 +7,8 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type interfaceDecoder struct { type interfaceDecoder struct {

View file

@ -4,8 +4,8 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type invalidDecoder struct { type invalidDecoder struct {

View file

@ -4,8 +4,8 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type mapDecoder struct { type mapDecoder struct {
@ -36,7 +36,7 @@ const (
mapMaxElemSize = 128 mapMaxElemSize = 128
) )
// See detail: https://github.com/goccy/go-json/pull/283 // See detail: https://git.gammaspectra.live/P2Pool/go-json/pull/283
func canUseAssignFaststrType(key *runtime.Type, value *runtime.Type) bool { func canUseAssignFaststrType(key *runtime.Type, value *runtime.Type) bool {
indirectElem := value.Size() > mapMaxElemSize indirectElem := value.Size() > mapMaxElemSize
if indirectElem { if indirectElem {

View file

@ -5,7 +5,7 @@ import (
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
type numberDecoder struct { type numberDecoder struct {

View file

@ -5,8 +5,8 @@ import (
"reflect" "reflect"
"strconv" "strconv"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type PathString string type PathString string

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type ptrDecoder struct { type ptrDecoder struct {
@ -85,6 +85,7 @@ func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
} }
c, err := d.dec.Decode(ctx, cursor, depth, newptr) c, err := d.dec.Decode(ctx, cursor, depth, newptr)
if err != nil { if err != nil {
*(*unsafe.Pointer)(p) = nil
return 0, err return 0, err
} }
cursor = c cursor = c

View file

@ -5,8 +5,8 @@ import (
"sync" "sync"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
var ( var (

View file

@ -7,7 +7,7 @@ import (
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
const ( const (

View file

@ -9,7 +9,7 @@ import (
"unicode/utf8" "unicode/utf8"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
type stringDecoder struct { type stringDecoder struct {

View file

@ -10,7 +10,7 @@ import (
"unicode/utf16" "unicode/utf16"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
type structFieldSet struct { type structFieldSet struct {

View file

@ -5,8 +5,8 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type uintDecoder struct { type uintDecoder struct {

View file

@ -6,8 +6,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type unmarshalJSONDecoder struct { type unmarshalJSONDecoder struct {

View file

@ -9,8 +9,8 @@ import (
"unicode/utf8" "unicode/utf8"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type unmarshalTextDecoder struct { type unmarshalTextDecoder struct {
@ -147,7 +147,7 @@ func (d *unmarshalTextDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int
return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path") return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path")
} }
func unquoteBytes(s []byte) (t []byte, ok bool) { func unquoteBytes(s []byte) (t []byte, ok bool) { //nolint: nonamedreturns
length := len(s) length := len(s)
if length < 2 || s[0] != '"' || s[length-1] != '"' { if length < 2 || s[0] != '"' || s[length-1] != '"' {
return return

View file

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type wrappedStringDecoder struct { type wrappedStringDecoder struct {

View file

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type Code interface { type Code interface {
@ -397,7 +397,7 @@ func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *
func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode { func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode {
// firstField is special StructHead operation for anonymous structure. // firstField is special StructHead operation for anonymous structure.
// So, StructHead's next operation is truly struct head operation. // So, StructHead's next operation is truly struct head operation.
for firstField.Op == OpStructHead { for firstField.Op == OpStructHead || firstField.Op == OpStructField {
firstField = firstField.Next firstField = firstField.Next
} }
lastField := firstField lastField := firstField

View file

@ -6,7 +6,7 @@ import (
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
var ( var (

View file

@ -8,8 +8,8 @@ import (
"sync/atomic" "sync/atomic"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type marshalerContext interface { type marshalerContext interface {
@ -489,7 +489,7 @@ func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) {
default: default:
// isPtr was originally used to indicate whether the type of top level is pointer. // 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. // 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 // See here for related issues: https://git.gammaspectra.live/P2Pool/go-json/issues/370
code, err := c.typeToCodeWithPtr(typ, true) code, err := c.typeToCodeWithPtr(typ, true)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -5,7 +5,7 @@ import (
"sync" "sync"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
type compileContext struct { type compileContext struct {

View file

@ -13,8 +13,8 @@ import (
"sync" "sync"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
func (t OpType) IsMultipleOpHead() bool { func (t OpType) IsMultipleOpHead() bool {
@ -589,6 +589,8 @@ func IsNilForMarshaler(v interface{}) bool {
return rv.IsNil() return rv.IsNil()
case reflect.Slice: case reflect.Slice:
return rv.IsNil() || rv.Len() == 0 return rv.IsNil() || rv.Len() == 0
case reflect.Array:
return rv.IsZero()
case reflect.String: case reflect.String:
return rv.Len() == 0 return rv.Len() == 0
} }

View file

@ -4,7 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/goccy/go-json/internal/errors" "git.gammaspectra.live/P2Pool/go-json/internal/errors"
) )
func takeIndentSrcRuntimeContext(src []byte) (*RuntimeContext, []byte) { func takeIndentSrcRuntimeContext(src []byte) (*RuntimeContext, []byte) {

View file

@ -1,3 +1,27 @@
// 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 package encoder
import ( import (

View file

@ -1,11 +1,13 @@
package encoder package encoder
import ( import (
"bytes"
"fmt" "fmt"
"sort"
"strings" "strings"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
const uintptrSize = 4 << (^uintptr(0) >> 63) const uintptrSize = 4 << (^uintptr(0) >> 63)
@ -555,6 +557,87 @@ func (c *Opcode) Dump() string {
return strings.Join(codes, "\n") 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 { func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()

View file

@ -23,6 +23,7 @@ type Option struct {
ColorScheme *ColorScheme ColorScheme *ColorScheme
Context context.Context Context context.Context
DebugOut io.Writer DebugOut io.Writer
DebugDOTOut io.WriteCloser
} }
type EncodeFormat struct { type EncodeFormat struct {

View file

@ -1,3 +1,27 @@
// 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 package encoder
import ( import (

View file

@ -2,8 +2,9 @@ package vm
import ( import (
"fmt" "fmt"
"io"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
@ -14,6 +15,11 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
} else { } else {
code = codeSet.NoescapeKeyCode 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 { if err := recover(); err != nil {
w := ctx.Option.DebugOut w := ctx.Option.DebugOut

View file

@ -5,5 +5,5 @@ import (
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile, // `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
// so forcibly make dependencies and avoid compiling in concurrent. // so forcibly make dependencies and avoid compiling in concurrent.
// dependency order: vm => vm_indent => vm_color => vm_color_indent // dependency order: vm => vm_indent => vm_color => vm_color_indent
_ "github.com/goccy/go-json/internal/encoder/vm_indent" _ "git.gammaspectra.live/P2Pool/go-json/internal/encoder/vm_indent"
) )

View file

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
const uintptrSize = 4 << (^uintptr(0) >> 63) const uintptrSize = 4 << (^uintptr(0) >> 63)

View file

@ -7,8 +7,8 @@ import (
"sort" "sort"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -3,7 +3,7 @@ package vm_color
import ( import (
"fmt" "fmt"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -5,5 +5,5 @@ import (
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile, // `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
// so forcibly make dependencies and avoid compiling in concurrent. // so forcibly make dependencies and avoid compiling in concurrent.
// dependency order: vm => vm_indent => vm_color => vm_color_indent // dependency order: vm => vm_indent => vm_color => vm_color_indent
_ "github.com/goccy/go-json/internal/encoder/vm_color_indent" _ "git.gammaspectra.live/P2Pool/go-json/internal/encoder/vm_color_indent"
) )

View file

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
const uintptrSize = 4 << (^uintptr(0) >> 63) const uintptrSize = 4 << (^uintptr(0) >> 63)

View file

@ -7,8 +7,8 @@ import (
"sort" "sort"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -3,7 +3,7 @@ package vm_color_indent
import ( import (
"fmt" "fmt"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
const uintptrSize = 4 << (^uintptr(0) >> 63) const uintptrSize = 4 << (^uintptr(0) >> 63)

View file

@ -7,8 +7,8 @@ import (
"sort" "sort"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -3,7 +3,7 @@ package vm_indent
import ( import (
"fmt" "fmt"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -5,5 +5,5 @@ import (
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile, // `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
// so forcibly make dependencies and avoid compiling in concurrent. // so forcibly make dependencies and avoid compiling in concurrent.
// dependency order: vm => vm_indent => vm_color => vm_color_indent // dependency order: vm => vm_indent => vm_color => vm_color_indent
_ "github.com/goccy/go-json/internal/encoder/vm_color" _ "git.gammaspectra.live/P2Pool/go-json/internal/encoder/vm_color"
) )

View file

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
const uintptrSize = 4 << (^uintptr(0) >> 63) const uintptrSize = 4 << (^uintptr(0) >> 63)

View file

@ -7,8 +7,8 @@ import (
"sort" "sort"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime" "git.gammaspectra.live/P2Pool/go-json/internal/runtime"
) )
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {

View file

@ -252,7 +252,6 @@ func IfaceIndir(*Type) bool
//go:noescape //go:noescape
func RType2Type(t *Type) reflect.Type func RType2Type(t *Type) reflect.Type
//go:nolint structcheck
type emptyInterface struct { type emptyInterface struct {
_ *Type _ *Type
ptr unsafe.Pointer ptr unsafe.Pointer

37
json.go
View file

@ -5,7 +5,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
// Marshaler is the interface implemented by types that // Marshaler is the interface implemented by types that
@ -89,31 +89,31 @@ type UnmarshalerContext interface {
// //
// Examples of struct field tags and their meanings: // Examples of struct field tags and their meanings:
// //
// // Field appears in JSON as key "myName". // // Field appears in JSON as key "myName".
// Field int `json:"myName"` // Field int `json:"myName"`
// //
// // Field appears in JSON as key "myName" and // // Field appears in JSON as key "myName" and
// // the field is omitted from the object if its value is empty, // // the field is omitted from the object if its value is empty,
// // as defined above. // // as defined above.
// Field int `json:"myName,omitempty"` // Field int `json:"myName,omitempty"`
// //
// // Field appears in JSON as key "Field" (the default), but // // Field appears in JSON as key "Field" (the default), but
// // the field is skipped if empty. // // the field is skipped if empty.
// // Note the leading comma. // // Note the leading comma.
// Field int `json:",omitempty"` // Field int `json:",omitempty"`
// //
// // Field is ignored by this package. // // Field is ignored by this package.
// Field int `json:"-"` // Field int `json:"-"`
// //
// // Field appears in JSON as key "-". // // Field appears in JSON as key "-".
// Field int `json:"-,"` // Field int `json:"-,"`
// //
// The "string" option signals that a field is stored as JSON inside a // 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, // JSON-encoded string. It applies only to fields of string, floating point,
// integer, or boolean types. This extra level of encoding is sometimes used // integer, or boolean types. This extra level of encoding is sometimes used
// when communicating with JavaScript programs: // when communicating with JavaScript programs:
// //
// Int64String int64 `json:",string"` // Int64String int64 `json:",string"`
// //
// The key name will be used if it's a non-empty string consisting of // The key name will be used if it's a non-empty string consisting of
// only Unicode letters, digits, and ASCII punctuation except quotation // only Unicode letters, digits, and ASCII punctuation except quotation
@ -166,7 +166,6 @@ type UnmarshalerContext interface {
// JSON cannot represent cyclic data structures and Marshal does not // JSON cannot represent cyclic data structures and Marshal does not
// handle them. Passing cyclic structures to Marshal will result in // handle them. Passing cyclic structures to Marshal will result in
// an infinite recursion. // an infinite recursion.
//
func Marshal(v interface{}) ([]byte, error) { func Marshal(v interface{}) ([]byte, error) {
return MarshalWithOption(v) return MarshalWithOption(v)
} }
@ -264,14 +263,13 @@ func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...E
// //
// The JSON null value unmarshals into an interface, map, pointer, or slice // 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 // 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 // “not present,” unmarshaling a JSON null into any other Go type has no effect
// on the value and produces no error. // on the value and produces no error.
// //
// When unmarshaling quoted strings, invalid UTF-8 or // When unmarshaling quoted strings, invalid UTF-8 or
// invalid UTF-16 surrogate pairs are not treated as an error. // invalid UTF-16 surrogate pairs are not treated as an error.
// Instead, they are replaced by the Unicode replacement // Instead, they are replaced by the Unicode replacement
// character U+FFFD. // character U+FFFD.
//
func Unmarshal(data []byte, v interface{}) error { func Unmarshal(data []byte, v interface{}) error {
return unmarshal(data, v) return unmarshal(data, v)
} }
@ -299,7 +297,6 @@ func UnmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc)
// Number, for JSON numbers // Number, for JSON numbers
// string, for JSON string literals // string, for JSON string literals
// nil, for JSON null // nil, for JSON null
//
type Token = json.Token type Token = json.Token
// A Number represents a JSON number literal. // A Number represents a JSON number literal.

View file

@ -8,7 +8,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
var validTests = []struct { var validTests = []struct {

View file

@ -8,7 +8,7 @@ import (
"regexp" "regexp"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestNumberIsValid(t *testing.T) { func TestNumberIsValid(t *testing.T) {

View file

@ -3,8 +3,8 @@ package json
import ( import (
"io" "io"
"github.com/goccy/go-json/internal/decoder" "git.gammaspectra.live/P2Pool/go-json/internal/decoder"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
type EncodeOption = encoder.Option type EncodeOption = encoder.Option
@ -48,6 +48,13 @@ func DebugWith(w io.Writer) EncodeOptionFunc {
} }
} }
// DebugDOT sets the destination to write opcodes graph.
func DebugDOT(w io.WriteCloser) EncodeOptionFunc {
return func(opt *EncodeOption) {
opt.DebugDOTOut = w
}
}
// Colorize add an identifier for coloring to the string of the encoded result. // Colorize add an identifier for coloring to the string of the encoded result.
func Colorize(scheme *ColorScheme) EncodeOptionFunc { func Colorize(scheme *ColorScheme) EncodeOptionFunc {
return func(opt *EncodeOption) { return func(opt *EncodeOption) {

View file

@ -3,7 +3,7 @@ package json
import ( import (
"reflect" "reflect"
"github.com/goccy/go-json/internal/decoder" "git.gammaspectra.live/P2Pool/go-json/internal/decoder"
) )
// CreatePath creates JSON Path. // CreatePath creates JSON Path.

View file

@ -6,7 +6,7 @@ import (
"sort" "sort"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestExtractPath(t *testing.T) { func TestExtractPath(t *testing.T) {

View file

@ -1,7 +1,7 @@
package json package json
import ( import (
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
type ( type (

View file

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type queryTestX struct { type queryTestX struct {

View file

@ -4,7 +4,7 @@ import (
"testing" "testing"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/encoder" "git.gammaspectra.live/P2Pool/go-json/internal/encoder"
) )
func TestOpcodeSize(t *testing.T) { func TestOpcodeSize(t *testing.T) {

View file

@ -19,7 +19,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
// Test values for the stream test. // Test values for the stream test.

View file

@ -7,7 +7,7 @@ package json_test
import ( import (
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type basicLatin2xTag struct { type basicLatin2xTag struct {

View file

@ -5,9 +5,17 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type customArray [2]int
type customArrayWithMarshaler [2]int
func (b customArrayWithMarshaler) MarshalJSON() ([]byte, error) {
return json.Marshal([2]int(b))
}
func TestCoverArray(t *testing.T) { func TestCoverArray(t *testing.T) {
type structArray struct { type structArray struct {
A [2]int `json:"a"` A [2]int `json:"a"`
@ -47,6 +55,24 @@ func TestCoverArray(t *testing.T) {
A *[2]*int `json:"a,string"` A *[2]*int `json:"a,string"`
} }
type structCustomArrayOmitEmpty struct {
A customArray `json:"a,omitempty"`
}
type structSecondFieldCustomArrayOmitEmpty struct {
C [2]int `json:"c"`
A customArray `json:"a,omitempty"`
}
type structCustomArrayWithMarshalerOmitEmpty struct {
A customArrayWithMarshaler `json:"a,omitempty"`
}
type structSecondFieldCustomArrayWithMarshalerOmitEmpty struct {
C [2]int `json:"c"`
A customArrayWithMarshaler `json:"a,omitempty"`
}
tests := []struct { tests := []struct {
name string name string
data interface{} data interface{}
@ -1421,6 +1447,46 @@ func TestCoverArray(t *testing.T) {
B: [2]int{1}, B: [2]int{1},
}, },
}, },
{
name: "AnonymousHeadCustomArrayOmitEmpty",
data: struct {
structCustomArrayOmitEmpty
B customArray `json:"b,omitempty"`
}{
structCustomArrayOmitEmpty: structCustomArrayOmitEmpty{A: customArray{-1}},
B: [2]int{1},
},
},
{
name: "AnonymousHeadCustomArrayOmitEmpty",
data: struct {
structCustomArrayOmitEmpty
B customArray `json:"b,omitempty"`
}{
structCustomArrayOmitEmpty: structCustomArrayOmitEmpty{A: customArray{-1}},
B: [2]int{1},
},
},
{
name: "AnonymousHeadCustomArrayWithMarshalerOmitEmpty",
data: struct {
structCustomArrayWithMarshalerOmitEmpty
B customArrayWithMarshaler `json:"b,omitempty"`
}{
structCustomArrayWithMarshalerOmitEmpty: structCustomArrayWithMarshalerOmitEmpty{A: customArrayWithMarshaler{-1}},
B: [2]int{1},
},
},
{
name: "AnonymousHeadCustomArrayWithMarshalerOmitEmpty",
data: struct {
structCustomArrayWithMarshalerOmitEmpty
B customArrayWithMarshaler `json:"b,omitempty"`
}{
structCustomArrayWithMarshalerOmitEmpty: structCustomArrayWithMarshalerOmitEmpty{A: customArrayWithMarshaler{-1}},
B: [2]int{1},
},
},
{ {
name: "AnonymousHeadArrayString", name: "AnonymousHeadArrayString",
data: struct { data: struct {

View file

@ -6,7 +6,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type customBool bool type customBool bool

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverBytes(t *testing.T) { func TestCoverBytes(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverFloat32(t *testing.T) { func TestCoverFloat32(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverFloat64(t *testing.T) { func TestCoverFloat64(t *testing.T) {

View file

@ -4,7 +4,7 @@ import (
"bytes" "bytes"
stdjson "encoding/json" stdjson "encoding/json"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func intptr(v int) *int { return &v } func intptr(v int) *int { return &v }

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverInt16(t *testing.T) { func TestCoverInt16(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverInt32(t *testing.T) { func TestCoverInt32(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverInt64(t *testing.T) { func TestCoverInt64(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverInt8(t *testing.T) { func TestCoverInt8(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverInt(t *testing.T) { func TestCoverInt(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type recursiveMap struct { type recursiveMap struct {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type coverMarshalJSON struct { type coverMarshalJSON struct {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
type coverMarshalText struct { type coverMarshalText struct {

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/goccy/go-json" "git.gammaspectra.live/P2Pool/go-json"
) )
func TestCoverNumber(t *testing.T) { func TestCoverNumber(t *testing.T) {

Some files were not shown because too many files have changed in this diff Show more