Update go dep (#1560)

This fix updates go dep with `dep ensure --update` as well as the following:
- Removed github.com/ugorji/go restriction in Gopkg.toml (fixes  #1557)
- Added github.com/flynn/go-shlex in Makefile (neede by Caddy, maybe removed later)

This fix fixes #1557

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Yong Tang 2018-02-23 12:10:34 -08:00 committed by Miek Gieben
parent 9047bdf3a0
commit 604c0045e7
563 changed files with 107278 additions and 95314 deletions

View file

@ -1,4 +1,4 @@
.idea
/coverage.txt
/profile.out
/vendor
/bug_test.go
/coverage.txt
/.idea

45
vendor/github.com/json-iterator/go/Gopkg.lock generated vendored Normal file
View file

@ -0,0 +1,45 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/davecgh/go-spew"
packages = ["spew"]
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "github.com/google/gofuzz"
packages = ["."]
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
name = "github.com/stretchr/testify"
packages = [
"assert",
"require"
]
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.1"
[[projects]]
name = "github.com/v2pro/plz"
packages = [
"concurrent",
"reflect2"
]
revision = "10fc95fad3224a032229e59f6e7023137d82b526"
version = "0.9.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "64fe3937a1afce5cb551c06ff7109065c971643e082512243d1071bab428ff14"
solver-name = "gps-cdcl"
solver-version = 1

37
vendor/github.com/json-iterator/go/Gopkg.toml generated vendored Normal file
View file

@ -0,0 +1,37 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "github.com/davecgh/go-spew"
version = "1.1.0"
[[constraint]]
branch = "master"
name = "github.com/google/gofuzz"
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.1.4"
[[constraint]]
name = "github.com/v2pro/plz"
version = "0.9.1"

View file

@ -8,6 +8,8 @@
A high-performance 100% compatible drop-in replacement of "encoding/json"
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
```
Go开发者们请加入我们滴滴出行平台技术部 taowen@didichuxing.com
```

View file

@ -16,15 +16,6 @@ func Unmarshal(data []byte, v interface{}) error {
return ConfigDefault.Unmarshal(data, v)
}
func lastNotSpacePos(data []byte) int {
for i := len(data) - 1; i >= 0; i-- {
if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
return i + 1
}
}
return 0
}
// UnmarshalFromString convenient method to read from string instead of []byte
func UnmarshalFromString(str string, v interface{}) error {
return ConfigDefault.UnmarshalFromString(str, v)
@ -71,6 +62,11 @@ type Decoder struct {
// Decode decode JSON into interface{}
func (adapter *Decoder) Decode(obj interface{}) error {
if adapter.iter.head == adapter.iter.tail && adapter.iter.reader != nil {
if !adapter.iter.loadMore() {
return io.EOF
}
}
adapter.iter.ReadVal(obj)
err := adapter.iter.Error
if err == io.EOF {
@ -90,11 +86,21 @@ func (adapter *Decoder) Buffered() io.Reader {
return bytes.NewReader(remaining)
}
// UseNumber for number JSON element, use float64 or json.NumberValue (alias of string)
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
// Number instead of as a float64.
func (adapter *Decoder) UseNumber() {
origCfg := adapter.iter.cfg.configBeforeFrozen
origCfg.UseNumber = true
adapter.iter.cfg = origCfg.Froze().(*frozenConfig)
cfg := adapter.iter.cfg.configBeforeFrozen
cfg.UseNumber = true
adapter.iter.cfg = cfg.frozeWithCacheReuse()
}
// 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 (adapter *Decoder) DisallowUnknownFields() {
cfg := adapter.iter.cfg.configBeforeFrozen
cfg.DisallowUnknownFields = true
adapter.iter.cfg = cfg.frozeWithCacheReuse()
}
// NewEncoder same as json.NewEncoder
@ -117,14 +123,16 @@ func (adapter *Encoder) Encode(val interface{}) error {
// SetIndent set the indention. Prefix is not supported
func (adapter *Encoder) SetIndent(prefix, indent string) {
adapter.stream.cfg.indentionStep = len(indent)
config := adapter.stream.cfg.configBeforeFrozen
config.IndentionStep = len(indent)
adapter.stream.cfg = config.frozeWithCacheReuse()
}
// SetEscapeHTML escape html by default, set to false to disable
func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) {
config := adapter.stream.cfg.configBeforeFrozen
config.EscapeHTML = escapeHTML
adapter.stream.cfg = config.Froze().(*frozenConfig)
adapter.stream.cfg = config.frozeWithCacheReuse()
}
// Valid reports whether data is a valid JSON encoding.

View file

@ -5,6 +5,9 @@ import (
"fmt"
"io"
"reflect"
"unsafe"
"github.com/v2pro/plz/reflect2"
"strconv"
)
// Any generic object representation.
@ -25,7 +28,6 @@ type Any interface {
ToString() string
ToVal(val interface{})
Get(path ...interface{}) Any
// TODO: add Set
Size() int
Keys() []string
GetInterface() interface{}
@ -35,7 +37,7 @@ type Any interface {
type baseAny struct{}
func (any *baseAny) Get(path ...interface{}) Any {
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
}
func (any *baseAny) Size() int {
@ -89,7 +91,7 @@ func Wrap(val interface{}) Any {
if isAny {
return asAny
}
typ := reflect.TypeOf(val)
typ := reflect2.TypeOf(val)
switch typ.Kind() {
case reflect.Slice:
return wrapArray(val)
@ -100,6 +102,9 @@ func Wrap(val interface{}) Any {
case reflect.String:
return WrapString(val.(string))
case reflect.Int:
if strconv.IntSize == 32 {
return WrapInt32(int32(val.(int)))
}
return WrapInt64(int64(val.(int)))
case reflect.Int8:
return WrapInt32(int32(val.(int8)))
@ -110,7 +115,15 @@ func Wrap(val interface{}) Any {
case reflect.Int64:
return WrapInt64(val.(int64))
case reflect.Uint:
if strconv.IntSize == 32 {
return WrapUint32(uint32(val.(uint)))
}
return WrapUint64(uint64(val.(uint)))
case reflect.Uintptr:
if ptrSize == 32 {
return WrapUint32(uint32(val.(uintptr)))
}
return WrapUint64(uint64(val.(uintptr)))
case reflect.Uint8:
return WrapUint32(uint32(val.(uint8)))
case reflect.Uint16:
@ -243,3 +256,66 @@ func locatePath(iter *Iterator, path []interface{}) Any {
}
return iter.readAny()
}
var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem()
func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ == anyType {
return &directAnyCodec{}
}
if typ.Implements(anyType) {
return &anyCodec{
valType: typ,
}
}
return nil
}
func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ == anyType {
return &directAnyCodec{}
}
if typ.Implements(anyType) {
return &anyCodec{
valType: typ,
}
}
return nil
}
type anyCodec struct {
valType reflect2.Type
}
func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
panic("not implemented")
}
func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
obj := codec.valType.UnsafeIndirect(ptr)
any := obj.(Any)
any.WriteTo(stream)
}
func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool {
obj := codec.valType.UnsafeIndirect(ptr)
any := obj.(Any)
return any.Size() == 0
}
type directAnyCodec struct {
}
func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*(*Any)(ptr) = iter.readAny()
}
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
any := *(*Any)(ptr)
any.WriteTo(stream)
}
func (codec *directAnyCodec) IsEmpty(ptr unsafe.Pointer) bool {
any := *(*Any)(ptr)
return any.Size() == 0
}

View file

@ -1,6 +1,9 @@
package jsoniter
import "unsafe"
import (
"io"
"unsafe"
)
type numberLazyAny struct {
baseAny
@ -29,7 +32,9 @@ func (any *numberLazyAny) ToInt() int {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadInt()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}
@ -37,7 +42,9 @@ func (any *numberLazyAny) ToInt32() int32 {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadInt32()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}
@ -45,7 +52,9 @@ func (any *numberLazyAny) ToInt64() int64 {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadInt64()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}
@ -53,7 +62,9 @@ func (any *numberLazyAny) ToUint() uint {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadUint()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}
@ -61,7 +72,9 @@ func (any *numberLazyAny) ToUint32() uint32 {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadUint32()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}
@ -69,7 +82,9 @@ func (any *numberLazyAny) ToUint64() uint64 {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadUint64()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}
@ -77,7 +92,9 @@ func (any *numberLazyAny) ToFloat32() float32 {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadFloat32()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}
@ -85,7 +102,9 @@ func (any *numberLazyAny) ToFloat64() float64 {
iter := any.cfg.BorrowIterator(any.buf)
defer any.cfg.ReturnIterator(iter)
val := iter.ReadFloat64()
any.err = iter.Error
if iter.Error != nil && iter.Error != io.EOF {
any.err = iter.Error
}
return val
}

View file

@ -14,7 +14,7 @@ func (any *stringAny) Get(path ...interface{}) Any {
if len(path) == 0 {
return any
}
return &invalidAny{baseAny{}, fmt.Errorf("Get %v from simple value", path)}
return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
}
func (any *stringAny) Parse() *Iterator {

12
vendor/github.com/json-iterator/go/build.sh generated vendored Executable file
View file

@ -0,0 +1,12 @@
#!/bin/bash
set -e
set -x
if [ ! -d /tmp/build-golang/src/github.com/json-iterator ]; then
mkdir -p /tmp/build-golang/src/github.com/json-iterator
ln -s $PWD /tmp/build-golang/src/github.com/json-iterator/go
fi
export GOPATH=/tmp/build-golang
go get -u github.com/golang/dep/cmd/dep
cd /tmp/build-golang/src/github.com/json-iterator/go
exec $GOPATH/bin/dep ensure -update

View file

@ -1,40 +0,0 @@
package jsoniter
import (
"bytes"
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
// Standard Encoder has trailing newline.
func TestEncoderHasTrailingNewline(t *testing.T) {
should := require.New(t)
var buf, stdbuf bytes.Buffer
enc := ConfigCompatibleWithStandardLibrary.NewEncoder(&buf)
enc.Encode(1)
stdenc := json.NewEncoder(&stdbuf)
stdenc.Encode(1)
should.Equal(stdbuf.Bytes(), buf.Bytes())
}
// Non-nil but empty map should be ignored.
func TestOmitempty(t *testing.T) {
o := struct {
A string `json:"a,omitempty"`
B string `json:"b,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
}{
A: "a",
B: "b",
Annotations: map[string]string{},
}
should := require.New(t)
var buf, stdbuf bytes.Buffer
enc := ConfigCompatibleWithStandardLibrary.NewEncoder(&buf)
enc.Encode(o)
stdenc := json.NewEncoder(&stdbuf)
stdenc.Encode(o)
should.Equal(string(stdbuf.Bytes()), string(buf.Bytes()))
}

View file

@ -2,11 +2,10 @@ package jsoniter
import (
"encoding/json"
"errors"
"io"
"reflect"
"sync/atomic"
"unsafe"
"github.com/v2pro/plz/reflect2"
"sync"
)
// Config customize how the API should behave.
@ -17,23 +16,13 @@ type Config struct {
EscapeHTML bool
SortMapKeys bool
UseNumber bool
DisallowUnknownFields bool
TagKey string
OnlyTaggedField bool
ValidateJsonRawMessage bool
ObjectFieldMustBeSimpleString bool
}
type frozenConfig struct {
configBeforeFrozen Config
sortMapKeys bool
indentionStep int
objectFieldMustBeSimpleString bool
decoderCache unsafe.Pointer
encoderCache unsafe.Pointer
extensions []Extension
streamPool chan *Stream
iteratorPool chan *Iterator
}
// API the public interface of this package.
// Primary Marshal and Unmarshal.
type API interface {
@ -48,6 +37,7 @@ type API interface {
NewEncoder(writer io.Writer) *Encoder
NewDecoder(reader io.Reader) *Decoder
Valid(data []byte) bool
RegisterExtension(extension Extension)
}
// ConfigDefault the default API
@ -71,33 +61,59 @@ var ConfigFastest = Config{
// Froze forge API from config
func (cfg Config) Froze() API {
// TODO: cache frozen config
frozenConfig := &frozenConfig{
api := &frozenConfig{
sortMapKeys: cfg.SortMapKeys,
indentionStep: cfg.IndentionStep,
objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
streamPool: make(chan *Stream, 16),
iteratorPool: make(chan *Iterator, 16),
onlyTaggedField: cfg.OnlyTaggedField,
disallowUnknownFields: cfg.DisallowUnknownFields,
}
atomic.StorePointer(&frozenConfig.decoderCache, unsafe.Pointer(&map[string]ValDecoder{}))
atomic.StorePointer(&frozenConfig.encoderCache, unsafe.Pointer(&map[string]ValEncoder{}))
api.streamPool = &sync.Pool{
New: func() interface{} {
return NewStream(api, nil, 512)
},
}
api.iteratorPool = &sync.Pool{
New: func() interface{} {
return NewIterator(api)
},
}
api.initCache()
encoderExtension := EncoderExtension{}
decoderExtension := DecoderExtension{}
if cfg.MarshalFloatWith6Digits {
frozenConfig.marshalFloatWith6Digits()
api.marshalFloatWith6Digits(encoderExtension)
}
if cfg.EscapeHTML {
frozenConfig.escapeHTML()
api.escapeHTML(encoderExtension)
}
if cfg.UseNumber {
frozenConfig.useNumber()
api.useNumber(decoderExtension)
}
if cfg.ValidateJsonRawMessage {
frozenConfig.validateJsonRawMessage()
api.validateJsonRawMessage(encoderExtension)
}
frozenConfig.configBeforeFrozen = cfg
return frozenConfig
if len(encoderExtension) > 0 {
api.extensions = append(api.extensions, encoderExtension)
}
if len(decoderExtension) > 0 {
api.extensions = append(api.extensions, decoderExtension)
}
api.configBeforeFrozen = cfg
return api
}
func (cfg *frozenConfig) validateJsonRawMessage() {
func (cfg Config) frozeWithCacheReuse() *frozenConfig {
api := getFrozenConfigFromCache(cfg)
if api != nil {
return api
}
api = cfg.Froze().(*frozenConfig)
addFrozenConfigToCache(cfg, api)
return api
}
func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) {
encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
rawMessage := *(*json.RawMessage)(ptr)
iter := cfg.BorrowIterator([]byte(rawMessage))
@ -111,18 +127,18 @@ func (cfg *frozenConfig) validateJsonRawMessage() {
}, func(ptr unsafe.Pointer) bool {
return false
}}
cfg.addEncoderToCache(reflect.TypeOf((*json.RawMessage)(nil)).Elem(), encoder)
cfg.addEncoderToCache(reflect.TypeOf((*RawMessage)(nil)).Elem(), encoder)
extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder
extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder
}
func (cfg *frozenConfig) useNumber() {
cfg.addDecoderToCache(reflect.TypeOf((*interface{})(nil)).Elem(), &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
func (cfg *frozenConfig) useNumber(extension DecoderExtension) {
extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
if iter.WhatIsNext() == NumberValue {
*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
} else {
*((*interface{})(ptr)) = iter.Read()
}
}})
}}
}
func (cfg *frozenConfig) getTagKey() string {
tagKey := cfg.configBeforeFrozen.TagKey
@ -132,7 +148,7 @@ func (cfg *frozenConfig) getTagKey() string {
return tagKey
}
func (cfg *frozenConfig) registerExtension(extension Extension) {
func (cfg *frozenConfig) RegisterExtension(extension Extension) {
cfg.extensions = append(cfg.extensions, extension)
}
@ -143,10 +159,6 @@ func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat32Lossy(*((*float32)(ptr)))
}
func (encoder *lossyFloat32Encoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float32)(ptr)) == 0
}
@ -158,20 +170,16 @@ func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat64Lossy(*((*float64)(ptr)))
}
func (encoder *lossyFloat64Encoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float64)(ptr)) == 0
}
// EnableLossyFloatMarshalling keeps 10**(-6) precision
// for float variables for better performance.
func (cfg *frozenConfig) marshalFloatWith6Digits() {
func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) {
// for better performance
cfg.addEncoderToCache(reflect.TypeOf((*float32)(nil)).Elem(), &lossyFloat32Encoder{})
cfg.addEncoderToCache(reflect.TypeOf((*float64)(nil)).Elem(), &lossyFloat64Encoder{})
extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{}
extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{}
}
type htmlEscapedStringEncoder struct {
@ -182,56 +190,12 @@ func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stre
stream.WriteStringWithHTMLEscaped(str)
}
func (encoder *htmlEscapedStringEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*string)(ptr)) == ""
}
func (cfg *frozenConfig) escapeHTML() {
cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{})
}
func (cfg *frozenConfig) addDecoderToCache(cacheKey reflect.Type, decoder ValDecoder) {
done := false
for !done {
ptr := atomic.LoadPointer(&cfg.decoderCache)
cache := *(*map[reflect.Type]ValDecoder)(ptr)
copied := map[reflect.Type]ValDecoder{}
for k, v := range cache {
copied[k] = v
}
copied[cacheKey] = decoder
done = atomic.CompareAndSwapPointer(&cfg.decoderCache, ptr, unsafe.Pointer(&copied))
}
}
func (cfg *frozenConfig) addEncoderToCache(cacheKey reflect.Type, encoder ValEncoder) {
done := false
for !done {
ptr := atomic.LoadPointer(&cfg.encoderCache)
cache := *(*map[reflect.Type]ValEncoder)(ptr)
copied := map[reflect.Type]ValEncoder{}
for k, v := range cache {
copied[k] = v
}
copied[cacheKey] = encoder
done = atomic.CompareAndSwapPointer(&cfg.encoderCache, ptr, unsafe.Pointer(&copied))
}
}
func (cfg *frozenConfig) getDecoderFromCache(cacheKey reflect.Type) ValDecoder {
ptr := atomic.LoadPointer(&cfg.decoderCache)
cache := *(*map[reflect.Type]ValDecoder)(ptr)
return cache[cacheKey]
}
func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
ptr := atomic.LoadPointer(&cfg.encoderCache)
cache := *(*map[reflect.Type]ValEncoder)(ptr)
return cache[cacheKey]
func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) {
encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{}
}
func (cfg *frozenConfig) cleanDecoders() {
@ -280,24 +244,22 @@ func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]
}
newCfg := cfg.configBeforeFrozen
newCfg.IndentionStep = len(indent)
return newCfg.Froze().Marshal(v)
return newCfg.frozeWithCacheReuse().Marshal(v)
}
func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
data := []byte(str)
data = data[:lastNotSpacePos(data)]
iter := cfg.BorrowIterator(data)
defer cfg.ReturnIterator(iter)
iter.ReadVal(v)
if iter.head == iter.tail {
iter.loadMore()
}
if iter.Error == io.EOF {
return nil
}
if iter.Error == nil {
iter.ReportError("UnmarshalFromString", "there are bytes left after unmarshal")
c := iter.nextToken()
if c == 0 {
if iter.Error == io.EOF {
return nil
}
return iter.Error
}
iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
return iter.Error
}
@ -308,24 +270,17 @@ func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
}
func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
data = data[:lastNotSpacePos(data)]
iter := cfg.BorrowIterator(data)
defer cfg.ReturnIterator(iter)
typ := reflect.TypeOf(v)
if typ.Kind() != reflect.Ptr {
// return non-pointer error
return errors.New("the second param must be ptr type")
}
iter.ReadVal(v)
if iter.head == iter.tail {
iter.loadMore()
}
if iter.Error == io.EOF {
return nil
}
if iter.Error == nil {
iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
c := iter.nextToken()
if c == 0 {
if iter.Error == io.EOF {
return nil
}
return iter.Error
}
iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
return iter.Error
}

View file

@ -0,0 +1,64 @@
//+build go1.9
package jsoniter
import (
"sync"
)
type frozenConfig struct {
configBeforeFrozen Config
sortMapKeys bool
indentionStep int
objectFieldMustBeSimpleString bool
onlyTaggedField bool
disallowUnknownFields bool
decoderCache sync.Map
encoderCache sync.Map
extensions []Extension
streamPool *sync.Pool
iteratorPool *sync.Pool
}
func (cfg *frozenConfig) initCache() {
cfg.decoderCache = sync.Map{}
cfg.encoderCache = sync.Map{}
}
func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) {
cfg.decoderCache.Store(cacheKey, decoder)
}
func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) {
cfg.encoderCache.Store(cacheKey, encoder)
}
func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder {
decoder, found := cfg.decoderCache.Load(cacheKey)
if found {
return decoder.(ValDecoder)
}
return nil
}
func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
encoder, found := cfg.encoderCache.Load(cacheKey)
if found {
return encoder.(ValEncoder)
}
return nil
}
var cfgCache = &sync.Map{}
func getFrozenConfigFromCache(cfg Config) *frozenConfig {
obj, found := cfgCache.Load(cfg)
if found {
return obj.(*frozenConfig)
}
return nil
}
func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) {
cfgCache.Store(cfg, frozenConfig)
}

View file

@ -0,0 +1,70 @@
//+build !go1.9
package jsoniter
import (
"sync"
)
type frozenConfig struct {
configBeforeFrozen Config
sortMapKeys bool
indentionStep int
objectFieldMustBeSimpleString bool
onlyTaggedField bool
disallowUnknownFields bool
cacheLock *sync.RWMutex
decoderCache map[uintptr]ValDecoder
encoderCache map[uintptr]ValEncoder
extensions []Extension
streamPool *sync.Pool
iteratorPool *sync.Pool
}
func (cfg *frozenConfig) initCache() {
cfg.cacheLock = &sync.RWMutex{}
cfg.decoderCache = map[uintptr]ValDecoder{}
cfg.encoderCache = map[uintptr]ValEncoder{}
}
func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) {
cfg.cacheLock.Lock()
cfg.decoderCache[cacheKey] = decoder
cfg.cacheLock.Unlock()
}
func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) {
cfg.cacheLock.Lock()
cfg.encoderCache[cacheKey] = encoder
cfg.cacheLock.Unlock()
}
func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder {
cfg.cacheLock.RLock()
decoder, _ := cfg.decoderCache[cacheKey].(ValDecoder)
cfg.cacheLock.RUnlock()
return decoder
}
func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
cfg.cacheLock.RLock()
encoder, _ := cfg.encoderCache[cacheKey].(ValEncoder)
cfg.cacheLock.RUnlock()
return encoder
}
var cfgCacheLock = &sync.RWMutex{}
var cfgCache = map[Config]*frozenConfig{}
func getFrozenConfigFromCache(cfg Config) *frozenConfig {
cfgCacheLock.RLock()
frozenConfig := cfgCache[cfg]
cfgCacheLock.RUnlock()
return frozenConfig
}
func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) {
cfgCacheLock.Lock()
cfgCache[cfg] = frozenConfig
cfgCacheLock.Unlock()
}

View file

@ -1,31 +0,0 @@
package jsoniter
import (
"encoding/json"
"strconv"
)
type Number string
// String returns the literal text of the number.
func (n Number) String() string { return string(n) }
// Float64 returns the number as a float64.
func (n Number) Float64() (float64, error) {
return strconv.ParseFloat(string(n), 64)
}
// Int64 returns the number as an int64.
func (n Number) Int64() (int64, error) {
return strconv.ParseInt(string(n), 10, 64)
}
func CastJsonNumber(val interface{}) (string, bool) {
switch typedVal := val.(type) {
case json.Number:
return string(typedVal), true
case Number:
return string(typedVal), true
}
return "", false
}

View file

@ -1,721 +0,0 @@
package jsoniter
import (
"encoding"
"encoding/json"
"fmt"
"reflect"
"time"
"unsafe"
)
// ValDecoder is an internal type registered to cache as needed.
// Don't confuse jsoniter.ValDecoder with json.Decoder.
// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link).
//
// Reflection on type to create decoders, which is then cached
// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions
// 1. create instance of new value, for example *int will need a int to be allocated
// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New
// 3. assignment to map, both key and value will be reflect.Value
// For a simple struct binding, it will be reflect.Value free and allocation free
type ValDecoder interface {
Decode(ptr unsafe.Pointer, iter *Iterator)
}
// ValEncoder is an internal type registered to cache as needed.
// Don't confuse jsoniter.ValEncoder with json.Encoder.
// For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link).
type ValEncoder interface {
IsEmpty(ptr unsafe.Pointer) bool
Encode(ptr unsafe.Pointer, stream *Stream)
EncodeInterface(val interface{}, stream *Stream)
}
type checkIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool
}
// WriteToStream the default implementation for TypeEncoder method EncodeInterface
func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) {
e := (*emptyInterface)(unsafe.Pointer(&val))
if e.word == nil {
stream.WriteNil()
return
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
}
}
var jsonNumberType reflect.Type
var jsoniterNumberType reflect.Type
var jsonRawMessageType reflect.Type
var jsoniterRawMessageType reflect.Type
var anyType reflect.Type
var marshalerType reflect.Type
var unmarshalerType reflect.Type
var textMarshalerType reflect.Type
var textUnmarshalerType reflect.Type
func init() {
jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem()
jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem()
jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem()
jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem()
anyType = reflect.TypeOf((*Any)(nil)).Elem()
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
}
type OptionalDecoder struct {
ValueType reflect.Type
ValueDecoder ValDecoder
}
func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
*((*unsafe.Pointer)(ptr)) = nil
} else {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
value := reflect.New(decoder.ValueType)
newPtr := extractInterface(value.Interface()).word
decoder.ValueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
} else {
//reuse existing instance
decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
}
}
}
type deferenceDecoder struct {
// only to deference a pointer
valueType reflect.Type
valueDecoder ValDecoder
}
func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
value := reflect.New(decoder.valueType)
newPtr := extractInterface(value.Interface()).word
decoder.valueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
} else {
//reuse existing instance
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
}
}
type OptionalEncoder struct {
ValueEncoder ValEncoder
}
func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *OptionalEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil
}
type optionalMapEncoder struct {
valueEncoder ValEncoder
}
func (encoder *optionalMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *optionalMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *optionalMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
p := *((*unsafe.Pointer)(ptr))
return p == nil || encoder.valueEncoder.IsEmpty(p)
}
type placeholderEncoder struct {
cfg *frozenConfig
cacheKey reflect.Type
}
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.getRealEncoder().Encode(ptr, stream)
}
func (encoder *placeholderEncoder) EncodeInterface(val interface{}, stream *Stream) {
encoder.getRealEncoder().EncodeInterface(val, stream)
}
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.getRealEncoder().IsEmpty(ptr)
}
func (encoder *placeholderEncoder) getRealEncoder() ValEncoder {
for i := 0; i < 500; i++ {
realDecoder := encoder.cfg.getEncoderFromCache(encoder.cacheKey)
_, isPlaceholder := realDecoder.(*placeholderEncoder)
if isPlaceholder {
time.Sleep(10 * time.Millisecond)
} else {
return realDecoder
}
}
panic(fmt.Sprintf("real encoder not found for cache key: %v", encoder.cacheKey))
}
type placeholderDecoder struct {
cfg *frozenConfig
cacheKey reflect.Type
}
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
for i := 0; i < 500; i++ {
realDecoder := decoder.cfg.getDecoderFromCache(decoder.cacheKey)
_, isPlaceholder := realDecoder.(*placeholderDecoder)
if isPlaceholder {
time.Sleep(10 * time.Millisecond)
} else {
realDecoder.Decode(ptr, iter)
return
}
}
panic(fmt.Sprintf("real decoder not found for cache key: %v", decoder.cacheKey))
}
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ unsafe.Pointer
word unsafe.Pointer
}
// emptyInterface is the header for an interface with method (not interface{})
type nonEmptyInterface struct {
// see ../runtime/iface.go:/Itab
itab *struct {
ityp unsafe.Pointer // static interface type
typ unsafe.Pointer // dynamic concrete type
link unsafe.Pointer
bad int32
unused int32
fun [100000]unsafe.Pointer // method table
}
word unsafe.Pointer
}
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
func (iter *Iterator) ReadVal(obj interface{}) {
typ := reflect.TypeOf(obj)
cacheKey := typ.Elem()
decoder, err := decoderOfType(iter.cfg, cacheKey)
if err != nil {
iter.Error = err
return
}
e := (*emptyInterface)(unsafe.Pointer(&obj))
decoder.Decode(e.word, iter)
}
// WriteVal copy the go interface into underlying JSON, same as json.Marshal
func (stream *Stream) WriteVal(val interface{}) {
if nil == val {
stream.WriteNil()
return
}
typ := reflect.TypeOf(val)
cacheKey := typ
encoder, err := encoderOfType(stream.cfg, cacheKey)
if err != nil {
stream.Error = err
return
}
encoder.EncodeInterface(val, stream)
}
type prefix string
func (p prefix) addToDecoder(decoder ValDecoder, err error) (ValDecoder, error) {
if err != nil {
return nil, fmt.Errorf("%s: %s", p, err.Error())
}
return decoder, err
}
func (p prefix) addToEncoder(encoder ValEncoder, err error) (ValEncoder, error) {
if err != nil {
return nil, fmt.Errorf("%s: %s", p, err.Error())
}
return encoder, err
}
func decoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
cacheKey := typ
decoder := cfg.getDecoderFromCache(cacheKey)
if decoder != nil {
return decoder, nil
}
decoder = getTypeDecoderFromExtension(typ)
if decoder != nil {
cfg.addDecoderToCache(cacheKey, decoder)
return decoder, nil
}
decoder = &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
cfg.addDecoderToCache(cacheKey, decoder)
decoder, err := createDecoderOfType(cfg, typ)
for _, extension := range extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
cfg.addDecoderToCache(cacheKey, decoder)
return decoder, err
}
func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
typeName := typ.String()
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}, nil
}
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}, nil
}
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}, nil
}
if typ.AssignableTo(jsoniterNumberType) {
return &jsoniterNumberCodec{}, nil
}
if typ.Implements(unmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
if typ.Kind() == reflect.Ptr {
decoder = &OptionalDecoder{typ.Elem(), decoder}
}
return decoder, nil
}
if reflect.PtrTo(typ).Implements(unmarshalerType) {
templateInterface := reflect.New(typ).Interface()
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
return decoder, nil
}
if typ.Implements(textUnmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
if typ.Kind() == reflect.Ptr {
decoder = &OptionalDecoder{typ.Elem(), decoder}
}
return decoder, nil
}
if reflect.PtrTo(typ).Implements(textUnmarshalerType) {
templateInterface := reflect.New(typ).Interface()
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
return decoder, nil
}
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
sliceDecoder, err := prefix("[slice]").addToDecoder(decoderOfSlice(cfg, typ))
if err != nil {
return nil, err
}
return &base64Codec{sliceDecoder: sliceDecoder}, nil
}
if typ.Implements(anyType) {
return &anyCodec{}, nil
}
switch typ.Kind() {
case reflect.String:
if typeName != "string" {
return decoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
}
return &stringCodec{}, nil
case reflect.Int:
if typeName != "int" {
return decoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
}
return &intCodec{}, nil
case reflect.Int8:
if typeName != "int8" {
return decoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
}
return &int8Codec{}, nil
case reflect.Int16:
if typeName != "int16" {
return decoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
}
return &int16Codec{}, nil
case reflect.Int32:
if typeName != "int32" {
return decoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
}
return &int32Codec{}, nil
case reflect.Int64:
if typeName != "int64" {
return decoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
}
return &int64Codec{}, nil
case reflect.Uint:
if typeName != "uint" {
return decoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
}
return &uintCodec{}, nil
case reflect.Uint8:
if typeName != "uint8" {
return decoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
}
return &uint8Codec{}, nil
case reflect.Uint16:
if typeName != "uint16" {
return decoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
}
return &uint16Codec{}, nil
case reflect.Uint32:
if typeName != "uint32" {
return decoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
}
return &uint32Codec{}, nil
case reflect.Uintptr:
if typeName != "uintptr" {
return decoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}, nil
case reflect.Uint64:
if typeName != "uint64" {
return decoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
}
return &uint64Codec{}, nil
case reflect.Float32:
if typeName != "float32" {
return decoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
}
return &float32Codec{}, nil
case reflect.Float64:
if typeName != "float64" {
return decoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
}
return &float64Codec{}, nil
case reflect.Bool:
if typeName != "bool" {
return decoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
}
return &boolCodec{}, nil
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}, nil
}
return &nonEmptyInterfaceCodec{}, nil
case reflect.Struct:
return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ))
case reflect.Array:
return prefix("[array]").addToDecoder(decoderOfArray(cfg, typ))
case reflect.Slice:
return prefix("[slice]").addToDecoder(decoderOfSlice(cfg, typ))
case reflect.Map:
return prefix("[map]").addToDecoder(decoderOfMap(cfg, typ))
case reflect.Ptr:
return prefix("[optional]").addToDecoder(decoderOfOptional(cfg, typ))
default:
return nil, fmt.Errorf("unsupported type: %v", typ)
}
}
func encoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
cacheKey := typ
encoder := cfg.getEncoderFromCache(cacheKey)
if encoder != nil {
return encoder, nil
}
encoder = getTypeEncoderFromExtension(typ)
if encoder != nil {
cfg.addEncoderToCache(cacheKey, encoder)
return encoder, nil
}
encoder = &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
cfg.addEncoderToCache(cacheKey, encoder)
encoder, err := createEncoderOfType(cfg, typ)
for _, extension := range extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
cfg.addEncoderToCache(cacheKey, encoder)
return encoder, err
}
func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}, nil
}
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}, nil
}
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}, nil
}
if typ.AssignableTo(jsoniterNumberType) {
return &jsoniterNumberCodec{}, nil
}
if typ.Implements(marshalerType) {
checkIsEmpty, err := createCheckIsEmpty(typ)
if err != nil {
return nil, err
}
templateInterface := reflect.New(typ).Elem().Interface()
var encoder ValEncoder = &marshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
if typ.Kind() == reflect.Ptr {
encoder = &OptionalEncoder{encoder}
}
return encoder, nil
}
if reflect.PtrTo(typ).Implements(marshalerType) {
checkIsEmpty, err := createCheckIsEmpty(reflect.PtrTo(typ))
if err != nil {
return nil, err
}
templateInterface := reflect.New(typ).Interface()
var encoder ValEncoder = &marshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
return encoder, nil
}
if typ.Implements(textMarshalerType) {
checkIsEmpty, err := createCheckIsEmpty(typ)
if err != nil {
return nil, err
}
templateInterface := reflect.New(typ).Elem().Interface()
var encoder ValEncoder = &textMarshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
if typ.Kind() == reflect.Ptr {
encoder = &OptionalEncoder{encoder}
}
return encoder, nil
}
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
return &base64Codec{}, nil
}
if typ.Implements(anyType) {
return &anyCodec{}, nil
}
return createEncoderOfSimpleType(cfg, typ)
}
func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) {
kind := typ.Kind()
switch kind {
case reflect.String:
return &stringCodec{}, nil
case reflect.Int:
return &intCodec{}, nil
case reflect.Int8:
return &int8Codec{}, nil
case reflect.Int16:
return &int16Codec{}, nil
case reflect.Int32:
return &int32Codec{}, nil
case reflect.Int64:
return &int64Codec{}, nil
case reflect.Uint:
return &uintCodec{}, nil
case reflect.Uint8:
return &uint8Codec{}, nil
case reflect.Uint16:
return &uint16Codec{}, nil
case reflect.Uint32:
return &uint32Codec{}, nil
case reflect.Uintptr:
return &uintptrCodec{}, nil
case reflect.Uint64:
return &uint64Codec{}, nil
case reflect.Float32:
return &float32Codec{}, nil
case reflect.Float64:
return &float64Codec{}, nil
case reflect.Bool:
return &boolCodec{}, nil
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}, nil
}
return &nonEmptyInterfaceCodec{}, nil
case reflect.Struct:
return &structEncoder{}, nil
case reflect.Array:
return &arrayEncoder{}, nil
case reflect.Slice:
return &sliceEncoder{}, nil
case reflect.Map:
return &mapEncoder{}, nil
case reflect.Ptr:
return &OptionalEncoder{}, nil
default:
return nil, fmt.Errorf("unsupported type: %v", typ)
}
}
func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
typeName := typ.String()
kind := typ.Kind()
switch kind {
case reflect.String:
if typeName != "string" {
return encoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
}
return &stringCodec{}, nil
case reflect.Int:
if typeName != "int" {
return encoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
}
return &intCodec{}, nil
case reflect.Int8:
if typeName != "int8" {
return encoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
}
return &int8Codec{}, nil
case reflect.Int16:
if typeName != "int16" {
return encoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
}
return &int16Codec{}, nil
case reflect.Int32:
if typeName != "int32" {
return encoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
}
return &int32Codec{}, nil
case reflect.Int64:
if typeName != "int64" {
return encoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
}
return &int64Codec{}, nil
case reflect.Uint:
if typeName != "uint" {
return encoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
}
return &uintCodec{}, nil
case reflect.Uint8:
if typeName != "uint8" {
return encoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
}
return &uint8Codec{}, nil
case reflect.Uint16:
if typeName != "uint16" {
return encoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
}
return &uint16Codec{}, nil
case reflect.Uint32:
if typeName != "uint32" {
return encoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
}
return &uint32Codec{}, nil
case reflect.Uintptr:
if typeName != "uintptr" {
return encoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}, nil
case reflect.Uint64:
if typeName != "uint64" {
return encoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
}
return &uint64Codec{}, nil
case reflect.Float32:
if typeName != "float32" {
return encoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
}
return &float32Codec{}, nil
case reflect.Float64:
if typeName != "float64" {
return encoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
}
return &float64Codec{}, nil
case reflect.Bool:
if typeName != "bool" {
return encoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
}
return &boolCodec{}, nil
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}, nil
}
return &nonEmptyInterfaceCodec{}, nil
case reflect.Struct:
return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ))
case reflect.Array:
return prefix("[array]").addToEncoder(encoderOfArray(cfg, typ))
case reflect.Slice:
return prefix("[slice]").addToEncoder(encoderOfSlice(cfg, typ))
case reflect.Map:
return prefix("[map]").addToEncoder(encoderOfMap(cfg, typ))
case reflect.Ptr:
return prefix("[optional]").addToEncoder(encoderOfOptional(cfg, typ))
default:
return nil, fmt.Errorf("unsupported type: %v", typ)
}
}
func decoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
elemType := typ.Elem()
decoder, err := decoderOfType(cfg, elemType)
if err != nil {
return nil, err
}
return &OptionalDecoder{elemType, decoder}, nil
}
func encoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
elemType := typ.Elem()
elemEncoder, err := encoderOfType(cfg, elemType)
if err != nil {
return nil, err
}
encoder := &OptionalEncoder{elemEncoder}
if elemType.Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder}
}
return encoder, nil
}
func decoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
decoder, err := decoderOfType(cfg, typ.Elem())
if err != nil {
return nil, err
}
mapInterface := reflect.New(typ).Interface()
return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}, nil
}
func extractInterface(val interface{}) emptyInterface {
return *((*emptyInterface)(unsafe.Pointer(&val)))
}
func encoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
elemType := typ.Elem()
encoder, err := encoderOfType(cfg, elemType)
if err != nil {
return nil, err
}
mapInterface := reflect.New(typ).Elem().Interface()
if cfg.sortMapKeys {
return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
}
return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
}

View file

@ -1,99 +0,0 @@
package jsoniter
import (
"fmt"
"io"
"reflect"
"unsafe"
)
func decoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
decoder, err := decoderOfType(cfg, typ.Elem())
if err != nil {
return nil, err
}
return &arrayDecoder{typ, typ.Elem(), decoder}, nil
}
func encoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
encoder, err := encoderOfType(cfg, typ.Elem())
if err != nil {
return nil, err
}
if typ.Elem().Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder}
}
return &arrayEncoder{typ, typ.Elem(), encoder}, nil
}
type arrayEncoder struct {
arrayType reflect.Type
elemType reflect.Type
elemEncoder ValEncoder
}
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteArrayStart()
elemPtr := unsafe.Pointer(ptr)
encoder.elemEncoder.Encode(elemPtr, stream)
for i := 1; i < encoder.arrayType.Len(); i++ {
stream.WriteMore()
elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
}
stream.WriteArrayEnd()
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error())
}
}
func (encoder *arrayEncoder) EncodeInterface(val interface{}, stream *Stream) {
// special optimization for interface{}
e := (*emptyInterface)(unsafe.Pointer(&val))
if e.word == nil {
stream.WriteArrayStart()
stream.WriteNil()
stream.WriteArrayEnd()
return
}
elemType := encoder.arrayType.Elem()
if encoder.arrayType.Len() == 1 && (elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map) {
ptr := uintptr(e.word)
e.word = unsafe.Pointer(&ptr)
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
}
}
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type arrayDecoder struct {
arrayType reflect.Type
elemType reflect.Type
elemDecoder ValDecoder
}
func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.doDecode(ptr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error())
}
}
func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
offset := uintptr(0)
iter.ReadArrayCB(func(iter *Iterator) bool {
if offset < decoder.arrayType.Size() {
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(ptr)+offset), iter)
offset += decoder.elemType.Size()
} else {
iter.Skip()
}
return true
})
}

View file

@ -1,244 +0,0 @@
package jsoniter
import (
"encoding"
"encoding/json"
"reflect"
"sort"
"strconv"
"unsafe"
)
type mapDecoder struct {
mapType reflect.Type
keyType reflect.Type
elemType reflect.Type
elemDecoder ValDecoder
mapInterface emptyInterface
}
func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
// dark magic to cast unsafe.Pointer back to interface{} using reflect.Type
mapInterface := decoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface).Elem()
if iter.ReadNil() {
realVal.Set(reflect.Zero(decoder.mapType))
return
}
if realVal.IsNil() {
realVal.Set(reflect.MakeMap(realVal.Type()))
}
iter.ReadMapCB(func(iter *Iterator, keyStr string) bool {
elem := reflect.New(decoder.elemType)
decoder.elemDecoder.Decode(unsafe.Pointer(elem.Pointer()), iter)
// to put into map, we have to use reflection
keyType := decoder.keyType
// TODO: remove this from loop
switch {
case keyType.Kind() == reflect.String:
realVal.SetMapIndex(reflect.ValueOf(keyStr).Convert(keyType), elem.Elem())
return true
case keyType.Implements(textUnmarshalerType):
textUnmarshaler := reflect.New(keyType.Elem()).Interface().(encoding.TextUnmarshaler)
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
if err != nil {
iter.ReportError("read map key as TextUnmarshaler", err.Error())
return false
}
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler), elem.Elem())
return true
case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
textUnmarshaler := reflect.New(keyType).Interface().(encoding.TextUnmarshaler)
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
if err != nil {
iter.ReportError("read map key as TextUnmarshaler", err.Error())
return false
}
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler).Elem(), elem.Elem())
return true
default:
switch keyType.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(keyStr, 10, 64)
if err != nil || reflect.Zero(keyType).OverflowInt(n) {
iter.ReportError("read map key as int64", "read int64 failed")
return false
}
realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
return true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(keyStr, 10, 64)
if err != nil || reflect.Zero(keyType).OverflowUint(n) {
iter.ReportError("read map key as uint64", "read uint64 failed")
return false
}
realVal.SetMapIndex(reflect.ValueOf(n).Convert(keyType), elem.Elem())
return true
}
}
iter.ReportError("read map key", "unexpected map key type "+keyType.String())
return true
})
}
type mapEncoder struct {
mapType reflect.Type
elemType reflect.Type
elemEncoder ValEncoder
mapInterface emptyInterface
}
func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
stream.WriteObjectStart()
for i, key := range realVal.MapKeys() {
if i != 0 {
stream.WriteMore()
}
encodeMapKey(key, stream)
if stream.indention > 0 {
stream.writeTwoBytes(byte(':'), byte(' '))
} else {
stream.writeByte(':')
}
val := realVal.MapIndex(key).Interface()
encoder.elemEncoder.EncodeInterface(val, stream)
}
stream.WriteObjectEnd()
}
func encodeMapKey(key reflect.Value, stream *Stream) {
if key.Kind() == reflect.String {
stream.WriteString(key.String())
return
}
if tm, ok := key.Interface().(encoding.TextMarshaler); ok {
buf, err := tm.MarshalText()
if err != nil {
stream.Error = err
return
}
stream.writeByte('"')
stream.Write(buf)
stream.writeByte('"')
return
}
switch key.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
stream.writeByte('"')
stream.WriteInt64(key.Int())
stream.writeByte('"')
return
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
stream.writeByte('"')
stream.WriteUint64(key.Uint())
stream.writeByte('"')
return
}
stream.Error = &json.UnsupportedTypeError{Type: key.Type()}
}
func (encoder *mapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
return realVal.Len() == 0
}
type sortKeysMapEncoder struct {
mapType reflect.Type
elemType reflect.Type
elemEncoder ValEncoder
mapInterface emptyInterface
}
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
// Extract and sort the keys.
keys := realVal.MapKeys()
sv := stringValues(make([]reflectWithString, len(keys)))
for i, v := range keys {
sv[i].v = v
if err := sv[i].resolve(); err != nil {
stream.Error = err
return
}
}
sort.Sort(sv)
stream.WriteObjectStart()
for i, key := range sv {
if i != 0 {
stream.WriteMore()
}
stream.WriteVal(key.s) // might need html escape, so can not WriteString directly
if stream.indention > 0 {
stream.writeTwoBytes(byte(':'), byte(' '))
} else {
stream.writeByte(':')
}
val := realVal.MapIndex(key.v).Interface()
encoder.elemEncoder.EncodeInterface(val, stream)
}
stream.WriteObjectEnd()
}
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflectWithString
type reflectWithString struct {
v reflect.Value
s string
}
func (w *reflectWithString) resolve() error {
if w.v.Kind() == reflect.String {
w.s = w.v.String()
return nil
}
if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
buf, err := tm.MarshalText()
w.s = string(buf)
return err
}
switch w.v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
w.s = strconv.FormatInt(w.v.Int(), 10)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
w.s = strconv.FormatUint(w.v.Uint(), 10)
return nil
}
return &json.UnsupportedTypeError{Type: w.v.Type()}
}
func (sv stringValues) Len() int { return len(sv) }
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv[i].s < sv[j].s }
func (encoder *sortKeysMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
mapInterface := encoder.mapInterface
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
return realVal.Len() == 0
}

View file

@ -1,764 +0,0 @@
package jsoniter
import (
"encoding"
"encoding/base64"
"encoding/json"
"reflect"
"unsafe"
)
type stringCodec struct {
}
func (codec *stringCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*string)(ptr)) = iter.ReadString()
}
func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
str := *((*string)(ptr))
stream.WriteString(str)
}
func (codec *stringCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*string)(ptr)) == ""
}
type intCodec struct {
}
func (codec *intCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int)(ptr)) = iter.ReadInt()
}
}
func (codec *intCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt(*((*int)(ptr)))
}
func (codec *intCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *intCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int)(ptr)) == 0
}
type uintptrCodec struct {
}
func (codec *uintptrCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uintptr)(ptr)) = uintptr(iter.ReadUint64())
}
}
func (codec *uintptrCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint64(uint64(*((*uintptr)(ptr))))
}
func (codec *uintptrCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uintptrCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uintptr)(ptr)) == 0
}
type int8Codec struct {
}
func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int8)(ptr)) = iter.ReadInt8()
}
}
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt8(*((*int8)(ptr)))
}
func (codec *int8Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *int8Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int8)(ptr)) == 0
}
type int16Codec struct {
}
func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int16)(ptr)) = iter.ReadInt16()
}
}
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt16(*((*int16)(ptr)))
}
func (codec *int16Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *int16Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int16)(ptr)) == 0
}
type int32Codec struct {
}
func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int32)(ptr)) = iter.ReadInt32()
}
}
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt32(*((*int32)(ptr)))
}
func (codec *int32Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int32)(ptr)) == 0
}
type int64Codec struct {
}
func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int64)(ptr)) = iter.ReadInt64()
}
}
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt64(*((*int64)(ptr)))
}
func (codec *int64Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int64)(ptr)) == 0
}
type uintCodec struct {
}
func (codec *uintCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint)(ptr)) = iter.ReadUint()
return
}
}
func (codec *uintCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint(*((*uint)(ptr)))
}
func (codec *uintCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uintCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint)(ptr)) == 0
}
type uint8Codec struct {
}
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint8)(ptr)) = iter.ReadUint8()
}
}
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint8(*((*uint8)(ptr)))
}
func (codec *uint8Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uint8Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint8)(ptr)) == 0
}
type uint16Codec struct {
}
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint16)(ptr)) = iter.ReadUint16()
}
}
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint16(*((*uint16)(ptr)))
}
func (codec *uint16Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uint16Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint16)(ptr)) == 0
}
type uint32Codec struct {
}
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint32)(ptr)) = iter.ReadUint32()
}
}
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint32(*((*uint32)(ptr)))
}
func (codec *uint32Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint32)(ptr)) == 0
}
type uint64Codec struct {
}
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint64)(ptr)) = iter.ReadUint64()
}
}
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint64(*((*uint64)(ptr)))
}
func (codec *uint64Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *uint64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint64)(ptr)) == 0
}
type float32Codec struct {
}
func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*float32)(ptr)) = iter.ReadFloat32()
}
}
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat32(*((*float32)(ptr)))
}
func (codec *float32Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *float32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float32)(ptr)) == 0
}
type float64Codec struct {
}
func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*float64)(ptr)) = iter.ReadFloat64()
}
}
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat64(*((*float64)(ptr)))
}
func (codec *float64Codec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *float64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float64)(ptr)) == 0
}
type boolCodec struct {
}
func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*bool)(ptr)) = iter.ReadBool()
}
}
func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteBool(*((*bool)(ptr)))
}
func (codec *boolCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, codec)
}
func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool {
return !(*((*bool)(ptr)))
}
type emptyInterfaceCodec struct {
}
func (codec *emptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
existing := *((*interface{})(ptr))
// Checking for both typed and untyped nil pointers.
if existing != nil &&
reflect.TypeOf(existing).Kind() == reflect.Ptr &&
!reflect.ValueOf(existing).IsNil() {
var ptrToExisting interface{}
for {
elem := reflect.ValueOf(existing).Elem()
if elem.Kind() != reflect.Ptr || elem.IsNil() {
break
}
ptrToExisting = existing
existing = elem.Interface()
}
if iter.ReadNil() {
if ptrToExisting != nil {
nilPtr := reflect.Zero(reflect.TypeOf(ptrToExisting).Elem())
reflect.ValueOf(ptrToExisting).Elem().Set(nilPtr)
} else {
*((*interface{})(ptr)) = nil
}
} else {
iter.ReadVal(existing)
}
return
}
if iter.ReadNil() {
*((*interface{})(ptr)) = nil
} else {
*((*interface{})(ptr)) = iter.Read()
}
}
func (codec *emptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteVal(*((*interface{})(ptr)))
}
func (codec *emptyInterfaceCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteVal(val)
}
func (codec *emptyInterfaceCodec) IsEmpty(ptr unsafe.Pointer) bool {
emptyInterface := (*emptyInterface)(ptr)
return emptyInterface.typ == nil
}
type nonEmptyInterfaceCodec struct {
}
func (codec *nonEmptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
nonEmptyInterface := (*nonEmptyInterface)(ptr)
if nonEmptyInterface.itab == nil {
iter.ReportError("read non-empty interface", "do not know which concrete type to decode to")
return
}
var i interface{}
e := (*emptyInterface)(unsafe.Pointer(&i))
e.typ = nonEmptyInterface.itab.typ
e.word = nonEmptyInterface.word
iter.ReadVal(&i)
if e.word == nil {
nonEmptyInterface.itab = nil
}
nonEmptyInterface.word = e.word
}
func (codec *nonEmptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
nonEmptyInterface := (*nonEmptyInterface)(ptr)
var i interface{}
if nonEmptyInterface.itab != nil {
e := (*emptyInterface)(unsafe.Pointer(&i))
e.typ = nonEmptyInterface.itab.typ
e.word = nonEmptyInterface.word
}
stream.WriteVal(i)
}
func (codec *nonEmptyInterfaceCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteVal(val)
}
func (codec *nonEmptyInterfaceCodec) IsEmpty(ptr unsafe.Pointer) bool {
nonEmptyInterface := (*nonEmptyInterface)(ptr)
return nonEmptyInterface.word == nil
}
type anyCodec struct {
}
func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*Any)(ptr)) = iter.ReadAny()
}
func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
(*((*Any)(ptr))).WriteTo(stream)
}
func (codec *anyCodec) EncodeInterface(val interface{}, stream *Stream) {
(val.(Any)).WriteTo(stream)
}
func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool {
return (*((*Any)(ptr))).Size() == 0
}
type jsonNumberCodec struct {
}
func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
switch iter.WhatIsNext() {
case StringValue:
*((*json.Number)(ptr)) = json.Number(iter.ReadString())
case NilValue:
iter.skipFourBytes('n', 'u', 'l', 'l')
*((*json.Number)(ptr)) = ""
default:
*((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString()))
}
}
func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*json.Number)(ptr))))
}
func (codec *jsonNumberCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteRaw(string(val.(json.Number)))
}
func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*json.Number)(ptr))) == 0
}
type jsoniterNumberCodec struct {
}
func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
switch iter.WhatIsNext() {
case StringValue:
*((*Number)(ptr)) = Number(iter.ReadString())
case NilValue:
iter.skipFourBytes('n', 'u', 'l', 'l')
*((*Number)(ptr)) = ""
default:
*((*Number)(ptr)) = Number([]byte(iter.readNumberAsString()))
}
}
func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*Number)(ptr))))
}
func (codec *jsoniterNumberCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteRaw(string(val.(Number)))
}
func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*Number)(ptr))) == 0
}
type jsonRawMessageCodec struct {
}
func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*json.RawMessage)(ptr))))
}
func (codec *jsonRawMessageCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteRaw(string(val.(json.RawMessage)))
}
func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*json.RawMessage)(ptr))) == 0
}
type jsoniterRawMessageCodec struct {
}
func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*RawMessage)(ptr))))
}
func (codec *jsoniterRawMessageCodec) EncodeInterface(val interface{}, stream *Stream) {
stream.WriteRaw(string(val.(RawMessage)))
}
func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*RawMessage)(ptr))) == 0
}
type base64Codec struct {
sliceDecoder ValDecoder
}
func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
ptrSlice := (*sliceHeader)(ptr)
ptrSlice.Len = 0
ptrSlice.Cap = 0
ptrSlice.Data = nil
return
}
switch iter.WhatIsNext() {
case StringValue:
encoding := base64.StdEncoding
src := iter.SkipAndReturnBytes()
src = src[1 : len(src)-1]
decodedLen := encoding.DecodedLen(len(src))
dst := make([]byte, decodedLen)
len, err := encoding.Decode(dst, src)
if err != nil {
iter.ReportError("decode base64", err.Error())
} else {
dst = dst[:len]
dstSlice := (*sliceHeader)(unsafe.Pointer(&dst))
ptrSlice := (*sliceHeader)(ptr)
ptrSlice.Data = dstSlice.Data
ptrSlice.Cap = dstSlice.Cap
ptrSlice.Len = dstSlice.Len
}
case ArrayValue:
codec.sliceDecoder.Decode(ptr, iter)
default:
iter.ReportError("base64Codec", "invalid input")
}
}
func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
toGrow := encoding.EncodedLen(len(src))
stream.ensure(toGrow)
encoding.Encode(stream.buf[stream.n:], src)
stream.n += toGrow
stream.writeByte('"')
}
func (codec *base64Codec) EncodeInterface(val interface{}, stream *Stream) {
ptr := extractInterface(val).word
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
toGrow := encoding.EncodedLen(len(src))
stream.ensure(toGrow)
encoding.Encode(stream.buf[stream.n:], src)
stream.n += toGrow
stream.writeByte('"')
}
func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*[]byte)(ptr))) == 0
}
type stringModeNumberDecoder struct {
elemDecoder ValDecoder
}
func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
c := iter.nextToken()
if c != '"' {
iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
return
}
decoder.elemDecoder.Decode(ptr, iter)
if iter.Error != nil {
return
}
c = iter.readByte()
if c != '"' {
iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
return
}
}
type stringModeStringDecoder struct {
elemDecoder ValDecoder
cfg *frozenConfig
}
func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.elemDecoder.Decode(ptr, iter)
str := *((*string)(ptr))
tempIter := decoder.cfg.BorrowIterator([]byte(str))
defer decoder.cfg.ReturnIterator(tempIter)
*((*string)(ptr)) = tempIter.ReadString()
}
type stringModeNumberEncoder struct {
elemEncoder ValEncoder
}
func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.writeByte('"')
encoder.elemEncoder.Encode(ptr, stream)
stream.writeByte('"')
}
func (encoder *stringModeNumberEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.elemEncoder.IsEmpty(ptr)
}
type stringModeStringEncoder struct {
elemEncoder ValEncoder
cfg *frozenConfig
}
func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
tempStream := encoder.cfg.BorrowStream(nil)
defer encoder.cfg.ReturnStream(tempStream)
encoder.elemEncoder.Encode(ptr, tempStream)
stream.WriteString(string(tempStream.Buffer()))
}
func (encoder *stringModeStringEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.elemEncoder.IsEmpty(ptr)
}
type marshalerEncoder struct {
templateInterface emptyInterface
checkIsEmpty checkIsEmpty
}
func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
templateInterface := encoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
marshaler, ok := (*realInterface).(json.Marshaler)
if !ok {
stream.WriteVal(nil)
return
}
bytes, err := marshaler.MarshalJSON()
if err != nil {
stream.Error = err
} else {
stream.Write(bytes)
}
}
func (encoder *marshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type textMarshalerEncoder struct {
templateInterface emptyInterface
checkIsEmpty checkIsEmpty
}
func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
templateInterface := encoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
marshaler := (*realInterface).(encoding.TextMarshaler)
bytes, err := marshaler.MarshalText()
if err != nil {
stream.Error = err
} else {
stream.WriteString(string(bytes))
}
}
func (encoder *textMarshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type unmarshalerDecoder struct {
templateInterface emptyInterface
}
func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
templateInterface := decoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
unmarshaler := (*realInterface).(json.Unmarshaler)
iter.nextToken()
iter.unreadByte() // skip spaces
bytes := iter.SkipAndReturnBytes()
err := unmarshaler.UnmarshalJSON(bytes)
if err != nil {
iter.ReportError("unmarshalerDecoder", err.Error())
}
}
type textUnmarshalerDecoder struct {
templateInterface emptyInterface
}
func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
templateInterface := decoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
unmarshaler := (*realInterface).(encoding.TextUnmarshaler)
str := iter.ReadString()
err := unmarshaler.UnmarshalText([]byte(str))
if err != nil {
iter.ReportError("textUnmarshalerDecoder", err.Error())
}
}

View file

@ -1,147 +0,0 @@
package jsoniter
import (
"fmt"
"io"
"reflect"
"unsafe"
)
func decoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
decoder, err := decoderOfType(cfg, typ.Elem())
if err != nil {
return nil, err
}
return &sliceDecoder{typ, typ.Elem(), decoder}, nil
}
func encoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
encoder, err := encoderOfType(cfg, typ.Elem())
if err != nil {
return nil, err
}
if typ.Elem().Kind() == reflect.Map {
encoder = &OptionalEncoder{encoder}
}
return &sliceEncoder{typ, typ.Elem(), encoder}, nil
}
type sliceEncoder struct {
sliceType reflect.Type
elemType reflect.Type
elemEncoder ValEncoder
}
func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
slice := (*sliceHeader)(ptr)
if slice.Data == nil {
stream.WriteNil()
return
}
if slice.Len == 0 {
stream.WriteEmptyArray()
return
}
stream.WriteArrayStart()
elemPtr := unsafe.Pointer(slice.Data)
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
for i := 1; i < slice.Len; i++ {
stream.WriteMore()
elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
}
stream.WriteArrayEnd()
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
}
}
func (encoder *sliceEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
slice := (*sliceHeader)(ptr)
return slice.Len == 0
}
type sliceDecoder struct {
sliceType reflect.Type
elemType reflect.Type
elemDecoder ValDecoder
}
// sliceHeader is a safe version of SliceHeader used within this package.
type sliceHeader struct {
Data unsafe.Pointer
Len int
Cap int
}
func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.doDecode(ptr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error())
}
}
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
slice := (*sliceHeader)(ptr)
if iter.ReadNil() {
slice.Len = 0
slice.Cap = 0
slice.Data = nil
return
}
reuseSlice(slice, decoder.sliceType, 4)
slice.Len = 0
offset := uintptr(0)
iter.ReadArrayCB(func(iter *Iterator) bool {
growOne(slice, decoder.sliceType, decoder.elemType)
decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
offset += decoder.elemType.Size()
return true
})
}
// grow grows the slice s so that it can hold extra more values, allocating
// more capacity if needed. It also returns the old and new slice lengths.
func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Type) {
newLen := slice.Len + 1
if newLen <= slice.Cap {
slice.Len = newLen
return
}
newCap := slice.Cap
if newCap == 0 {
newCap = 1
} else {
for newCap < newLen {
if slice.Len < 1024 {
newCap += newCap
} else {
newCap += newCap / 4
}
}
}
newVal := reflect.MakeSlice(sliceType, newLen, newCap)
dst := unsafe.Pointer(newVal.Pointer())
// copy old array into new array
originalBytesCount := slice.Len * int(elementType.Size())
srcSliceHeader := (unsafe.Pointer)(&sliceHeader{slice.Data, originalBytesCount, originalBytesCount})
dstSliceHeader := (unsafe.Pointer)(&sliceHeader{dst, originalBytesCount, originalBytesCount})
copy(*(*[]byte)(dstSliceHeader), *(*[]byte)(srcSliceHeader))
slice.Data = dst
slice.Len = newLen
slice.Cap = newCap
}
func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) {
if expectedCap <= slice.Cap {
return
}
newVal := reflect.MakeSlice(sliceType, 0, expectedCap)
dst := unsafe.Pointer(newVal.Pointer())
slice.Data = dst
slice.Cap = expectedCap
}

View file

@ -1,320 +0,0 @@
package jsoniter
var digits []uint32
func init() {
digits = make([]uint32, 1000)
for i := uint32(0); i < 1000; i++ {
digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0'
if i < 10 {
digits[i] += 2 << 24
} else if i < 100 {
digits[i] += 1 << 24
}
}
}
func writeFirstBuf(buf []byte, v uint32, n int) int {
start := v >> 24
if start == 0 {
buf[n] = byte(v >> 16)
n++
buf[n] = byte(v >> 8)
n++
} else if start == 1 {
buf[n] = byte(v >> 8)
n++
}
buf[n] = byte(v)
n++
return n
}
func writeBuf(buf []byte, v uint32, n int) {
buf[n] = byte(v >> 16)
buf[n+1] = byte(v >> 8)
buf[n+2] = byte(v)
}
// WriteUint8 write uint8 to stream
func (stream *Stream) WriteUint8(val uint8) {
stream.ensure(3)
stream.n = writeFirstBuf(stream.buf, digits[val], stream.n)
}
// WriteInt8 write int8 to stream
func (stream *Stream) WriteInt8(nval int8) {
stream.ensure(4)
n := stream.n
var val uint8
if nval < 0 {
val = uint8(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint8(nval)
}
stream.n = writeFirstBuf(stream.buf, digits[val], n)
}
// WriteUint16 write uint16 to stream
func (stream *Stream) WriteUint16(val uint16) {
stream.ensure(5)
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], stream.n)
return
}
r1 := val - q1*1000
n := writeFirstBuf(stream.buf, digits[q1], stream.n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
// WriteInt16 write int16 to stream
func (stream *Stream) WriteInt16(nval int16) {
stream.ensure(6)
n := stream.n
var val uint16
if nval < 0 {
val = uint16(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint16(nval)
}
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
n = writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
// WriteUint32 write uint32 to stream
func (stream *Stream) WriteUint32(val uint32) {
stream.ensure(10)
n := stream.n
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
} else {
r3 := q2 - q3*1000
stream.buf[n] = byte(q3 + '0')
n++
writeBuf(stream.buf, digits[r3], n)
n += 3
}
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
}
// WriteInt32 write int32 to stream
func (stream *Stream) WriteInt32(nval int32) {
stream.ensure(11)
n := stream.n
var val uint32
if nval < 0 {
val = uint32(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint32(nval)
}
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
} else {
r3 := q2 - q3*1000
stream.buf[n] = byte(q3 + '0')
n++
writeBuf(stream.buf, digits[r3], n)
n += 3
}
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
}
// WriteUint64 write uint64 to stream
func (stream *Stream) WriteUint64(val uint64) {
stream.ensure(20)
n := stream.n
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
return
}
r3 := q2 - q3*1000
q4 := q3 / 1000
if q4 == 0 {
n = writeFirstBuf(stream.buf, digits[q3], n)
writeBuf(stream.buf, digits[r3], n)
writeBuf(stream.buf, digits[r2], n+3)
writeBuf(stream.buf, digits[r1], n+6)
stream.n = n + 9
return
}
r4 := q3 - q4*1000
q5 := q4 / 1000
if q5 == 0 {
n = writeFirstBuf(stream.buf, digits[q4], n)
writeBuf(stream.buf, digits[r4], n)
writeBuf(stream.buf, digits[r3], n+3)
writeBuf(stream.buf, digits[r2], n+6)
writeBuf(stream.buf, digits[r1], n+9)
stream.n = n + 12
return
}
r5 := q4 - q5*1000
q6 := q5 / 1000
if q6 == 0 {
n = writeFirstBuf(stream.buf, digits[q5], n)
} else {
n = writeFirstBuf(stream.buf, digits[q6], n)
r6 := q5 - q6*1000
writeBuf(stream.buf, digits[r6], n)
n += 3
}
writeBuf(stream.buf, digits[r5], n)
writeBuf(stream.buf, digits[r4], n+3)
writeBuf(stream.buf, digits[r3], n+6)
writeBuf(stream.buf, digits[r2], n+9)
writeBuf(stream.buf, digits[r1], n+12)
stream.n = n + 15
}
// WriteInt64 write int64 to stream
func (stream *Stream) WriteInt64(nval int64) {
stream.ensure(20)
n := stream.n
var val uint64
if nval < 0 {
val = uint64(-nval)
stream.buf[n] = '-'
n++
} else {
val = uint64(nval)
}
q1 := val / 1000
if q1 == 0 {
stream.n = writeFirstBuf(stream.buf, digits[val], n)
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
n := writeFirstBuf(stream.buf, digits[q1], n)
writeBuf(stream.buf, digits[r1], n)
stream.n = n + 3
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
n = writeFirstBuf(stream.buf, digits[q2], n)
writeBuf(stream.buf, digits[r2], n)
writeBuf(stream.buf, digits[r1], n+3)
stream.n = n + 6
return
}
r3 := q2 - q3*1000
q4 := q3 / 1000
if q4 == 0 {
n = writeFirstBuf(stream.buf, digits[q3], n)
writeBuf(stream.buf, digits[r3], n)
writeBuf(stream.buf, digits[r2], n+3)
writeBuf(stream.buf, digits[r1], n+6)
stream.n = n + 9
return
}
r4 := q3 - q4*1000
q5 := q4 / 1000
if q5 == 0 {
n = writeFirstBuf(stream.buf, digits[q4], n)
writeBuf(stream.buf, digits[r4], n)
writeBuf(stream.buf, digits[r3], n+3)
writeBuf(stream.buf, digits[r2], n+6)
writeBuf(stream.buf, digits[r1], n+9)
stream.n = n + 12
return
}
r5 := q4 - q5*1000
q6 := q5 / 1000
if q6 == 0 {
n = writeFirstBuf(stream.buf, digits[q5], n)
} else {
stream.buf[n] = byte(q6 + '0')
n++
r6 := q5 - q6*1000
writeBuf(stream.buf, digits[r6], n)
n += 3
}
writeBuf(stream.buf, digits[r5], n)
writeBuf(stream.buf, digits[r4], n+3)
writeBuf(stream.buf, digits[r3], n+6)
writeBuf(stream.buf, digits[r2], n+9)
writeBuf(stream.buf, digits[r1], n+12)
stream.n = n + 15
}
// WriteInt write int to stream
func (stream *Stream) WriteInt(val int) {
stream.WriteInt64(int64(val))
}
// WriteUint write uint to stream
func (stream *Stream) WriteUint(val uint) {
stream.WriteUint64(uint64(val))
}

View file

@ -1,6 +1,7 @@
package jsoniter
import (
"encoding/json"
"io"
"math/big"
"strconv"
@ -339,3 +340,8 @@ func validateFloat(str string) string {
}
return ""
}
// ReadNumber read json.Number
func (iter *Iterator) ReadNumber() (ret json.Number) {
return json.Number(iter.readNumberAsString())
}

View file

@ -22,11 +22,17 @@ func init() {
// ReadUint read uint
func (iter *Iterator) ReadUint() uint {
if strconv.IntSize == 32 {
return uint(iter.ReadUint32())
}
return uint(iter.ReadUint64())
}
// ReadInt read int
func (iter *Iterator) ReadInt() int {
if strconv.IntSize == 32 {
return int(iter.ReadInt32())
}
return int(iter.ReadInt64())
}
@ -113,13 +119,9 @@ func (iter *Iterator) ReadUint32() (ret uint32) {
}
func (iter *Iterator) readUint32(c byte) (ret uint32) {
defer func() {
if iter.head < len(iter.buf) && iter.buf[iter.head] == '.' {
iter.ReportError("readUint32", "can not decode float as int")
}
}()
ind := intDigits[c]
if ind == 0 {
iter.assertInteger()
return 0 // single zero
}
if ind == invalidCharForNumber {
@ -132,12 +134,14 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
ind2 := intDigits[iter.buf[i]]
if ind2 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value
}
i++
ind3 := intDigits[iter.buf[i]]
if ind3 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*10 + uint32(ind2)
}
//iter.head = i + 1
@ -146,30 +150,35 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
ind4 := intDigits[iter.buf[i]]
if ind4 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*100 + uint32(ind2)*10 + uint32(ind3)
}
i++
ind5 := intDigits[iter.buf[i]]
if ind5 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*1000 + uint32(ind2)*100 + uint32(ind3)*10 + uint32(ind4)
}
i++
ind6 := intDigits[iter.buf[i]]
if ind6 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*10000 + uint32(ind2)*1000 + uint32(ind3)*100 + uint32(ind4)*10 + uint32(ind5)
}
i++
ind7 := intDigits[iter.buf[i]]
if ind7 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*100000 + uint32(ind2)*10000 + uint32(ind3)*1000 + uint32(ind4)*100 + uint32(ind5)*10 + uint32(ind6)
}
i++
ind8 := intDigits[iter.buf[i]]
if ind8 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*1000000 + uint32(ind2)*100000 + uint32(ind3)*10000 + uint32(ind4)*1000 + uint32(ind5)*100 + uint32(ind6)*10 + uint32(ind7)
}
i++
@ -177,6 +186,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
value = value*10000000 + uint32(ind2)*1000000 + uint32(ind3)*100000 + uint32(ind4)*10000 + uint32(ind5)*1000 + uint32(ind6)*100 + uint32(ind7)*10 + uint32(ind8)
iter.head = i
if ind9 == invalidCharForNumber {
iter.assertInteger()
return value
}
}
@ -185,6 +195,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
ind = intDigits[iter.buf[i]]
if ind == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value
}
if value > uint32SafeToMultiply10 {
@ -199,6 +210,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
value = (value << 3) + (value << 1) + uint32(ind)
}
if !iter.loadMore() {
iter.assertInteger()
return value
}
}
@ -229,13 +241,9 @@ func (iter *Iterator) ReadUint64() uint64 {
}
func (iter *Iterator) readUint64(c byte) (ret uint64) {
defer func() {
if iter.head < len(iter.buf) && iter.buf[iter.head] == '.' {
iter.ReportError("readUint64", "can not decode float as int")
}
}()
ind := intDigits[c]
if ind == 0 {
iter.assertInteger()
return 0 // single zero
}
if ind == invalidCharForNumber {
@ -243,11 +251,73 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) {
return
}
value := uint64(ind)
if iter.tail-iter.head > 10 {
i := iter.head
ind2 := intDigits[iter.buf[i]]
if ind2 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value
}
i++
ind3 := intDigits[iter.buf[i]]
if ind3 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*10 + uint64(ind2)
}
//iter.head = i + 1
//value = value * 100 + uint32(ind2) * 10 + uint32(ind3)
i++
ind4 := intDigits[iter.buf[i]]
if ind4 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*100 + uint64(ind2)*10 + uint64(ind3)
}
i++
ind5 := intDigits[iter.buf[i]]
if ind5 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*1000 + uint64(ind2)*100 + uint64(ind3)*10 + uint64(ind4)
}
i++
ind6 := intDigits[iter.buf[i]]
if ind6 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*10000 + uint64(ind2)*1000 + uint64(ind3)*100 + uint64(ind4)*10 + uint64(ind5)
}
i++
ind7 := intDigits[iter.buf[i]]
if ind7 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*100000 + uint64(ind2)*10000 + uint64(ind3)*1000 + uint64(ind4)*100 + uint64(ind5)*10 + uint64(ind6)
}
i++
ind8 := intDigits[iter.buf[i]]
if ind8 == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value*1000000 + uint64(ind2)*100000 + uint64(ind3)*10000 + uint64(ind4)*1000 + uint64(ind5)*100 + uint64(ind6)*10 + uint64(ind7)
}
i++
ind9 := intDigits[iter.buf[i]]
value = value*10000000 + uint64(ind2)*1000000 + uint64(ind3)*100000 + uint64(ind4)*10000 + uint64(ind5)*1000 + uint64(ind6)*100 + uint64(ind7)*10 + uint64(ind8)
iter.head = i
if ind9 == invalidCharForNumber {
iter.assertInteger()
return value
}
}
for {
for i := iter.head; i < iter.tail; i++ {
ind = intDigits[iter.buf[i]]
if ind == invalidCharForNumber {
iter.head = i
iter.assertInteger()
return value
}
if value > uint64SafeToMultiple10 {
@ -262,7 +332,14 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) {
value = (value << 3) + (value << 1) + uint64(ind)
}
if !iter.loadMore() {
iter.assertInteger()
return value
}
}
}
func (iter *Iterator) assertInteger() {
if iter.head < len(iter.buf) && iter.buf[iter.head] == '.' {
iter.ReportError("assertInteger", "can not decode float as int")
}
}

View file

@ -3,7 +3,6 @@ package jsoniter
import (
"fmt"
"unicode"
"unsafe"
)
// ReadObject read one field from object.
@ -19,26 +18,6 @@ func (iter *Iterator) ReadObject() (ret string) {
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
if iter.cfg.objectFieldMustBeSimpleString {
return string(iter.readObjectFieldAsBytes())
} else {
field := iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
return field
}
}
if c == '}' {
return "" // end of object
}
iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))
return
case ',':
if iter.cfg.objectFieldMustBeSimpleString {
return string(iter.readObjectFieldAsBytes())
} else {
field := iter.ReadString()
c = iter.nextToken()
if c != ':' {
@ -46,6 +25,18 @@ func (iter *Iterator) ReadObject() (ret string) {
}
return field
}
if c == '}' {
return "" // end of object
}
iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))
return
case ',':
field := iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
return field
case '}':
return "" // end of object
default:
@ -54,97 +45,87 @@ func (iter *Iterator) ReadObject() (ret string) {
}
}
func (iter *Iterator) readFieldHash() int32 {
// CaseInsensitive
func (iter *Iterator) readFieldHash() int64 {
hash := int64(0x811c9dc5)
c := iter.nextToken()
if c == '"' {
for {
for i := iter.head; i < iter.tail; i++ {
// require ascii string and no escape
b := iter.buf[i]
if !iter.cfg.objectFieldMustBeSimpleString && b == '\\' {
iter.head = i
for _, b := range iter.readStringSlowPath() {
if 'A' <= b && b <= 'Z' {
b += 'a' - 'A'
}
hash ^= int64(b)
hash *= 0x1000193
if c != '"' {
iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
return 0
}
for {
for i := iter.head; i < iter.tail; i++ {
// require ascii string and no escape
b := iter.buf[i]
if b == '\\' {
iter.head = i
for _, b := range iter.readStringSlowPath() {
if 'A' <= b && b <= 'Z' {
b += 'a' - 'A'
}
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
return int32(hash)
hash ^= int64(b)
hash *= 0x1000193
}
if b == '"' {
iter.head = i + 1
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
return int32(hash)
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
if 'A' <= b && b <= 'Z' {
b += 'a' - 'A'
}
hash ^= int64(b)
hash *= 0x1000193
return hash
}
if !iter.loadMore() {
iter.ReportError("readFieldHash", `incomplete field name`)
return 0
if b == '"' {
iter.head = i + 1
c = iter.nextToken()
if c != ':' {
iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
return 0
}
return hash
}
if 'A' <= b && b <= 'Z' {
b += 'a' - 'A'
}
hash ^= int64(b)
hash *= 0x1000193
}
if !iter.loadMore() {
iter.ReportError("readFieldHash", `incomplete field name`)
return 0
}
}
iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
return 0
}
func calcHash(str string) int32 {
func calcHash(str string) int64 {
hash := int64(0x811c9dc5)
for _, b := range str {
hash ^= int64(unicode.ToLower(b))
hash *= 0x1000193
}
return int32(hash)
return int64(hash)
}
// ReadObjectCB read object with callback, the key is ascii only and field name not copied
func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
c := iter.nextToken()
var fieldBytes []byte
var field string
if c == '{' {
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
} else {
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
if !callback(iter, field) {
return false
}
c = iter.nextToken()
for c == ',' {
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes = iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
} else {
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
if !callback(iter, field) {
return false

View file

@ -1,4 +1,4 @@
//+build jsoniter-sloppy
//+build jsoniter_sloppy
package jsoniter

View file

@ -1,45 +0,0 @@
// +build go1.8
package jsoniter
import (
"bytes"
"encoding/json"
"testing"
"unicode/utf8"
"github.com/stretchr/testify/require"
)
func Test_new_encoder(t *testing.T) {
should := require.New(t)
buf1 := &bytes.Buffer{}
encoder1 := json.NewEncoder(buf1)
encoder1.SetEscapeHTML(false)
encoder1.Encode([]int{1})
should.Equal("[1]\n", buf1.String())
buf2 := &bytes.Buffer{}
encoder2 := NewEncoder(buf2)
encoder2.SetEscapeHTML(false)
encoder2.Encode([]int{1})
should.Equal("[1]\n", buf2.String())
}
func Test_string_encode_with_std_without_html_escape(t *testing.T) {
api := Config{EscapeHTML: false}.Froze()
should := require.New(t)
for i := 0; i < utf8.RuneSelf; i++ {
input := string([]byte{byte(i)})
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(input)
should.Nil(err)
stdOutput := buf.String()
stdOutput = stdOutput[:len(stdOutput)-1]
jsoniterOutputBytes, err := api.Marshal(input)
should.Nil(err)
jsoniterOutput := string(jsoniterOutputBytes)
should.Equal(stdOutput, jsoniterOutput)
}
}

View file

@ -1,84 +0,0 @@
package jsoniter
import (
"bytes"
"encoding/json"
"github.com/stretchr/testify/require"
"io/ioutil"
"testing"
)
func Test_new_decoder(t *testing.T) {
should := require.New(t)
decoder1 := json.NewDecoder(bytes.NewBufferString(`[1][2]`))
decoder2 := NewDecoder(bytes.NewBufferString(`[1][2]`))
arr1 := []int{}
should.Nil(decoder1.Decode(&arr1))
should.Equal([]int{1}, arr1)
arr2 := []int{}
should.True(decoder1.More())
buffered, _ := ioutil.ReadAll(decoder1.Buffered())
should.Equal("[2]", string(buffered))
should.Nil(decoder2.Decode(&arr2))
should.Equal([]int{1}, arr2)
should.True(decoder2.More())
buffered, _ = ioutil.ReadAll(decoder2.Buffered())
should.Equal("[2]", string(buffered))
should.Nil(decoder1.Decode(&arr1))
should.Equal([]int{2}, arr1)
should.False(decoder1.More())
should.Nil(decoder2.Decode(&arr2))
should.Equal([]int{2}, arr2)
should.False(decoder2.More())
}
func Test_use_number(t *testing.T) {
should := require.New(t)
decoder1 := json.NewDecoder(bytes.NewBufferString(`123`))
decoder1.UseNumber()
decoder2 := NewDecoder(bytes.NewBufferString(`123`))
decoder2.UseNumber()
var obj1 interface{}
should.Nil(decoder1.Decode(&obj1))
should.Equal(json.Number("123"), obj1)
var obj2 interface{}
should.Nil(decoder2.Decode(&obj2))
should.Equal(json.Number("123"), obj2)
}
func Test_use_number_for_unmarshal(t *testing.T) {
should := require.New(t)
api := Config{UseNumber: true}.Froze()
var obj interface{}
should.Nil(api.UnmarshalFromString("123", &obj))
should.Equal(json.Number("123"), obj)
}
func Test_marshal_indent(t *testing.T) {
should := require.New(t)
obj := struct {
F1 int
F2 []int
}{1, []int{2, 3, 4}}
output, err := json.MarshalIndent(obj, "", " ")
should.Nil(err)
should.Equal("{\n \"F1\": 1,\n \"F2\": [\n 2,\n 3,\n 4\n ]\n}", string(output))
output, err = MarshalIndent(obj, "", " ")
should.Nil(err)
should.Equal("{\n \"F1\": 1,\n \"F2\": [\n 2,\n 3,\n 4\n ]\n}", string(output))
}
func Test_marshal_indent_map(t *testing.T) {
should := require.New(t)
obj := map[int]int{1: 2}
output, err := json.MarshalIndent(obj, "", " ")
should.Nil(err)
should.Equal("{\n \"1\": 2\n}", string(output))
output, err = MarshalIndent(obj, "", " ")
should.Nil(err)
should.Equal("{\n \"1\": 2\n}", string(output))
output, err = ConfigCompatibleWithStandardLibrary.MarshalIndent(obj, "", " ")
should.Nil(err)
should.Equal("{\n \"1\": 2\n}", string(output))
}

View file

@ -1,62 +0,0 @@
package jsoniter
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_alias(t *testing.T) {
should := require.New(t)
type myint int
type myint8 int8
type myint16 int16
type myint32 int32
type myint64 int64
type myuint uint
type myuint8 uint8
type myuint16 uint16
type myuint32 uint32
type myuint64 uint64
type myfloat32 float32
type myfloat64 float64
type mystring string
type mybool bool
type myuintptr uintptr
var a struct {
A myint8 `json:"a"`
B myint16 `json:"stream"`
C myint32 `json:"c"`
D myint64 `json:"d"`
E myuint8 `json:"e"`
F myuint16 `json:"f"`
G myuint32 `json:"g"`
H myuint64 `json:"h"`
I myfloat32 `json:"i"`
J myfloat64 `json:"j"`
K mystring `json:"k"`
L myint `json:"l"`
M myuint `json:"m"`
N mybool `json:"n"`
O myuintptr `json:"o"`
}
should.Nil(UnmarshalFromString(`{"a" : 1, "stream" : 1, "c": 1, "d" : 1, "e" : 1, "f" : 1, "g" : 1, "h": 1, "i" : 1, "j" : 1, "k" :"xxxx", "l" : 1, "m":1, "n": true, "o" : 1}`, &a))
should.Equal(myfloat32(1), a.I)
should.Equal(myfloat64(1), a.J)
should.Equal(myint8(1), a.A)
should.Equal(myint16(1), a.B)
should.Equal(myint32(1), a.C)
should.Equal(myint64(1), a.D)
should.Equal(myuint8(1), a.E)
should.Equal(myuint16(1), a.F)
should.Equal(myuint32(1), a.G)
should.Equal(myuint64(1), a.H)
should.Equal(mystring("xxxx"), a.K)
should.Equal(mybool(true), a.N)
should.Equal(myuintptr(1), a.O)
b, err := Marshal(a)
should.Nil(err)
should.Equal(`{"a":1,"stream":1,"c":1,"d":1,"e":1,"f":1,"g":1,"h":1,"i":1,"j":1,"k":"xxxx","l":1,"m":1,"n":true,"o":1}`, string(b))
}

View file

@ -1,122 +0,0 @@
package jsoniter
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_read_empty_array_as_any(t *testing.T) {
should := require.New(t)
any := Get([]byte("[]"))
should.Equal(ArrayValue, any.Get().ValueType())
should.Equal(InvalidValue, any.Get(0.3).ValueType())
should.Equal(0, any.Size())
should.Equal(ArrayValue, any.ValueType())
should.Nil(any.LastError())
should.Equal(0, any.ToInt())
should.Equal(int32(0), any.ToInt32())
should.Equal(int64(0), any.ToInt64())
should.Equal(uint(0), any.ToUint())
should.Equal(uint32(0), any.ToUint32())
should.Equal(uint64(0), any.ToUint64())
should.Equal(float32(0), any.ToFloat32())
should.Equal(float64(0), any.ToFloat64())
}
func Test_read_one_element_array_as_any(t *testing.T) {
should := require.New(t)
any := Get([]byte("[1]"))
should.Equal(1, any.Size())
}
func Test_read_two_element_array_as_any(t *testing.T) {
should := require.New(t)
any := Get([]byte("[1,2]"))
should.Equal(1, any.Get(0).ToInt())
should.Equal(2, any.Size())
should.True(any.ToBool())
should.Equal(1, any.ToInt())
should.Equal([]interface{}{float64(1), float64(2)}, any.GetInterface())
stream := NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("[1,2]", string(stream.Buffer()))
arr := []int{}
any.ToVal(&arr)
should.Equal([]int{1, 2}, arr)
}
func Test_wrap_array_and_convert_to_any(t *testing.T) {
should := require.New(t)
any := Wrap([]int{1, 2, 3})
any2 := Wrap([]int{})
should.Equal("[1,2,3]", any.ToString())
should.True(any.ToBool())
should.False(any2.ToBool())
should.Equal(1, any.ToInt())
should.Equal(0, any2.ToInt())
should.Equal(int32(1), any.ToInt32())
should.Equal(int32(0), any2.ToInt32())
should.Equal(int64(1), any.ToInt64())
should.Equal(int64(0), any2.ToInt64())
should.Equal(uint(1), any.ToUint())
should.Equal(uint(0), any2.ToUint())
should.Equal(uint32(1), any.ToUint32())
should.Equal(uint32(0), any2.ToUint32())
should.Equal(uint64(1), any.ToUint64())
should.Equal(uint64(0), any2.ToUint64())
should.Equal(float32(1), any.ToFloat32())
should.Equal(float32(0), any2.ToFloat32())
should.Equal(float64(1), any.ToFloat64())
should.Equal(float64(0), any2.ToFloat64())
should.Equal(3, any.Size())
should.Equal(0, any2.Size())
var i interface{} = []int{1, 2, 3}
should.Equal(i, any.GetInterface())
}
func Test_array_lazy_any_get(t *testing.T) {
should := require.New(t)
any := Get([]byte("[1,[2,3],4]"))
should.Equal(3, any.Get(1, 1).ToInt())
should.Equal("[1,[2,3],4]", any.ToString())
}
func Test_array_lazy_any_get_all(t *testing.T) {
should := require.New(t)
any := Get([]byte("[[1],[2],[3,4]]"))
should.Equal("[1,2,3]", any.Get('*', 0).ToString())
any = Get([]byte("[[[1],[2],[3,4]]]"), 0, '*', 0)
should.Equal("[1,2,3]", any.ToString())
}
func Test_array_wrapper_any_get_all(t *testing.T) {
should := require.New(t)
any := wrapArray([][]int{
{1, 2},
{3, 4},
{5, 6},
})
should.Equal("[1,3,5]", any.Get('*', 0).ToString())
should.Equal(ArrayValue, any.ValueType())
should.True(any.ToBool())
should.Equal(1, any.Get(0, 0).ToInt())
}
func Test_array_lazy_any_get_invalid(t *testing.T) {
should := require.New(t)
any := Get([]byte("[]"))
should.Equal(InvalidValue, any.Get(1, 1).ValueType())
should.NotNil(any.Get(1, 1).LastError())
should.Equal(InvalidValue, any.Get("1").ValueType())
should.NotNil(any.Get("1").LastError())
}
func Test_invalid_array(t *testing.T) {
should := require.New(t)
any := Get([]byte("["), 0)
should.Equal(InvalidValue, any.ValueType())
}

View file

@ -1,64 +0,0 @@
package jsoniter
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
var boolConvertMap = map[string]bool{
"null": false,
"true": true,
"false": false,
`"true"`: true,
`"false"`: true,
"123": true,
`"123"`: true,
"0": false,
`"0"`: false,
"-1": true,
`"-1"`: true,
"1.1": true,
"0.0": false,
"-1.1": true,
`""`: false,
"[1,2]": true,
"[]": false,
"{}": true,
`{"abc":1}`: true,
}
func Test_read_bool_as_any(t *testing.T) {
should := require.New(t)
var any Any
for k, v := range boolConvertMap {
any = Get([]byte(k))
if v {
should.True(any.ToBool(), fmt.Sprintf("origin val is %v", k))
} else {
should.False(any.ToBool(), fmt.Sprintf("origin val is %v", k))
}
}
}
func Test_write_bool_to_stream(t *testing.T) {
should := require.New(t)
any := Get([]byte("true"))
stream := NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("true", string(stream.Buffer()))
should.Equal(any.ValueType(), BoolValue)
any = Get([]byte("false"))
stream = NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("false", string(stream.Buffer()))
should.Equal(any.ValueType(), BoolValue)
}

View file

@ -1,102 +0,0 @@
package jsoniter
import (
"testing"
"github.com/stretchr/testify/require"
)
var floatConvertMap = map[string]float64{
"null": 0,
"true": 1,
"false": 0,
`"true"`: 0,
`"false"`: 0,
"1e1": 10,
"1e+1": 10,
"1e-1": .1,
"1E1": 10,
"1E+1": 10,
"1E-1": .1,
"-1e1": -10,
"-1e+1": -10,
"-1e-1": -.1,
"-1E1": -10,
"-1E+1": -10,
"-1E-1": -.1,
`"1e1"`: 10,
`"1e+1"`: 10,
`"1e-1"`: .1,
`"1E1"`: 10,
`"1E+1"`: 10,
`"1E-1"`: .1,
`"-1e1"`: -10,
`"-1e+1"`: -10,
`"-1e-1"`: -.1,
`"-1E1"`: -10,
`"-1E+1"`: -10,
`"-1E-1"`: -.1,
"123": 123,
`"123true"`: 123,
`"+"`: 0,
`"-"`: 0,
`"-123true"`: -123,
`"-99.9true"`: -99.9,
"0": 0,
`"0"`: 0,
"-1": -1,
"1.1": 1.1,
"0.0": 0,
"-1.1": -1.1,
`"+1.1"`: 1.1,
`""`: 0,
"[1,2]": 1,
"[]": 0,
"{}": 0,
`{"abc":1}`: 0,
}
func Test_read_any_to_float(t *testing.T) {
should := require.New(t)
for k, v := range floatConvertMap {
any := Get([]byte(k))
should.Equal(float64(v), any.ToFloat64(), "the original val is "+k)
}
for k, v := range floatConvertMap {
any := Get([]byte(k))
should.Equal(float32(v), any.ToFloat32(), "the original val is "+k)
}
}
func Test_read_float_to_any(t *testing.T) {
should := require.New(t)
any := WrapFloat64(12.3)
anyFloat64 := float64(12.3)
//negaAnyFloat64 := float64(-1.1)
any2 := WrapFloat64(-1.1)
should.Equal(float64(12.3), any.ToFloat64())
//should.Equal("12.3", any.ToString())
should.True(any.ToBool())
should.Equal(float32(anyFloat64), any.ToFloat32())
should.Equal(int(anyFloat64), any.ToInt())
should.Equal(int32(anyFloat64), any.ToInt32())
should.Equal(int64(anyFloat64), any.ToInt64())
should.Equal(uint(anyFloat64), any.ToUint())
should.Equal(uint32(anyFloat64), any.ToUint32())
should.Equal(uint64(anyFloat64), any.ToUint64())
should.Equal(uint(0), any2.ToUint())
should.Equal(uint32(0), any2.ToUint32())
should.Equal(uint64(0), any2.ToUint64())
should.Equal(any.ValueType(), NumberValue)
should.Equal("1.23E+01", any.ToString())
}

View file

@ -1,197 +0,0 @@
package jsoniter
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
var intConvertMap = map[string]int{
"null": 0,
"321.1": 321,
"-321.1": -321,
`"1.1"`: 1,
`"-321.1"`: -321,
"0.0": 0,
"0": 0,
`"0"`: 0,
`"0.0"`: 0,
"-1.1": -1,
"true": 1,
"false": 0,
`"true"`: 0,
`"false"`: 0,
`"true123"`: 0,
`"123true"`: 123,
`"-123true"`: -123,
`"1.2332e6"`: 1,
`""`: 0,
"+": 0,
"-": 0,
"[]": 0,
"[1,2]": 1,
`["1","2"]`: 1,
// object in php cannot convert to int
"{}": 0,
}
func Test_read_any_to_int(t *testing.T) {
should := require.New(t)
// int
for k, v := range intConvertMap {
any := Get([]byte(k))
should.Equal(v, any.ToInt(), fmt.Sprintf("origin val %v", k))
}
// int32
for k, v := range intConvertMap {
any := Get([]byte(k))
should.Equal(int32(v), any.ToInt32(), fmt.Sprintf("original val is %v", k))
}
// int64
for k, v := range intConvertMap {
any := Get([]byte(k))
should.Equal(int64(v), any.ToInt64(), fmt.Sprintf("original val is %v", k))
}
}
var uintConvertMap = map[string]int{
"null": 0,
"321.1": 321,
`"1.1"`: 1,
`"-123.1"`: 0,
"0.0": 0,
"0": 0,
`"0"`: 0,
`"0.0"`: 0,
`"00.0"`: 0,
"true": 1,
"false": 0,
`"true"`: 0,
`"false"`: 0,
`"true123"`: 0,
`"+1"`: 1,
`"123true"`: 123,
`"-123true"`: 0,
`"1.2332e6"`: 1,
`""`: 0,
"+": 0,
"-": 0,
".": 0,
"[]": 0,
"[1,2]": 1,
"{}": 0,
"{1,2}": 0,
"-1.1": 0,
"-321.1": 0,
}
func Test_read_any_to_uint(t *testing.T) {
should := require.New(t)
for k, v := range uintConvertMap {
any := Get([]byte(k))
should.Equal(uint64(v), any.ToUint64(), fmt.Sprintf("origin val %v", k))
}
for k, v := range uintConvertMap {
any := Get([]byte(k))
should.Equal(uint32(v), any.ToUint32(), fmt.Sprintf("origin val %v", k))
}
for k, v := range uintConvertMap {
any := Get([]byte(k))
should.Equal(uint(v), any.ToUint(), fmt.Sprintf("origin val %v", k))
}
}
func Test_read_int64_to_any(t *testing.T) {
should := require.New(t)
any := WrapInt64(12345)
should.Equal(12345, any.ToInt())
should.Equal(int32(12345), any.ToInt32())
should.Equal(int64(12345), any.ToInt64())
should.Equal(uint(12345), any.ToUint())
should.Equal(uint32(12345), any.ToUint32())
should.Equal(uint64(12345), any.ToUint64())
should.Equal(float32(12345), any.ToFloat32())
should.Equal(float64(12345), any.ToFloat64())
should.Equal("12345", any.ToString())
should.Equal(true, any.ToBool())
should.Equal(any.ValueType(), NumberValue)
stream := NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("12345", string(stream.Buffer()))
}
func Test_read_int32_to_any(t *testing.T) {
should := require.New(t)
any := WrapInt32(12345)
should.Equal(12345, any.ToInt())
should.Equal(int32(12345), any.ToInt32())
should.Equal(int64(12345), any.ToInt64())
should.Equal(uint(12345), any.ToUint())
should.Equal(uint32(12345), any.ToUint32())
should.Equal(uint64(12345), any.ToUint64())
should.Equal(float32(12345), any.ToFloat32())
should.Equal(float64(12345), any.ToFloat64())
should.Equal("12345", any.ToString())
should.Equal(true, any.ToBool())
should.Equal(any.ValueType(), NumberValue)
stream := NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("12345", string(stream.Buffer()))
}
func Test_read_uint32_to_any(t *testing.T) {
should := require.New(t)
any := WrapUint32(12345)
should.Equal(12345, any.ToInt())
should.Equal(int32(12345), any.ToInt32())
should.Equal(int64(12345), any.ToInt64())
should.Equal(uint(12345), any.ToUint())
should.Equal(uint32(12345), any.ToUint32())
should.Equal(uint64(12345), any.ToUint64())
should.Equal(float32(12345), any.ToFloat32())
should.Equal(float64(12345), any.ToFloat64())
should.Equal("12345", any.ToString())
should.Equal(true, any.ToBool())
should.Equal(any.ValueType(), NumberValue)
stream := NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("12345", string(stream.Buffer()))
}
func Test_read_uint64_to_any(t *testing.T) {
should := require.New(t)
any := WrapUint64(12345)
should.Equal(12345, any.ToInt())
should.Equal(int32(12345), any.ToInt32())
should.Equal(int64(12345), any.ToInt64())
should.Equal(uint(12345), any.ToUint())
should.Equal(uint32(12345), any.ToUint32())
should.Equal(uint64(12345), any.ToUint64())
should.Equal(float32(12345), any.ToFloat32())
should.Equal(float64(12345), any.ToFloat64())
should.Equal("12345", any.ToString())
should.Equal(true, any.ToBool())
should.Equal(any.ValueType(), NumberValue)
stream := NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("12345", string(stream.Buffer()))
stream = NewStream(ConfigDefault, nil, 32)
stream.WriteUint(uint(123))
should.Equal("123", string(stream.Buffer()))
}
func Test_int_lazy_any_get(t *testing.T) {
should := require.New(t)
any := Get([]byte("1234"))
// panic!!
//should.Equal(any.LastError(), io.EOF)
should.Equal(InvalidValue, any.Get(1, "2").ValueType())
}

View file

@ -1,14 +0,0 @@
package jsoniter
import (
"github.com/stretchr/testify/require"
"testing"
)
func Test_wrap_map(t *testing.T) {
should := require.New(t)
any := Wrap(map[string]string{"Field1": "hello"})
should.Equal("hello", any.Get("Field1").ToString())
any = Wrap(map[string]string{"Field1": "hello"})
should.Equal(1, any.Size())
}

View file

@ -1,15 +0,0 @@
package jsoniter
import (
"github.com/stretchr/testify/require"
"testing"
)
func Test_read_null_as_any(t *testing.T) {
should := require.New(t)
any := Get([]byte(`null`))
should.Equal(0, any.ToInt())
should.Equal(float64(0), any.ToFloat64())
should.Equal("", any.ToString())
should.False(any.ToBool())
}

View file

@ -1,107 +0,0 @@
package jsoniter
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_read_object_as_any(t *testing.T) {
should := require.New(t)
any := Get([]byte(`{"a":"stream","c":"d"}`))
should.Equal(`{"a":"stream","c":"d"}`, any.ToString())
// partial parse
should.Equal("stream", any.Get("a").ToString())
should.Equal("d", any.Get("c").ToString())
should.Equal(2, len(any.Keys()))
any = Get([]byte(`{"a":"stream","c":"d"}`))
// full parse
should.Equal(2, len(any.Keys()))
should.Equal(2, any.Size())
should.True(any.ToBool())
should.Equal(0, any.ToInt())
should.Equal(ObjectValue, any.ValueType())
should.Nil(any.LastError())
obj := struct {
A string
}{}
any.ToVal(&obj)
should.Equal("stream", obj.A)
}
func Test_object_lazy_any_get(t *testing.T) {
should := require.New(t)
any := Get([]byte(`{"a":{"stream":{"c":"d"}}}`))
should.Equal("d", any.Get("a", "stream", "c").ToString())
}
func Test_object_lazy_any_get_all(t *testing.T) {
should := require.New(t)
any := Get([]byte(`{"a":[0],"stream":[1]}`))
should.Contains(any.Get('*', 0).ToString(), `"a":0`)
}
func Test_object_lazy_any_get_invalid(t *testing.T) {
should := require.New(t)
any := Get([]byte(`{}`))
should.Equal(InvalidValue, any.Get("a", "stream", "c").ValueType())
should.Equal(InvalidValue, any.Get(1).ValueType())
}
func Test_wrap_map_and_convert_to_any(t *testing.T) {
should := require.New(t)
any := Wrap(map[string]interface{}{"a": 1})
should.True(any.ToBool())
should.Equal(0, any.ToInt())
should.Equal(int32(0), any.ToInt32())
should.Equal(int64(0), any.ToInt64())
should.Equal(float32(0), any.ToFloat32())
should.Equal(float64(0), any.ToFloat64())
should.Equal(uint(0), any.ToUint())
should.Equal(uint32(0), any.ToUint32())
should.Equal(uint64(0), any.ToUint64())
}
func Test_wrap_object_and_convert_to_any(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
field2 string
}
any := Wrap(TestObject{"hello", "world"})
should.Equal("hello", any.Get("Field1").ToString())
any = Wrap(TestObject{"hello", "world"})
should.Equal(2, any.Size())
should.Equal(`{"Field1":"hello"}`, any.Get('*').ToString())
should.Equal(0, any.ToInt())
should.Equal(int32(0), any.ToInt32())
should.Equal(int64(0), any.ToInt64())
should.Equal(float32(0), any.ToFloat32())
should.Equal(float64(0), any.ToFloat64())
should.Equal(uint(0), any.ToUint())
should.Equal(uint32(0), any.ToUint32())
should.Equal(uint64(0), any.ToUint64())
should.True(any.ToBool())
should.Equal(`{"Field1":"hello"}`, any.ToString())
// cannot pass!
//stream := NewStream(ConfigDefault, nil, 32)
//any.WriteTo(stream)
//should.Equal(`{"Field1":"hello"}`, string(stream.Buffer()))
// cannot pass!
}
func Test_any_within_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 Any
Field2 Any
}
obj := TestObject{}
err := UnmarshalFromString(`{"Field1": "hello", "Field2": [1,2,3]}`, &obj)
should.Nil(err)
should.Equal("hello", obj.Field1.ToString())
should.Equal("[1,2,3]", obj.Field2.ToString())
}

View file

@ -1,56 +0,0 @@
package jsoniter
import (
"testing"
"github.com/stretchr/testify/require"
)
var stringConvertMap = map[string]string{
"null": "",
"321.1": "321.1",
`"1.1"`: "1.1",
`"-123.1"`: "-123.1",
"0.0": "0.0",
"0": "0",
`"0"`: "0",
`"0.0"`: "0.0",
`"00.0"`: "00.0",
"true": "true",
"false": "false",
`"true"`: "true",
`"false"`: "false",
`"true123"`: "true123",
`"+1"`: "+1",
"[]": "[]",
"[1,2]": "[1,2]",
"{}": "{}",
`{"a":1, "stream":true}`: `{"a":1, "stream":true}`,
}
func Test_read_any_to_string(t *testing.T) {
should := require.New(t)
for k, v := range stringConvertMap {
any := Get([]byte(k))
should.Equal(v, any.ToString(), "original val "+k)
}
}
func Test_read_string_as_any(t *testing.T) {
should := require.New(t)
any := Get([]byte(`"hello"`))
should.Equal("hello", any.ToString())
should.True(any.ToBool())
any = Get([]byte(`" "`))
should.False(any.ToBool())
any = Get([]byte(`"false"`))
should.True(any.ToBool())
any = Get([]byte(`"123"`))
should.Equal(123, any.ToInt())
}
func Test_wrap_string(t *testing.T) {
should := require.New(t)
any := WrapString("123")
should.Equal(123, any.ToInt())
}

View file

@ -1,213 +0,0 @@
package jsoniter
import (
"bytes"
"encoding/json"
"github.com/stretchr/testify/require"
"testing"
)
func Test_empty_array(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[]`)
cont := iter.ReadArray()
should.False(cont)
iter = ParseString(ConfigDefault, `[]`)
iter.ReadArrayCB(func(iter *Iterator) bool {
should.FailNow("should not call")
return true
})
}
func Test_one_element(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[1]`)
should.True(iter.ReadArray())
should.Equal(1, iter.ReadInt())
should.False(iter.ReadArray())
iter = ParseString(ConfigDefault, `[1]`)
iter.ReadArrayCB(func(iter *Iterator) bool {
should.Equal(1, iter.ReadInt())
return true
})
}
func Test_two_elements(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[1,2]`)
should.True(iter.ReadArray())
should.Equal(int64(1), iter.ReadInt64())
should.True(iter.ReadArray())
should.Equal(int64(2), iter.ReadInt64())
should.False(iter.ReadArray())
iter = ParseString(ConfigDefault, `[1,2]`)
should.Equal([]interface{}{float64(1), float64(2)}, iter.Read())
}
func Test_whitespace_in_head(t *testing.T) {
iter := ParseString(ConfigDefault, ` [1]`)
cont := iter.ReadArray()
if cont != true {
t.FailNow()
}
if iter.ReadUint64() != 1 {
t.FailNow()
}
}
func Test_whitespace_after_array_start(t *testing.T) {
iter := ParseString(ConfigDefault, `[ 1]`)
cont := iter.ReadArray()
if cont != true {
t.FailNow()
}
if iter.ReadUint64() != 1 {
t.FailNow()
}
}
func Test_whitespace_before_array_end(t *testing.T) {
iter := ParseString(ConfigDefault, `[1 ]`)
cont := iter.ReadArray()
if cont != true {
t.FailNow()
}
if iter.ReadUint64() != 1 {
t.FailNow()
}
cont = iter.ReadArray()
if cont != false {
t.FailNow()
}
}
func Test_whitespace_before_comma(t *testing.T) {
iter := ParseString(ConfigDefault, `[1 ,2]`)
cont := iter.ReadArray()
if cont != true {
t.FailNow()
}
if iter.ReadUint64() != 1 {
t.FailNow()
}
cont = iter.ReadArray()
if cont != true {
t.FailNow()
}
if iter.ReadUint64() != 2 {
t.FailNow()
}
cont = iter.ReadArray()
if cont != false {
t.FailNow()
}
}
func Test_write_array(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(Config{IndentionStep: 2}.Froze(), buf, 4096)
stream.WriteArrayStart()
stream.WriteInt(1)
stream.WriteMore()
stream.WriteInt(2)
stream.WriteArrayEnd()
stream.Flush()
should.Nil(stream.Error)
should.Equal("[\n 1,\n 2\n]", buf.String())
}
func Test_write_val_array(t *testing.T) {
should := require.New(t)
val := []int{1, 2, 3}
str, err := MarshalToString(&val)
should.Nil(err)
should.Equal("[1,2,3]", str)
}
func Test_write_val_empty_array(t *testing.T) {
should := require.New(t)
val := []int{}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal("[]", str)
}
func Test_write_array_of_interface_in_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field []interface{}
Field2 string
}
val := TestObject{[]interface{}{1, 2}, ""}
str, err := MarshalToString(val)
should.Nil(err)
should.Contains(str, `"Field":[1,2]`)
should.Contains(str, `"Field2":""`)
}
func Test_encode_byte_array(t *testing.T) {
should := require.New(t)
bytes, err := json.Marshal([]byte{1, 2, 3})
should.Nil(err)
should.Equal(`"AQID"`, string(bytes))
bytes, err = Marshal([]byte{1, 2, 3})
should.Nil(err)
should.Equal(`"AQID"`, string(bytes))
}
func Test_decode_byte_array_from_base64(t *testing.T) {
should := require.New(t)
data := []byte{}
err := json.Unmarshal([]byte(`"AQID"`), &data)
should.Nil(err)
should.Equal([]byte{1, 2, 3}, data)
err = Unmarshal([]byte(`"AQID"`), &data)
should.Nil(err)
should.Equal([]byte{1, 2, 3}, data)
}
func Test_decode_byte_array_from_array(t *testing.T) {
should := require.New(t)
data := []byte{}
err := json.Unmarshal([]byte(`[1,2,3]`), &data)
should.Nil(err)
should.Equal([]byte{1, 2, 3}, data)
err = Unmarshal([]byte(`[1,2,3]`), &data)
should.Nil(err)
should.Equal([]byte{1, 2, 3}, data)
}
func Test_decode_slice(t *testing.T) {
should := require.New(t)
slice := make([]string, 0, 5)
UnmarshalFromString(`["hello", "world"]`, &slice)
should.Equal([]string{"hello", "world"}, slice)
}
func Test_decode_large_slice(t *testing.T) {
should := require.New(t)
slice := make([]int, 0, 1)
UnmarshalFromString(`[1,2,3,4,5,6,7,8,9]`, &slice)
should.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}, slice)
}
func Benchmark_jsoniter_array(b *testing.B) {
b.ReportAllocs()
input := []byte(`[1,2,3,4,5,6,7,8,9]`)
iter := ParseBytes(ConfigDefault, input)
b.ResetTimer()
for n := 0; n < b.N; n++ {
iter.ResetBytes(input)
for iter.ReadArray() {
iter.ReadUint64()
}
}
}
func Benchmark_json_array(b *testing.B) {
for n := 0; n < b.N; n++ {
result := []interface{}{}
json.Unmarshal([]byte(`[1,2,3]`), &result)
}
}

View file

@ -1,113 +0,0 @@
package jsoniter
import (
"bytes"
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
func Test_true(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `true`)
should.True(iter.ReadBool())
iter = ParseString(ConfigDefault, `true`)
should.Equal(true, iter.Read())
}
func Test_false(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `false`)
should.False(iter.ReadBool())
}
func Test_write_true_false(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteTrue()
stream.WriteFalse()
stream.WriteBool(false)
stream.Flush()
should.Nil(stream.Error)
should.Equal("truefalsefalse", buf.String())
}
func Test_write_val_bool(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(true)
should.Equal(stream.Buffered(), 4)
stream.Flush()
should.Equal(stream.Buffered(), 0)
should.Nil(stream.Error)
should.Equal("true", buf.String())
}
func Test_encode_string_bool(t *testing.T) {
type TestObject struct {
Field bool `json:",omitempty,string"`
}
should := require.New(t)
output, err := json.Marshal(TestObject{true})
should.Nil(err)
should.Equal(`{"Field":"true"}`, string(output))
output, err = Marshal(TestObject{true})
should.Nil(err)
should.Equal(`{"Field":"true"}`, string(output))
}
func Test_decode_string_bool(t *testing.T) {
type TestObject struct {
Field bool `json:",omitempty,string"`
}
should := require.New(t)
obj := TestObject{}
err := json.Unmarshal([]byte(`{"Field":"true"}`), &obj)
should.Nil(err)
should.True(obj.Field)
obj = TestObject{}
err = json.Unmarshal([]byte(`{"Field":true}`), &obj)
should.NotNil(err)
obj = TestObject{}
err = Unmarshal([]byte(`{"Field":"true"}`), &obj)
should.Nil(err)
should.True(obj.Field)
obj = TestObject{}
err = Unmarshal([]byte(`{"Field":true}`), &obj)
should.NotNil(err)
}
func Test_bool_can_be_null(t *testing.T) {
type TestData struct {
Field bool `json:"field"`
}
should := require.New(t)
obj := TestData{}
data1 := []byte(`{"field": true}`)
err := Unmarshal(data1, &obj)
should.NoError(err)
should.Equal(true, obj.Field)
data2 := []byte(`{"field": null}`)
err = Unmarshal(data2, &obj)
should.NoError(err)
// Same behavior as stdlib, not touching the existing value.
should.Equal(true, obj.Field)
// Checking stdlib behavior as well
obj2 := TestData{}
err = json.Unmarshal(data1, &obj2)
should.NoError(err)
should.Equal(true, obj2.Field)
err = json.Unmarshal(data2, &obj2)
should.NoError(err)
should.Equal(true, obj2.Field)
}

View file

@ -1,341 +0,0 @@
package jsoniter
import (
"encoding/json"
"strconv"
"testing"
"time"
"unsafe"
"github.com/stretchr/testify/require"
)
func Test_customize_type_decoder(t *testing.T) {
RegisterTypeDecoderFunc("time.Time", func(ptr unsafe.Pointer, iter *Iterator) {
t, err := time.ParseInLocation("2006-01-02 15:04:05", iter.ReadString(), time.UTC)
if err != nil {
iter.Error = err
return
}
*((*time.Time)(ptr)) = t
})
defer ConfigDefault.(*frozenConfig).cleanDecoders()
val := time.Time{}
err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val)
if err != nil {
t.Fatal(err)
}
year, month, day := val.Date()
if year != 2016 || month != 12 || day != 5 {
t.Fatal(val)
}
}
func Test_customize_type_encoder(t *testing.T) {
should := require.New(t)
RegisterTypeEncoderFunc("time.Time", func(ptr unsafe.Pointer, stream *Stream) {
t := *((*time.Time)(ptr))
stream.WriteString(t.UTC().Format("2006-01-02 15:04:05"))
}, nil)
defer ConfigDefault.(*frozenConfig).cleanEncoders()
val := time.Unix(0, 0)
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`"1970-01-01 00:00:00"`, str)
}
func Test_customize_byte_array_encoder(t *testing.T) {
ConfigDefault.(*frozenConfig).cleanEncoders()
should := require.New(t)
RegisterTypeEncoderFunc("[]uint8", func(ptr unsafe.Pointer, stream *Stream) {
t := *((*[]byte)(ptr))
stream.WriteString(string(t))
}, nil)
defer ConfigDefault.(*frozenConfig).cleanEncoders()
val := []byte("abc")
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`"abc"`, str)
}
func Test_customize_float_marshal(t *testing.T) {
should := require.New(t)
json := Config{MarshalFloatWith6Digits: true}.Froze()
str, err := json.MarshalToString(float32(1.23456789))
should.Nil(err)
should.Equal("1.234568", str)
}
type Tom struct {
field1 string
}
func Test_customize_field_decoder(t *testing.T) {
RegisterFieldDecoderFunc("jsoniter.Tom", "field1", func(ptr unsafe.Pointer, iter *Iterator) {
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
})
defer ConfigDefault.(*frozenConfig).cleanDecoders()
tom := Tom{}
err := Unmarshal([]byte(`{"field1": 100}`), &tom)
if err != nil {
t.Fatal(err)
}
}
type TestObject1 struct {
Field1 string
}
type testExtension struct {
DummyExtension
}
func (extension *testExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
if structDescriptor.Type.String() != "jsoniter.TestObject1" {
return
}
binding := structDescriptor.GetField("Field1")
binding.Encoder = &funcEncoder{fun: func(ptr unsafe.Pointer, stream *Stream) {
str := *((*string)(ptr))
val, _ := strconv.Atoi(str)
stream.WriteInt(val)
}}
binding.Decoder = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
}}
binding.ToNames = []string{"field-1"}
binding.FromNames = []string{"field-1"}
}
func Test_customize_field_by_extension(t *testing.T) {
should := require.New(t)
RegisterExtension(&testExtension{})
obj := TestObject1{}
err := UnmarshalFromString(`{"field-1": 100}`, &obj)
should.Nil(err)
should.Equal("100", obj.Field1)
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"field-1":100}`, str)
}
type timeImplementedMarshaler time.Time
func (obj timeImplementedMarshaler) MarshalJSON() ([]byte, error) {
seconds := time.Time(obj).Unix()
return []byte(strconv.FormatInt(seconds, 10)), nil
}
func Test_marshaler(t *testing.T) {
type TestObject struct {
Field timeImplementedMarshaler
}
should := require.New(t)
val := timeImplementedMarshaler(time.Unix(123, 0))
obj := TestObject{val}
bytes, err := json.Marshal(obj)
should.Nil(err)
should.Equal(`{"Field":123}`, string(bytes))
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Field":123}`, str)
}
func Test_marshaler_and_encoder(t *testing.T) {
type TestObject struct {
Field *timeImplementedMarshaler
}
ConfigDefault.(*frozenConfig).cleanEncoders()
should := require.New(t)
RegisterTypeEncoderFunc("jsoniter.timeImplementedMarshaler", func(ptr unsafe.Pointer, stream *Stream) {
stream.WriteString("hello from encoder")
}, nil)
val := timeImplementedMarshaler(time.Unix(123, 0))
obj := TestObject{&val}
bytes, err := json.Marshal(obj)
should.Nil(err)
should.Equal(`{"Field":123}`, string(bytes))
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Field":"hello from encoder"}`, str)
}
type ObjectImplementedUnmarshaler int
func (obj *ObjectImplementedUnmarshaler) UnmarshalJSON(s []byte) error {
val, _ := strconv.ParseInt(string(s[1:len(s)-1]), 10, 64)
*obj = ObjectImplementedUnmarshaler(val)
return nil
}
func Test_unmarshaler(t *testing.T) {
should := require.New(t)
var obj ObjectImplementedUnmarshaler
err := json.Unmarshal([]byte(` "100" `), &obj)
should.Nil(err)
should.Equal(100, int(obj))
iter := ParseString(ConfigDefault, ` "100" `)
iter.ReadVal(&obj)
should.Nil(err)
should.Equal(100, int(obj))
}
func Test_unmarshaler_and_decoder(t *testing.T) {
type TestObject struct {
Field *ObjectImplementedUnmarshaler
Field2 string
}
ConfigDefault.(*frozenConfig).cleanDecoders()
should := require.New(t)
RegisterTypeDecoderFunc("jsoniter.ObjectImplementedUnmarshaler", func(ptr unsafe.Pointer, iter *Iterator) {
*(*ObjectImplementedUnmarshaler)(ptr) = 10
iter.Skip()
})
obj := TestObject{}
val := ObjectImplementedUnmarshaler(0)
obj.Field = &val
err := json.Unmarshal([]byte(`{"Field":"100"}`), &obj)
should.Nil(err)
should.Equal(100, int(*obj.Field))
err = Unmarshal([]byte(`{"Field":"100"}`), &obj)
should.Nil(err)
should.Equal(10, int(*obj.Field))
}
type tmString string
type tmStruct struct {
String tmString
}
func (s tmStruct) MarshalJSON() ([]byte, error) {
var b []byte
b = append(b, '"')
b = append(b, s.String...)
b = append(b, '"')
return b, nil
}
func Test_marshaler_on_struct(t *testing.T) {
fixed := tmStruct{"hello"}
//json.Marshal(fixed)
Marshal(fixed)
}
type withChan struct {
F2 chan []byte
}
func (q withChan) MarshalJSON() ([]byte, error) {
return []byte(`""`), nil
}
func (q *withChan) UnmarshalJSON(value []byte) error {
return nil
}
func Test_marshal_json_with_chan(t *testing.T) {
type TestObject struct {
F1 withChan
}
should := require.New(t)
output, err := MarshalToString(TestObject{})
should.Nil(err)
should.Equal(`{"F1":""}`, output)
}
type withTime struct {
time.Time
}
func (t *withTime) UnmarshalJSON(b []byte) error {
return nil
}
func (t withTime) MarshalJSON() ([]byte, error) {
return []byte(`"fake"`), nil
}
func Test_marshal_json_with_time(t *testing.T) {
type S1 struct {
F1 withTime
F2 *withTime
}
type TestObject struct {
TF1 S1
}
should := require.New(t)
obj := TestObject{
S1{
F1: withTime{
time.Unix(0, 0),
},
F2: &withTime{
time.Unix(0, 0),
},
},
}
output, err := json.Marshal(obj)
should.Nil(err)
should.Equal(`{"TF1":{"F1":"fake","F2":"fake"}}`, string(output))
output, err = Marshal(obj)
should.Nil(err)
should.Equal(`{"TF1":{"F1":"fake","F2":"fake"}}`, string(output))
obj = TestObject{}
should.Nil(json.Unmarshal([]byte(`{"TF1":{"F1":"fake","F2":"fake"}}`), &obj))
should.NotNil(obj.TF1.F2)
obj = TestObject{}
should.Nil(Unmarshal([]byte(`{"TF1":{"F1":"fake","F2":"fake"}}`), &obj))
should.NotNil(obj.TF1.F2)
}
func Test_customize_tag_key(t *testing.T) {
type TestObject struct {
Field string `orm:"field"`
}
should := require.New(t)
json := Config{TagKey: "orm"}.Froze()
str, err := json.MarshalToString(TestObject{"hello"})
should.Nil(err)
should.Equal(`{"field":"hello"}`, str)
}
func Test_recursive_empty_interface_customization(t *testing.T) {
t.Skip()
var obj interface{}
RegisterTypeDecoderFunc("interface {}", func(ptr unsafe.Pointer, iter *Iterator) {
switch iter.WhatIsNext() {
case NumberValue:
*(*interface{})(ptr) = iter.ReadInt64()
default:
*(*interface{})(ptr) = iter.Read()
}
})
should := require.New(t)
Unmarshal([]byte("[100]"), &obj)
should.Equal([]interface{}{int64(100)}, obj)
}
type GeoLocation struct {
Id string `json:"id,omitempty" db:"id"`
}
func (p *GeoLocation) MarshalJSON() ([]byte, error) {
return []byte(`{}`), nil
}
func (p *GeoLocation) UnmarshalJSON(input []byte) error {
p.Id = "hello"
return nil
}
func Test_marshal_and_unmarshal_on_non_pointer(t *testing.T) {
should := require.New(t)
locations := []GeoLocation{{"000"}}
bytes, err := Marshal(locations)
should.Nil(err)
should.Equal("[{}]", string(bytes))
err = Unmarshal([]byte("[1]"), &locations)
should.Nil(err)
should.Equal("hello", locations[0].Id)
}

View file

@ -1,87 +0,0 @@
package jsoniter
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
func Test_bind_api_demo(t *testing.T) {
should := require.New(t)
val := []int{}
err := UnmarshalFromString(`[0,1,2,3] `, &val)
should.Nil(err)
should.Equal([]int{0, 1, 2, 3}, val)
}
func Test_iterator_api_demo(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[0,1,2,3]`)
total := 0
for iter.ReadArray() {
total += iter.ReadInt()
}
should.Equal(6, total)
}
type People struct {
Name string
Gender string
Age int
Address string
Mobile string
Country string
Height int
}
func jsoniterMarshal(p *People) error {
_, err := Marshal(p)
if nil != err {
return err
}
return nil
}
func stdMarshal(p *People) error {
_, err := json.Marshal(p)
if nil != err {
return err
}
return nil
}
func BenchmarkJosniterMarshal(b *testing.B) {
var p People
p.Address = "上海市徐汇区漕宝路"
p.Age = 30
p.Country = "中国"
p.Gender = "male"
p.Height = 170
p.Mobile = "18502120533"
p.Name = "Elvin"
b.ReportAllocs()
for i := 0; i < b.N; i++ {
err := jsoniterMarshal(&p)
if nil != err {
b.Error(err)
}
}
}
func BenchmarkStdMarshal(b *testing.B) {
var p People
p.Address = "上海市徐汇区漕宝路"
p.Age = 30
p.Country = "中国"
p.Gender = "male"
p.Height = 170
p.Mobile = "18502120533"
p.Name = "Elvin"
b.ReportAllocs()
for i := 0; i < b.N; i++ {
err := stdMarshal(&p)
if nil != err {
b.Error(err)
}
}
}

View file

@ -1,42 +0,0 @@
package jsoniter
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
func Test_encode_interface(t *testing.T) {
should := require.New(t)
var a interface{}
a = int8(10)
str, err := MarshalToString(a)
should.Nil(err)
should.Equal(str, "10")
a = float32(3)
str, err = MarshalToString(a)
should.Nil(err)
should.Equal(str, "3")
a = map[string]interface{}{"abc": 1}
str, err = MarshalToString(a)
should.Nil(err)
should.Equal(str, `{"abc":1}`)
a = uintptr(1)
str, err = MarshalToString(a)
should.Nil(err)
should.Equal(str, "1")
a = uint(1)
str, err = MarshalToString(a)
should.Nil(err)
should.Equal(str, "1")
a = uint8(1)
str, err = MarshalToString(a)
should.Nil(err)
should.Equal(str, "1")
a = json.RawMessage("abc")
MarshalToString(a)
str, err = MarshalToString(a)
should.Nil(err)
should.Equal(str, "abc")
}

View file

@ -1,50 +0,0 @@
package jsoniter
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
type MyEnum int64
const (
MyEnumA MyEnum = iota
MyEnumB
)
func (m *MyEnum) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"foo-%d"`, int(*m))), nil
}
func (m *MyEnum) UnmarshalJSON(jb []byte) error {
switch string(jb) {
case `"foo-1"`:
*m = MyEnumB
default:
*m = MyEnumA
}
return nil
}
func Test_custom_marshaler_on_enum(t *testing.T) {
type Wrapper struct {
Payload interface{}
}
type Wrapper2 struct {
Payload MyEnum
}
should := require.New(t)
w := Wrapper{Payload: MyEnumB}
jb, err := Marshal(w)
should.NoError(err)
should.Equal(`{"Payload":"foo-1"}`, string(jb))
var w2 Wrapper2
err = Unmarshal(jb, &w2)
should.NoError(err)
should.Equal(MyEnumB, w2.Payload)
}

View file

@ -1,37 +0,0 @@
package jsoniter
import (
"encoding/json"
"github.com/stretchr/testify/require"
"testing"
)
func Test_encode_fixed_array(t *testing.T) {
should := require.New(t)
type FixedArray [2]float64
fixed := FixedArray{0.1, 1.0}
output, err := MarshalToString(fixed)
should.Nil(err)
should.Equal("[0.1,1]", output)
}
func Test_encode_fixed_array_of_map(t *testing.T) {
should := require.New(t)
type FixedArray [2]map[string]string
fixed := FixedArray{map[string]string{"1": "2"}, map[string]string{"3": "4"}}
output, err := MarshalToString(fixed)
should.Nil(err)
should.Equal(`[{"1":"2"},{"3":"4"}]`, output)
}
func Test_decode_fixed_array(t *testing.T) {
should := require.New(t)
type FixedArray [2]float64
var fixed FixedArray
should.Nil(json.Unmarshal([]byte("[1,2,3]"), &fixed))
should.Equal(float64(1), fixed[0])
should.Equal(float64(2), fixed[1])
should.Nil(Unmarshal([]byte("[1,2,3]"), &fixed))
should.Equal(float64(1), fixed[0])
should.Equal(float64(2), fixed[1])
}

View file

@ -1,210 +0,0 @@
// +build go1.8
package jsoniter
import (
"bytes"
"encoding/json"
"fmt"
"strconv"
"testing"
"github.com/stretchr/testify/require"
)
func Test_read_big_float(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `12.3`)
val := iter.ReadBigFloat()
val64, _ := val.Float64()
should.Equal(12.3, val64)
}
func Test_read_big_int(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `92233720368547758079223372036854775807`)
val := iter.ReadBigInt()
should.NotNil(val)
should.Equal(`92233720368547758079223372036854775807`, val.String())
}
func Test_read_float(t *testing.T) {
inputs := []string{
`1.1`, `1000`, `9223372036854775807`, `12.3`, `-12.3`, `720368.54775807`, `720368.547758075`,
`1e1`, `1e+1`, `1e-1`, `1E1`, `1E+1`, `1E-1`, `-1e1`, `-1e+1`, `-1e-1`,
}
for _, input := range inputs {
// non-streaming
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input+",")
expected, err := strconv.ParseFloat(input, 32)
should.Nil(err)
should.Equal(float32(expected), iter.ReadFloat32())
})
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input+",")
expected, err := strconv.ParseFloat(input, 64)
should.Nil(err)
should.Equal(expected, iter.ReadFloat64())
})
// streaming
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(input+","), 2)
expected, err := strconv.ParseFloat(input, 32)
should.Nil(err)
should.Equal(float32(expected), iter.ReadFloat32())
})
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(input+","), 2)
val := float64(0)
err := json.Unmarshal([]byte(input), &val)
should.Nil(err)
should.Equal(val, iter.ReadFloat64())
})
}
}
func Test_read_float_as_interface(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `12.3`)
should.Equal(float64(12.3), iter.Read())
}
func Test_wrap_float(t *testing.T) {
should := require.New(t)
str, err := MarshalToString(WrapFloat64(12.3))
should.Nil(err)
should.Equal("12.3", str)
}
func Test_write_float32(t *testing.T) {
vals := []float32{0, 1, -1, 99, 0xff, 0xfff, 0xffff, 0xfffff, 0xffffff, 0x4ffffff, 0xfffffff,
-0x4ffffff, -0xfffffff, 1.2345, 1.23456, 1.234567, 1.001}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteFloat32Lossy(val)
stream.Flush()
should.Nil(stream.Error)
output, err := json.Marshal(val)
should.Nil(err)
should.Equal(string(output), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
output, err := json.Marshal(val)
should.Nil(err)
should.Equal(string(output), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 10)
stream.WriteRaw("abcdefg")
stream.WriteFloat32Lossy(1.123456)
stream.Flush()
should.Nil(stream.Error)
should.Equal("abcdefg1.123456", buf.String())
stream = NewStream(ConfigDefault, nil, 0)
stream.WriteFloat32(float32(0.0000001))
should.Equal("1e-07", string(stream.buf))
}
func Test_write_float64(t *testing.T) {
vals := []float64{0, 1, -1, 99, 0xff, 0xfff, 0xffff, 0xfffff, 0xffffff, 0x4ffffff, 0xfffffff,
-0x4ffffff, -0xfffffff, 1.2345, 1.23456, 1.234567, 1.001}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteFloat64Lossy(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatFloat(val, 'f', -1, 64), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatFloat(val, 'f', -1, 64), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 10)
stream.WriteRaw("abcdefg")
stream.WriteFloat64Lossy(1.123456)
stream.Flush()
should.Nil(stream.Error)
should.Equal("abcdefg1.123456", buf.String())
stream = NewStream(ConfigDefault, nil, 0)
stream.WriteFloat64(float64(0.0000001))
should.Equal("1e-07", string(stream.buf))
}
func Test_read_float64_cursor(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, "[1.23456789\n,2,3]")
should.True(iter.ReadArray())
should.Equal(1.23456789, iter.Read())
should.True(iter.ReadArray())
should.Equal(float64(2), iter.Read())
}
func Test_read_float_scientific(t *testing.T) {
should := require.New(t)
var obj interface{}
should.Nil(UnmarshalFromString(`1e1`, &obj))
should.Equal(float64(10), obj)
should.Nil(json.Unmarshal([]byte(`1e1`), &obj))
should.Equal(float64(10), obj)
should.Nil(UnmarshalFromString(`1.0e1`, &obj))
should.Equal(float64(10), obj)
should.Nil(json.Unmarshal([]byte(`1.0e1`), &obj))
should.Equal(float64(10), obj)
}
func Test_lossy_float_marshal(t *testing.T) {
should := require.New(t)
api := Config{MarshalFloatWith6Digits: true}.Froze()
output, err := api.MarshalToString(float64(0.1234567))
should.Nil(err)
should.Equal("0.123457", output)
output, err = api.MarshalToString(float32(0.1234567))
should.Nil(err)
should.Equal("0.123457", output)
}
func Benchmark_jsoniter_float(b *testing.B) {
b.ReportAllocs()
input := []byte(`1.1123,`)
iter := NewIterator(ConfigDefault)
for n := 0; n < b.N; n++ {
iter.ResetBytes(input)
iter.ReadFloat64()
}
}
func Benchmark_json_float(b *testing.B) {
for n := 0; n < b.N; n++ {
result := float64(0)
json.Unmarshal([]byte(`1.1`), &result)
}
}

View file

@ -1,567 +0,0 @@
// +build go1.8
package jsoniter
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"strconv"
"testing"
"github.com/stretchr/testify/require"
)
func Test_read_uint64_invalid(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, ",")
iter.ReadUint64()
should.NotNil(iter.Error)
}
func Test_read_int_from_null(t *testing.T) {
type TestObject struct {
F1 int8
F2 int16
F3 int32
F4 int64
F5 int
F6 uint8
F7 uint16
F8 uint32
F9 uint64
F10 uint
F11 float32
F12 float64
F13 uintptr
}
should := require.New(t)
obj := TestObject{}
err := Unmarshal([]byte(`{
"f1":null,
"f2":null,
"f3":null,
"f4":null,
"f5":null,
"f6":null,
"f7":null,
"f8":null,
"f9":null,
"f10":null,
"f11":null,
"f12":null,
"f13":null
}`), &obj)
should.Nil(err)
}
func _int8(t *testing.T) {
inputs := []string{`127`, `-128`}
for _, input := range inputs {
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input)
expected, err := strconv.ParseInt(input, 10, 8)
should.Nil(err)
should.Equal(int8(expected), iter.ReadInt8())
})
}
}
func Test_read_int16(t *testing.T) {
inputs := []string{`32767`, `-32768`}
for _, input := range inputs {
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input)
expected, err := strconv.ParseInt(input, 10, 16)
should.Nil(err)
should.Equal(int16(expected), iter.ReadInt16())
})
}
}
func Test_read_int32(t *testing.T) {
inputs := []string{`1`, `12`, `123`, `1234`, `12345`, `123456`, `2147483647`, `-2147483648`}
for _, input := range inputs {
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input)
expected, err := strconv.ParseInt(input, 10, 32)
should.Nil(err)
should.Equal(int32(expected), iter.ReadInt32())
})
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
expected, err := strconv.ParseInt(input, 10, 32)
should.Nil(err)
should.Equal(int32(expected), iter.ReadInt32())
})
}
}
func Test_read_int32_array(t *testing.T) {
should := require.New(t)
input := `[123,456,789]`
val := make([]int32, 0)
UnmarshalFromString(input, &val)
should.Equal(3, len(val))
}
func Test_read_int64_array(t *testing.T) {
should := require.New(t)
input := `[123,456,789]`
val := make([]int64, 0)
UnmarshalFromString(input, &val)
should.Equal(3, len(val))
}
func Test_read_int_overflow(t *testing.T) {
should := require.New(t)
inputArr := []string{"123451", "-123451"}
for _, s := range inputArr {
iter := ParseString(ConfigDefault, s)
iter.ReadInt8()
should.NotNil(iter.Error)
iterU := ParseString(ConfigDefault, s)
iterU.ReadUint8()
should.NotNil(iterU.Error)
}
inputArr = []string{"12345678912", "-12345678912"}
for _, s := range inputArr {
iter := ParseString(ConfigDefault, s)
iter.ReadInt16()
should.NotNil(iter.Error)
iterUint := ParseString(ConfigDefault, s)
iterUint.ReadUint16()
should.NotNil(iterUint.Error)
}
inputArr = []string{"3111111111", "-3111111111", "1234232323232323235678912", "-1234567892323232323212"}
for _, s := range inputArr {
iter := ParseString(ConfigDefault, s)
iter.ReadInt32()
should.NotNil(iter.Error)
iterUint := ParseString(ConfigDefault, s)
iterUint.ReadUint32()
should.NotNil(iterUint.Error)
}
inputArr = []string{"9223372036854775811", "-9523372036854775807", "1234232323232323235678912", "-1234567892323232323212"}
for _, s := range inputArr {
iter := ParseString(ConfigDefault, s)
iter.ReadInt64()
should.NotNil(iter.Error)
iterUint := ParseString(ConfigDefault, s)
iterUint.ReadUint64()
should.NotNil(iterUint.Error)
}
}
func Test_read_int64(t *testing.T) {
inputs := []string{`1`, `12`, `123`, `1234`, `12345`, `123456`, `9223372036854775807`, `-9223372036854775808`}
for _, input := range inputs {
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input)
expected, err := strconv.ParseInt(input, 10, 64)
should.Nil(err)
should.Equal(expected, iter.ReadInt64())
})
t.Run(fmt.Sprintf("%v", input), func(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
expected, err := strconv.ParseInt(input, 10, 64)
should.Nil(err)
should.Equal(expected, iter.ReadInt64())
})
}
}
func Test_read_int64_overflow(t *testing.T) {
should := require.New(t)
input := "123456789123456789123456789123456789,"
iter := ParseString(ConfigDefault, input)
iter.ReadInt64()
should.NotNil(iter.Error)
}
func Test_wrap_int(t *testing.T) {
should := require.New(t)
str, err := MarshalToString(WrapInt64(100))
should.Nil(err)
should.Equal("100", str)
}
func Test_write_uint8(t *testing.T) {
vals := []uint8{0, 1, 11, 111, 255}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteUint8(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 3)
stream.WriteRaw("a")
stream.WriteUint8(100) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a100", buf.String())
}
func Test_write_int8(t *testing.T) {
vals := []int8{0, 1, -1, 99, 0x7f, -0x80}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteInt8(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(int64(val), 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(int64(val), 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4)
stream.WriteRaw("a")
stream.WriteInt8(-100) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a-100", buf.String())
}
func Test_write_uint16(t *testing.T) {
vals := []uint16{0, 1, 11, 111, 255, 0xfff, 0xffff}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteUint16(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 5)
stream.WriteRaw("a")
stream.WriteUint16(10000) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a10000", buf.String())
}
func Test_write_int16(t *testing.T) {
vals := []int16{0, 1, 11, 111, 255, 0xfff, 0x7fff, -0x8000}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteInt16(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(int64(val), 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(int64(val), 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 6)
stream.WriteRaw("a")
stream.WriteInt16(-10000) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a-10000", buf.String())
}
func Test_write_uint32(t *testing.T) {
vals := []uint32{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0xffffffff}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteUint32(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 10)
stream.WriteRaw("a")
stream.WriteUint32(0xffffffff) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a4294967295", buf.String())
}
func Test_write_int32(t *testing.T) {
vals := []int32{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0x7fffffff, -0x80000000}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteInt32(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(int64(val), 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(int64(val), 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 11)
stream.WriteRaw("a")
stream.WriteInt32(-0x7fffffff) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a-2147483647", buf.String())
}
func Test_write_uint64(t *testing.T) {
vals := []uint64{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0xffffffff,
0xfffffffff, 0xffffffffff, 0xfffffffffff, 0xffffffffffff, 0xfffffffffffff, 0xffffffffffffff,
0xfffffffffffffff, 0xffffffffffffffff}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteUint64(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatUint(uint64(val), 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 10)
stream.WriteRaw("a")
stream.WriteUint64(0xffffffff) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a4294967295", buf.String())
}
func Test_write_int64(t *testing.T) {
vals := []int64{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0xffffffff,
0xfffffffff, 0xffffffffff, 0xfffffffffff, 0xffffffffffff, 0xfffffffffffff, 0xffffffffffffff,
0xfffffffffffffff, 0x7fffffffffffffff, -0x8000000000000000}
for _, val := range vals {
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteInt64(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(val, 10), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatInt(val, 10), buf.String())
})
}
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 10)
stream.WriteRaw("a")
stream.WriteInt64(0xffffffff) // should clear buffer
stream.Flush()
should.Nil(stream.Error)
should.Equal("a4294967295", buf.String())
}
func Test_write_val_int(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal(1001)
stream.Flush()
should.Nil(stream.Error)
should.Equal("1001", buf.String())
}
func Test_write_val_int_ptr(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
val := 1001
stream.WriteVal(&val)
stream.Flush()
should.Nil(stream.Error)
should.Equal("1001", buf.String())
}
func Test_json_number(t *testing.T) {
should := require.New(t)
var arr []json.Number
err := Unmarshal([]byte(`[1]`), &arr)
should.Nil(err)
should.Equal(json.Number("1"), arr[0])
str, err := MarshalToString(arr)
should.Nil(err)
should.Equal(`[1]`, str)
}
func Test_jsoniter_number(t *testing.T) {
should := require.New(t)
var arr []Number
err := Unmarshal([]byte(`[1]`), &arr)
should.Nil(err)
should.Equal(Number("1"), arr[0])
str, isNumber := CastJsonNumber(arr[0])
should.True(isNumber)
should.Equal("1", str)
}
func Test_non_numeric_as_number(t *testing.T) {
should := require.New(t)
var v1 json.Number
err := Unmarshal([]byte(`"500"`), &v1)
should.Nil(err)
should.Equal("500", string(v1))
var v2 Number
err = Unmarshal([]byte(`"500"`), &v2)
should.Nil(err)
should.Equal("500", string(v2))
}
func Test_null_as_number(t *testing.T) {
should := require.New(t)
var v1 json.Number
err := json.Unmarshal([]byte(`null`), &v1)
should.Nil(err)
should.Equal("", string(v1))
var v2 Number
err = Unmarshal([]byte(`null`), &v2)
should.Nil(err)
should.Equal("", string(v2))
}
func Test_float_as_int(t *testing.T) {
should := require.New(t)
var i int
should.NotNil(Unmarshal([]byte(`1.1`), &i))
}
func Benchmark_jsoniter_encode_int(b *testing.B) {
stream := NewStream(ConfigDefault, ioutil.Discard, 64)
for n := 0; n < b.N; n++ {
stream.n = 0
stream.WriteUint64(0xffffffff)
}
}
func Benchmark_itoa(b *testing.B) {
for n := 0; n < b.N; n++ {
strconv.FormatInt(0xffffffff, 10)
}
}
func Benchmark_jsoniter_int(b *testing.B) {
iter := NewIterator(ConfigDefault)
input := []byte(`100`)
for n := 0; n < b.N; n++ {
iter.ResetBytes(input)
iter.ReadInt64()
}
}
func Benchmark_json_int(b *testing.B) {
for n := 0; n < b.N; n++ {
result := int64(0)
json.Unmarshal([]byte(`-100`), &result)
}
}

View file

@ -1,576 +0,0 @@
package jsoniter
import (
"encoding/json"
"fmt"
"testing"
"unsafe"
"github.com/stretchr/testify/require"
"reflect"
)
func Test_write_empty_interface_via_placeholder(t *testing.T) {
fmt.Println(^uint(0) >> 1)
should := require.New(t)
m := map[uint32]interface{}{1: "hello"}
inf := reflect.ValueOf(m).MapIndex(reflect.ValueOf(uint32(1))).Interface()
encoder := &placeholderEncoder{
cfg: ConfigFastest.(*frozenConfig),
cacheKey: reflect.TypeOf(m).Elem(),
}
stream := ConfigFastest.BorrowStream(nil)
encoderOfType(ConfigFastest.(*frozenConfig), reflect.TypeOf(m).Elem())
encoder.EncodeInterface(inf, stream)
should.Equal(`"hello"`, string(stream.Buffer()))
}
func Test_write_array_of_interface(t *testing.T) {
should := require.New(t)
array := []interface{}{"hello"}
str, err := MarshalToString(array)
should.Nil(err)
should.Equal(`["hello"]`, str)
}
func Test_write_map_of_interface(t *testing.T) {
should := require.New(t)
val := map[string]interface{}{"hello": "world"}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`{"hello":"world"}`, str)
}
func Test_write_map_of_interface_in_struct(t *testing.T) {
type TestObject struct {
Field map[string]interface{}
}
should := require.New(t)
val := TestObject{map[string]interface{}{"hello": "world"}}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`{"Field":{"hello":"world"}}`, str)
}
func Test_write_map_of_interface_in_struct_with_two_fields(t *testing.T) {
type TestObject struct {
Field map[string]interface{}
Field2 string
}
should := require.New(t)
val := TestObject{map[string]interface{}{"hello": "world"}, ""}
str, err := MarshalToString(val)
should.Nil(err)
should.Contains(str, `"Field":{"hello":"world"}`)
}
type MyInterface interface {
Hello() string
}
type MyString string
func (ms MyString) Hello() string {
return string(ms)
}
func Test_write_map_of_custom_interface(t *testing.T) {
should := require.New(t)
myStr := MyString("world")
should.Equal("world", myStr.Hello())
val := map[string]MyInterface{"hello": myStr}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`{"hello":"world"}`, str)
}
func Test_write_interface(t *testing.T) {
should := require.New(t)
var val interface{}
val = "hello"
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`"hello"`, str)
}
func Test_read_interface(t *testing.T) {
should := require.New(t)
var val interface{}
err := UnmarshalFromString(`"hello"`, &val)
should.Nil(err)
should.Equal("hello", val)
err = UnmarshalFromString(`1e1`, &val)
should.Nil(err)
should.Equal(float64(10), val)
err = UnmarshalFromString(`1.0e1`, &val)
should.Nil(err)
should.Equal(float64(10), val)
err = json.Unmarshal([]byte(`1.0e1`), &val)
should.Nil(err)
should.Equal(float64(10), val)
}
func Test_read_custom_interface(t *testing.T) {
should := require.New(t)
var val MyInterface
RegisterTypeDecoderFunc("jsoniter.MyInterface", func(ptr unsafe.Pointer, iter *Iterator) {
*((*MyInterface)(ptr)) = MyString(iter.ReadString())
})
err := UnmarshalFromString(`"hello"`, &val)
should.Nil(err)
should.Equal("hello", val.Hello())
}
func Test_decode_object_contain_empty_interface(t *testing.T) {
type TestObject struct {
Field interface{}
}
should := require.New(t)
obj := TestObject{}
obj.Field = 1024
should.Nil(UnmarshalFromString(`{"Field": "hello"}`, &obj))
should.Equal("hello", obj.Field)
}
func Test_decode_object_contain_non_empty_interface(t *testing.T) {
type TestObject struct {
Field MyInterface
}
should := require.New(t)
obj := TestObject{}
obj.Field = MyString("abc")
should.Nil(UnmarshalFromString(`{"Field": "hello"}`, &obj))
should.Equal(MyString("hello"), obj.Field)
}
func Test_encode_object_contain_empty_interface(t *testing.T) {
type TestObject struct {
Field interface{}
}
should := require.New(t)
obj := TestObject{}
obj.Field = 1024
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Field":1024}`, str)
}
func Test_encode_object_contain_non_empty_interface(t *testing.T) {
type TestObject struct {
Field MyInterface
}
should := require.New(t)
obj := TestObject{}
obj.Field = MyString("hello")
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Field":"hello"}`, str)
}
func Test_nil_non_empty_interface(t *testing.T) {
ConfigDefault.(*frozenConfig).cleanEncoders()
ConfigDefault.(*frozenConfig).cleanDecoders()
type TestObject struct {
Field []MyInterface
}
should := require.New(t)
obj := TestObject{}
b := []byte(`{"Field":["AAA"]}`)
should.NotNil(json.Unmarshal(b, &obj))
should.NotNil(Unmarshal(b, &obj))
}
func Test_read_large_number_as_interface(t *testing.T) {
should := require.New(t)
var val interface{}
err := Config{UseNumber: true}.Froze().UnmarshalFromString(`123456789123456789123456789`, &val)
should.Nil(err)
output, err := MarshalToString(val)
should.Nil(err)
should.Equal(`123456789123456789123456789`, output)
}
func Test_nested_one_field_struct(t *testing.T) {
should := require.New(t)
type YetYetAnotherObject struct {
Field string
}
type YetAnotherObject struct {
Field *YetYetAnotherObject
}
type AnotherObject struct {
Field *YetAnotherObject
}
type TestObject struct {
Me *AnotherObject
}
obj := TestObject{&AnotherObject{&YetAnotherObject{&YetYetAnotherObject{"abc"}}}}
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Me":{"Field":{"Field":{"Field":"abc"}}}}`, str)
str, err = MarshalToString(&obj)
should.Nil(err)
should.Equal(`{"Me":{"Field":{"Field":{"Field":"abc"}}}}`, str)
}
func Test_struct_with_embedded_ptr_with_tag(t *testing.T) {
type O1 struct {
O1F string
}
type Option struct {
O1 *O1
}
type T struct {
Option `json:","`
}
var obj T
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"O1":null}`, output)
}
func Test_struct_with_one_nil(t *testing.T) {
type TestObject struct {
F *float64
}
var obj TestObject
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"F":null}`, output)
}
func Test_struct_with_one_nil_embedded(t *testing.T) {
type Parent struct {
Field1 string
Field2 string
}
type TestObject struct {
*Parent
}
obj := TestObject{}
should := require.New(t)
bytes, err := json.Marshal(obj)
should.Nil(err)
should.Equal("{}", string(bytes))
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{}`, output)
}
func Test_struct_with_not_nil_embedded(t *testing.T) {
type Parent struct {
Field0 string
Field1 []string
Field2 map[string]interface{}
}
type TestObject struct {
*Parent
}
should := require.New(t)
var obj TestObject
err := UnmarshalFromString(`{"Field0":"1","Field1":null,"Field2":{"K":"V"}}`, &obj)
should.Nil(err)
should.Nil(obj.Field1)
should.Equal(map[string]interface{}{"K": "V"}, obj.Field2)
should.Equal("1", obj.Field0)
}
func Test_array_with_one_nil_ptr(t *testing.T) {
obj := [1]*float64{nil}
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`[null]`, output)
}
func Test_array_with_one_not_nil_ptr(t *testing.T) {
two := float64(2)
obj := [1]*float64{&two}
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`[2]`, output)
}
func Test_embedded_array_with_one_nil(t *testing.T) {
type TestObject struct {
Field1 int
Field2 [1]*float64
}
var obj TestObject
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Contains(output, `"Field2":[null]`)
}
func Test_array_with_nothing(t *testing.T) {
var obj [2]*float64
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`[null,null]`, output)
}
func Test_unmarshal_ptr_to_interface(t *testing.T) {
type TestData struct {
Name string `json:"name"`
}
should := require.New(t)
var obj interface{} = &TestData{}
err := json.Unmarshal([]byte(`{"name":"value"}`), &obj)
should.Nil(err)
should.Equal("&{value}", fmt.Sprintf("%v", obj))
obj = interface{}(&TestData{})
err = Unmarshal([]byte(`{"name":"value"}`), &obj)
should.Nil(err)
should.Equal("&{value}", fmt.Sprintf("%v", obj))
}
func Test_nil_out_null_interface(t *testing.T) {
type TestData struct {
Field interface{} `json:"field"`
}
should := require.New(t)
var boolVar bool
obj := TestData{
Field: &boolVar,
}
data1 := []byte(`{"field": true}`)
err := Unmarshal(data1, &obj)
should.NoError(err)
should.Equal(true, *(obj.Field.(*bool)))
data2 := []byte(`{"field": null}`)
err = Unmarshal(data2, &obj)
should.NoError(err)
should.Equal(nil, obj.Field)
// Checking stdlib behavior matches.
obj2 := TestData{
Field: &boolVar,
}
err = json.Unmarshal(data1, &obj2)
should.NoError(err)
should.Equal(true, *(obj2.Field.(*bool)))
err = json.Unmarshal(data2, &obj2)
should.NoError(err)
should.Equal(nil, obj2.Field)
}
func Test_omitempty_nil_interface(t *testing.T) {
type TestData struct {
Field interface{} `json:"field,omitempty"`
}
should := require.New(t)
obj := TestData{
Field: nil,
}
js, err := json.Marshal(obj)
should.NoError(err)
should.Equal("{}", string(js))
str, err := MarshalToString(obj)
should.NoError(err)
should.Equal(string(js), str)
}
func Test_omitempty_nil_nonempty_interface(t *testing.T) {
type TestData struct {
Field MyInterface `json:"field,omitempty"`
}
should := require.New(t)
obj := TestData{
Field: nil,
}
js, err := json.Marshal(obj)
should.NoError(err)
should.Equal("{}", string(js))
str, err := MarshalToString(obj)
should.NoError(err)
should.Equal(string(js), str)
obj.Field = MyString("hello")
err = UnmarshalFromString(`{"field":null}`, &obj)
should.NoError(err)
should.Equal(nil, obj.Field)
}
func Test_marshal_nil_marshaler_interface(t *testing.T) {
type TestData struct {
Field json.Marshaler `json:"field"`
}
should := require.New(t)
obj := TestData{
Field: nil,
}
js, err := json.Marshal(obj)
should.NoError(err)
should.Equal(`{"field":null}`, string(js))
str, err := MarshalToString(obj)
should.NoError(err)
should.Equal(string(js), str)
}
func Test_marshal_nil_nonempty_interface(t *testing.T) {
type TestData struct {
Field MyInterface `json:"field"`
}
should := require.New(t)
obj := TestData{
Field: nil,
}
js, err := json.Marshal(obj)
should.NoError(err)
should.Equal(`{"field":null}`, string(js))
str, err := MarshalToString(obj)
should.NoError(err)
should.Equal(string(js), str)
obj.Field = MyString("hello")
err = Unmarshal(js, &obj)
should.NoError(err)
should.Equal(nil, obj.Field)
}
func Test_overwrite_interface_ptr_value_with_nil(t *testing.T) {
type Wrapper struct {
Payload interface{} `json:"payload,omitempty"`
}
type Payload struct {
Value int `json:"val,omitempty"`
}
should := require.New(t)
payload := &Payload{}
wrapper := &Wrapper{
Payload: &payload,
}
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.Equal(nil, err)
should.Equal(&payload, wrapper.Payload)
should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.Equal(nil, err)
should.Equal(&payload, wrapper.Payload)
should.Equal((*Payload)(nil), payload)
payload = &Payload{}
wrapper = &Wrapper{
Payload: &payload,
}
err = Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.Equal(nil, err)
should.Equal(&payload, wrapper.Payload)
should.Equal(42, (*(wrapper.Payload.(**Payload))).Value)
err = Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.Equal(nil, err)
should.Equal(&payload, wrapper.Payload)
should.Equal((*Payload)(nil), payload)
}
func Test_overwrite_interface_value_with_nil(t *testing.T) {
type Wrapper struct {
Payload interface{} `json:"payload,omitempty"`
}
type Payload struct {
Value int `json:"val,omitempty"`
}
should := require.New(t)
payload := &Payload{}
wrapper := &Wrapper{
Payload: payload,
}
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.Equal(nil, err)
should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.Equal(nil, err)
should.Equal(nil, wrapper.Payload)
should.Equal(42, payload.Value)
payload = &Payload{}
wrapper = &Wrapper{
Payload: payload,
}
err = Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.Equal(nil, err)
should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)
err = Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.Equal(nil, err)
should.Equal(nil, wrapper.Payload)
should.Equal(42, payload.Value)
}
func Test_unmarshal_into_nil(t *testing.T) {
type Payload struct {
Value int `json:"val,omitempty"`
}
type Wrapper struct {
Payload interface{} `json:"payload,omitempty"`
}
should := require.New(t)
var payload *Payload
wrapper := &Wrapper{
Payload: payload,
}
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.Nil(err)
should.NotNil(wrapper.Payload)
should.Nil(payload)
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.Nil(err)
should.Nil(wrapper.Payload)
should.Nil(payload)
payload = nil
wrapper = &Wrapper{
Payload: payload,
}
err = Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.Nil(err)
should.NotNil(wrapper.Payload)
should.Nil(payload)
err = Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.Nil(err)
should.Nil(wrapper.Payload)
should.Nil(payload)
}

View file

@ -1,138 +0,0 @@
package jsoniter
import (
"bytes"
"encoding/json"
"github.com/stretchr/testify/require"
"io"
"testing"
)
func Test_missing_object_end(t *testing.T) {
should := require.New(t)
type TestObject struct {
Metric string `json:"metric"`
Tags map[string]interface{} `json:"tags"`
}
obj := TestObject{}
should.NotNil(UnmarshalFromString(`{"metric": "sys.777","tags": {"a":"123"}`, &obj))
}
func Test_missing_array_end(t *testing.T) {
should := require.New(t)
should.NotNil(UnmarshalFromString(`[1,2,3`, &[]int{}))
}
func Test_invalid_any(t *testing.T) {
should := require.New(t)
any := Get([]byte("[]"))
should.Equal(InvalidValue, any.Get(0.3).ValueType())
// is nil correct ?
should.Equal(nil, any.Get(0.3).GetInterface())
any = any.Get(0.3)
should.Equal(false, any.ToBool())
should.Equal(int(0), any.ToInt())
should.Equal(int32(0), any.ToInt32())
should.Equal(int64(0), any.ToInt64())
should.Equal(uint(0), any.ToUint())
should.Equal(uint32(0), any.ToUint32())
should.Equal(uint64(0), any.ToUint64())
should.Equal(float32(0), any.ToFloat32())
should.Equal(float64(0), any.ToFloat64())
should.Equal("", any.ToString())
should.Equal(InvalidValue, any.Get(0.1).Get(1).ValueType())
}
func Test_invalid_struct_input(t *testing.T) {
should := require.New(t)
type TestObject struct{}
input := []byte{54, 141, 30}
obj := TestObject{}
should.NotNil(Unmarshal(input, &obj))
}
func Test_invalid_slice_input(t *testing.T) {
should := require.New(t)
type TestObject struct{}
input := []byte{93}
obj := []string{}
should.NotNil(Unmarshal(input, &obj))
}
func Test_invalid_array_input(t *testing.T) {
should := require.New(t)
type TestObject struct{}
input := []byte{93}
obj := [0]string{}
should.NotNil(Unmarshal(input, &obj))
}
func Test_invalid_float(t *testing.T) {
inputs := []string{
`1.e1`, // dot without following digit
`1.`, // dot can not be the last char
``, // empty number
`01`, // extra leading zero
`-`, // negative without digit
`--`, // double negative
`--2`, // double negative
}
for _, input := range inputs {
t.Run(input, func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input+",")
iter.Skip()
should.NotEqual(io.EOF, iter.Error)
should.NotNil(iter.Error)
v := float64(0)
should.NotNil(json.Unmarshal([]byte(input), &v))
iter = ParseString(ConfigDefault, input+",")
iter.ReadFloat64()
should.NotEqual(io.EOF, iter.Error)
should.NotNil(iter.Error)
iter = ParseString(ConfigDefault, input+",")
iter.ReadFloat32()
should.NotEqual(io.EOF, iter.Error)
should.NotNil(iter.Error)
})
}
}
func Test_chan(t *testing.T) {
t.Skip("do not support chan")
type TestObject struct {
MyChan chan bool
MyField int
}
should := require.New(t)
obj := TestObject{}
str, err := json.Marshal(obj)
should.Nil(err)
should.Equal(``, str)
}
func Test_invalid_number(t *testing.T) {
type Message struct {
Number int `json:"number"`
}
obj := Message{}
decoder := ConfigCompatibleWithStandardLibrary.NewDecoder(bytes.NewBufferString(`{"number":"5"}`))
err := decoder.Decode(&obj)
invalidStr := err.Error()
result, err := ConfigCompatibleWithStandardLibrary.Marshal(invalidStr)
should := require.New(t)
should.Nil(err)
result2, err := json.Marshal(invalidStr)
should.Nil(err)
should.Equal(string(result2), string(result))
}
func Test_valid(t *testing.T) {
should := require.New(t)
should.True(Valid([]byte(`{}`)))
should.False(Valid([]byte(`{`)))
}

View file

@ -1,65 +0,0 @@
package jsoniter
import (
"bytes"
"github.com/stretchr/testify/require"
"io"
"testing"
)
func Test_read_by_one(t *testing.T) {
iter := Parse(ConfigDefault, bytes.NewBufferString("abc"), 1)
b := iter.readByte()
if iter.Error != nil {
t.Fatal(iter.Error)
}
if b != 'a' {
t.Fatal(b)
}
iter.unreadByte()
if iter.Error != nil {
t.Fatal(iter.Error)
}
b = iter.readByte()
if iter.Error != nil {
t.Fatal(iter.Error)
}
if b != 'a' {
t.Fatal(b)
}
}
func Test_read_by_two(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString("abc"), 2)
b := iter.readByte()
should.Nil(iter.Error)
should.Equal(byte('a'), b)
b = iter.readByte()
should.Nil(iter.Error)
should.Equal(byte('b'), b)
iter.unreadByte()
should.Nil(iter.Error)
iter.unreadByte()
should.Nil(iter.Error)
b = iter.readByte()
should.Nil(iter.Error)
should.Equal(byte('a'), b)
}
func Test_read_until_eof(t *testing.T) {
iter := Parse(ConfigDefault, bytes.NewBufferString("abc"), 2)
iter.readByte()
iter.readByte()
b := iter.readByte()
if iter.Error != nil {
t.Fatal(iter.Error)
}
if b != 'c' {
t.Fatal(b)
}
iter.readByte()
if iter.Error != io.EOF {
t.Fatal(iter.Error)
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,157 +0,0 @@
package jsoniter
import (
"encoding/json"
"io/ioutil"
"os"
"testing"
)
//func Test_large_file(t *testing.T) {
// file, err := os.Open("/tmp/large-file.json")
// if err != nil {
// t.Fatal(err)
// }
// iter := Parse(file, 4096)
// count := 0
// for iter.ReadArray() {
// iter.Skip()
// count++
// }
// if count != 11351 {
// t.Fatal(count)
// }
//}
func init() {
ioutil.WriteFile("/tmp/large-file.json", []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": "hello"
}]`), 0666)
}
/*
200000 8886 ns/op 4336 B/op 6 allocs/op
50000 34244 ns/op 6744 B/op 14 allocs/op
*/
func Benchmark_jsoniter_large_file(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
file, _ := os.Open("/tmp/large-file.json")
iter := Parse(ConfigDefault, file, 4096)
count := 0
iter.ReadArrayCB(func(iter *Iterator) bool {
// Skip() is strict by default, use --tags jsoniter-sloppy to skip without validation
iter.Skip()
count++
return true
})
file.Close()
if iter.Error != nil {
b.Error(iter.Error)
}
}
}
func Benchmark_json_large_file(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
file, _ := os.Open("/tmp/large-file.json")
bytes, _ := ioutil.ReadAll(file)
file.Close()
result := []struct{}{}
err := json.Unmarshal(bytes, &result)
if err != nil {
b.Error(err)
}
}
}

View file

@ -1,160 +0,0 @@
package jsoniter
import (
"encoding/json"
"math/big"
"testing"
"github.com/stretchr/testify/require"
"strings"
)
func Test_read_map(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `{"hello": "world"}`)
m := map[string]string{"1": "2"}
iter.ReadVal(&m)
copy(iter.buf, []byte{0, 0, 0, 0, 0, 0})
should.Equal(map[string]string{"1": "2", "hello": "world"}, m)
}
func Test_read_map_of_interface(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `{"hello": "world"}`)
m := map[string]interface{}{"1": "2"}
iter.ReadVal(&m)
should.Equal(map[string]interface{}{"1": "2", "hello": "world"}, m)
iter = ParseString(ConfigDefault, `{"hello": "world"}`)
should.Equal(map[string]interface{}{"hello": "world"}, iter.Read())
}
func Test_map_wrapper_any_get_all(t *testing.T) {
should := require.New(t)
any := Wrap(map[string][]int{"Field1": {1, 2}})
should.Equal(`{"Field1":1}`, any.Get('*', 0).ToString())
should.Contains(any.Keys(), "Field1")
// map write to
stream := NewStream(ConfigDefault, nil, 0)
any.WriteTo(stream)
// TODO cannot pass
//should.Equal(string(stream.buf), "")
}
func Test_write_val_map(t *testing.T) {
should := require.New(t)
val := map[string]string{"1": "2"}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`{"1":"2"}`, str)
}
func Test_slice_of_map(t *testing.T) {
should := require.New(t)
val := []map[string]string{{"1": "2"}}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`[{"1":"2"}]`, str)
val = []map[string]string{}
should.Nil(UnmarshalFromString(str, &val))
should.Equal("2", val[0]["1"])
}
func Test_encode_int_key_map(t *testing.T) {
should := require.New(t)
val := map[int]string{1: "2"}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`{"1":"2"}`, str)
}
func Test_decode_int_key_map(t *testing.T) {
should := require.New(t)
var val map[int]string
should.Nil(UnmarshalFromString(`{"1":"2"}`, &val))
should.Equal(map[int]string{1: "2"}, val)
}
func Test_encode_TextMarshaler_key_map(t *testing.T) {
should := require.New(t)
f, _, _ := big.ParseFloat("1", 10, 64, big.ToZero)
val := map[*big.Float]string{f: "2"}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`{"1":"2"}`, str)
}
func Test_decode_TextMarshaler_key_map(t *testing.T) {
should := require.New(t)
var val map[*big.Float]string
should.Nil(UnmarshalFromString(`{"1":"2"}`, &val))
str, err := MarshalToString(val)
should.Nil(err)
should.Equal(`{"1":"2"}`, str)
}
func Test_map_key_with_escaped_char(t *testing.T) {
type Ttest struct {
Map map[string]string
}
var jsonBytes = []byte(`
{
"Map":{
"k\"ey": "val"
}
}`)
should := require.New(t)
{
var obj Ttest
should.Nil(json.Unmarshal(jsonBytes, &obj))
should.Equal(map[string]string{"k\"ey": "val"}, obj.Map)
}
{
var obj Ttest
should.Nil(Unmarshal(jsonBytes, &obj))
should.Equal(map[string]string{"k\"ey": "val"}, obj.Map)
}
}
func Test_encode_map_with_sorted_keys(t *testing.T) {
should := require.New(t)
m := map[string]interface{}{
"3": 3,
"1": 1,
"2": 2,
}
bytes, err := json.Marshal(m)
should.Nil(err)
output, err := ConfigCompatibleWithStandardLibrary.MarshalToString(m)
should.Nil(err)
should.Equal(string(bytes), output)
}
func Test_encode_map_uint_keys(t *testing.T) {
should := require.New(t)
m := map[uint64]interface{}{
uint64(1): "a",
uint64(2): "a",
uint64(4): "a",
}
bytes, err := json.Marshal(m)
should.Nil(err)
output, err := ConfigCompatibleWithStandardLibrary.MarshalToString(m)
should.Nil(err)
should.Equal(string(bytes), output)
}
func Test_read_map_with_reader(t *testing.T) {
should := require.New(t)
input := `{"branch":"beta","change_log":"add the rows{10}","channel":"fros","create_time":"2017-06-13 16:39:08","firmware_list":"","md5":"80dee2bf7305bcf179582088e29fd7b9","note":{"CoreServices":{"md5":"d26975c0a8c7369f70ed699f2855cc2e","package_name":"CoreServices","version_code":"76","version_name":"1.0.76"},"FrDaemon":{"md5":"6b1f0626673200bc2157422cd2103f5d","package_name":"FrDaemon","version_code":"390","version_name":"1.0.390"},"FrGallery":{"md5":"90d767f0f31bcd3c1d27281ec979ba65","package_name":"FrGallery","version_code":"349","version_name":"1.0.349"},"FrLocal":{"md5":"f15a215b2c070a80a01f07bde4f219eb","package_name":"FrLocal","version_code":"791","version_name":"1.0.791"}},"pack_region_urls":{"CN":"https://s3.cn-north-1.amazonaws.com.cn/xxx-os/ttt_xxx_android_1.5.3.344.393.zip","default":"http://192.168.8.78/ttt_xxx_android_1.5.3.344.393.zip","local":"http://192.168.8.78/ttt_xxx_android_1.5.3.344.393.zip"},"pack_version":"1.5.3.344.393","pack_version_code":393,"region":"all","release_flag":0,"revision":62,"size":38966875,"status":3}`
reader := strings.NewReader(input)
decoder := ConfigCompatibleWithStandardLibrary.NewDecoder(reader)
m1 := map[string]interface{}{}
should.Nil(decoder.Decode(&m1))
m2 := map[string]interface{}{}
should.Nil(json.Unmarshal([]byte(input), &m2))
should.Equal(m2, m1)
should.Equal("1.0.76", m1["note"].(map[string]interface{})["CoreServices"].(map[string]interface{})["version_name"])
}

View file

@ -1,71 +0,0 @@
package jsoniter
import (
"testing"
"github.com/stretchr/testify/require"
)
// if must be valid is useless, just drop this test
func Test_must_be_valid(t *testing.T) {
should := require.New(t)
any := Get([]byte("123"))
should.Equal(any.MustBeValid().ToInt(), 123)
any = Wrap(int8(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(int16(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(int32(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(int64(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(uint(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(uint8(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(uint16(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(uint32(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(uint64(10))
should.Equal(any.MustBeValid().ToInt(), 10)
any = Wrap(float32(10))
should.Equal(any.MustBeValid().ToFloat64(), float64(10))
any = Wrap(float64(10))
should.Equal(any.MustBeValid().ToFloat64(), float64(10))
any = Wrap(true)
should.Equal(any.MustBeValid().ToFloat64(), float64(1))
any = Wrap(false)
should.Equal(any.MustBeValid().ToFloat64(), float64(0))
any = Wrap(nil)
should.Equal(any.MustBeValid().ToFloat64(), float64(0))
any = Wrap(struct{ age int }{age: 1})
should.Equal(any.MustBeValid().ToFloat64(), float64(0))
any = Wrap(map[string]interface{}{"abc": 1})
should.Equal(any.MustBeValid().ToFloat64(), float64(0))
any = Wrap("abc")
should.Equal(any.MustBeValid().ToFloat64(), float64(0))
any = Wrap([]int{})
should.Equal(any.MustBeValid().ToFloat64(), float64(0))
any = Wrap([]int{1, 2})
should.Equal(any.MustBeValid().ToFloat64(), float64(1))
}

View file

@ -1,88 +0,0 @@
package jsoniter
import (
"encoding/json"
"reflect"
"testing"
)
type Level1 struct {
Hello []Level2
}
type Level2 struct {
World string
}
func Test_nested(t *testing.T) {
iter := ParseString(ConfigDefault, `{"hello": [{"world": "value1"}, {"world": "value2"}]}`)
l1 := Level1{}
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
switch l1Field {
case "hello":
l2Array := []Level2{}
for iter.ReadArray() {
l2 := Level2{}
for l2Field := iter.ReadObject(); l2Field != ""; l2Field = iter.ReadObject() {
switch l2Field {
case "world":
l2.World = iter.ReadString()
default:
iter.ReportError("bind l2", "unexpected field: "+l2Field)
}
}
l2Array = append(l2Array, l2)
}
l1.Hello = l2Array
default:
iter.ReportError("bind l1", "unexpected field: "+l1Field)
}
}
if !reflect.DeepEqual(l1, Level1{
Hello: []Level2{
{World: "value1"},
{World: "value2"},
},
}) {
t.Fatal(l1)
}
}
func Benchmark_jsoniter_nested(b *testing.B) {
for n := 0; n < b.N; n++ {
iter := ParseString(ConfigDefault, `{"hello": [{"world": "value1"}, {"world": "value2"}]}`)
l1 := Level1{}
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
switch l1Field {
case "hello":
l1.Hello = readLevel1Hello(iter)
default:
iter.Skip()
}
}
}
}
func readLevel1Hello(iter *Iterator) []Level2 {
l2Array := make([]Level2, 0, 2)
for iter.ReadArray() {
l2 := Level2{}
for l2Field := iter.ReadObject(); l2Field != ""; l2Field = iter.ReadObject() {
switch l2Field {
case "world":
l2.World = iter.ReadString()
default:
iter.Skip()
}
}
l2Array = append(l2Array, l2)
}
return l2Array
}
func Benchmark_json_nested(b *testing.B) {
for n := 0; n < b.N; n++ {
l1 := Level1{}
json.Unmarshal([]byte(`{"hello": [{"world": "value1"}, {"world": "value2"}]}`), &l1)
}
}

View file

@ -1,168 +0,0 @@
package jsoniter
import (
"bytes"
"encoding/json"
"io"
"testing"
"github.com/stretchr/testify/require"
)
func Test_read_null(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `null`)
should.True(iter.ReadNil())
iter = ParseString(ConfigDefault, `null`)
should.Nil(iter.Read())
iter = ParseString(ConfigDefault, `navy`)
iter.Read()
should.True(iter.Error != nil && iter.Error != io.EOF)
iter = ParseString(ConfigDefault, `navy`)
iter.ReadNil()
should.True(iter.Error != nil && iter.Error != io.EOF)
}
func Test_write_null(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteNil()
stream.Flush()
should.Nil(stream.Error)
should.Equal("null", buf.String())
}
func Test_encode_null(t *testing.T) {
should := require.New(t)
str, err := MarshalToString(nil)
should.Nil(err)
should.Equal("null", str)
}
func Test_decode_null_object_field(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[null,"a"]`)
iter.ReadArray()
if iter.ReadObject() != "" {
t.FailNow()
}
iter.ReadArray()
if iter.ReadString() != "a" {
t.FailNow()
}
type TestObject struct {
Field string
}
objs := []TestObject{}
should.Nil(UnmarshalFromString("[null]", &objs))
should.Len(objs, 1)
}
func Test_decode_null_array_element(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[null,"a"]`)
should.True(iter.ReadArray())
should.True(iter.ReadNil())
should.True(iter.ReadArray())
should.Equal("a", iter.ReadString())
}
func Test_decode_null_array(t *testing.T) {
should := require.New(t)
arr := []string{}
should.Nil(UnmarshalFromString("null", &arr))
should.Nil(arr)
}
func Test_decode_null_map(t *testing.T) {
should := require.New(t)
arr := map[string]string{}
should.Nil(UnmarshalFromString("null", &arr))
should.Nil(arr)
}
func Test_decode_null_string(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[null,"a"]`)
should.True(iter.ReadArray())
should.Equal("", iter.ReadString())
should.True(iter.ReadArray())
should.Equal("a", iter.ReadString())
}
func Test_decode_null_skip(t *testing.T) {
iter := ParseString(ConfigDefault, `[null,"a"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
if iter.ReadString() != "a" {
t.FailNow()
}
}
func Test_encode_nil_map(t *testing.T) {
should := require.New(t)
type Ttest map[string]string
var obj1 Ttest
output, err := json.Marshal(obj1)
should.Nil(err)
should.Equal("null", string(output))
output, err = json.Marshal(&obj1)
should.Nil(err)
should.Equal("null", string(output))
output, err = Marshal(obj1)
should.Nil(err)
should.Equal("null", string(output))
output, err = Marshal(&obj1)
should.Nil(err)
should.Equal("null", string(output))
}
func Test_encode_nil_array(t *testing.T) {
should := require.New(t)
type Ttest []string
var obj1 Ttest
output, err := json.Marshal(obj1)
should.Nil(err)
should.Equal("null", string(output))
output, err = json.Marshal(&obj1)
should.Nil(err)
should.Equal("null", string(output))
output, err = Marshal(obj1)
should.Nil(err)
should.Equal("null", string(output))
output, err = Marshal(&obj1)
should.Nil(err)
should.Equal("null", string(output))
}
func Test_decode_nil_num(t *testing.T) {
type TestData struct {
Field int `json:"field"`
}
should := require.New(t)
data1 := []byte(`{"field": 42}`)
data2 := []byte(`{"field": null}`)
// Checking stdlib behavior as well
obj2 := TestData{}
err := json.Unmarshal(data1, &obj2)
should.Equal(nil, err)
should.Equal(42, obj2.Field)
err = json.Unmarshal(data2, &obj2)
should.Equal(nil, err)
should.Equal(42, obj2.Field)
obj := TestData{}
err = Unmarshal(data1, &obj)
should.Equal(nil, err)
should.Equal(42, obj.Field)
err = Unmarshal(data2, &obj)
should.Equal(nil, err)
should.Equal(42, obj.Field)
}

View file

@ -1,342 +0,0 @@
package jsoniter
import (
"bytes"
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func Test_empty_object(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `{}`)
field := iter.ReadObject()
should.Equal("", field)
iter = ParseString(ConfigDefault, `{}`)
iter.ReadObjectCB(func(iter *Iterator, field string) bool {
should.FailNow("should not call")
return true
})
}
func Test_one_field(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `{"a": "stream"}`)
field := iter.ReadObject()
should.Equal("a", field)
value := iter.ReadString()
should.Equal("stream", value)
field = iter.ReadObject()
should.Equal("", field)
iter = ParseString(ConfigDefault, `{"a": "stream"}`)
should.True(iter.ReadObjectCB(func(iter *Iterator, field string) bool {
should.Equal("a", field)
iter.Skip()
return true
}))
}
func Test_two_field(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `{ "a": "stream" , "c": "d" }`)
field := iter.ReadObject()
should.Equal("a", field)
value := iter.ReadString()
should.Equal("stream", value)
field = iter.ReadObject()
should.Equal("c", field)
value = iter.ReadString()
should.Equal("d", value)
field = iter.ReadObject()
should.Equal("", field)
iter = ParseString(ConfigDefault, `{"field1": "1", "field2": 2}`)
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
switch field {
case "field1":
iter.ReadString()
case "field2":
iter.ReadInt64()
default:
iter.ReportError("bind object", "unexpected field")
}
}
}
func Test_object_wrapper_any_get_all(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 []int
Field2 []int
}
any := Wrap(TestObject{[]int{1, 2}, []int{3, 4}})
should.Contains(any.Get('*', 0).ToString(), `"Field2":3`)
should.Contains(any.Keys(), "Field1")
should.Contains(any.Keys(), "Field2")
should.NotContains(any.Keys(), "Field3")
//should.Contains(any.GetObject()["Field1"].GetArray()[0], 1)
}
func Test_write_object(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(Config{IndentionStep: 2}.Froze(), buf, 4096)
stream.WriteObjectStart()
stream.WriteObjectField("hello")
stream.WriteInt(1)
stream.WriteMore()
stream.WriteObjectField("world")
stream.WriteInt(2)
stream.WriteObjectEnd()
stream.Flush()
should.Nil(stream.Error)
should.Equal("{\n \"hello\": 1,\n \"world\": 2\n}", buf.String())
}
func Test_write_val_zero_field_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
}
obj := TestObject{}
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{}`, str)
}
func Test_write_val_one_field_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string `json:"field-1"`
}
obj := TestObject{"hello"}
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"field-1":"hello"}`, str)
}
func Test_mixed(t *testing.T) {
should := require.New(t)
type AA struct {
ID int `json:"id"`
Payload map[string]interface{} `json:"payload"`
buf *bytes.Buffer
}
aa := AA{}
err := UnmarshalFromString(` {"id":1, "payload":{"account":"123","password":"456"}}`, &aa)
should.Nil(err)
should.Equal(1, aa.ID)
should.Equal("123", aa.Payload["account"])
}
func Test_omit_empty(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string `json:"field-1,omitempty"`
Field2 string `json:"field-2,omitempty"`
Field3 string `json:"field-3,omitempty"`
}
obj := TestObject{}
obj.Field2 = "hello"
str, err := MarshalToString(&obj)
should.Nil(err)
should.Equal(`{"field-2":"hello"}`, str)
}
func Test_ignore_field_on_not_valid_type(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string `json:"field-1,omitempty"`
Field2 func() `json:"-"`
}
obj := TestObject{}
obj.Field1 = "hello world"
obj.Field2 = func() {}
str, err := MarshalToString(&obj)
should.Nil(err)
should.Equal(`{"field-1":"hello world"}`, str)
}
func Test_recursive_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Me *TestObject
}
obj := TestObject{}
str, err := MarshalToString(obj)
should.Nil(err)
should.Contains(str, `"Field1":""`)
should.Contains(str, `"Me":null`)
err = UnmarshalFromString(str, &obj)
should.Nil(err)
}
func Test_encode_anonymous_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field string
}
str, err := MarshalToString(struct {
TestObject
Field int
}{
Field: 100,
})
should.Nil(err)
should.Equal(`{"Field":100}`, str)
}
func Test_decode_anonymous_struct(t *testing.T) {
should := require.New(t)
type Inner struct {
Key string `json:"key"`
}
type Outer struct {
Inner
}
var outer Outer
j := []byte("{\"key\":\"value\"}")
should.Nil(Unmarshal(j, &outer))
should.Equal("value", outer.Key)
}
func Test_multiple_level_anonymous_struct(t *testing.T) {
type Level1 struct {
Field1 string
}
type Level2 struct {
Level1
Field2 string
}
type Level3 struct {
Level2
Field3 string
}
should := require.New(t)
obj := Level3{Level2{Level1{"1"}, "2"}, "3"}
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Field1":"1","Field2":"2","Field3":"3"}`, output)
}
func Test_multiple_level_anonymous_struct_with_ptr(t *testing.T) {
type Level1 struct {
Field1 string
Field2 string
Field4 string
}
type Level2 struct {
*Level1
Field2 string
Field3 string
}
type Level3 struct {
*Level2
Field3 string
}
should := require.New(t)
obj := Level3{&Level2{&Level1{"1", "", "4"}, "2", ""}, "3"}
output, err := MarshalToString(obj)
should.Nil(err)
should.Contains(output, `"Field1":"1"`)
should.Contains(output, `"Field2":"2"`)
should.Contains(output, `"Field3":"3"`)
should.Contains(output, `"Field4":"4"`)
}
func Test_shadow_struct_field(t *testing.T) {
should := require.New(t)
type omit *struct{}
type CacheItem struct {
Key string `json:"key"`
MaxAge int `json:"cacheAge"`
}
output, err := MarshalToString(struct {
*CacheItem
// Omit bad keys
OmitMaxAge omit `json:"cacheAge,omitempty"`
// Add nice keys
MaxAge int `json:"max_age"`
}{
CacheItem: &CacheItem{
Key: "value",
MaxAge: 100,
},
MaxAge: 20,
})
should.Nil(err)
should.Contains(output, `"key":"value"`)
should.Contains(output, `"max_age":20`)
}
func Test_embedded_order(t *testing.T) {
type A struct {
Field2 string
}
type C struct {
Field5 string
}
type B struct {
Field4 string
C
Field6 string
}
type TestObject struct {
Field1 string
A
Field3 string
B
Field7 string
}
should := require.New(t)
s := TestObject{}
output, err := MarshalToString(s)
should.Nil(err)
should.Equal(`{"Field1":"","Field2":"","Field3":"","Field4":"","Field5":"","Field6":"","Field7":""}`, output)
}
func Test_decode_nested(t *testing.T) {
type StructOfString struct {
Field1 string
Field2 string
}
iter := ParseString(ConfigDefault, `[{"field1": "hello"}, null, {"field2": "world"}]`)
slice := []*StructOfString{}
iter.ReadVal(&slice)
if len(slice) != 3 {
fmt.Println(iter.Error)
t.Fatal(len(slice))
}
if slice[0].Field1 != "hello" {
fmt.Println(iter.Error)
t.Fatal(slice[0])
}
if slice[1] != nil {
fmt.Println(iter.Error)
t.Fatal(slice[1])
}
if slice[2].Field2 != "world" {
fmt.Println(iter.Error)
t.Fatal(slice[2])
}
}
func Test_decode_field_with_escape(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
}
var obj TestObject
should.Nil(ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(`{"Field\"1":"hello"}`), &obj))
should.Equal("", obj.Field1)
should.Nil(ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(`{"\u0046ield1":"hello"}`), &obj))
should.Equal("hello", obj.Field1)
}

View file

@ -1,46 +0,0 @@
package jsoniter
import (
"github.com/stretchr/testify/require"
"testing"
)
func Test_encode_optional_int_pointer(t *testing.T) {
should := require.New(t)
var ptr *int
str, err := MarshalToString(ptr)
should.Nil(err)
should.Equal("null", str)
val := 100
ptr = &val
str, err = MarshalToString(ptr)
should.Nil(err)
should.Equal("100", str)
}
func Test_decode_struct_with_optional_field(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 *string
Field2 *string
}
obj := TestObject{}
UnmarshalFromString(`{"field1": null, "field2": "world"}`, &obj)
should.Nil(obj.Field1)
should.Equal("world", *obj.Field2)
}
func Test_encode_struct_with_optional_field(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 *string
Field2 *string
}
obj := TestObject{}
world := "world"
obj.Field2 = &world
str, err := MarshalToString(obj)
should.Nil(err)
should.Contains(str, `"Field1":null`)
should.Contains(str, `"Field2":"world"`)
}

View file

@ -1,114 +0,0 @@
package jsoniter
import (
"encoding/json"
"github.com/stretchr/testify/require"
"strings"
"testing"
)
func Test_json_RawMessage(t *testing.T) {
should := require.New(t)
var data json.RawMessage
should.Nil(Unmarshal([]byte(`[1,2,3]`), &data))
should.Equal(`[1,2,3]`, string(data))
str, err := MarshalToString(data)
should.Nil(err)
should.Equal(`[1,2,3]`, str)
}
func Test_jsoniter_RawMessage(t *testing.T) {
should := require.New(t)
var data RawMessage
should.Nil(Unmarshal([]byte(`[1,2,3]`), &data))
should.Equal(`[1,2,3]`, string(data))
str, err := MarshalToString(data)
should.Nil(err)
should.Equal(`[1,2,3]`, str)
}
func Test_json_RawMessage_in_struct(t *testing.T) {
type TestObject struct {
Field1 string
Field2 json.RawMessage
}
should := require.New(t)
var data TestObject
should.Nil(Unmarshal([]byte(`{"field1": "hello", "field2": [1,2,3]}`), &data))
should.Equal(` [1,2,3]`, string(data.Field2))
should.Equal(`hello`, data.Field1)
}
func Test_decode_map_of_raw_message(t *testing.T) {
should := require.New(t)
type RawMap map[string]*json.RawMessage
b := []byte("{\"test\":[{\"key\":\"value\"}]}")
var rawMap RawMap
should.Nil(Unmarshal(b, &rawMap))
should.Equal(`[{"key":"value"}]`, string(*rawMap["test"]))
type Inner struct {
Key string `json:"key"`
}
var inner []Inner
Unmarshal(*rawMap["test"], &inner)
should.Equal("value", inner[0].Key)
}
func Test_encode_map_of_raw_message(t *testing.T) {
should := require.New(t)
type RawMap map[string]*json.RawMessage
value := json.RawMessage("[]")
rawMap := RawMap{"hello": &value}
output, err := MarshalToString(rawMap)
should.Nil(err)
should.Equal(`{"hello":[]}`, output)
}
func Test_encode_map_of_jsoniter_raw_message(t *testing.T) {
should := require.New(t)
type RawMap map[string]*RawMessage
value := RawMessage("[]")
rawMap := RawMap{"hello": &value}
output, err := MarshalToString(rawMap)
should.Nil(err)
should.Equal(`{"hello":[]}`, output)
}
func Test_marshal_invalid_json_raw_message(t *testing.T) {
type A struct {
Raw json.RawMessage `json:"raw"`
}
message := []byte(`{}`)
a := A{}
should := require.New(t)
should.Nil(ConfigCompatibleWithStandardLibrary.Unmarshal(message, &a))
aout, aouterr := ConfigCompatibleWithStandardLibrary.Marshal(&a)
should.Equal(`{"raw":null}`, string(aout))
should.Nil(aouterr)
}
func Test_raw_message_memory_not_copied_issue(t *testing.T) {
jsonStream := `{"name":"xxxxx","bundle_id":"com.zonst.majiang","app_platform":"ios","app_category":"100103", "budget_day":1000,"bidding_min":1,"bidding_max":2,"bidding_type":"CPM", "freq":{"open":true,"type":"day","num":100},"speed":1, "targeting":{"vendor":{"open":true,"list":["zonst"]}, "geo_code":{"open":true,"list":["156110100"]},"app_category":{"open":true,"list":["100101"]}, "day_parting":{"open":true,"list":["100409","100410"]},"device_type":{"open":true,"list":["ipad"]}, "os_version":{"open":true,"list":[10]},"carrier":{"open":true,"list":["mobile"]}, "network":{"open":true,"list":["4G"]}},"url":{"tracking_imp_url":"http://www.baidu.com", "tracking_clk_url":"http://www.baidu.com","jump_url":"http://www.baidu.com","deep_link_url":"http://www.baidu.com"}}`
type IteratorObject struct {
Name *string `json:"name"`
BundleId *string `json:"bundle_id"`
AppCategory *string `json:"app_category"`
AppPlatform *string `json:"app_platform"`
BudgetDay *float32 `json:"budget_day"`
BiddingMax *float32 `json:"bidding_max"`
BiddingMin *float32 `json:"bidding_min"`
BiddingType *string `json:"bidding_type"`
Freq *RawMessage `json:"freq"`
Targeting *RawMessage `json:"targeting"`
Url *RawMessage `json:"url"`
Speed *int `json:"speed" db:"speed"`
}
obj := &IteratorObject{}
decoder := NewDecoder(strings.NewReader(jsonStream))
err := decoder.Decode(obj)
should := require.New(t)
should.Nil(err)
should.Equal(`{"open":true,"type":"day","num":100}`, string(*obj.Freq))
}

View file

@ -1,57 +0,0 @@
package jsoniter
import (
"github.com/stretchr/testify/require"
"strings"
"testing"
"time"
)
func Test_reader_and_load_more(t *testing.T) {
should := require.New(t)
type TestObject struct {
CreatedAt time.Time
}
reader := strings.NewReader(`
{
"agency": null,
"candidateId": 0,
"candidate": "Blah Blah",
"bookingId": 0,
"shiftId": 1,
"shiftTypeId": 0,
"shift": "Standard",
"bonus": 0,
"bonusNI": 0,
"days": [],
"totalHours": 27,
"expenses": [],
"weekEndingDateSystem": "2016-10-09",
"weekEndingDateClient": "2016-10-09",
"submittedAt": null,
"submittedById": null,
"approvedAt": "2016-10-10T18:38:04Z",
"approvedById": 0,
"authorisedAt": "2016-10-10T18:38:04Z",
"authorisedById": 0,
"invoicedAt": "2016-10-10T20:00:00Z",
"revokedAt": null,
"revokedById": null,
"revokeReason": null,
"rejectedAt": null,
"rejectedById": null,
"rejectReasonCode": null,
"rejectReason": null,
"createdAt": "2016-10-03T00:00:00Z",
"updatedAt": "2016-11-09T10:26:13Z",
"updatedById": null,
"overrides": [],
"bookingApproverId": null,
"bookingApprover": null,
"status": "approved"
}
`)
decoder := ConfigCompatibleWithStandardLibrary.NewDecoder(reader)
obj := TestObject{}
should.Nil(decoder.Decode(&obj))
}

View file

@ -1,154 +0,0 @@
package jsoniter
import (
"fmt"
"testing"
)
func Test_reflect_str(t *testing.T) {
iter := ParseString(ConfigDefault, `"hello"`)
str := ""
iter.ReadVal(&str)
if str != "hello" {
fmt.Println(iter.Error)
t.Fatal(str)
}
}
func Test_reflect_ptr_str(t *testing.T) {
iter := ParseString(ConfigDefault, `"hello"`)
var str *string
iter.ReadVal(&str)
if *str != "hello" {
t.Fatal(str)
}
}
func Test_reflect_int(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := int(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_int8(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := int8(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_int16(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := int16(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_int32(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := int32(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_int64(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := int64(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_uint(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := uint(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_uint8(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := uint8(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_uint16(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := uint16(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_uint32(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := uint32(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_uint64(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := uint64(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_byte(t *testing.T) {
iter := ParseString(ConfigDefault, `123`)
val := byte(0)
iter.ReadVal(&val)
if val != 123 {
t.Fatal(val)
}
}
func Test_reflect_float32(t *testing.T) {
iter := ParseString(ConfigDefault, `1.23`)
val := float32(0)
iter.ReadVal(&val)
if val != 1.23 {
fmt.Println(iter.Error)
t.Fatal(val)
}
}
func Test_reflect_float64(t *testing.T) {
iter := ParseString(ConfigDefault, `1.23`)
val := float64(0)
iter.ReadVal(&val)
if val != 1.23 {
fmt.Println(iter.Error)
t.Fatal(val)
}
}
func Test_reflect_bool(t *testing.T) {
iter := ParseString(ConfigDefault, `true`)
val := false
iter.ReadVal(&val)
if val != true {
fmt.Println(iter.Error)
t.Fatal(val)
}
}

View file

@ -1,184 +0,0 @@
package jsoniter
import (
"bytes"
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
func Test_skip_number_in_array(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[-0.12, "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
should.Nil(iter.Error)
should.Equal("stream", iter.ReadString())
}
func Test_skip_string_in_array(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `["hello", "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
should.Nil(iter.Error)
should.Equal("stream", iter.ReadString())
}
func Test_skip_null(t *testing.T) {
iter := ParseString(ConfigDefault, `[null , "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
if iter.ReadString() != "stream" {
t.FailNow()
}
}
func Test_skip_true(t *testing.T) {
iter := ParseString(ConfigDefault, `[true , "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
if iter.ReadString() != "stream" {
t.FailNow()
}
}
func Test_skip_false(t *testing.T) {
iter := ParseString(ConfigDefault, `[false , "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
if iter.ReadString() != "stream" {
t.FailNow()
}
}
func Test_skip_array(t *testing.T) {
iter := ParseString(ConfigDefault, `[[1, [2, [3], 4]], "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
if iter.ReadString() != "stream" {
t.FailNow()
}
}
func Test_skip_empty_array(t *testing.T) {
iter := ParseString(ConfigDefault, `[ [ ], "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
if iter.ReadString() != "stream" {
t.FailNow()
}
}
func Test_skip_nested(t *testing.T) {
iter := ParseString(ConfigDefault, `[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`)
iter.ReadArray()
iter.Skip()
iter.ReadArray()
if iter.ReadString() != "stream" {
t.FailNow()
}
}
func Test_skip_and_return_bytes(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`)
iter.ReadArray()
skipped := iter.SkipAndReturnBytes()
should.Equal(`{"a" : [{"stream": "c"}], "d": 102 }`, string(skipped))
}
func Test_skip_and_return_bytes_with_reader(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(`[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`), 4)
iter.ReadArray()
skipped := iter.SkipAndReturnBytes()
should.Equal(`{"a" : [{"stream": "c"}], "d": 102 }`, string(skipped))
}
func Test_skip_empty(t *testing.T) {
should := require.New(t)
should.NotNil(Get([]byte("")).LastError())
}
type TestResp struct {
Code uint64
}
func Benchmark_jsoniter_skip(b *testing.B) {
input := []byte(`
{
"_shards":{
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits":{
"total" : 1,
"hits" : [
{
"_index" : "twitter",
"_type" : "tweet",
"_id" : "1",
"_source" : {
"user" : "kimchy",
"postDate" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
}
]
},
"code": 200
}`)
for n := 0; n < b.N; n++ {
result := TestResp{}
iter := ParseBytes(ConfigDefault, input)
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
switch field {
case "code":
result.Code = iter.ReadUint64()
default:
iter.Skip()
}
}
}
}
func Benchmark_json_skip(b *testing.B) {
input := []byte(`
{
"_shards":{
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits":{
"total" : 1,
"hits" : [
{
"_index" : "twitter",
"_type" : "tweet",
"_id" : "1",
"_source" : {
"user" : "kimchy",
"postDate" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
}
]
},
"code": 200
}`)
for n := 0; n < b.N; n++ {
result := TestResp{}
json.Unmarshal(input, &result)
}
}

View file

@ -1,261 +0,0 @@
// +build go1.8
package jsoniter
import (
"bytes"
"encoding/json"
"fmt"
"testing"
"unicode/utf8"
"github.com/stretchr/testify/require"
)
func Test_read_string(t *testing.T) {
badInputs := []string{
``,
`"`,
`"\"`,
`"\\\"`,
"\"\n\"",
`"\U0001f64f"`,
`"\uD83D\u00"`,
}
for i := 0; i < 32; i++ {
// control characters are invalid
badInputs = append(badInputs, string([]byte{'"', byte(i), '"'}))
}
for _, input := range badInputs {
testReadString(t, input, "", true, "json.Unmarshal", json.Unmarshal)
testReadString(t, input, "", true, "jsoniter.Unmarshal", Unmarshal)
testReadString(t, input, "", true, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal)
}
goodInputs := []struct {
input string
expectValue string
}{
{`""`, ""},
{`"a"`, "a"},
{`null`, ""},
{`"Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"`, "Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"},
{`"\uD83D"`, string([]byte{239, 191, 189})},
{`"\uD83D\\"`, string([]byte{239, 191, 189, '\\'})},
{`"\uD83D\ub000"`, string([]byte{239, 191, 189, 235, 128, 128})},
{`"\uD83D\ude04"`, "😄"},
{`"\uDEADBEEF"`, string([]byte{239, 191, 189, 66, 69, 69, 70})},
}
for _, tc := range goodInputs {
testReadString(t, tc.input, tc.expectValue, false, "json.Unmarshal", json.Unmarshal)
testReadString(t, tc.input, tc.expectValue, false, "jsoniter.Unmarshal", Unmarshal)
testReadString(t, tc.input, tc.expectValue, false, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal)
}
}
func testReadString(t *testing.T, input string, expectValue string, expectError bool, marshalerName string, marshaler func([]byte, interface{}) error) {
var value string
err := marshaler([]byte(input), &value)
if expectError != (err != nil) {
t.Errorf("%q: %s: expected error %v, got %v", input, marshalerName, expectError, err)
return
}
if value != expectValue {
t.Errorf("%q: %s: expected %q, got %q", input, marshalerName, expectValue, value)
return
}
}
func Test_read_normal_string(t *testing.T) {
cases := map[string]string{
`"0123456789012345678901234567890123456789"`: `0123456789012345678901234567890123456789`,
`""`: ``,
`"hello"`: `hello`,
}
for input, output := range cases {
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input)
should.Equal(output, iter.ReadString())
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
should.Equal(output, iter.ReadString())
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input)
should.Equal(output, string(iter.ReadStringAsSlice()))
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
should.Equal(output, string(iter.ReadStringAsSlice()))
})
}
}
func Test_read_exotic_string(t *testing.T) {
cases := map[string]string{
`"hel\"lo"`: `hel"lo`,
`"hel\\\/lo"`: `hel\/lo`,
`"hel\\blo"`: `hel\blo`,
`"hel\\\blo"`: "hel\\\blo",
`"hel\\nlo"`: `hel\nlo`,
`"hel\\\nlo"`: "hel\\\nlo",
`"hel\\tlo"`: `hel\tlo`,
`"hel\\flo"`: `hel\flo`,
`"hel\\\flo"`: "hel\\\flo",
`"hel\\\rlo"`: "hel\\\rlo",
`"hel\\\tlo"`: "hel\\\tlo",
`"\u4e2d\u6587"`: "中文",
`"\ud83d\udc4a"`: "\xf0\x9f\x91\x8a", // surrogate
}
for input, output := range cases {
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, input)
var v string
should.Nil(json.Unmarshal([]byte(input), &v))
should.Equal(v, iter.ReadString())
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
should.Equal(output, iter.ReadString())
})
}
}
func Test_read_string_as_interface(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `"hello"`)
should.Equal("hello", iter.Read())
}
func Test_write_string(t *testing.T) {
should := require.New(t)
str, err := MarshalToString("hello")
should.Equal(`"hello"`, str)
should.Nil(err)
str, err = MarshalToString(`hel"lo`)
should.Equal(`"hel\"lo"`, str)
should.Nil(err)
}
func Test_write_val_string(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
stream := NewStream(ConfigDefault, buf, 4096)
stream.WriteVal("hello")
stream.Flush()
should.Nil(stream.Error)
should.Equal(`"hello"`, buf.String())
}
func Test_decode_slash(t *testing.T) {
should := require.New(t)
var obj interface{}
should.NotNil(json.Unmarshal([]byte("\\"), &obj))
should.NotNil(UnmarshalFromString("\\", &obj))
}
func Test_html_escape(t *testing.T) {
should := require.New(t)
output, err := json.Marshal(`>`)
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
output, err = ConfigCompatibleWithStandardLibrary.Marshal(`>`)
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
type MyString string
output, err = ConfigCompatibleWithStandardLibrary.Marshal(MyString(`>`))
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
}
func Test_string_encode_with_std(t *testing.T) {
should := require.New(t)
for i := 0; i < utf8.RuneSelf; i++ {
input := string([]byte{byte(i)})
stdOutputBytes, err := json.Marshal(input)
should.Nil(err)
stdOutput := string(stdOutputBytes)
jsoniterOutputBytes, err := ConfigCompatibleWithStandardLibrary.Marshal(input)
should.Nil(err)
jsoniterOutput := string(jsoniterOutputBytes)
should.Equal(stdOutput, jsoniterOutput)
}
}
func Test_unicode(t *testing.T) {
should := require.New(t)
output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
should.Equal(`{"a":"数字山谷"}`, output)
output, _ = Config{EscapeHTML: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"})
should.Equal(`{"a":"数字山谷"}`, output)
}
func Test_unicode_and_escape(t *testing.T) {
should := require.New(t)
output, err := MarshalToString(`"数字山谷"`)
should.Nil(err)
should.Equal(`"\"数字山谷\""`, output)
output, err = ConfigFastest.MarshalToString(`"数字山谷"`)
should.Nil(err)
should.Equal(`"\"数字山谷\""`, output)
}
func Test_unsafe_unicode(t *testing.T) {
ConfigDefault.(*frozenConfig).cleanEncoders()
should := require.New(t)
output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
should.Nil(err)
should.Equal(`"he\u2029\u2028he"`, output)
output, err = ConfigFastest.MarshalToString("he\u2029\u2028he")
should.Nil(err)
should.Equal("\"he\u2029\u2028he\"", output)
}
func Benchmark_jsoniter_unicode(b *testing.B) {
for n := 0; n < b.N; n++ {
iter := ParseString(ConfigDefault, `"\ud83d\udc4a"`)
iter.ReadString()
}
}
func Benchmark_jsoniter_ascii(b *testing.B) {
iter := NewIterator(ConfigDefault)
input := []byte(`"hello, world! hello, world!"`)
b.ResetTimer()
for n := 0; n < b.N; n++ {
iter.ResetBytes(input)
iter.ReadString()
}
}
func Benchmark_jsoniter_string_as_bytes(b *testing.B) {
iter := ParseString(ConfigDefault, `"hello, world!"`)
b.ResetTimer()
for n := 0; n < b.N; n++ {
iter.ResetBytes(iter.buf)
iter.ReadStringAsSlice()
}
}
func Benchmark_json_unicode(b *testing.B) {
for n := 0; n < b.N; n++ {
result := ""
json.Unmarshal([]byte(`"\ud83d\udc4a"`), &result)
}
}
func Benchmark_json_ascii(b *testing.B) {
for n := 0; n < b.N; n++ {
result := ""
json.Unmarshal([]byte(`"hello"`), &result)
}
}

View file

@ -1,267 +0,0 @@
package jsoniter
import (
"github.com/stretchr/testify/require"
"testing"
)
func Test_decode_one_field_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"field1": "hello"}`, &obj))
should.Equal("hello", obj.Field1)
}
func Test_decode_two_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
}
func Test_decode_three_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
}
func Test_decode_four_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
}
func Test_decode_five_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
Field5 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
should.Equal("e", obj.Field5)
}
func Test_decode_six_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
Field5 string
Field6 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
should.Equal("e", obj.Field5)
should.Equal("x", obj.Field6)
}
func Test_decode_seven_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
Field5 string
Field6 string
Field7 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x", "Field7":"y"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
should.Equal("e", obj.Field5)
should.Equal("x", obj.Field6)
should.Equal("y", obj.Field7)
}
func Test_decode_eight_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
Field5 string
Field6 string
Field7 string
Field8 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field8":"1", "Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x", "Field7":"y"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
should.Equal("e", obj.Field5)
should.Equal("x", obj.Field6)
should.Equal("y", obj.Field7)
should.Equal("1", obj.Field8)
}
func Test_decode_nine_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
Field5 string
Field6 string
Field7 string
Field8 string
Field9 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field8" : "zzzzzzzzzzz", "Field7": "zz", "Field6" : "xx", "Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field9":"f"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
should.Equal("e", obj.Field5)
should.Equal("xx", obj.Field6)
should.Equal("zz", obj.Field7)
should.Equal("zzzzzzzzzzz", obj.Field8)
should.Equal("f", obj.Field9)
}
func Test_decode_ten_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
Field5 string
Field6 string
Field7 string
Field8 string
Field9 string
Field10 string
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"Field10":"x", "Field9": "x", "Field8":"x", "Field7":"x", "Field6":"x", "Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
should.Equal("e", obj.Field5)
should.Equal("x", obj.Field6)
should.Equal("x", obj.Field7)
should.Equal("x", obj.Field8)
should.Equal("x", obj.Field9)
should.Equal("x", obj.Field10)
}
func Test_decode_more_than_ten_fields_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string
Field2 string
Field3 string
Field4 string
Field5 string
Field6 string
Field7 string
Field8 string
Field9 string
Field10 string
Field11 int
}
obj := TestObject{}
should.Nil(UnmarshalFromString(`{}`, &obj))
should.Equal("", obj.Field1)
should.Nil(UnmarshalFromString(`{"field11":1, "field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj))
should.Equal("a", obj.Field1)
should.Equal("stream", obj.Field2)
should.Equal("c", obj.Field3)
should.Equal("d", obj.Field4)
should.Equal("e", obj.Field5)
should.Equal(1, obj.Field11)
}
func Test_decode_struct_field_with_tag(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 string `json:"field-1"`
Field2 string `json:"-"`
Field3 int `json:",string"`
}
obj := TestObject{Field2: "world"}
UnmarshalFromString(`{"field-1": "hello", "field2": "", "Field3": "100"}`, &obj)
should.Equal("hello", obj.Field1)
should.Equal("world", obj.Field2)
should.Equal(100, obj.Field3)
}
func Test_decode_struct_field_with_tag_string(t *testing.T) {
should := require.New(t)
type TestObject struct {
Field1 int `json:",string"`
}
obj := TestObject{Field1: 100}
should.Nil(UnmarshalFromString(`{"Field1": "100"}`, &obj))
should.Equal(100, obj.Field1)
}

View file

@ -1,52 +0,0 @@
package jsoniter
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func Test_encode_unexported_field(t *testing.T) {
type TestData struct {
a int
b <-chan int
C int
d *time.Timer
}
should := require.New(t)
testChan := make(<-chan int, 10)
testTimer := time.NewTimer(10 * time.Second)
obj := &TestData{
a: 42,
b: testChan,
C: 21,
d: testTimer,
}
jb, err := json.Marshal(obj)
should.NoError(err)
should.Equal([]byte(`{"C":21}`), jb)
err = json.Unmarshal([]byte(`{"a": 444, "b":"bad", "C":55, "d":{"not": "a timer"}}`), obj)
should.NoError(err)
should.Equal(42, obj.a)
should.Equal(testChan, obj.b)
should.Equal(55, obj.C)
should.Equal(testTimer, obj.d)
jb, err = Marshal(obj)
should.NoError(err)
should.Equal(jb, []byte(`{"C":55}`))
err = Unmarshal([]byte(`{"a": 444, "b":"bad", "C":256, "d":{"not":"a timer"}}`), obj)
should.NoError(err)
should.Equal(42, obj.a)
should.Equal(testChan, obj.b)
should.Equal(256, obj.C)
should.Equal(testTimer, obj.d)
}

View file

@ -1,118 +0,0 @@
package jsoniter
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_wrap_and_valuetype_everything(t *testing.T) {
should := require.New(t)
var i interface{}
any := Get([]byte("123"))
// default of number type is float64
i = float64(123)
should.Equal(i, any.GetInterface())
any = Wrap(int8(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
// get interface is not int8 interface
// i = int8(10)
// should.Equal(i, any.GetInterface())
any = Wrap(int16(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
//i = int16(10)
//should.Equal(i, any.GetInterface())
any = Wrap(int32(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
i = int32(10)
should.Equal(i, any.GetInterface())
any = Wrap(int64(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
i = int64(10)
should.Equal(i, any.GetInterface())
any = Wrap(uint(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
// not equal
//i = uint(10)
//should.Equal(i, any.GetInterface())
any = Wrap(uint8(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
// not equal
// i = uint8(10)
// should.Equal(i, any.GetInterface())
any = Wrap(uint16(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
any = Wrap(uint32(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
i = uint32(10)
should.Equal(i, any.GetInterface())
any = Wrap(uint64(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
i = uint64(10)
should.Equal(i, any.GetInterface())
any = Wrap(float32(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
// not equal
//i = float32(10)
//should.Equal(i, any.GetInterface())
any = Wrap(float64(10))
should.Equal(any.ValueType(), NumberValue)
should.Equal(any.LastError(), nil)
i = float64(10)
should.Equal(i, any.GetInterface())
any = Wrap(true)
should.Equal(any.ValueType(), BoolValue)
should.Equal(any.LastError(), nil)
i = true
should.Equal(i, any.GetInterface())
any = Wrap(false)
should.Equal(any.ValueType(), BoolValue)
should.Equal(any.LastError(), nil)
i = false
should.Equal(i, any.GetInterface())
any = Wrap(nil)
should.Equal(any.ValueType(), NilValue)
should.Equal(any.LastError(), nil)
i = nil
should.Equal(i, any.GetInterface())
stream := NewStream(ConfigDefault, nil, 32)
any.WriteTo(stream)
should.Equal("null", string(stream.Buffer()))
should.Equal(any.LastError(), nil)
any = Wrap(struct{ age int }{age: 1})
should.Equal(any.ValueType(), ObjectValue)
should.Equal(any.LastError(), nil)
i = struct{ age int }{age: 1}
should.Equal(i, any.GetInterface())
any = Wrap(map[string]interface{}{"abc": 1})
should.Equal(any.ValueType(), ObjectValue)
should.Equal(any.LastError(), nil)
i = map[string]interface{}{"abc": 1}
should.Equal(i, any.GetInterface())
any = Wrap("abc")
i = "abc"
should.Equal(i, any.GetInterface())
should.Equal(nil, any.LastError())
}

View file

@ -17,43 +17,25 @@ type StreamPool interface {
}
func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream {
select {
case stream := <-cfg.streamPool:
stream.Reset(writer)
return stream
default:
return NewStream(cfg, writer, 512)
}
stream := cfg.streamPool.Get().(*Stream)
stream.Reset(writer)
return stream
}
func (cfg *frozenConfig) ReturnStream(stream *Stream) {
stream.Error = nil
stream.Attachment = nil
select {
case cfg.streamPool <- stream:
return
default:
return
}
cfg.streamPool.Put(stream)
}
func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator {
select {
case iter := <-cfg.iteratorPool:
iter.ResetBytes(data)
return iter
default:
return ParseBytes(cfg, data)
}
iter := cfg.iteratorPool.Get().(*Iterator)
iter.ResetBytes(data)
return iter
}
func (cfg *frozenConfig) ReturnIterator(iter *Iterator) {
iter.Error = nil
iter.Attachment = nil
select {
case cfg.iteratorPool <- iter:
return
default:
return
}
cfg.iteratorPool.Put(iter)
}

321
vendor/github.com/json-iterator/go/reflect.go generated vendored Normal file
View file

@ -0,0 +1,321 @@
package jsoniter
import (
"fmt"
"reflect"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
// ValDecoder is an internal type registered to cache as needed.
// Don't confuse jsoniter.ValDecoder with json.Decoder.
// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link).
//
// Reflection on type to create decoders, which is then cached
// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions
// 1. create instance of new value, for example *int will need a int to be allocated
// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New
// 3. assignment to map, both key and value will be reflect.Value
// For a simple struct binding, it will be reflect.Value free and allocation free
type ValDecoder interface {
Decode(ptr unsafe.Pointer, iter *Iterator)
}
// ValEncoder is an internal type registered to cache as needed.
// Don't confuse jsoniter.ValEncoder with json.Encoder.
// For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link).
type ValEncoder interface {
IsEmpty(ptr unsafe.Pointer) bool
Encode(ptr unsafe.Pointer, stream *Stream)
}
type checkIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool
}
type ctx struct {
*frozenConfig
prefix string
encoders map[reflect2.Type]ValEncoder
decoders map[reflect2.Type]ValDecoder
}
func (b *ctx) append(prefix string) *ctx {
return &ctx{
frozenConfig: b.frozenConfig,
prefix: b.prefix + " " + prefix,
encoders: b.encoders,
decoders: b.decoders,
}
}
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
func (iter *Iterator) ReadVal(obj interface{}) {
cacheKey := reflect2.RTypeOf(obj)
decoder := iter.cfg.getDecoderFromCache(cacheKey)
if decoder == nil {
typ := reflect2.TypeOf(obj)
if typ.Kind() != reflect.Ptr {
iter.ReportError("ReadVal", "can only unmarshal into pointer")
return
}
decoder = iter.cfg.DecoderOf(typ)
}
ptr := reflect2.PtrOf(obj)
if ptr == nil {
iter.ReportError("ReadVal", "can not read into nil pointer")
return
}
decoder.Decode(ptr, iter)
}
// WriteVal copy the go interface into underlying JSON, same as json.Marshal
func (stream *Stream) WriteVal(val interface{}) {
if nil == val {
stream.WriteNil()
return
}
cacheKey := reflect2.RTypeOf(val)
encoder := stream.cfg.getEncoderFromCache(cacheKey)
if encoder == nil {
typ := reflect2.TypeOf(val)
encoder = stream.cfg.EncoderOf(typ)
}
encoder.Encode(reflect2.PtrOf(val), stream)
}
func (cfg *frozenConfig) DecoderOf(typ reflect2.Type) ValDecoder {
cacheKey := typ.RType()
decoder := cfg.getDecoderFromCache(cacheKey)
if decoder != nil {
return decoder
}
ctx := &ctx{
frozenConfig: cfg,
prefix: "",
decoders: map[reflect2.Type]ValDecoder{},
encoders: map[reflect2.Type]ValEncoder{},
}
ptrType := typ.(*reflect2.UnsafePtrType)
decoder = decoderOfType(ctx, ptrType.Elem())
cfg.addDecoderToCache(cacheKey, decoder)
return decoder
}
func decoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := getTypeDecoderFromExtension(ctx, typ)
if decoder != nil {
return decoder
}
decoder = createDecoderOfType(ctx, typ)
for _, extension := range extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
for _, extension := range ctx.extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
return decoder
}
func createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := ctx.decoders[typ]
if decoder != nil {
return decoder
}
placeholder := &placeholderDecoder{}
ctx.decoders[typ] = placeholder
decoder = _createDecoderOfType(ctx, typ)
placeholder.decoder = decoder
return decoder
}
func _createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := createDecoderOfJsonRawMessage(ctx, typ)
if decoder != nil {
return decoder
}
decoder = createDecoderOfJsonNumber(ctx, typ)
if decoder != nil {
return decoder
}
decoder = createDecoderOfMarshaler(ctx, typ)
if decoder != nil {
return decoder
}
decoder = createDecoderOfAny(ctx, typ)
if decoder != nil {
return decoder
}
decoder = createDecoderOfNative(ctx, typ)
if decoder != nil {
return decoder
}
switch typ.Kind() {
case reflect.Interface:
ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType)
if isIFace {
return &ifaceDecoder{valType: ifaceType}
}
return &efaceDecoder{}
case reflect.Struct:
return decoderOfStruct(ctx, typ)
case reflect.Array:
return decoderOfArray(ctx, typ)
case reflect.Slice:
return decoderOfSlice(ctx, typ)
case reflect.Map:
return decoderOfMap(ctx, typ)
case reflect.Ptr:
return decoderOfOptional(ctx, typ)
default:
return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
}
}
func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder {
cacheKey := typ.RType()
encoder := cfg.getEncoderFromCache(cacheKey)
if encoder != nil {
return encoder
}
ctx := &ctx{
frozenConfig: cfg,
prefix: "",
decoders: map[reflect2.Type]ValDecoder{},
encoders: map[reflect2.Type]ValEncoder{},
}
encoder = encoderOfType(ctx, typ)
if typ.LikePtr() {
encoder = &onePtrEncoder{encoder}
}
cfg.addEncoderToCache(cacheKey, encoder)
return encoder
}
type onePtrEncoder struct {
encoder ValEncoder
}
func (encoder *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
}
func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
}
func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := getTypeEncoderFromExtension(ctx, typ)
if encoder != nil {
return encoder
}
encoder = createEncoderOfType(ctx, typ)
for _, extension := range extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
for _, extension := range ctx.extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
return encoder
}
func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := ctx.encoders[typ]
if encoder != nil {
return encoder
}
placeholder := &placeholderEncoder{}
ctx.encoders[typ] = placeholder
encoder = _createEncoderOfType(ctx, typ)
placeholder.encoder = encoder
return encoder
}
func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := createEncoderOfJsonRawMessage(ctx, typ)
if encoder != nil {
return encoder
}
encoder = createEncoderOfJsonNumber(ctx, typ)
if encoder != nil {
return encoder
}
encoder = createEncoderOfMarshaler(ctx, typ)
if encoder != nil {
return encoder
}
encoder = createEncoderOfAny(ctx, typ)
if encoder != nil {
return encoder
}
encoder = createEncoderOfNative(ctx, typ)
if encoder != nil {
return encoder
}
kind := typ.Kind()
switch kind {
case reflect.Interface:
return &dynamicEncoder{typ}
case reflect.Struct:
return encoderOfStruct(ctx, typ)
case reflect.Array:
return encoderOfArray(ctx, typ)
case reflect.Slice:
return encoderOfSlice(ctx, typ)
case reflect.Map:
return encoderOfMap(ctx, typ)
case reflect.Ptr:
return encoderOfOptional(ctx, typ)
default:
return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())}
}
}
type lazyErrorDecoder struct {
err error
}
func (decoder *lazyErrorDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.WhatIsNext() != NilValue {
if iter.Error == nil {
iter.Error = decoder.err
}
} else {
iter.Skip()
}
}
type lazyErrorEncoder struct {
err error
}
func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if ptr == nil {
stream.WriteNil()
} else if stream.Error == nil {
stream.Error = encoder.err
}
}
func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type placeholderDecoder struct {
decoder ValDecoder
}
func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.decoder.Decode(ptr, iter)
}
type placeholderEncoder struct {
encoder ValEncoder
}
func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.encoder.Encode(ptr, stream)
}
func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(ptr)
}

104
vendor/github.com/json-iterator/go/reflect_array.go generated vendored Normal file
View file

@ -0,0 +1,104 @@
package jsoniter
import (
"fmt"
"io"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder {
arrayType := typ.(*reflect2.UnsafeArrayType)
decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
return &arrayDecoder{arrayType, decoder}
}
func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder {
arrayType := typ.(*reflect2.UnsafeArrayType)
if arrayType.Len() == 0 {
return emptyArrayEncoder{}
}
encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
return &arrayEncoder{arrayType, encoder}
}
type emptyArrayEncoder struct{}
func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteEmptyArray()
}
func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return true
}
type arrayEncoder struct {
arrayType *reflect2.UnsafeArrayType
elemEncoder ValEncoder
}
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteArrayStart()
elemPtr := unsafe.Pointer(ptr)
encoder.elemEncoder.Encode(elemPtr, stream)
for i := 1; i < encoder.arrayType.Len(); i++ {
stream.WriteMore()
elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error())
}
}
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type arrayDecoder struct {
arrayType *reflect2.UnsafeArrayType
elemDecoder ValDecoder
}
func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.doDecode(ptr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error())
}
}
func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
c := iter.nextToken()
arrayType := decoder.arrayType
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
return
}
if c != '[' {
iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c}))
return
}
c = iter.nextToken()
if c == ']' {
return
}
iter.unreadByte()
elemPtr := arrayType.UnsafeGetIndex(ptr, 0)
decoder.elemDecoder.Decode(elemPtr, iter)
length := 1
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
if length >= arrayType.Len() {
iter.Skip()
continue
}
idx := length
length += 1
elemPtr = arrayType.UnsafeGetIndex(ptr, idx)
decoder.elemDecoder.Decode(elemPtr, iter)
}
if c != ']' {
iter.ReportError("decode array", "expect ], but found "+string([]byte{c}))
return
}
}

70
vendor/github.com/json-iterator/go/reflect_dynamic.go generated vendored Normal file
View file

@ -0,0 +1,70 @@
package jsoniter
import (
"github.com/v2pro/plz/reflect2"
"unsafe"
"reflect"
)
type dynamicEncoder struct {
valType reflect2.Type
}
func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
obj := encoder.valType.UnsafeIndirect(ptr)
stream.WriteVal(obj)
}
func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.valType.UnsafeIndirect(ptr) == nil
}
type efaceDecoder struct {
}
func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
pObj := (*interface{})(ptr)
obj := *pObj
if obj == nil {
*pObj = iter.Read()
return
}
typ := reflect2.TypeOf(obj)
if typ.Kind() != reflect.Ptr {
*pObj = iter.Read()
return
}
ptrType := typ.(*reflect2.UnsafePtrType)
ptrElemType := ptrType.Elem()
if iter.WhatIsNext() == NilValue {
if ptrElemType.Kind() != reflect.Ptr {
iter.skipFourBytes('n', 'u', 'l', 'l')
*pObj = nil
return
}
}
if reflect2.IsNil(obj) {
obj := ptrElemType.New()
iter.ReadVal(obj)
*pObj = obj
return
}
iter.ReadVal(obj)
}
type ifaceDecoder struct {
valType *reflect2.UnsafeIFaceType
}
func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew())
return
}
obj := decoder.valType.UnsafeIndirect(ptr)
if reflect2.IsNil(obj) {
iter.ReportError("decode non empty interface", "can not unmarshal into nil")
return
}
iter.ReadVal(obj)
}

View file

@ -7,6 +7,7 @@ import (
"strings"
"unicode"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
var typeDecoders = map[string]ValDecoder{}
@ -17,9 +18,7 @@ var extensions = []Extension{}
// StructDescriptor describe how should we encode/decode the struct
type StructDescriptor struct {
onePtrEmbedded bool
onePtrOptimization bool
Type reflect.Type
Type reflect2.Type
Fields []*Binding
}
@ -27,7 +26,7 @@ type StructDescriptor struct {
// Can not use map here to keep field orders.
func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
for _, binding := range structDescriptor.Fields {
if binding.Field.Name == fieldName {
if binding.Field.Name() == fieldName {
return binding
}
}
@ -37,7 +36,7 @@ func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
// Binding describe how should we encode/decode the struct field
type Binding struct {
levels []int
Field *reflect.StructField
Field reflect2.StructField
FromNames []string
ToNames []string
Encoder ValEncoder
@ -48,10 +47,10 @@ type Binding struct {
// Can also rename fields by UpdateStructDescriptor.
type Extension interface {
UpdateStructDescriptor(structDescriptor *StructDescriptor)
CreateDecoder(typ reflect.Type) ValDecoder
CreateEncoder(typ reflect.Type) ValEncoder
DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder
DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder
CreateDecoder(typ reflect2.Type) ValDecoder
CreateEncoder(typ reflect2.Type) ValEncoder
DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder
DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder
}
// DummyExtension embed this type get dummy implementation for all methods of Extension
@ -63,22 +62,74 @@ func (extension *DummyExtension) UpdateStructDescriptor(structDescriptor *Struct
}
// CreateDecoder No-op
func (extension *DummyExtension) CreateDecoder(typ reflect.Type) ValDecoder {
func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateEncoder No-op
func (extension *DummyExtension) CreateEncoder(typ reflect.Type) ValEncoder {
func (extension *DummyExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// DecorateDecoder No-op
func (extension *DummyExtension) DecorateDecoder(typ reflect.Type, decoder ValDecoder) ValDecoder {
func (extension *DummyExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
}
// DecorateEncoder No-op
func (extension *DummyExtension) DecorateEncoder(typ reflect.Type, encoder ValEncoder) ValEncoder {
func (extension *DummyExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder {
return encoder
}
type EncoderExtension map[reflect2.Type]ValEncoder
// UpdateStructDescriptor No-op
func (extension EncoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
}
// CreateDecoder No-op
func (extension EncoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return nil
}
// CreateEncoder get encoder from map
func (extension EncoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return extension[typ]
}
// DecorateDecoder No-op
func (extension EncoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
}
// DecorateEncoder No-op
func (extension EncoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder {
return encoder
}
type DecoderExtension map[reflect2.Type]ValDecoder
// UpdateStructDescriptor No-op
func (extension DecoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) {
}
// CreateDecoder get decoder from map
func (extension DecoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder {
return extension[typ]
}
// CreateEncoder No-op
func (extension DecoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder {
return nil
}
// DecorateDecoder No-op
func (extension DecoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder {
return decoder
}
// DecorateEncoder No-op
func (extension DecoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder {
return encoder
}
@ -99,10 +150,6 @@ func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.fun(ptr, stream)
}
func (encoder *funcEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool {
if encoder.isEmptyFunc == nil {
return false
@ -161,60 +208,80 @@ func RegisterExtension(extension Extension) {
extensions = append(extensions, extension)
}
func getTypeDecoderFromExtension(typ reflect.Type) ValDecoder {
decoder := _getTypeDecoderFromExtension(typ)
func getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := _getTypeDecoderFromExtension(ctx, typ)
if decoder != nil {
for _, extension := range extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
for _, extension := range ctx.extensions {
decoder = extension.DecorateDecoder(typ, decoder)
}
}
return decoder
}
func _getTypeDecoderFromExtension(typ reflect.Type) ValDecoder {
func _getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder {
for _, extension := range extensions {
decoder := extension.CreateDecoder(typ)
if decoder != nil {
return decoder
}
}
for _, extension := range ctx.extensions {
decoder := extension.CreateDecoder(typ)
if decoder != nil {
return decoder
}
}
typeName := typ.String()
decoder := typeDecoders[typeName]
if decoder != nil {
return decoder
}
if typ.Kind() == reflect.Ptr {
decoder := typeDecoders[typ.Elem().String()]
ptrType := typ.(*reflect2.UnsafePtrType)
decoder := typeDecoders[ptrType.Elem().String()]
if decoder != nil {
return &OptionalDecoder{typ.Elem(), decoder}
return &OptionalDecoder{ptrType.Elem(), decoder}
}
}
return nil
}
func getTypeEncoderFromExtension(typ reflect.Type) ValEncoder {
encoder := _getTypeEncoderFromExtension(typ)
func getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder {
encoder := _getTypeEncoderFromExtension(ctx, typ)
if encoder != nil {
for _, extension := range extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
for _, extension := range ctx.extensions {
encoder = extension.DecorateEncoder(typ, encoder)
}
}
return encoder
}
func _getTypeEncoderFromExtension(typ reflect.Type) ValEncoder {
func _getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder {
for _, extension := range extensions {
encoder := extension.CreateEncoder(typ)
if encoder != nil {
return encoder
}
}
for _, extension := range ctx.extensions {
encoder := extension.CreateEncoder(typ)
if encoder != nil {
return encoder
}
}
typeName := typ.String()
encoder := typeEncoders[typeName]
if encoder != nil {
return encoder
}
if typ.Kind() == reflect.Ptr {
encoder := typeEncoders[typ.Elem().String()]
typePtr := typ.(*reflect2.UnsafePtrType)
encoder := typeEncoders[typePtr.Elem().String()]
if encoder != nil {
return &OptionalEncoder{encoder}
}
@ -222,72 +289,60 @@ func _getTypeEncoderFromExtension(typ reflect.Type) ValEncoder {
return nil
}
func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, error) {
func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
structType := typ.(*reflect2.UnsafeStructType)
embeddedBindings := []*Binding{}
bindings := []*Binding{}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
tag := field.Tag.Get(cfg.getTagKey())
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
if ctx.onlyTaggedField && !hastag {
continue
}
tagParts := strings.Split(tag, ",")
if tag == "-" {
continue
}
if field.Anonymous && (tag == "" || tagParts[0] == "") {
if field.Type.Kind() == reflect.Struct {
structDescriptor, err := describeStruct(cfg, field.Type)
if err != nil {
return nil, err
}
if field.Anonymous() && (tag == "" || tagParts[0] == "") {
if field.Type().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, field.Type())
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty}
binding.Decoder = &structFieldDecoder{field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
structDescriptor, err := describeStruct(cfg, field.Type.Elem())
if err != nil {
return nil, err
} else if field.Type().Kind() == reflect.Ptr {
ptrType := field.Type().(*reflect2.UnsafePtrType)
if ptrType.Elem().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, ptrType.Elem())
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &dereferenceEncoder{binding.Encoder}
binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty}
binding.Decoder = &dereferenceDecoder{ptrType.Elem(), binding.Decoder}
binding.Decoder = &structFieldDecoder{field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
}
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &OptionalEncoder{binding.Encoder}
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
binding.Decoder = &deferenceDecoder{field.Type.Elem(), binding.Decoder}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
}
}
fieldNames := calcFieldNames(field.Name, tagParts[0], tag)
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
fieldNames := calcFieldNames(field.Name(), tagParts[0], tag)
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name())
decoder := fieldDecoders[fieldCacheKey]
if decoder == nil {
var err error
decoder, err = decoderOfType(cfg, field.Type)
if len(fieldNames) > 0 && err != nil {
return nil, err
}
decoder = decoderOfType(ctx.append(field.Name()), field.Type())
}
encoder := fieldEncoders[fieldCacheKey]
if encoder == nil {
var err error
encoder, err = encoderOfType(cfg, field.Type)
if len(fieldNames) > 0 && err != nil {
return nil, err
}
// map is stored as pointer in the struct,
// and treat nil or empty map as empty field
if encoder != nil && field.Type.Kind() == reflect.Map {
encoder = &optionalMapEncoder{encoder}
}
encoder = encoderOfType(ctx.append(field.Name()), field.Type())
}
binding := &Binding{
Field: &field,
Field: field,
FromNames: fieldNames,
ToNames: fieldNames,
Decoder: decoder,
@ -296,35 +351,20 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
binding.levels = []int{i}
bindings = append(bindings, binding)
}
return createStructDescriptor(cfg, typ, bindings, embeddedBindings), nil
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
}
func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
onePtrEmbedded := false
onePtrOptimization := false
if typ.NumField() == 1 {
firstField := typ.Field(0)
switch firstField.Type.Kind() {
case reflect.Ptr:
if firstField.Anonymous && firstField.Type.Elem().Kind() == reflect.Struct {
onePtrEmbedded = true
}
fallthrough
case reflect.Map:
onePtrOptimization = true
case reflect.Struct:
onePtrOptimization = isStructOnePtr(firstField.Type)
}
}
func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
structDescriptor := &StructDescriptor{
onePtrEmbedded: onePtrEmbedded,
onePtrOptimization: onePtrOptimization,
Type: typ,
Fields: bindings,
}
for _, extension := range extensions {
extension.UpdateStructDescriptor(structDescriptor)
}
processTags(structDescriptor, cfg)
for _, extension := range ctx.extensions {
extension.UpdateStructDescriptor(structDescriptor)
}
processTags(structDescriptor, ctx.frozenConfig)
// merge normal & embedded bindings & sort with original order
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
sort.Sort(allBindings)
@ -332,21 +372,6 @@ func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Bin
return structDescriptor
}
func isStructOnePtr(typ reflect.Type) bool {
if typ.NumField() == 1 {
firstField := typ.Field(0)
switch firstField.Type.Kind() {
case reflect.Ptr:
return true
case reflect.Map:
return true
case reflect.Struct:
return isStructOnePtr(firstField.Type)
}
}
return false
}
type sortableBindings []*Binding
func (bindings sortableBindings) Len() int {
@ -374,12 +399,12 @@ func (bindings sortableBindings) Swap(i, j int) {
func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) {
for _, binding := range structDescriptor.Fields {
shouldOmitEmpty := false
tagParts := strings.Split(binding.Field.Tag.Get(cfg.getTagKey()), ",")
tagParts := strings.Split(binding.Field.Tag().Get(cfg.getTagKey()), ",")
for _, tagPart := range tagParts[1:] {
if tagPart == "omitempty" {
shouldOmitEmpty = true
} else if tagPart == "string" {
if binding.Field.Type.Kind() == reflect.String {
if binding.Field.Type().Kind() == reflect.String {
binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg}
binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg}
} else {

View file

@ -0,0 +1,112 @@
package jsoniter
import (
"encoding/json"
"strconv"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
type Number string
// String returns the literal text of the number.
func (n Number) String() string { return string(n) }
// Float64 returns the number as a float64.
func (n Number) Float64() (float64, error) {
return strconv.ParseFloat(string(n), 64)
}
// Int64 returns the number as an int64.
func (n Number) Int64() (int64, error) {
return strconv.ParseInt(string(n), 10, 64)
}
func CastJsonNumber(val interface{}) (string, bool) {
switch typedVal := val.(type) {
case json.Number:
return string(typedVal), true
case Number:
return string(typedVal), true
}
return "", false
}
var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem()
var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem()
func createDecoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}
}
if typ.AssignableTo(jsoniterNumberType) {
return &jsoniterNumberCodec{}
}
return nil
}
func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}
}
if typ.AssignableTo(jsoniterNumberType) {
return &jsoniterNumberCodec{}
}
return nil
}
type jsonNumberCodec struct {
}
func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
switch iter.WhatIsNext() {
case StringValue:
*((*json.Number)(ptr)) = json.Number(iter.ReadString())
case NilValue:
iter.skipFourBytes('n', 'u', 'l', 'l')
*((*json.Number)(ptr)) = ""
default:
*((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString()))
}
}
func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
number := *((*json.Number)(ptr))
if len(number) == 0 {
stream.writeByte('0')
} else {
stream.WriteRaw(string(number))
}
}
func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*json.Number)(ptr))) == 0
}
type jsoniterNumberCodec struct {
}
func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
switch iter.WhatIsNext() {
case StringValue:
*((*Number)(ptr)) = Number(iter.ReadString())
case NilValue:
iter.skipFourBytes('n', 'u', 'l', 'l')
*((*Number)(ptr)) = ""
default:
*((*Number)(ptr)) = Number([]byte(iter.readNumberAsString()))
}
}
func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
number := *((*Number)(ptr))
if len(number) == 0 {
stream.writeByte('0')
} else {
stream.WriteRaw(string(number))
}
}
func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*Number)(ptr))) == 0
}

View file

@ -0,0 +1,60 @@
package jsoniter
import (
"unsafe"
"encoding/json"
"github.com/v2pro/plz/reflect2"
)
var jsonRawMessageType = reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()
var jsoniterRawMessageType = reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()
func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}
}
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}
}
return nil
}
func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}
}
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}
}
return nil
}
type jsonRawMessageCodec struct {
}
func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*json.RawMessage)(ptr))))
}
func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*json.RawMessage)(ptr))) == 0
}
type jsoniterRawMessageCodec struct {
}
func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes())
}
func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteRaw(string(*((*RawMessage)(ptr))))
}
func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*RawMessage)(ptr))) == 0
}

284
vendor/github.com/json-iterator/go/reflect_map.go generated vendored Normal file
View file

@ -0,0 +1,284 @@
package jsoniter
import (
"reflect"
"sort"
"unsafe"
"github.com/v2pro/plz/reflect2"
"fmt"
)
func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder {
mapType := typ.(*reflect2.UnsafeMapType)
keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key())
elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem())
return &mapDecoder{
mapType: mapType,
keyType: mapType.Key(),
elemType: mapType.Elem(),
keyDecoder: keyDecoder,
elemDecoder: elemDecoder,
}
}
func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
mapType := typ.(*reflect2.UnsafeMapType)
if ctx.sortMapKeys {
return &sortKeysMapEncoder{
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
}
}
return &mapEncoder{
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
}
}
func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
switch typ.Kind() {
case reflect.String:
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
reflect.Uint32, reflect.Int32,
reflect.Uint64, reflect.Int64,
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind())
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
default:
ptrType := reflect2.PtrTo(typ)
if ptrType.Implements(textMarshalerType) {
return &referenceDecoder{
&textUnmarshalerDecoder{
valType: ptrType,
},
}
}
if typ.Implements(textMarshalerType) {
return &textUnmarshalerDecoder{
valType: typ,
}
}
return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
}
}
func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
switch typ.Kind() {
case reflect.String:
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
reflect.Uint32, reflect.Int32,
reflect.Uint64, reflect.Int64,
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind())
return &numericMapKeyEncoder{encoderOfType(ctx, typ)}
default:
if typ == textMarshalerType {
return &directTextMarshalerEncoder{
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
}
if typ.Implements(textMarshalerType) {
return &textMarshalerEncoder{
valType: typ,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
}
return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
}
}
type mapDecoder struct {
mapType *reflect2.UnsafeMapType
keyType reflect2.Type
elemType reflect2.Type
keyDecoder ValDecoder
elemDecoder ValDecoder
}
func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
mapType := decoder.mapType
c := iter.nextToken()
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
*(*unsafe.Pointer)(ptr) = nil
mapType.UnsafeSet(ptr, mapType.UnsafeNew())
return
}
if mapType.UnsafeIsNil(ptr) {
mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0))
}
if c != '{' {
iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
return
}
c = iter.nextToken()
if c == '}' {
return
}
if c != '"' {
iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c}))
return
}
iter.unreadByte()
key := decoder.keyType.UnsafeNew()
decoder.keyDecoder.Decode(key, iter)
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
return
}
elem := decoder.elemType.UnsafeNew()
decoder.elemDecoder.Decode(elem, iter)
decoder.mapType.UnsafeSetIndex(ptr, key, elem)
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
key := decoder.keyType.UnsafeNew()
decoder.keyDecoder.Decode(key, iter)
c = iter.nextToken()
if c != ':' {
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
return
}
elem := decoder.elemType.UnsafeNew()
decoder.elemDecoder.Decode(elem, iter)
decoder.mapType.UnsafeSetIndex(ptr, key, elem)
}
if c != '}' {
iter.ReportError("ReadMapCB", `expect }, but found `+string([]byte{c}))
}
}
type numericMapKeyDecoder struct {
decoder ValDecoder
}
func (decoder *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
c := iter.nextToken()
if c != '"' {
iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
return
}
decoder.decoder.Decode(ptr, iter)
c = iter.nextToken()
if c != '"' {
iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
return
}
}
type numericMapKeyEncoder struct {
encoder ValEncoder
}
func (encoder *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.writeByte('"')
encoder.encoder.Encode(ptr, stream)
stream.writeByte('"')
}
func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type mapEncoder struct {
mapType *reflect2.UnsafeMapType
keyEncoder ValEncoder
elemEncoder ValEncoder
}
func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteObjectStart()
iter := encoder.mapType.UnsafeIterate(ptr)
for i := 0; iter.HasNext(); i++ {
if i != 0 {
stream.WriteMore()
}
key, elem := iter.UnsafeNext()
encoder.keyEncoder.Encode(key, stream)
if stream.indention > 0 {
stream.writeTwoBytes(byte(':'), byte(' '))
} else {
stream.writeByte(':')
}
encoder.elemEncoder.Encode(elem, stream)
}
stream.WriteObjectEnd()
}
func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
iter := encoder.mapType.UnsafeIterate(ptr)
return !iter.HasNext()
}
type sortKeysMapEncoder struct {
mapType *reflect2.UnsafeMapType
keyEncoder ValEncoder
elemEncoder ValEncoder
}
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *(*unsafe.Pointer)(ptr) == nil {
stream.WriteNil()
return
}
stream.WriteObjectStart()
mapIter := encoder.mapType.UnsafeIterate(ptr)
subStream := stream.cfg.BorrowStream(nil)
subIter := stream.cfg.BorrowIterator(nil)
keyValues := encodedKeyValues{}
for mapIter.HasNext() {
subStream.buf = make([]byte, 0, 64)
key, elem := mapIter.UnsafeNext()
encoder.keyEncoder.Encode(key, subStream)
encodedKey := subStream.Buffer()
subIter.ResetBytes(encodedKey)
decodedKey := subIter.ReadString()
if stream.indention > 0 {
subStream.writeTwoBytes(byte(':'), byte(' '))
} else {
subStream.writeByte(':')
}
encoder.elemEncoder.Encode(elem, subStream)
keyValues = append(keyValues, encodedKV{
key: decodedKey,
keyValue: subStream.Buffer(),
})
}
sort.Sort(keyValues)
for i, keyValue := range keyValues {
if i != 0 {
stream.WriteMore()
}
stream.Write(keyValue.keyValue)
}
stream.WriteObjectEnd()
stream.cfg.ReturnStream(subStream)
stream.cfg.ReturnIterator(subIter)
}
func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
iter := encoder.mapType.UnsafeIterate(ptr)
return !iter.HasNext()
}
type encodedKeyValues []encodedKV
type encodedKV struct {
key string
keyValue []byte
}
func (sv encodedKeyValues) Len() int { return len(sv) }
func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key }

218
vendor/github.com/json-iterator/go/reflect_marshaler.go generated vendored Normal file
View file

@ -0,0 +1,218 @@
package jsoniter
import (
"github.com/v2pro/plz/reflect2"
"unsafe"
"encoding"
"encoding/json"
)
var marshalerType = reflect2.TypeOfPtr((*json.Marshaler)(nil)).Elem()
var unmarshalerType = reflect2.TypeOfPtr((*json.Unmarshaler)(nil)).Elem()
var textMarshalerType = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem()
var textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem()
func createDecoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValDecoder {
ptrType := reflect2.PtrTo(typ)
if ptrType.Implements(unmarshalerType) {
return &referenceDecoder{
&unmarshalerDecoder{ptrType},
}
}
if ptrType.Implements(textUnmarshalerType) {
return &referenceDecoder{
&textUnmarshalerDecoder{ptrType},
}
}
return nil
}
func createEncoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ == marshalerType {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &directMarshalerEncoder{
checkIsEmpty: checkIsEmpty,
}
return encoder
}
if typ.Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &marshalerEncoder{
valType: typ,
checkIsEmpty: checkIsEmpty,
}
return encoder
}
ptrType := reflect2.PtrTo(typ)
if ctx.prefix != "" && ptrType.Implements(marshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
var encoder ValEncoder = &marshalerEncoder{
valType: ptrType,
checkIsEmpty: checkIsEmpty,
}
return &referenceEncoder{encoder}
}
if typ == textMarshalerType {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &directTextMarshalerEncoder{
checkIsEmpty: checkIsEmpty,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
}
return encoder
}
if typ.Implements(textMarshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, typ)
var encoder ValEncoder = &textMarshalerEncoder{
valType: typ,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
checkIsEmpty: checkIsEmpty,
}
return encoder
}
// if prefix is empty, the type is the root type
if ctx.prefix != "" && ptrType.Implements(textMarshalerType) {
checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
var encoder ValEncoder = &textMarshalerEncoder{
valType: ptrType,
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
checkIsEmpty: checkIsEmpty,
}
return &referenceEncoder{encoder}
}
return nil
}
type marshalerEncoder struct {
checkIsEmpty checkIsEmpty
valType reflect2.Type
}
func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
obj := encoder.valType.UnsafeIndirect(ptr)
if encoder.valType.IsNullable() && reflect2.IsNil(obj) {
stream.WriteNil()
return
}
marshaler := obj.(json.Marshaler)
bytes, err := marshaler.MarshalJSON()
if err != nil {
stream.Error = err
} else {
stream.Write(bytes)
}
}
func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type directMarshalerEncoder struct {
checkIsEmpty checkIsEmpty
}
func (encoder *directMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
marshaler := *(*json.Marshaler)(ptr)
if marshaler == nil {
stream.WriteNil()
return
}
bytes, err := marshaler.MarshalJSON()
if err != nil {
stream.Error = err
} else {
stream.Write(bytes)
}
}
func (encoder *directMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type textMarshalerEncoder struct {
valType reflect2.Type
stringEncoder ValEncoder
checkIsEmpty checkIsEmpty
}
func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
obj := encoder.valType.UnsafeIndirect(ptr)
if encoder.valType.IsNullable() && reflect2.IsNil(obj) {
stream.WriteNil()
return
}
marshaler := (obj).(encoding.TextMarshaler)
bytes, err := marshaler.MarshalText()
if err != nil {
stream.Error = err
} else {
str := string(bytes)
encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream)
}
}
func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type directTextMarshalerEncoder struct {
stringEncoder ValEncoder
checkIsEmpty checkIsEmpty
}
func (encoder *directTextMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
marshaler := *(*encoding.TextMarshaler)(ptr)
if marshaler == nil {
stream.WriteNil()
return
}
bytes, err := marshaler.MarshalText()
if err != nil {
stream.Error = err
} else {
str := string(bytes)
encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream)
}
}
func (encoder *directTextMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type unmarshalerDecoder struct {
valType reflect2.Type
}
func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
valType := decoder.valType
obj := valType.UnsafeIndirect(ptr)
unmarshaler := obj.(json.Unmarshaler)
iter.nextToken()
iter.unreadByte() // skip spaces
bytes := iter.SkipAndReturnBytes()
err := unmarshaler.UnmarshalJSON(bytes)
if err != nil {
iter.ReportError("unmarshalerDecoder", err.Error())
}
}
type textUnmarshalerDecoder struct {
valType reflect2.Type
}
func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
valType := decoder.valType
obj := valType.UnsafeIndirect(ptr)
if reflect2.IsNil(obj) {
ptrType := valType.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
elem := elemType.UnsafeNew()
ptrType.UnsafeSet(ptr, unsafe.Pointer(&elem))
obj = valType.UnsafeIndirect(ptr)
}
unmarshaler := (obj).(encoding.TextUnmarshaler)
str := iter.ReadString()
err := unmarshaler.UnmarshalText([]byte(str))
if err != nil {
iter.ReportError("textUnmarshalerDecoder", err.Error())
}
}

455
vendor/github.com/json-iterator/go/reflect_native.go generated vendored Normal file
View file

@ -0,0 +1,455 @@
package jsoniter
import (
"encoding/base64"
"reflect"
"unsafe"
"github.com/v2pro/plz/reflect2"
"strconv"
)
const ptrSize = 32 << uintptr(^uintptr(0)>>63)
func createEncoderOfNative(ctx *ctx, typ reflect2.Type) ValEncoder {
if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 {
sliceDecoder := decoderOfSlice(ctx, typ)
return &base64Codec{sliceDecoder: sliceDecoder}
}
typeName := typ.String()
kind := typ.Kind()
switch kind {
case reflect.String:
if typeName != "string" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &int32Codec{}
}
return &int64Codec{}
case reflect.Int8:
if typeName != "int8" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint8:
if typeName != "uint8" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem())
}
if ptrSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint64:
if typeName != "uint64" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return encoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem())
}
return &boolCodec{}
}
return nil
}
func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder {
if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 {
sliceDecoder := decoderOfSlice(ctx, typ)
return &base64Codec{sliceDecoder: sliceDecoder}
}
typeName := typ.String()
switch typ.Kind() {
case reflect.String:
if typeName != "string" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &int32Codec{}
}
return &int64Codec{}
case reflect.Int8:
if typeName != "int8" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint8:
if typeName != "uint8" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem())
}
if ptrSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint64:
if typeName != "uint64" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return decoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem())
}
return &boolCodec{}
}
return nil
}
type stringCodec struct {
}
func (codec *stringCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*string)(ptr)) = iter.ReadString()
}
func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
str := *((*string)(ptr))
stream.WriteString(str)
}
func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*string)(ptr)) == ""
}
type int8Codec struct {
}
func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int8)(ptr)) = iter.ReadInt8()
}
}
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt8(*((*int8)(ptr)))
}
func (codec *int8Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int8)(ptr)) == 0
}
type int16Codec struct {
}
func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int16)(ptr)) = iter.ReadInt16()
}
}
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt16(*((*int16)(ptr)))
}
func (codec *int16Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int16)(ptr)) == 0
}
type int32Codec struct {
}
func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int32)(ptr)) = iter.ReadInt32()
}
}
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt32(*((*int32)(ptr)))
}
func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int32)(ptr)) == 0
}
type int64Codec struct {
}
func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*int64)(ptr)) = iter.ReadInt64()
}
}
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteInt64(*((*int64)(ptr)))
}
func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int64)(ptr)) == 0
}
type uint8Codec struct {
}
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint8)(ptr)) = iter.ReadUint8()
}
}
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint8(*((*uint8)(ptr)))
}
func (codec *uint8Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint8)(ptr)) == 0
}
type uint16Codec struct {
}
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint16)(ptr)) = iter.ReadUint16()
}
}
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint16(*((*uint16)(ptr)))
}
func (codec *uint16Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint16)(ptr)) == 0
}
type uint32Codec struct {
}
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint32)(ptr)) = iter.ReadUint32()
}
}
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint32(*((*uint32)(ptr)))
}
func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint32)(ptr)) == 0
}
type uint64Codec struct {
}
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*uint64)(ptr)) = iter.ReadUint64()
}
}
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint64(*((*uint64)(ptr)))
}
func (codec *uint64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint64)(ptr)) == 0
}
type float32Codec struct {
}
func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*float32)(ptr)) = iter.ReadFloat32()
}
}
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat32(*((*float32)(ptr)))
}
func (codec *float32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float32)(ptr)) == 0
}
type float64Codec struct {
}
func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*float64)(ptr)) = iter.ReadFloat64()
}
}
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteFloat64(*((*float64)(ptr)))
}
func (codec *float64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float64)(ptr)) == 0
}
type boolCodec struct {
}
func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.ReadNil() {
*((*bool)(ptr)) = iter.ReadBool()
}
}
func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteBool(*((*bool)(ptr)))
}
func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool {
return !(*((*bool)(ptr)))
}
type base64Codec struct {
sliceType *reflect2.UnsafeSliceType
sliceDecoder ValDecoder
}
func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
codec.sliceType.UnsafeSetNil(ptr)
return
}
switch iter.WhatIsNext() {
case StringValue:
encoding := base64.StdEncoding
src := iter.SkipAndReturnBytes()
src = src[1: len(src)-1]
decodedLen := encoding.DecodedLen(len(src))
dst := make([]byte, decodedLen)
len, err := encoding.Decode(dst, src)
if err != nil {
iter.ReportError("decode base64", err.Error())
} else {
dst = dst[:len]
codec.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst))
}
case ArrayValue:
codec.sliceDecoder.Decode(ptr, iter)
default:
iter.ReportError("base64Codec", "invalid input")
}
}
func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
size := encoding.EncodedLen(len(src))
buf := make([]byte, size)
encoding.Encode(buf, src)
stream.buf = append(stream.buf, buf...)
stream.writeByte('"')
}
func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*[]byte)(ptr))) == 0
}

133
vendor/github.com/json-iterator/go/reflect_optional.go generated vendored Normal file
View file

@ -0,0 +1,133 @@
package jsoniter
import (
"reflect"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
decoder := decoderOfType(ctx, elemType)
if ctx.prefix == "" && elemType.Kind() == reflect.Ptr {
return &dereferenceDecoder{elemType, decoder}
}
return &OptionalDecoder{elemType, decoder}
}
func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
elemEncoder := encoderOfType(ctx, elemType)
encoder := &OptionalEncoder{elemEncoder}
return encoder
}
type OptionalDecoder struct {
ValueType reflect2.Type
ValueDecoder ValDecoder
}
func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
*((*unsafe.Pointer)(ptr)) = nil
} else {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
newPtr := decoder.ValueType.UnsafeNew()
decoder.ValueDecoder.Decode(newPtr, iter)
*((*unsafe.Pointer)(ptr)) = newPtr
} else {
//reuse existing instance
decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
}
}
}
type dereferenceDecoder struct {
// only to deference a pointer
valueType reflect2.Type
valueDecoder ValDecoder
}
func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
newPtr := decoder.valueType.UnsafeNew()
decoder.valueDecoder.Decode(newPtr, iter)
*((*unsafe.Pointer)(ptr)) = newPtr
} else {
//reuse existing instance
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
}
}
type OptionalEncoder struct {
ValueEncoder ValEncoder
}
func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil
}
type dereferenceEncoder struct {
ValueEncoder ValEncoder
}
func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
dePtr := *((*unsafe.Pointer)(ptr))
if dePtr == nil {
return true
}
return encoder.ValueEncoder.IsEmpty(dePtr)
}
func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
deReferenced := *((*unsafe.Pointer)(ptr))
if deReferenced == nil {
return true
}
isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil)
if !converted {
return false
}
fieldPtr := unsafe.Pointer(deReferenced)
return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
}
type referenceEncoder struct {
encoder ValEncoder
}
func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
}
func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
}
type referenceDecoder struct {
decoder ValDecoder
}
func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.decoder.Decode(unsafe.Pointer(&ptr), iter)
}

99
vendor/github.com/json-iterator/go/reflect_slice.go generated vendored Normal file
View file

@ -0,0 +1,99 @@
package jsoniter
import (
"fmt"
"io"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
return &sliceDecoder{sliceType, decoder}
}
func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem())
return &sliceEncoder{sliceType, encoder}
}
type sliceEncoder struct {
sliceType *reflect2.UnsafeSliceType
elemEncoder ValEncoder
}
func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if encoder.sliceType.UnsafeIsNil(ptr) {
stream.WriteNil()
return
}
length := encoder.sliceType.UnsafeLengthOf(ptr)
if length == 0 {
stream.WriteEmptyArray()
return
}
stream.WriteArrayStart()
encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream)
for i := 1; i < length; i++ {
stream.WriteMore()
elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
}
}
func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.sliceType.UnsafeLengthOf(ptr) == 0
}
type sliceDecoder struct {
sliceType *reflect2.UnsafeSliceType
elemDecoder ValDecoder
}
func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.doDecode(ptr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error())
}
}
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
c := iter.nextToken()
sliceType := decoder.sliceType
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
sliceType.UnsafeSetNil(ptr)
return
}
if c != '[' {
iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c}))
return
}
c = iter.nextToken()
if c == ']' {
sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0))
return
}
iter.unreadByte()
sliceType.UnsafeGrow(ptr, 1)
elemPtr := sliceType.UnsafeGetIndex(ptr, 0)
decoder.elemDecoder.Decode(elemPtr, iter)
length := 1
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
idx := length
length += 1
sliceType.UnsafeGrow(ptr, length)
elemPtr = sliceType.UnsafeGetIndex(ptr, idx)
decoder.elemDecoder.Decode(elemPtr, iter)
}
if c != ']' {
iter.ReportError("decode slice", "expect ], but found "+string([]byte{c}))
return
}
}

View file

@ -3,38 +3,67 @@ package jsoniter
import (
"fmt"
"io"
"reflect"
"strings"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) (ValDecoder, error) {
knownHash := map[int32]struct{}{
func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder {
bindings := map[string]*Binding{}
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames {
old := bindings[fromName]
if old == nil {
bindings[fromName] = binding
continue
}
ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding)
if ignoreOld {
delete(bindings, fromName)
}
if !ignoreNew {
bindings[fromName] = binding
}
}
}
fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder)
}
return createStructDecoder(ctx, typ, fields)
}
func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder {
if ctx.disallowUnknownFields {
return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
}
knownHash := map[int64]struct{}{
0: {},
}
switch len(fields) {
case 0:
return &skipObjectDecoder{typ}, nil
return &skipObjectDecoder{typ}
case 1:
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}, nil
return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}
}
case 2:
var fieldHash1 int32
var fieldHash2 int32
var fieldHash1 int64
var fieldHash2 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
for fieldName, fieldDecoder := range fields {
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldHash1 == 0 {
@ -45,11 +74,11 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldDecoder2 = fieldDecoder
}
}
return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}, nil
return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}
case 3:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -57,7 +86,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -72,12 +101,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &threeFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3}
case 4:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldName4 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -86,7 +117,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -104,14 +135,16 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &fourFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4}
case 5:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldName4 int64
var fieldName5 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -121,7 +154,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -142,15 +175,18 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &fiveFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5}
case 6:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldName4 int64
var fieldName5 int64
var fieldName6 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -161,7 +197,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -185,16 +221,20 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &sixFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6}
case 7:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldName4 int64
var fieldName5 int64
var fieldName6 int64
var fieldName7 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -206,7 +246,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -233,18 +273,22 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &sevenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7}
case 8:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldName4 int64
var fieldName5 int64
var fieldName6 int64
var fieldName7 int64
var fieldName8 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -257,7 +301,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -287,19 +331,24 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &eightFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7,
fieldName8, fieldDecoder8}
case 9:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldName9 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldName4 int64
var fieldName5 int64
var fieldName6 int64
var fieldName7 int64
var fieldName8 int64
var fieldName9 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -313,7 +362,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -346,20 +395,26 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &nineFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7,
fieldName8, fieldDecoder8,
fieldName9, fieldDecoder9}
case 10:
var fieldName1 int32
var fieldName2 int32
var fieldName3 int32
var fieldName4 int32
var fieldName5 int32
var fieldName6 int32
var fieldName7 int32
var fieldName8 int32
var fieldName9 int32
var fieldName10 int32
var fieldName1 int64
var fieldName2 int64
var fieldName3 int64
var fieldName4 int64
var fieldName5 int64
var fieldName6 int64
var fieldName7 int64
var fieldName8 int64
var fieldName9 int64
var fieldName10 int64
var fieldDecoder1 *structFieldDecoder
var fieldDecoder2 *structFieldDecoder
var fieldDecoder3 *structFieldDecoder
@ -374,7 +429,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
fieldHash := calcHash(fieldName)
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
knownHash[fieldHash] = struct{}{}
if fieldName1 == 0 {
@ -410,66 +465,77 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
}
}
return &tenFieldsStructDecoder{typ,
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}, nil
fieldName1, fieldDecoder1,
fieldName2, fieldDecoder2,
fieldName3, fieldDecoder3,
fieldName4, fieldDecoder4,
fieldName5, fieldDecoder5,
fieldName6, fieldDecoder6,
fieldName7, fieldDecoder7,
fieldName8, fieldDecoder8,
fieldName9, fieldDecoder9,
fieldName10, fieldDecoder10}
}
return &generalStructDecoder{typ, fields}, nil
return &generalStructDecoder{typ, fields, false}
}
type generalStructDecoder struct {
typ reflect.Type
fields map[string]*structFieldDecoder
typ reflect2.Type
fields map[string]*structFieldDecoder
disallowUnknownFields bool
}
func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if !iter.readObjectStart() {
return
}
var fieldBytes []byte
decoder.decodeOneField(ptr, iter)
for iter.nextToken() == ',' {
decoder.decodeOneField(ptr, iter)
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) {
var field string
var fieldDecoder *structFieldDecoder
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes = iter.readObjectFieldAsBytes()
fieldBytes := iter.ReadStringAsSlice()
field = *(*string)(unsafe.Pointer(&fieldBytes))
fieldDecoder = decoder.fields[field]
if fieldDecoder == nil {
fieldDecoder = decoder.fields[strings.ToLower(field)]
}
} else {
field = iter.ReadString()
fieldDecoder = decoder.fields[field]
if fieldDecoder == nil {
fieldDecoder = decoder.fields[strings.ToLower(field)]
}
}
if fieldDecoder == nil {
msg := "found unknown field: " + field
if decoder.disallowUnknownFields {
iter.ReportError("ReadObject", msg)
}
c := iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
}
fieldDecoder := decoder.fields[strings.ToLower(field)]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.Decode(ptr, iter)
return
}
for iter.nextToken() == ',' {
if iter.cfg.objectFieldMustBeSimpleString {
fieldBytes := iter.readObjectFieldAsBytes()
field = *(*string)(unsafe.Pointer(&fieldBytes))
} else {
field = iter.ReadString()
c := iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
}
fieldDecoder = decoder.fields[strings.ToLower(field)]
if fieldDecoder == nil {
iter.Skip()
} else {
fieldDecoder.Decode(ptr, iter)
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
c := iter.nextToken()
if c != ':' {
iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
fieldDecoder.Decode(ptr, iter)
}
type skipObjectDecoder struct {
typ reflect.Type
typ reflect2.Type
}
func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
@ -482,8 +548,8 @@ func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
type oneFieldStructDecoder struct {
typ reflect.Type
fieldHash int32
typ reflect2.Type
fieldHash int64
fieldDecoder *structFieldDecoder
}
@ -502,15 +568,15 @@ func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type twoFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
}
@ -532,17 +598,17 @@ func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type threeFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
}
@ -566,19 +632,19 @@ func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type fourFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
}
@ -604,21 +670,21 @@ func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type fiveFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
}
@ -646,23 +712,23 @@ func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type sixFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
}
@ -692,25 +758,25 @@ func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type sevenFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
}
@ -742,27 +808,27 @@ func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type eightFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldHash8 int64
fieldDecoder8 *structFieldDecoder
}
@ -796,29 +862,29 @@ func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type nineFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldHash8 int64
fieldDecoder8 *structFieldDecoder
fieldHash9 int32
fieldHash9 int64
fieldDecoder9 *structFieldDecoder
}
@ -854,31 +920,31 @@ func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type tenFieldsStructDecoder struct {
typ reflect.Type
fieldHash1 int32
typ reflect2.Type
fieldHash1 int64
fieldDecoder1 *structFieldDecoder
fieldHash2 int32
fieldHash2 int64
fieldDecoder2 *structFieldDecoder
fieldHash3 int32
fieldHash3 int64
fieldDecoder3 *structFieldDecoder
fieldHash4 int32
fieldHash4 int64
fieldDecoder4 *structFieldDecoder
fieldHash5 int32
fieldHash5 int64
fieldDecoder5 *structFieldDecoder
fieldHash6 int32
fieldHash6 int64
fieldDecoder6 *structFieldDecoder
fieldHash7 int32
fieldHash7 int64
fieldDecoder7 *structFieldDecoder
fieldHash8 int32
fieldHash8 int64
fieldDecoder8 *structFieldDecoder
fieldHash9 int32
fieldHash9 int64
fieldDecoder9 *structFieldDecoder
fieldHash10 int32
fieldHash10 int64
fieldDecoder10 *structFieldDecoder
}
@ -916,19 +982,53 @@ func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
}
}
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
}
}
type structFieldDecoder struct {
field *reflect.StructField
field reflect2.StructField
fieldDecoder ValDecoder
}
func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
fieldPtr := unsafe.Pointer(uintptr(ptr) + decoder.field.Offset)
fieldPtr := decoder.field.UnsafeGet(ptr)
decoder.fieldDecoder.Decode(fieldPtr, iter)
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name, iter.Error.Error())
iter.Error = fmt.Errorf("%s: %s", decoder.field.Name(), iter.Error.Error())
}
}
type stringModeStringDecoder struct {
elemDecoder ValDecoder
cfg *frozenConfig
}
func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.elemDecoder.Decode(ptr, iter)
str := *((*string)(ptr))
tempIter := decoder.cfg.BorrowIterator([]byte(str))
defer decoder.cfg.ReturnIterator(tempIter)
*((*string)(ptr)) = tempIter.ReadString()
}
type stringModeNumberDecoder struct {
elemDecoder ValDecoder
}
func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
c := iter.nextToken()
if c != '"' {
iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
return
}
decoder.elemDecoder.Decode(ptr, iter)
if iter.Error != nil {
return
}
c = iter.readByte()
if c != '"' {
iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
return
}
}

View file

@ -4,21 +4,18 @@ import (
"fmt"
"io"
"reflect"
"strings"
"unsafe"
"github.com/v2pro/plz/reflect2"
)
func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder {
type bindingTo struct {
binding *Binding
toName string
ignored bool
}
orderedBindings := []*bindingTo{}
structDescriptor, err := describeStruct(cfg, typ)
if err != nil {
return nil, err
}
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames {
new := &bindingTo{
@ -29,13 +26,13 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
if old.toName != toName {
continue
}
old.ignored, new.ignored = resolveConflictBinding(cfg, old.binding, new.binding)
old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding)
}
orderedBindings = append(orderedBindings, new)
}
}
if len(orderedBindings) == 0 {
return &emptyStructEncoder{}, nil
return &emptyStructEncoder{}
}
finalOrderedFields := []structFieldTo{}
for _, bindingTo := range orderedBindings {
@ -46,12 +43,36 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
})
}
}
return &structEncoder{structDescriptor.onePtrEmbedded, structDescriptor.onePtrOptimization, finalOrderedFields}, nil
return &structEncoder{typ, finalOrderedFields}
}
func createCheckIsEmpty(ctx *ctx, typ reflect2.Type) checkIsEmpty {
encoder := createEncoderOfNative(ctx, typ)
if encoder != nil {
return encoder
}
kind := typ.Kind()
switch kind {
case reflect.Interface:
return &dynamicEncoder{typ}
case reflect.Struct:
return &structEncoder{typ: typ}
case reflect.Array:
return &arrayEncoder{}
case reflect.Slice:
return &sliceEncoder{}
case reflect.Map:
return encoderOfMap(ctx, typ)
case reflect.Ptr:
return &OptionalEncoder{}
default:
return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)}
}
}
func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) {
newTagged := new.Field.Tag.Get(cfg.getTagKey()) != ""
oldTagged := old.Field.Tag.Get(cfg.getTagKey()) != ""
newTagged := new.Field.Tag().Get(cfg.getTagKey()) != ""
oldTagged := old.Field.Tag().Get(cfg.getTagKey()) != ""
if newTagged {
if oldTagged {
if len(old.levels) > len(new.levels) {
@ -78,62 +99,41 @@ func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ig
}
}
func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
bindings := map[string]*Binding{}
structDescriptor, err := describeStruct(cfg, typ)
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames {
old := bindings[fromName]
if old == nil {
bindings[fromName] = binding
continue
}
ignoreOld, ignoreNew := resolveConflictBinding(cfg, old, binding)
if ignoreOld {
delete(bindings, fromName)
}
if !ignoreNew {
bindings[fromName] = binding
}
}
}
fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
}
return createStructDecoder(typ, fields)
}
type structFieldEncoder struct {
field *reflect.StructField
field reflect2.StructField
fieldEncoder ValEncoder
omitempty bool
}
func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
fieldPtr := unsafe.Pointer(uintptr(ptr) + encoder.field.Offset)
fieldPtr := encoder.field.UnsafeGet(ptr)
encoder.fieldEncoder.Encode(fieldPtr, stream)
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%s: %s", encoder.field.Name, stream.Error.Error())
stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error())
}
}
func (encoder *structFieldEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
fieldPtr := unsafe.Pointer(uintptr(ptr) + encoder.field.Offset)
fieldPtr := encoder.field.UnsafeGet(ptr)
return encoder.fieldEncoder.IsEmpty(fieldPtr)
}
func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
isEmbeddedPtrNil, converted := encoder.fieldEncoder.(IsEmbeddedPtrNil)
if !converted {
return false
}
fieldPtr := encoder.field.UnsafeGet(ptr)
return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
}
type IsEmbeddedPtrNil interface {
IsEmbeddedPtrNil(ptr unsafe.Pointer) bool
}
type structEncoder struct {
onePtrEmbedded bool
onePtrOptimization bool
fields []structFieldTo
typ reflect2.Type
fields []structFieldTo
}
type structFieldTo struct {
@ -148,6 +148,9 @@ func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
continue
}
if field.encoder.IsEmbeddedPtrNil(ptr) {
continue
}
if isNotFirst {
stream.WriteMore()
}
@ -156,23 +159,8 @@ func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
isNotFirst = true
}
stream.WriteObjectEnd()
}
func (encoder *structEncoder) EncodeInterface(val interface{}, stream *Stream) {
e := (*emptyInterface)(unsafe.Pointer(&val))
if encoder.onePtrOptimization {
if e.word == nil && encoder.onePtrEmbedded {
stream.WriteObjectStart()
stream.WriteObjectEnd()
return
}
ptr := uintptr(e.word)
e.word = unsafe.Pointer(&ptr)
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error())
}
}
@ -187,10 +175,36 @@ func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteEmptyObject()
}
func (encoder *emptyStructEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type stringModeNumberEncoder struct {
elemEncoder ValEncoder
}
func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.writeByte('"')
encoder.elemEncoder.Encode(ptr, stream)
stream.writeByte('"')
}
func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.elemEncoder.IsEmpty(ptr)
}
type stringModeStringEncoder struct {
elemEncoder ValEncoder
cfg *frozenConfig
}
func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
tempStream := encoder.cfg.BorrowStream(nil)
defer encoder.cfg.ReturnStream(tempStream)
encoder.elemEncoder.Encode(ptr, tempStream)
stream.WriteString(string(tempStream.Buffer()))
}
func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.elemEncoder.IsEmpty(ptr)
}

View file

@ -10,7 +10,6 @@ type Stream struct {
cfg *frozenConfig
out io.Writer
buf []byte
n int
Error error
indention int
Attachment interface{} // open for customized encoder
@ -24,8 +23,7 @@ func NewStream(cfg API, out io.Writer, bufSize int) *Stream {
return &Stream{
cfg: cfg.(*frozenConfig),
out: out,
buf: make([]byte, bufSize),
n: 0,
buf: make([]byte, 0, bufSize),
Error: nil,
indention: 0,
}
@ -39,22 +37,22 @@ func (stream *Stream) Pool() StreamPool {
// Reset reuse this stream instance by assign a new writer
func (stream *Stream) Reset(out io.Writer) {
stream.out = out
stream.n = 0
stream.buf = stream.buf[:0]
}
// Available returns how many bytes are unused in the buffer.
func (stream *Stream) Available() int {
return len(stream.buf) - stream.n
return cap(stream.buf) - len(stream.buf)
}
// Buffered returns the number of bytes that have been written into the current buffer.
func (stream *Stream) Buffered() int {
return stream.n
return len(stream.buf)
}
// Buffer if writer is nil, use this method to take the result
func (stream *Stream) Buffer() []byte {
return stream.buf[:stream.n]
return stream.buf
}
// Write writes the contents of p into the buffer.
@ -62,97 +60,34 @@ func (stream *Stream) Buffer() []byte {
// If nn < len(p), it also returns an error explaining
// why the write is short.
func (stream *Stream) Write(p []byte) (nn int, err error) {
for len(p) > stream.Available() && stream.Error == nil {
if stream.out == nil {
stream.growAtLeast(len(p))
} else {
var n int
if stream.Buffered() == 0 {
// Large write, empty buffer.
// Write directly from p to avoid copy.
n, stream.Error = stream.out.Write(p)
} else {
n = copy(stream.buf[stream.n:], p)
stream.n += n
stream.Flush()
}
nn += n
p = p[n:]
}
stream.buf = append(stream.buf, p...)
if stream.out != nil {
nn, err = stream.out.Write(stream.buf)
stream.buf = stream.buf[nn:]
return
}
if stream.Error != nil {
return nn, stream.Error
}
n := copy(stream.buf[stream.n:], p)
stream.n += n
nn += n
return nn, nil
return len(p), nil
}
// WriteByte writes a single byte.
func (stream *Stream) writeByte(c byte) {
if stream.Error != nil {
return
}
if stream.Available() < 1 {
stream.growAtLeast(1)
}
stream.buf[stream.n] = c
stream.n++
stream.buf = append(stream.buf, c)
}
func (stream *Stream) writeTwoBytes(c1 byte, c2 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 2 {
stream.growAtLeast(2)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.n += 2
stream.buf = append(stream.buf, c1, c2)
}
func (stream *Stream) writeThreeBytes(c1 byte, c2 byte, c3 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 3 {
stream.growAtLeast(3)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.buf[stream.n+2] = c3
stream.n += 3
stream.buf = append(stream.buf, c1, c2, c3)
}
func (stream *Stream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 4 {
stream.growAtLeast(4)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.buf[stream.n+2] = c3
stream.buf[stream.n+3] = c4
stream.n += 4
stream.buf = append(stream.buf, c1, c2, c3, c4)
}
func (stream *Stream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) {
if stream.Error != nil {
return
}
if stream.Available() < 5 {
stream.growAtLeast(5)
}
stream.buf[stream.n] = c1
stream.buf[stream.n+1] = c2
stream.buf[stream.n+2] = c3
stream.buf[stream.n+3] = c4
stream.buf[stream.n+4] = c5
stream.n += 5
stream.buf = append(stream.buf, c1, c2, c3, c4, c5)
}
// Flush writes any buffered data to the underlying io.Writer.
@ -163,56 +98,20 @@ func (stream *Stream) Flush() error {
if stream.Error != nil {
return stream.Error
}
if stream.n == 0 {
return nil
}
n, err := stream.out.Write(stream.buf[0:stream.n])
if n < stream.n && err == nil {
err = io.ErrShortWrite
}
n, err := stream.out.Write(stream.buf)
if err != nil {
if n > 0 && n < stream.n {
copy(stream.buf[0:stream.n-n], stream.buf[n:stream.n])
if stream.Error == nil {
stream.Error = err
}
stream.n -= n
stream.Error = err
return err
}
stream.n = 0
stream.buf = stream.buf[n:]
return nil
}
func (stream *Stream) ensure(minimal int) {
available := stream.Available()
if available < minimal {
stream.growAtLeast(minimal)
}
}
func (stream *Stream) growAtLeast(minimal int) {
if stream.out != nil {
stream.Flush()
if stream.Available() >= minimal {
return
}
}
toGrow := len(stream.buf)
if toGrow < minimal {
toGrow = minimal
}
newBuf := make([]byte, len(stream.buf)+toGrow)
copy(newBuf, stream.Buffer())
stream.buf = newBuf
}
// WriteRaw write string out without quotes, just like []byte
func (stream *Stream) WriteRaw(s string) {
stream.ensure(len(s))
if stream.Error != nil {
return
}
n := copy(stream.buf[stream.n:], s)
stream.n += n
stream.buf = append(stream.buf, s...)
}
// WriteNil write null to stream
@ -273,6 +172,7 @@ func (stream *Stream) WriteEmptyObject() {
func (stream *Stream) WriteMore() {
stream.writeByte(',')
stream.writeIndention(0)
stream.Flush()
}
// WriteArrayStart write [ with possible indention
@ -300,9 +200,7 @@ func (stream *Stream) writeIndention(delta int) {
}
stream.writeByte('\n')
toWrite := stream.indention - delta
stream.ensure(toWrite)
for i := 0; i < toWrite && stream.n < len(stream.buf); i++ {
stream.buf[stream.n] = ' '
stream.n++
for i := 0; i < toWrite; i++ {
stream.buf = append(stream.buf, ' ')
}
}

View file

@ -21,7 +21,7 @@ func (stream *Stream) WriteFloat32(val float32) {
fmt = 'e'
}
}
stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 32))
stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 32)
}
// WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster
@ -43,13 +43,12 @@ func (stream *Stream) WriteFloat32Lossy(val float32) {
return
}
stream.writeByte('.')
stream.ensure(10)
for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
stream.writeByte('0')
}
stream.WriteUint64(fval)
for stream.buf[stream.n-1] == '0' {
stream.n--
for stream.buf[len(stream.buf)-1] == '0' {
stream.buf = stream.buf[:len(stream.buf)-1]
}
}
@ -63,7 +62,7 @@ func (stream *Stream) WriteFloat64(val float64) {
fmt = 'e'
}
}
stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 64))
stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 64)
}
// WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster
@ -85,12 +84,11 @@ func (stream *Stream) WriteFloat64Lossy(val float64) {
return
}
stream.writeByte('.')
stream.ensure(10)
for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
stream.writeByte('0')
}
stream.WriteUint64(fval)
for stream.buf[stream.n-1] == '0' {
stream.n--
for stream.buf[len(stream.buf)-1] == '0' {
stream.buf = stream.buf[:len(stream.buf)-1]
}
}

190
vendor/github.com/json-iterator/go/stream_int.go generated vendored Normal file
View file

@ -0,0 +1,190 @@
package jsoniter
var digits []uint32
func init() {
digits = make([]uint32, 1000)
for i := uint32(0); i < 1000; i++ {
digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0'
if i < 10 {
digits[i] += 2 << 24
} else if i < 100 {
digits[i] += 1 << 24
}
}
}
func writeFirstBuf(space []byte, v uint32) []byte {
start := v >> 24
if start == 0 {
space = append(space, byte(v >> 16), byte(v >> 8))
} else if start == 1 {
space = append(space, byte(v >> 8))
}
space = append(space, byte(v))
return space
}
func writeBuf(buf []byte, v uint32) []byte {
return append(buf, byte(v >> 16), byte(v >> 8), byte(v))
}
// WriteUint8 write uint8 to stream
func (stream *Stream) WriteUint8(val uint8) {
stream.buf = writeFirstBuf(stream.buf, digits[val])
}
// WriteInt8 write int8 to stream
func (stream *Stream) WriteInt8(nval int8) {
var val uint8
if nval < 0 {
val = uint8(-nval)
stream.buf = append(stream.buf, '-')
} else {
val = uint8(nval)
}
stream.buf = writeFirstBuf(stream.buf, digits[val])
}
// WriteUint16 write uint16 to stream
func (stream *Stream) WriteUint16(val uint16) {
q1 := val / 1000
if q1 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[val])
return
}
r1 := val - q1*1000
stream.buf = writeFirstBuf(stream.buf, digits[q1])
stream.buf = writeBuf(stream.buf, digits[r1])
return
}
// WriteInt16 write int16 to stream
func (stream *Stream) WriteInt16(nval int16) {
var val uint16
if nval < 0 {
val = uint16(-nval)
stream.buf = append(stream.buf, '-')
} else {
val = uint16(nval)
}
stream.WriteUint16(val)
}
// WriteUint32 write uint32 to stream
func (stream *Stream) WriteUint32(val uint32) {
q1 := val / 1000
if q1 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[val])
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[q1])
stream.buf = writeBuf(stream.buf, digits[r1])
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[q2])
} else {
r3 := q2 - q3*1000
stream.buf = append(stream.buf, byte(q3 + '0'))
stream.buf = writeBuf(stream.buf, digits[r3])
}
stream.buf = writeBuf(stream.buf, digits[r2])
stream.buf = writeBuf(stream.buf, digits[r1])
}
// WriteInt32 write int32 to stream
func (stream *Stream) WriteInt32(nval int32) {
var val uint32
if nval < 0 {
val = uint32(-nval)
stream.buf = append(stream.buf, '-')
} else {
val = uint32(nval)
}
stream.WriteUint32(val)
}
// WriteUint64 write uint64 to stream
func (stream *Stream) WriteUint64(val uint64) {
q1 := val / 1000
if q1 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[val])
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[q1])
stream.buf = writeBuf(stream.buf, digits[r1])
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[q2])
stream.buf = writeBuf(stream.buf, digits[r2])
stream.buf = writeBuf(stream.buf, digits[r1])
return
}
r3 := q2 - q3*1000
q4 := q3 / 1000
if q4 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[q3])
stream.buf = writeBuf(stream.buf, digits[r3])
stream.buf = writeBuf(stream.buf, digits[r2])
stream.buf = writeBuf(stream.buf, digits[r1])
return
}
r4 := q3 - q4*1000
q5 := q4 / 1000
if q5 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[q4])
stream.buf = writeBuf(stream.buf, digits[r4])
stream.buf = writeBuf(stream.buf, digits[r3])
stream.buf = writeBuf(stream.buf, digits[r2])
stream.buf = writeBuf(stream.buf, digits[r1])
return
}
r5 := q4 - q5*1000
q6 := q5 / 1000
if q6 == 0 {
stream.buf = writeFirstBuf(stream.buf, digits[q5])
} else {
stream.buf = writeFirstBuf(stream.buf, digits[q6])
r6 := q5 - q6*1000
stream.buf = writeBuf(stream.buf, digits[r6])
}
stream.buf = writeBuf(stream.buf, digits[r5])
stream.buf = writeBuf(stream.buf, digits[r4])
stream.buf = writeBuf(stream.buf, digits[r3])
stream.buf = writeBuf(stream.buf, digits[r2])
stream.buf = writeBuf(stream.buf, digits[r1])
}
// WriteInt64 write int64 to stream
func (stream *Stream) WriteInt64(nval int64) {
var val uint64
if nval < 0 {
val = uint64(-nval)
stream.buf = append(stream.buf, '-')
} else {
val = uint64(nval)
}
stream.WriteUint64(val)
}
// WriteInt write int to stream
func (stream *Stream) WriteInt(val int) {
stream.WriteInt64(int64(val))
}
// WriteUint write uint to stream
func (stream *Stream) WriteUint(val uint) {
stream.WriteUint64(uint64(val))
}

View file

@ -219,34 +219,22 @@ var hex = "0123456789abcdef"
// WriteStringWithHTMLEscaped write string to stream with html special characters escaped
func (stream *Stream) WriteStringWithHTMLEscaped(s string) {
stream.ensure(32)
valLen := len(s)
toWriteLen := valLen
bufLengthMinusTwo := len(stream.buf) - 2 // make room for the quotes
if stream.n+toWriteLen > bufLengthMinusTwo {
toWriteLen = bufLengthMinusTwo - stream.n
}
n := stream.n
stream.buf[n] = '"'
n++
stream.buf = append(stream.buf, '"')
// write string, the fast path, without utf8 and escape support
i := 0
for ; i < toWriteLen; i++ {
for ; i < valLen; i++ {
c := s[i]
if c < utf8.RuneSelf && htmlSafeSet[c] {
stream.buf[n] = c
n++
stream.buf = append(stream.buf, c)
} else {
break
}
}
if i == valLen {
stream.buf[n] = '"'
n++
stream.n = n
stream.buf = append(stream.buf, '"')
return
}
stream.n = n
writeStringSlowPathWithHTMLEscaped(stream, i, s, valLen)
}
@ -321,34 +309,22 @@ func writeStringSlowPathWithHTMLEscaped(stream *Stream, i int, s string, valLen
// WriteString write string to stream without html escape
func (stream *Stream) WriteString(s string) {
stream.ensure(32)
valLen := len(s)
toWriteLen := valLen
bufLengthMinusTwo := len(stream.buf) - 2 // make room for the quotes
if stream.n+toWriteLen > bufLengthMinusTwo {
toWriteLen = bufLengthMinusTwo - stream.n
}
n := stream.n
stream.buf[n] = '"'
n++
stream.buf = append(stream.buf, '"')
// write string, the fast path, without utf8 and escape support
i := 0
for ; i < toWriteLen; i++ {
for ; i < valLen; i++ {
c := s[i]
if c > 31 && c != '"' && c != '\\' {
stream.buf[n] = c
n++
stream.buf = append(stream.buf, c)
} else {
break
}
}
if i == valLen {
stream.buf[n] = '"'
n++
stream.n = n
stream.buf = append(stream.buf, '"')
return
}
stream.n = n
writeStringSlowPath(stream, i, s, valLen)
}

View file

@ -23,10 +23,10 @@ func Test_writeBytes_should_grow_buffer(t *testing.T) {
stream := NewStream(ConfigDefault, nil, 1)
stream.Write([]byte{'1', '2'})
should.Equal("12", string(stream.Buffer()))
should.Equal(3, len(stream.buf))
should.Equal(2, len(stream.buf))
stream.Write([]byte{'3', '4', '5', '6', '7'})
should.Equal("1234567", string(stream.Buffer()))
should.Equal(8, len(stream.buf))
should.Equal(7, len(stream.buf))
}
func Test_writeIndention_should_grow_buffer(t *testing.T) {
@ -65,5 +65,5 @@ func Test_flush_buffer_should_stop_grow_buffer(t *testing.T) {
writer := new(NopWriter)
NewEncoder(writer).Encode(make([]int, 10000000))
should := require.New(t)
should.Equal(512, writer.bufferSize)
should.Equal(8, writer.bufferSize)
}

View file

@ -4,7 +4,7 @@ set -e
echo "" > coverage.txt
for d in $(go list ./... | grep -v vendor); do
go test -coverprofile=profile.out $d
go test -coverprofile=profile.out -coverpkg=github.com/json-iterator/go $d
if [ -f profile.out ]; then
cat profile.out >> coverage.txt
rm profile.out

View file

@ -1,72 +0,0 @@
package jsoniter
import (
"encoding/json"
"reflect"
"testing"
fuzz "github.com/google/gofuzz"
)
func Test_NilInput(t *testing.T) {
var jb []byte // nil
var out string
err := Unmarshal(jb, &out)
if err == nil {
t.Errorf("Expected error")
}
}
func Test_EmptyInput(t *testing.T) {
jb := []byte("")
var out string
err := Unmarshal(jb, &out)
if err == nil {
t.Errorf("Expected error")
}
}
func Test_RandomInput_Bytes(t *testing.T) {
fz := fuzz.New().NilChance(0)
for i := 0; i < 10000; i++ {
var jb []byte
fz.Fuzz(&jb)
testRandomInput(t, jb)
}
}
func Test_RandomInput_String(t *testing.T) {
fz := fuzz.New().NilChance(0)
for i := 0; i < 10000; i++ {
var js string
fz.Fuzz(&js)
jb := []byte(js)
testRandomInput(t, jb)
}
}
func testRandomInput(t *testing.T, jb []byte) {
var outString string
testRandomInputTo(t, jb, &outString)
var outInt int
testRandomInputTo(t, jb, &outInt)
var outStruct struct{}
testRandomInputTo(t, jb, &outStruct)
var outSlice []string
testRandomInputTo(t, jb, &outSlice)
}
func testRandomInputTo(t *testing.T, jb []byte, out interface{}) {
err := Unmarshal(jb, out)
if err == nil {
// Cross-check stdlib to see if we just happened to fuzz a legit value.
err := json.Unmarshal(jb, out)
if err != nil {
t.Fatalf("Expected error unmarshaling as %s:\nas string: %q\nas bytes: %v",
reflect.TypeOf(out).Elem().Kind(), string(jb), jb)
}
}
}