Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Opt/decoder #641

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/compatibility_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
build:
strategy:
matrix:
go-version: [1.15.x, 1.16.x, 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x]
go-version: [1.16.x, 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x]
os: [arm, X64]
runs-on: ${{ matrix.os }}
steps:
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/unit_test-linux-arm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Unit Test Linux arm

on: push

jobs:
build:
strategy:
matrix:
go-version: [1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x]
runs-on: [arm]
steps:
- name: Clear repository
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE

- uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}

- uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-

- name: Unit Test
run: |
go test -race -covermode=atomic -coverprofile=coverage.txt ./...

- name: external
run: |
cd ./external_jsonlib_test
GOMAXPROCS=4 go test -v -race ./...

- name: external
run: |
cd ./loader
GOMAXPROCS=4 go test -v -race ./...

- name: Codecov
run: bash <(curl -s https://codecov.io/bash)
4 changes: 2 additions & 2 deletions .github/workflows/unit_test-linux-x64.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: Unit Test Linux-X64
name: Unit Test Linux X64

on: push

jobs:
build:
strategy:
matrix:
go-version: [1.16.x, 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x]
go-version: [1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x]
runs-on: [self-hosted, X64]
steps:
- name: Clear repository
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ ast/bench.sh

!testdata/*.json.gz
fuzz/testdata
*__debug_bin
*__debug_bin*
*pprof
*coverage.txt
4 changes: 2 additions & 2 deletions ast/api.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build (amd64 && go1.16 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.16,!go1.23 arm64,go1.20,!go1.23
//go:build (amd64 && go1.17 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.17,!go1.23 arm64,go1.20,!go1.23

/*
* Copyright 2022 ByteDance Inc.
Expand Down
4 changes: 2 additions & 2 deletions ast/api_compat.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !amd64,!arm64 go1.23 !go1.16 arm64,!go1.20
// +build !amd64,!arm64 go1.23 !go1.17 arm64,!go1.20

/*
* Copyright 2022 ByteDance Inc.
Expand Down Expand Up @@ -27,7 +27,7 @@ import (
)

func init() {
println("WARNING:(ast) sonic only supports Go1.16~1.22, but your environment is not suitable")
println("WARNING:(ast) sonic only supports go1.17~1.22, but your environment is not suitable")
}

func quote(buf *[]byte, val string) {
Expand Down
4 changes: 2 additions & 2 deletions ast/api_native_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build (amd64 && go1.16 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.16,!go1.23 arm64,go1.20,!go1.23
//go:build (amd64 && go1.17 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.17,!go1.23 arm64,go1.20,!go1.23

/*
* Copyright 2022 ByteDance Inc.
Expand Down
2 changes: 1 addition & 1 deletion ast/b64_amd64.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build amd64,go1.16
// +build amd64,go1.17

/**
* Copyright 2023 ByteDance Inc.
Expand Down
2 changes: 1 addition & 1 deletion ast/b64_compat.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !amd64 !go1.16
// +build !amd64 !go1.17

/*
* Copyright 2022 ByteDance Inc.
Expand Down
2 changes: 1 addition & 1 deletion compat.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !amd64 !go1.16 go1.23
// +build !amd64 !go1.17 go1.23

/*
* Copyright 2021 ByteDance Inc.
Expand Down
6 changes: 4 additions & 2 deletions decode_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// +build amd64,go1.16,!go1.23
//go:build (amd64 && go1.17 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.17,!go1.23 arm64,go1.20,!go1.23

/*
* Copyright 2021 ByteDance Inc.
Expand Down Expand Up @@ -458,6 +459,8 @@ var unmarshalTests = []unmarshalTest{
{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},
{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
{in: `{"":""}`, ptr: new(struct{}), out: struct{}{}},
{in: `{"x":""}`, ptr: new(struct{ X json.Number }), err: errors.New("empty string into json number")},

// raw values with whitespace
{in: "\n true ", ptr: new(bool), out: true},
Expand Down Expand Up @@ -1116,7 +1119,6 @@ func TestMarshalEmbeds(t *testing.T) {

func TestUnmarshal(t *testing.T) {
for i, tt := range unmarshalTests {
t.Log(i, tt.in)
if !json.Valid([]byte(tt.in)) {
continue
}
Expand Down
4 changes: 2 additions & 2 deletions decoder/decoder_compat.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !amd64 !go1.16 go1.23
// +build !amd64,!arm64 go1.23 !go1.17 arm64,!go1.20

/*
* Copyright 2023 ByteDance Inc.
Expand Down Expand Up @@ -30,7 +30,7 @@ import (
)

func init() {
println("WARNING: sonic only supports Go1.16~1.22 && CPU amd64, but your environment is not suitable")
println("WARNING: sonic/decoder only supports (go1.17~1.22 && CPU amd64) or (go1.20~1.22 && CPU arm64), but your environment is not suitable")
}

const (
Expand Down
36 changes: 19 additions & 17 deletions decoder/decoder_amd64.go → decoder/decoder_native.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// +build amd64,go1.16,!go1.23
//go:build (amd64 && go1.17 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.17,!go1.23 arm64,go1.20,!go1.23


/*
* Copyright 2023 ByteDance Inc.
Expand All @@ -19,50 +21,50 @@
package decoder

import (
`github.com/bytedance/sonic/internal/decoder`
`github.com/bytedance/sonic/internal/decoder/api`
)

// Decoder is the decoder context object
type Decoder = decoder.Decoder
type Decoder = api.Decoder

// SyntaxError represents json syntax error
type SyntaxError = decoder.SyntaxError
type SyntaxError = api.SyntaxError

// MismatchTypeError represents dismatching between json and object
type MismatchTypeError = decoder.MismatchTypeError
type MismatchTypeError = api.MismatchTypeError

// Options for decode.
type Options = decoder.Options
type Options = api.Options

const (
OptionUseInt64 Options = decoder.OptionUseInt64
OptionUseNumber Options = decoder.OptionUseNumber
OptionUseUnicodeErrors Options = decoder.OptionUseUnicodeErrors
OptionDisableUnknown Options = decoder.OptionDisableUnknown
OptionCopyString Options = decoder.OptionCopyString
OptionValidateString Options = decoder.OptionValidateString
OptionUseInt64 Options = api.OptionUseInt64
OptionUseNumber Options = api.OptionUseNumber
OptionUseUnicodeErrors Options = api.OptionUseUnicodeErrors
OptionDisableUnknown Options = api.OptionDisableUnknown
OptionCopyString Options = api.OptionCopyString
OptionValidateString Options = api.OptionValidateString
)

// StreamDecoder is the decoder context object for streaming input.
type StreamDecoder = decoder.StreamDecoder
type StreamDecoder = api.StreamDecoder

var (
// NewDecoder creates a new decoder instance.
NewDecoder = decoder.NewDecoder
NewDecoder = api.NewDecoder

// NewStreamDecoder adapts to encoding/json.NewDecoder API.
//
// NewStreamDecoder returns a new decoder that reads from r.
NewStreamDecoder = decoder.NewStreamDecoder
NewStreamDecoder = api.NewStreamDecoder

// Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
// order to reduce the first-hit latency.
//
// Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
// a compile option to set the depth of recursive compile for the nested struct type.
Pretouch = decoder.Pretouch
Pretouch = api.Pretouch

// Skip skips only one json value, and returns first non-blank character position and its ending position if it is valid.
// Otherwise, returns negative error code using start and invalid character position using end
Skip = decoder.Skip
Skip = api.Skip
)
82 changes: 42 additions & 40 deletions decoder/decoder_amd64_test.go → decoder/decoder_native_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// +build amd64,go1.16,!go1.23
//go:build (amd64 && go1.17 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.17,!go1.23 arm64,go1.20,!go1.23


/*
* Copyright 2021 ByteDance Inc.
Expand All @@ -20,61 +22,61 @@ package decoder

import (
`encoding/json`
`strings`
_`strings`
`testing`
`reflect`
_`reflect`

`github.com/bytedance/sonic/internal/rt`
`github.com/stretchr/testify/assert`
)

func TestSkipMismatchTypeAmd64Error(t *testing.T) {
t.Run("struct", func(t *testing.T) {
println("TestSkipError")
type skiptype struct {
A int `json:"a"`
B string `json:"b"`
// t.Run("struct", func(t *testing.T) {
// println("TestSkipError")
// type skiptype struct {
// A int `json:"a"`
// B string `json:"b"`

Pass *int `json:"pass"`
// Pass *int `json:"pass"`

C struct{
// C struct{

Pass4 interface{} `json:"pass4"`
// Pass4 interface{} `json:"pass4"`

D struct{
E float32 `json:"e"`
} `json:"d"`
// D struct{
// E float32 `json:"e"`
// } `json:"d"`

Pass2 int `json:"pass2"`
// Pass2 int `json:"pass2"`

} `json:"c"`
// } `json:"c"`

E bool `json:"e"`
F []int `json:"f"`
G map[string]int `json:"g"`
H bool `json:"h,string"`
// E bool `json:"e"`
// F []int `json:"f"`
// G map[string]int `json:"g"`
// H bool `json:"h,string"`

Pass3 int `json:"pass2"`
// Pass3 int `json:"pass2"`

I json.Number `json:"i"`
}
var obj, obj2 = &skiptype{Pass:new(int)}, &skiptype{Pass:new(int)}
var data = `{"a":"","b":1,"c":{"d":true,"pass2":1,"pass4":true},"e":{},"f":"","g":[],"pass":null,"h":"1.0","i":true,"pass3":1}`
d := NewDecoder(data)
err := d.Decode(obj)
err2 := json.Unmarshal([]byte(data), obj2)
println(err2.Error())
assert.Equal(t, err2 == nil, err == nil)
// assert.Equal(t, len(data), d.i)
assert.Equal(t, obj2, obj)
if te, ok := err.(*MismatchTypeError); ok {
assert.Equal(t, reflect.TypeOf(obj.I), te.Type)
assert.Equal(t, strings.Index(data, `"i":t`)+4, te.Pos)
println(err.Error())
} else {
t.Fatal("invalid error")
}
})
// I json.Number `json:"i"`
// }
// var obj, obj2 = &skiptype{Pass:new(int)}, &skiptype{Pass:new(int)}
// var data = `{"a":"","b":1,"c":{"d":true,"pass2":1,"pass4":true},"e":{},"f":"","g":[],"pass":null,"h":"1.0","i":true,"pass3":1}`
// d := NewDecoder(data)
// err := d.Decode(obj)
// err2 := json.Unmarshal([]byte(data), obj2)
// println(err2.Error())
// assert.Equal(t, err2 == nil, err == nil)
// // assert.Equal(t, len(data), d.i)
// assert.Equal(t, obj2, obj)
// if te, ok := err.(*MismatchTypeError); ok {
// assert.Equal(t, reflect.TypeOf(obj.I), te.Type)
// assert.Equal(t, strings.Index(data, `"i":t`)+4, te.Pos)
// println(err.Error())
// } else {
// t.Fatal("invalid error")
// }
// })
t.Run("short array", func(t *testing.T) {
var obj, obj2 = &[]int{}, &[]int{}
var data = `[""]`
Expand Down
2 changes: 1 addition & 1 deletion decoder/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func TestDecodeCorrupt(t *testing.T) {
if err == nil {
t.Fatalf("%#v", d)
}
if !strings.Contains(err.Error(), "invalid char"){
if !strings.Contains(err.Error(), "Syntax error"){
t.Fatal(err.Error())
}
}
Expand Down
3 changes: 2 additions & 1 deletion encode_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// +build amd64,go1.16,!go1.23
//go:build (amd64 && go1.17 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.17,!go1.23 arm64,go1.20,!go1.23

/*
* Copyright 2021 ByteDance Inc.
Expand Down
2 changes: 1 addition & 1 deletion encoder/encoder_amd64.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build amd64,go1.16,!go1.23
// +build amd64,go1.17,!go1.23

/*
* Copyright 2023 ByteDance Inc.
Expand Down
2 changes: 1 addition & 1 deletion encoder/encoder_amd64_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build amd64,go1.16,!go1.23
// +build amd64,go1.17,!go1.23

/*
* Copyright 2021 ByteDance Inc.
Expand Down
4 changes: 2 additions & 2 deletions encoder/encoder_compat.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !amd64 !go1.16 go1.23
// +build !amd64 !go1.17 go1.23

/*
* Copyright 2023 ByteDance Inc.
Expand Down Expand Up @@ -28,7 +28,7 @@ import (
)

func init() {
println("WARNING:(encoder) sonic only supports Go1.16~1.22 && CPU amd64, but your environment is not suitable")
println("WARNING:(encoder) sonic only supports go1.17~1.22 && CPU amd64, but your environment is not suitable")
}

// EnableFallback indicates if encoder use fallback
Expand Down
Loading
Loading