forked from mirror/go-json
Merge pull request #238 from goccy/feature/refactor-decoder
Refactor package layout for decoder
This commit is contained in:
commit
7d7af9fb36
|
@ -191,7 +191,7 @@ For this reason, to date `reflect.Type` is the same as `*reflect.rtype`.
|
||||||
|
|
||||||
Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`.
|
Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`.
|
||||||
|
|
||||||
The technique for working with `*reflect.rtype` directly from `go-json` is implemented at https://github.com/goccy/go-json/blob/master/rtype.go.
|
The technique for working with `*reflect.rtype` directly from `go-json` is implemented at [rtype.go](https://github.com/goccy/go-json/blob/master/internal/runtime/rtype.go)
|
||||||
|
|
||||||
Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect )
|
Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect )
|
||||||
|
|
||||||
|
@ -352,7 +352,7 @@ However, if there is too much type information, it will use a lot of memory, so
|
||||||
|
|
||||||
If this approach is not available, it will fall back to the `atomic` based process described above.
|
If this approach is not available, it will fall back to the `atomic` based process described above.
|
||||||
|
|
||||||
If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/codec.go#L24-L76 )
|
If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/internal/runtime/type.go#L36-L100)
|
||||||
|
|
||||||
## Decoder
|
## Decoder
|
||||||
|
|
||||||
|
|
104
codec.go
104
codec.go
|
@ -1,104 +0,0 @@
|
||||||
package json
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"sync/atomic"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
maxAcceptableTypeAddrRange = 1024 * 1024 * 2 // 2 Mib
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
cachedDecoder []decoder
|
|
||||||
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
|
|
||||||
baseTypeAddr uintptr
|
|
||||||
maxTypeAddr uintptr
|
|
||||||
typeAddrShift uintptr
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:linkname typelinks reflect.typelinks
|
|
||||||
func typelinks() ([]unsafe.Pointer, [][]int32)
|
|
||||||
|
|
||||||
//go:linkname rtypeOff reflect.rtypeOff
|
|
||||||
func rtypeOff(unsafe.Pointer, int32) unsafe.Pointer
|
|
||||||
|
|
||||||
func setupCodec() error {
|
|
||||||
sections, offsets := typelinks()
|
|
||||||
if len(sections) != 1 {
|
|
||||||
return fmt.Errorf("failed to get sections")
|
|
||||||
}
|
|
||||||
if len(offsets) != 1 {
|
|
||||||
return fmt.Errorf("failed to get offsets")
|
|
||||||
}
|
|
||||||
section := sections[0]
|
|
||||||
offset := offsets[0]
|
|
||||||
var (
|
|
||||||
min uintptr = uintptr(^uint(0))
|
|
||||||
max uintptr = 0
|
|
||||||
isAligned64 = true
|
|
||||||
isAligned32 = true
|
|
||||||
)
|
|
||||||
for i := 0; i < len(offset); i++ {
|
|
||||||
typ := (*rtype)(rtypeOff(section, offset[i]))
|
|
||||||
addr := uintptr(unsafe.Pointer(typ))
|
|
||||||
if min > addr {
|
|
||||||
min = addr
|
|
||||||
}
|
|
||||||
if max < addr {
|
|
||||||
max = addr
|
|
||||||
}
|
|
||||||
if typ.Kind() == reflect.Ptr {
|
|
||||||
addr = uintptr(unsafe.Pointer(typ.Elem()))
|
|
||||||
if min > addr {
|
|
||||||
min = addr
|
|
||||||
}
|
|
||||||
if max < addr {
|
|
||||||
max = addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check every address is aligned from the base address
|
|
||||||
isAligned64 = isAligned64 && (addr-min)&63 == 0
|
|
||||||
isAligned32 = isAligned32 && (addr-min)&31 == 0
|
|
||||||
}
|
|
||||||
addrRange := max - min
|
|
||||||
if addrRange == 0 {
|
|
||||||
return fmt.Errorf("failed to get address range of types")
|
|
||||||
}
|
|
||||||
if isAligned64 {
|
|
||||||
typeAddrShift = 6
|
|
||||||
} else if isAligned32 {
|
|
||||||
typeAddrShift = 5
|
|
||||||
}
|
|
||||||
cacheSize := addrRange >> typeAddrShift
|
|
||||||
if cacheSize > maxAcceptableTypeAddrRange {
|
|
||||||
return fmt.Errorf("too big address range %d", addrRange)
|
|
||||||
}
|
|
||||||
cachedDecoder = make([]decoder, cacheSize)
|
|
||||||
baseTypeAddr = min
|
|
||||||
maxTypeAddr = max
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
_ = setupCodec()
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadDecoderMap() map[uintptr]decoder {
|
|
||||||
p := atomic.LoadPointer(&cachedDecoderMap)
|
|
||||||
return *(*map[uintptr]decoder)(unsafe.Pointer(&p))
|
|
||||||
}
|
|
||||||
|
|
||||||
func storeDecoder(typ uintptr, dec decoder, m map[uintptr]decoder) {
|
|
||||||
newDecoderMap := make(map[uintptr]decoder, len(m)+1)
|
|
||||||
newDecoderMap[typ] = dec
|
|
||||||
|
|
||||||
for k, v := range m {
|
|
||||||
newDecoderMap[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap)))
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
// +build go1.16
|
|
||||||
|
|
||||||
package json
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTypeAddressAligned32(t *testing.T) {
|
|
||||||
if typeAddrShift != 5 {
|
|
||||||
t.Fatalf("unexpected type address shift %d, want 5", typeAddrShift)
|
|
||||||
}
|
|
||||||
}
|
|
150
decode.go
150
decode.go
|
@ -1,33 +1,29 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
|
||||||
|
|
||||||
type decoder interface {
|
"github.com/goccy/go-json/internal/decoder"
|
||||||
decode([]byte, int64, int64, unsafe.Pointer) (int64, error)
|
"github.com/goccy/go-json/internal/errors"
|
||||||
decodeStream(*stream, int64, unsafe.Pointer) error
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
}
|
)
|
||||||
|
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
s *stream
|
s *decoder.Stream
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
unmarshalJSONType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
|
||||||
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
nul = '\000'
|
nul = '\000'
|
||||||
maxDecodeNestingDepth = 10000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type emptyInterface struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
ptr unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
func unmarshal(data []byte, v interface{}) error {
|
func unmarshal(data []byte, v interface{}) error {
|
||||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||||
copy(src, data)
|
copy(src, data)
|
||||||
|
@ -37,11 +33,11 @@ func unmarshal(data []byte, v interface{}) error {
|
||||||
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dec, err := decodeCompileToGetDecoder(header.typ)
|
dec, err := decoder.CompileToGetDecoder(header.typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cursor, err := dec.decode(src, 0, 0, header.ptr)
|
cursor, err := dec.Decode(src, 0, 0, header.ptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -57,11 +53,11 @@ func unmarshalNoEscape(data []byte, v interface{}) error {
|
||||||
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dec, err := decodeCompileToGetDecoder(header.typ)
|
dec, err := decoder.CompileToGetDecoder(header.typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cursor, err := dec.decode(src, 0, 0, noescape(header.ptr))
|
cursor, err := dec.Decode(src, 0, 0, noescape(header.ptr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -77,7 +73,7 @@ func validateEndBuf(src []byte, cursor int64) error {
|
||||||
case nul:
|
case nul:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errSyntax(
|
return errors.ErrSyntax(
|
||||||
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
|
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
|
||||||
cursor+1,
|
cursor+1,
|
||||||
)
|
)
|
||||||
|
@ -91,9 +87,9 @@ func noescape(p unsafe.Pointer) unsafe.Pointer {
|
||||||
return unsafe.Pointer(x ^ 0)
|
return unsafe.Pointer(x ^ 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateType(typ *rtype, p uintptr) error {
|
func validateType(typ *runtime.Type, p uintptr) error {
|
||||||
if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
|
if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
|
||||||
return &InvalidUnmarshalError{Type: rtype2type(typ)}
|
return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -103,7 +99,7 @@ func validateType(typ *rtype, p uintptr) error {
|
||||||
// The decoder introduces its own buffering and may
|
// The decoder introduces its own buffering and may
|
||||||
// read data from r beyond the JSON values requested.
|
// read data from r beyond the JSON values requested.
|
||||||
func NewDecoder(r io.Reader) *Decoder {
|
func NewDecoder(r io.Reader) *Decoder {
|
||||||
s := newStream(r)
|
s := decoder.NewStream(r)
|
||||||
return &Decoder{
|
return &Decoder{
|
||||||
s: s,
|
s: s,
|
||||||
}
|
}
|
||||||
|
@ -112,28 +108,7 @@ func NewDecoder(r io.Reader) *Decoder {
|
||||||
// Buffered returns a reader of the data remaining in the Decoder's
|
// Buffered returns a reader of the data remaining in the Decoder's
|
||||||
// buffer. The reader is valid until the next call to Decode.
|
// buffer. The reader is valid until the next call to Decode.
|
||||||
func (d *Decoder) Buffered() io.Reader {
|
func (d *Decoder) Buffered() io.Reader {
|
||||||
return d.s.buffered()
|
return d.s.Buffered()
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) prepareForDecode() error {
|
|
||||||
s := d.s
|
|
||||||
for {
|
|
||||||
switch s.char() {
|
|
||||||
case ' ', '\t', '\r', '\n':
|
|
||||||
s.cursor++
|
|
||||||
continue
|
|
||||||
case ',', ':':
|
|
||||||
s.cursor++
|
|
||||||
return nil
|
|
||||||
case nul:
|
|
||||||
if s.read() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return io.EOF
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode reads the next JSON-encoded value from its
|
// Decode reads the next JSON-encoded value from its
|
||||||
|
@ -147,115 +122,48 @@ func (d *Decoder) Decode(v interface{}) error {
|
||||||
ptr := uintptr(header.ptr)
|
ptr := uintptr(header.ptr)
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
// noescape trick for header.typ ( reflect.*rtype )
|
// noescape trick for header.typ ( reflect.*rtype )
|
||||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
||||||
|
|
||||||
if err := validateType(copiedType, ptr); err != nil {
|
if err := validateType(copiedType, ptr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dec, err := decodeCompileToGetDecoder(typ)
|
dec, err := decoder.CompileToGetDecoder(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := d.prepareForDecode(); err != nil {
|
if err := d.s.PrepareForDecode(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s := d.s
|
s := d.s
|
||||||
if err := dec.decodeStream(s, 0, header.ptr); err != nil {
|
if err := dec.DecodeStream(s, 0, header.ptr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.reset()
|
s.Reset()
|
||||||
s.bufSize = initBufSize
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) More() bool {
|
func (d *Decoder) More() bool {
|
||||||
s := d.s
|
return d.s.More()
|
||||||
for {
|
|
||||||
switch s.char() {
|
|
||||||
case ' ', '\n', '\r', '\t':
|
|
||||||
s.cursor++
|
|
||||||
continue
|
|
||||||
case '}', ']':
|
|
||||||
return false
|
|
||||||
case nul:
|
|
||||||
if s.read() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) Token() (Token, error) {
|
func (d *Decoder) Token() (Token, error) {
|
||||||
s := d.s
|
return d.s.Token()
|
||||||
for {
|
|
||||||
c := s.char()
|
|
||||||
switch c {
|
|
||||||
case ' ', '\n', '\r', '\t':
|
|
||||||
s.cursor++
|
|
||||||
case '{', '[', ']', '}':
|
|
||||||
s.cursor++
|
|
||||||
return Delim(c), nil
|
|
||||||
case ',', ':':
|
|
||||||
s.cursor++
|
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
|
||||||
bytes := floatBytes(s)
|
|
||||||
s := *(*string)(unsafe.Pointer(&bytes))
|
|
||||||
f64, err := strconv.ParseFloat(s, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return f64, nil
|
|
||||||
case '"':
|
|
||||||
bytes, err := stringBytes(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return string(bytes), nil
|
|
||||||
case 't':
|
|
||||||
if err := trueBytes(s); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
case 'f':
|
|
||||||
if err := falseBytes(s); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
case 'n':
|
|
||||||
if err := nullBytes(s); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
case nul:
|
|
||||||
if s.read() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
goto END
|
|
||||||
default:
|
|
||||||
return nil, errInvalidCharacter(s.char(), "token", s.totalOffset())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
END:
|
|
||||||
return nil, io.EOF
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisallowUnknownFields causes the Decoder to return an error when the destination
|
// 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
|
// is a struct and the input contains object keys which do not match any
|
||||||
// non-ignored, exported fields in the destination.
|
// non-ignored, exported fields in the destination.
|
||||||
func (d *Decoder) DisallowUnknownFields() {
|
func (d *Decoder) DisallowUnknownFields() {
|
||||||
d.s.disallowUnknownFields = true
|
d.s.DisallowUnknownFields = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) InputOffset() int64 {
|
func (d *Decoder) InputOffset() int64 {
|
||||||
return d.s.totalOffset()
|
return d.s.TotalOffset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
||||||
// Number instead of as a float64.
|
// Number instead of as a float64.
|
||||||
func (d *Decoder) UseNumber() {
|
func (d *Decoder) UseNumber() {
|
||||||
d.s.useNumber = true
|
d.s.UseNumber = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
// +build !race
|
|
||||||
|
|
||||||
package json
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
|
||||||
if typeptr > maxTypeAddr {
|
|
||||||
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
|
|
||||||
}
|
|
||||||
|
|
||||||
index := (typeptr - baseTypeAddr) >> typeAddrShift
|
|
||||||
if dec := cachedDecoder[index]; dec != nil {
|
|
||||||
return dec, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
dec, err := decodeCompileHead(typ, map[uintptr]decoder{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cachedDecoder[index] = dec
|
|
||||||
return dec, nil
|
|
||||||
}
|
|
10
error.go
10
error.go
|
@ -37,13 +37,3 @@ type UnmarshalTypeError = errors.UnmarshalTypeError
|
||||||
type UnsupportedTypeError = errors.UnsupportedTypeError
|
type UnsupportedTypeError = errors.UnsupportedTypeError
|
||||||
|
|
||||||
type UnsupportedValueError = errors.UnsupportedValueError
|
type UnsupportedValueError = errors.UnsupportedValueError
|
||||||
|
|
||||||
var (
|
|
||||||
errExceededMaxDepth = errors.ErrExceededMaxDepth
|
|
||||||
errNotAtBeginningOfValue = errors.ErrNotAtBeginningOfValue
|
|
||||||
errUnexpectedEndOfJSON = errors.ErrUnexpectedEndOfJSON
|
|
||||||
errExpected = errors.ErrExpected
|
|
||||||
errInvalidCharacter = errors.ErrInvalidCharacter
|
|
||||||
errSyntax = errors.ErrSyntax
|
|
||||||
errMarshaler = errors.ErrMarshaler
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
var (
|
import (
|
||||||
NewSyntaxError = errSyntax
|
"github.com/goccy/go-json/internal/errors"
|
||||||
NewMarshalerError = errMarshaler
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
NewSyntaxError = errors.ErrSyntax
|
||||||
|
NewMarshalerError = errors.ErrMarshaler
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type anonymousFieldDecoder struct {
|
type anonymousFieldDecoder struct {
|
||||||
structType *rtype
|
structType *runtime.Type
|
||||||
offset uintptr
|
offset uintptr
|
||||||
dec decoder
|
dec Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAnonymousFieldDecoder(structType *rtype, offset uintptr, dec decoder) *anonymousFieldDecoder {
|
func newAnonymousFieldDecoder(structType *runtime.Type, offset uintptr, dec Decoder) *anonymousFieldDecoder {
|
||||||
return &anonymousFieldDecoder{
|
return &anonymousFieldDecoder{
|
||||||
structType: structType,
|
structType: structType,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
|
@ -18,18 +20,18 @@ func newAnonymousFieldDecoder(structType *rtype, offset uintptr, dec decoder) *a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *anonymousFieldDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *anonymousFieldDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
if *(*unsafe.Pointer)(p) == nil {
|
if *(*unsafe.Pointer)(p) == nil {
|
||||||
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
|
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
|
||||||
}
|
}
|
||||||
p = *(*unsafe.Pointer)(p)
|
p = *(*unsafe.Pointer)(p)
|
||||||
return d.dec.decodeStream(s, depth, unsafe.Pointer(uintptr(p)+d.offset))
|
return d.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+d.offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *anonymousFieldDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *anonymousFieldDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
if *(*unsafe.Pointer)(p) == nil {
|
if *(*unsafe.Pointer)(p) == nil {
|
||||||
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
|
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
|
||||||
}
|
}
|
||||||
p = *(*unsafe.Pointer)(p)
|
p = *(*unsafe.Pointer)(p)
|
||||||
return d.dec.decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
|
return d.dec.Decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
|
||||||
}
|
}
|
|
@ -1,20 +1,23 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type arrayDecoder struct {
|
type arrayDecoder struct {
|
||||||
elemType *rtype
|
elemType *runtime.Type
|
||||||
size uintptr
|
size uintptr
|
||||||
valueDecoder decoder
|
valueDecoder Decoder
|
||||||
alen int
|
alen int
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
zeroValue unsafe.Pointer
|
zeroValue unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayDecoder(dec decoder, elemType *rtype, alen int, structName, fieldName string) *arrayDecoder {
|
func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
|
||||||
zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
|
zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
|
||||||
return &arrayDecoder{
|
return &arrayDecoder{
|
||||||
valueDecoder: dec,
|
valueDecoder: dec,
|
||||||
|
@ -27,10 +30,10 @@ func newArrayDecoder(dec decoder, elemType *rtype, alen int, structName, fieldNa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -46,7 +49,7 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
||||||
for {
|
for {
|
||||||
s.cursor++
|
s.cursor++
|
||||||
if idx < d.alen {
|
if idx < d.alen {
|
||||||
if err := d.valueDecoder.decodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
|
if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -86,13 +89,13 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
||||||
s.cursor++
|
s.cursor++
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return errUnexpectedEndOfJSON("array", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *arrayDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -111,7 +114,7 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
||||||
for {
|
for {
|
||||||
cursor++
|
cursor++
|
||||||
if idx < d.alen {
|
if idx < d.alen {
|
||||||
c, err := d.valueDecoder.decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
|
c, err := d.valueDecoder.Decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -136,11 +139,11 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
||||||
case ',':
|
case ',':
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
return 0, errInvalidCharacter(buf[cursor], "array", cursor)
|
return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 0, errUnexpectedEndOfJSON("array", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type boolDecoder struct {
|
type boolDecoder struct {
|
||||||
|
@ -13,7 +15,7 @@ func newBoolDecoder(structName, fieldName string) *boolDecoder {
|
||||||
return &boolDecoder{structName: structName, fieldName: fieldName}
|
return &boolDecoder{structName: structName, fieldName: fieldName}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
|
@ -43,10 +45,10 @@ func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return errUnexpectedEndOfJSON("bool", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("bool", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *boolDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
switch buf[cursor] {
|
switch buf[cursor] {
|
||||||
case 't':
|
case 't':
|
||||||
|
@ -70,5 +72,5 @@ func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
||||||
cursor += 4
|
cursor += 4
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
return 0, errUnexpectedEndOfJSON("bool", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
|
||||||
}
|
}
|
|
@ -1,24 +1,27 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bytesDecoder struct {
|
type bytesDecoder struct {
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
sliceDecoder decoder
|
sliceDecoder Decoder
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func byteUnmarshalerSliceDecoder(typ *rtype, structName string, fieldName string) decoder {
|
func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder {
|
||||||
var unmarshalDecoder decoder
|
var unmarshalDecoder Decoder
|
||||||
switch {
|
switch {
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||||
unmarshalDecoder = newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName)
|
unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||||
unmarshalDecoder = newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName)
|
unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
|
||||||
}
|
}
|
||||||
if unmarshalDecoder == nil {
|
if unmarshalDecoder == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -26,7 +29,7 @@ func byteUnmarshalerSliceDecoder(typ *rtype, structName string, fieldName string
|
||||||
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
|
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBytesDecoder(typ *rtype, structName string, fieldName string) *bytesDecoder {
|
func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder {
|
||||||
return &bytesDecoder{
|
return &bytesDecoder{
|
||||||
typ: typ,
|
typ: typ,
|
||||||
sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName),
|
sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName),
|
||||||
|
@ -35,7 +38,7 @@ func newBytesDecoder(typ *rtype, structName string, fieldName string) *bytesDeco
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bytesDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *bytesDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
bytes, err := d.decodeStreamBinary(s, depth, p)
|
bytes, err := d.decodeStreamBinary(s, depth, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -54,7 +57,7 @@ func (d *bytesDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bytesDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *bytesDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
bytes, c, err := d.decodeBinary(buf, cursor, depth, p)
|
bytes, c, err := d.decodeBinary(buf, cursor, depth, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -73,7 +76,7 @@ func (d *bytesDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func binaryBytes(s *stream) ([]byte, error) {
|
func binaryBytes(s *Stream) ([]byte, error) {
|
||||||
s.cursor++
|
s.cursor++
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
for {
|
for {
|
||||||
|
@ -91,10 +94,10 @@ func binaryBytes(s *stream) ([]byte, error) {
|
||||||
s.cursor++
|
s.cursor++
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return nil, errUnexpectedEndOfJSON("[]byte", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("[]byte", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Pointer) ([]byte, error) {
|
func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case ' ', '\n', '\t', '\r':
|
case ' ', '\n', '\t', '\r':
|
||||||
|
@ -109,12 +112,12 @@ func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Point
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case '[':
|
case '[':
|
||||||
if d.sliceDecoder == nil {
|
if d.sliceDecoder == nil {
|
||||||
return nil, &UnmarshalTypeError{
|
return nil, &errors.UnmarshalTypeError{
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: s.totalOffset(),
|
Offset: s.totalOffset(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := d.sliceDecoder.decodeStream(s, depth, p); err != nil {
|
if err := d.sliceDecoder.DecodeStream(s, depth, p); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -125,7 +128,7 @@ func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Point
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return nil, errNotAtBeginningOfValue(s.totalOffset())
|
return nil, errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
|
func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
|
||||||
|
@ -143,18 +146,18 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Po
|
||||||
cursor++
|
cursor++
|
||||||
return literal, cursor, nil
|
return literal, cursor, nil
|
||||||
case nul:
|
case nul:
|
||||||
return nil, 0, errUnexpectedEndOfJSON("[]byte", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("[]byte", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
case '[':
|
case '[':
|
||||||
if d.sliceDecoder == nil {
|
if d.sliceDecoder == nil {
|
||||||
return nil, 0, &UnmarshalTypeError{
|
return nil, 0, &errors.UnmarshalTypeError{
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: cursor,
|
Offset: cursor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c, err := d.sliceDecoder.decode(buf, cursor, depth, p)
|
c, err := d.sliceDecoder.Decode(buf, cursor, depth, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
@ -166,7 +169,7 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Po
|
||||||
cursor += 4
|
cursor += 4
|
||||||
return nil, cursor, nil
|
return nil, cursor, nil
|
||||||
default:
|
default:
|
||||||
return nil, 0, errNotAtBeginningOfValue(cursor)
|
return nil, 0, errors.ErrNotAtBeginningOfValue(cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,27 +1,56 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||||
|
typeAddr *runtime.TypeAddr
|
||||||
|
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
|
||||||
|
cachedDecoder []Decoder
|
||||||
)
|
)
|
||||||
|
|
||||||
func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, error) {
|
func init() {
|
||||||
|
typeAddr = runtime.AnalyzeTypeAddr()
|
||||||
|
if typeAddr == nil {
|
||||||
|
typeAddr = &runtime.TypeAddr{}
|
||||||
|
}
|
||||||
|
cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadDecoderMap() map[uintptr]Decoder {
|
||||||
|
p := atomic.LoadPointer(&cachedDecoderMap)
|
||||||
|
return *(*map[uintptr]Decoder)(unsafe.Pointer(&p))
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeDecoder(typ uintptr, dec Decoder, m map[uintptr]Decoder) {
|
||||||
|
newDecoderMap := make(map[uintptr]Decoder, len(m)+1)
|
||||||
|
newDecoderMap[typ] = dec
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
newDecoderMap[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func compileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (Decoder, error) {
|
||||||
decoderMap := loadDecoderMap()
|
decoderMap := loadDecoderMap()
|
||||||
if dec, exists := decoderMap[typeptr]; exists {
|
if dec, exists := decoderMap[typeptr]; exists {
|
||||||
return dec, nil
|
return dec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dec, err := decodeCompileHead(typ, map[uintptr]decoder{})
|
dec, err := compileHead(typ, map[uintptr]Decoder{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -29,84 +58,84 @@ func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, er
|
||||||
return dec, nil
|
return dec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileHead(typ *rtype, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
switch {
|
switch {
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil
|
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil
|
return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil
|
||||||
}
|
}
|
||||||
return decodeCompile(typ.Elem(), "", "", structTypeToDecoder)
|
return compile(typ.Elem(), "", "", structTypeToDecoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompile(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
switch {
|
switch {
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return decodeCompilePtr(typ, structName, fieldName, structTypeToDecoder)
|
return compilePtr(typ, structName, fieldName, structTypeToDecoder)
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return decodeCompileStruct(typ, structName, fieldName, structTypeToDecoder)
|
return compileStruct(typ, structName, fieldName, structTypeToDecoder)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
elem := typ.Elem()
|
elem := typ.Elem()
|
||||||
if elem.Kind() == reflect.Uint8 {
|
if elem.Kind() == reflect.Uint8 {
|
||||||
return decodeCompileBytes(elem, structName, fieldName)
|
return compileBytes(elem, structName, fieldName)
|
||||||
}
|
}
|
||||||
return decodeCompileSlice(typ, structName, fieldName, structTypeToDecoder)
|
return compileSlice(typ, structName, fieldName, structTypeToDecoder)
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
return decodeCompileArray(typ, structName, fieldName, structTypeToDecoder)
|
return compileArray(typ, structName, fieldName, structTypeToDecoder)
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return decodeCompileMap(typ, structName, fieldName, structTypeToDecoder)
|
return compileMap(typ, structName, fieldName, structTypeToDecoder)
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
return decodeCompileInterface(typ, structName, fieldName)
|
return compileInterface(typ, structName, fieldName)
|
||||||
case reflect.Uintptr:
|
case reflect.Uintptr:
|
||||||
return decodeCompileUint(typ, structName, fieldName)
|
return compileUint(typ, structName, fieldName)
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
return decodeCompileInt(typ, structName, fieldName)
|
return compileInt(typ, structName, fieldName)
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
return decodeCompileInt8(typ, structName, fieldName)
|
return compileInt8(typ, structName, fieldName)
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
return decodeCompileInt16(typ, structName, fieldName)
|
return compileInt16(typ, structName, fieldName)
|
||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
return decodeCompileInt32(typ, structName, fieldName)
|
return compileInt32(typ, structName, fieldName)
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
return decodeCompileInt64(typ, structName, fieldName)
|
return compileInt64(typ, structName, fieldName)
|
||||||
case reflect.Uint:
|
case reflect.Uint:
|
||||||
return decodeCompileUint(typ, structName, fieldName)
|
return compileUint(typ, structName, fieldName)
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
return decodeCompileUint8(typ, structName, fieldName)
|
return compileUint8(typ, structName, fieldName)
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
return decodeCompileUint16(typ, structName, fieldName)
|
return compileUint16(typ, structName, fieldName)
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
return decodeCompileUint32(typ, structName, fieldName)
|
return compileUint32(typ, structName, fieldName)
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
return decodeCompileUint64(typ, structName, fieldName)
|
return compileUint64(typ, structName, fieldName)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return decodeCompileString(typ, structName, fieldName)
|
return compileString(typ, structName, fieldName)
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return decodeCompileBool(structName, fieldName)
|
return compileBool(structName, fieldName)
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
return decodeCompileFloat32(structName, fieldName)
|
return compileFloat32(structName, fieldName)
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
return decodeCompileFloat64(structName, fieldName)
|
return compileFloat64(structName, fieldName)
|
||||||
}
|
}
|
||||||
return nil, &UnmarshalTypeError{
|
return nil, &errors.UnmarshalTypeError{
|
||||||
Value: "object",
|
Value: "object",
|
||||||
Type: rtype2type(typ),
|
Type: runtime.RType2Type(typ),
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isStringTagSupportedType(typ *rtype) bool {
|
func isStringTagSupportedType(typ *runtime.Type) bool {
|
||||||
switch {
|
switch {
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||||
return false
|
return false
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
|
@ -124,11 +153,11 @@ func isStringTagSupportedType(typ *rtype) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
if rtype_ptrTo(typ).Implements(unmarshalTextType) {
|
if runtime.PtrTo(typ).Implements(unmarshalTextType) {
|
||||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
||||||
}
|
}
|
||||||
dec, err := decodeCompile(typ, structName, fieldName, structTypeToDecoder)
|
dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -145,145 +174,145 @@ func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return nil, &UnmarshalTypeError{
|
return nil, &errors.UnmarshalTypeError{
|
||||||
Value: "object",
|
Value: "object",
|
||||||
Type: rtype2type(typ),
|
Type: runtime.RType2Type(typ),
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompilePtr(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
dec, err := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder)
|
dec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil
|
return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileInt(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileInt(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||||
*(*int)(p) = int(v)
|
*(*int)(p) = int(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileInt8(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileInt8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||||
*(*int8)(p) = int8(v)
|
*(*int8)(p) = int8(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileInt16(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileInt16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||||
*(*int16)(p) = int16(v)
|
*(*int16)(p) = int16(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileInt32(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileInt32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||||
*(*int32)(p) = int32(v)
|
*(*int32)(p) = int32(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileInt64(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileInt64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||||
*(*int64)(p) = v
|
*(*int64)(p) = v
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileUint(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileUint(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||||
*(*uint)(p) = uint(v)
|
*(*uint)(p) = uint(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileUint8(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileUint8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||||
*(*uint8)(p) = uint8(v)
|
*(*uint8)(p) = uint8(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileUint16(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileUint16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||||
*(*uint16)(p) = uint16(v)
|
*(*uint16)(p) = uint16(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileUint32(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileUint32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||||
*(*uint32)(p) = uint32(v)
|
*(*uint32)(p) = uint32(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileUint64(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileUint64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||||
*(*uint64)(p) = v
|
*(*uint64)(p) = v
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileFloat32(structName, fieldName string) (decoder, error) {
|
func compileFloat32(structName, fieldName string) (Decoder, error) {
|
||||||
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||||
*(*float32)(p) = float32(v)
|
*(*float32)(p) = float32(v)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileFloat64(structName, fieldName string) (decoder, error) {
|
func compileFloat64(structName, fieldName string) (Decoder, error) {
|
||||||
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||||
*(*float64)(p) = v
|
*(*float64)(p) = v
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileString(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileString(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
if typ == type2rtype(jsonNumberType) {
|
if typ == runtime.Type2RType(jsonNumberType) {
|
||||||
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
|
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
||||||
*(*Number)(p) = v
|
*(*json.Number)(p) = v
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
return newStringDecoder(structName, fieldName), nil
|
return newStringDecoder(structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileBool(structName, fieldName string) (decoder, error) {
|
func compileBool(structName, fieldName string) (Decoder, error) {
|
||||||
return newBoolDecoder(structName, fieldName), nil
|
return newBoolDecoder(structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileBytes(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileBytes(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newBytesDecoder(typ, structName, fieldName), nil
|
return newBytesDecoder(typ, structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileSlice(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
elem := typ.Elem()
|
elem := typ.Elem()
|
||||||
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
|
decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
|
return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileArray(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
elem := typ.Elem()
|
elem := typ.Elem()
|
||||||
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
|
decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
|
return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileMap(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
keyDec, err := decodeCompileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
|
keyDec, err := compileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
valueDec, err := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder)
|
valueDec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil
|
return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileInterface(typ *rtype, structName, fieldName string) (decoder, error) {
|
func compileInterface(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
|
||||||
return newInterfaceDecoder(typ, structName, fieldName), nil
|
return newInterfaceDecoder(typ, structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeRemoveConflictFields(fieldMap map[string]*structFieldSet, conflictedMap map[string]struct{}, dec *structDecoder, field reflect.StructField) {
|
func removeConflictFields(fieldMap map[string]*structFieldSet, conflictedMap map[string]struct{}, dec *structDecoder, field reflect.StructField) {
|
||||||
for k, v := range dec.fieldMap {
|
for k, v := range dec.fieldMap {
|
||||||
if _, exists := conflictedMap[k]; exists {
|
if _, exists := conflictedMap[k]; exists {
|
||||||
// already conflicted key
|
// already conflicted key
|
||||||
|
@ -338,7 +367,7 @@ func decodeRemoveConflictFields(fieldMap map[string]*structFieldSet, conflictedM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
|
||||||
fieldNum := typ.NumField()
|
fieldNum := typ.NumField()
|
||||||
conflictedMap := map[string]struct{}{}
|
conflictedMap := map[string]struct{}{}
|
||||||
fieldMap := map[string]*structFieldSet{}
|
fieldMap := map[string]*structFieldSet{}
|
||||||
|
@ -356,17 +385,17 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
|
||||||
}
|
}
|
||||||
isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
|
isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
|
||||||
tag := runtime.StructTagFromField(field)
|
tag := runtime.StructTagFromField(field)
|
||||||
dec, err := decodeCompile(type2rtype(field.Type), structName, field.Name, structTypeToDecoder)
|
dec, err := compile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if field.Anonymous && !tag.IsTaggedKey {
|
if field.Anonymous && !tag.IsTaggedKey {
|
||||||
if stDec, ok := dec.(*structDecoder); ok {
|
if stDec, ok := dec.(*structDecoder); ok {
|
||||||
if type2rtype(field.Type) == typ {
|
if runtime.Type2RType(field.Type) == typ {
|
||||||
// recursive definition
|
// recursive definition
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
decodeRemoveConflictFields(fieldMap, conflictedMap, stDec, field)
|
removeConflictFields(fieldMap, conflictedMap, stDec, field)
|
||||||
} else if pdec, ok := dec.(*ptrDecoder); ok {
|
} else if pdec, ok := dec.(*ptrDecoder); ok {
|
||||||
contentDec := pdec.contentDecoder()
|
contentDec := pdec.contentDecoder()
|
||||||
if pdec.typ == typ {
|
if pdec.typ == typ {
|
||||||
|
@ -438,8 +467,8 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if tag.IsString && isStringTagSupportedType(type2rtype(field.Type)) {
|
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
|
||||||
dec = newWrappedStringDecoder(type2rtype(field.Type), dec, structName, field.Name)
|
dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name)
|
||||||
}
|
}
|
||||||
var key string
|
var key string
|
||||||
if tag.Key != "" {
|
if tag.Key != "" {
|
|
@ -0,0 +1,28 @@
|
||||||
|
// +build !race
|
||||||
|
|
||||||
|
package decoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
|
||||||
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
|
if typeptr > typeAddr.MaxTypeAddr {
|
||||||
|
return compileToGetDecoderSlowPath(typeptr, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
||||||
|
if dec := cachedDecoder[index]; dec != nil {
|
||||||
|
return dec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dec, err := compileHead(typ, map[uintptr]Decoder{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cachedDecoder[index] = dec
|
||||||
|
return dec, nil
|
||||||
|
}
|
|
@ -1,21 +1,23 @@
|
||||||
// +build race
|
// +build race
|
||||||
|
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var decMu sync.RWMutex
|
var decMu sync.RWMutex
|
||||||
|
|
||||||
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
if typeptr > maxTypeAddr {
|
if typeptr > typeAddr.MaxTypeAddr {
|
||||||
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
|
return compileToGetDecoderSlowPath(typeptr, typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
index := (typeptr - baseTypeAddr) >> typeAddrShift
|
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
||||||
decMu.RLock()
|
decMu.RLock()
|
||||||
if dec := cachedDecoder[index]; dec != nil {
|
if dec := cachedDecoder[index]; dec != nil {
|
||||||
decMu.RUnlock()
|
decMu.RUnlock()
|
||||||
|
@ -23,7 +25,7 @@ func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
||||||
}
|
}
|
||||||
decMu.RUnlock()
|
decMu.RUnlock()
|
||||||
|
|
||||||
dec, err := decodeCompileHead(typ, map[uintptr]decoder{})
|
dec, err := compileHead(typ, map[uintptr]Decoder{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -34,7 +36,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
braceCount++
|
braceCount++
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
case '}':
|
case '}':
|
||||||
depth--
|
depth--
|
||||||
|
@ -45,7 +47,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
case '[':
|
case '[':
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
case ']':
|
case ']':
|
||||||
depth--
|
depth--
|
||||||
|
@ -56,16 +58,16 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
case '\\':
|
case '\\':
|
||||||
cursor++
|
cursor++
|
||||||
if buf[cursor] == nul {
|
if buf[cursor] == nul {
|
||||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
case '"':
|
case '"':
|
||||||
goto SWITCH_OUT
|
goto SWITCH_OUT
|
||||||
case nul:
|
case nul:
|
||||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case nul:
|
case nul:
|
||||||
return 0, errUnexpectedEndOfJSON("object of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
|
||||||
}
|
}
|
||||||
SWITCH_OUT:
|
SWITCH_OUT:
|
||||||
cursor++
|
cursor++
|
||||||
|
@ -80,7 +82,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
bracketCount++
|
bracketCount++
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
case ']':
|
case ']':
|
||||||
bracketCount--
|
bracketCount--
|
||||||
|
@ -91,7 +93,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
case '{':
|
case '{':
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
case '}':
|
case '}':
|
||||||
depth--
|
depth--
|
||||||
|
@ -102,16 +104,16 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
case '\\':
|
case '\\':
|
||||||
cursor++
|
cursor++
|
||||||
if buf[cursor] == nul {
|
if buf[cursor] == nul {
|
||||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
case '"':
|
case '"':
|
||||||
goto SWITCH_OUT
|
goto SWITCH_OUT
|
||||||
case nul:
|
case nul:
|
||||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case nul:
|
case nul:
|
||||||
return 0, errUnexpectedEndOfJSON("array of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
|
||||||
}
|
}
|
||||||
SWITCH_OUT:
|
SWITCH_OUT:
|
||||||
cursor++
|
cursor++
|
||||||
|
@ -135,12 +137,12 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
case '\\':
|
case '\\':
|
||||||
cursor++
|
cursor++
|
||||||
if buf[cursor] == nul {
|
if buf[cursor] == nul {
|
||||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
case '"':
|
case '"':
|
||||||
return cursor + 1, nil
|
return cursor + 1, nil
|
||||||
case nul:
|
case nul:
|
||||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
@ -171,58 +173,58 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
|
||||||
cursor += 4
|
cursor += 4
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
default:
|
default:
|
||||||
return cursor, errUnexpectedEndOfJSON("null", cursor)
|
return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateTrue(buf []byte, cursor int64) error {
|
func validateTrue(buf []byte, cursor int64) error {
|
||||||
if cursor+3 >= int64(len(buf)) {
|
if cursor+3 >= int64(len(buf)) {
|
||||||
return errUnexpectedEndOfJSON("true", cursor)
|
return errors.ErrUnexpectedEndOfJSON("true", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+1] != 'r' {
|
if buf[cursor+1] != 'r' {
|
||||||
return errInvalidCharacter(buf[cursor+1], "true", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+2] != 'u' {
|
if buf[cursor+2] != 'u' {
|
||||||
return errInvalidCharacter(buf[cursor+2], "true", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+3] != 'e' {
|
if buf[cursor+3] != 'e' {
|
||||||
return errInvalidCharacter(buf[cursor+3], "true", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateFalse(buf []byte, cursor int64) error {
|
func validateFalse(buf []byte, cursor int64) error {
|
||||||
if cursor+4 >= int64(len(buf)) {
|
if cursor+4 >= int64(len(buf)) {
|
||||||
return errUnexpectedEndOfJSON("false", cursor)
|
return errors.ErrUnexpectedEndOfJSON("false", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+1] != 'a' {
|
if buf[cursor+1] != 'a' {
|
||||||
return errInvalidCharacter(buf[cursor+1], "false", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+2] != 'l' {
|
if buf[cursor+2] != 'l' {
|
||||||
return errInvalidCharacter(buf[cursor+2], "false", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+3] != 's' {
|
if buf[cursor+3] != 's' {
|
||||||
return errInvalidCharacter(buf[cursor+3], "false", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+4] != 'e' {
|
if buf[cursor+4] != 'e' {
|
||||||
return errInvalidCharacter(buf[cursor+4], "false", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateNull(buf []byte, cursor int64) error {
|
func validateNull(buf []byte, cursor int64) error {
|
||||||
if cursor+3 >= int64(len(buf)) {
|
if cursor+3 >= int64(len(buf)) {
|
||||||
return errUnexpectedEndOfJSON("null", cursor)
|
return errors.ErrUnexpectedEndOfJSON("null", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+1] != 'u' {
|
if buf[cursor+1] != 'u' {
|
||||||
return errInvalidCharacter(buf[cursor+1], "null", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+2] != 'l' {
|
if buf[cursor+2] != 'l' {
|
||||||
return errInvalidCharacter(buf[cursor+2], "null", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
|
||||||
}
|
}
|
||||||
if buf[cursor+3] != 'l' {
|
if buf[cursor+3] != 'l' {
|
||||||
return errInvalidCharacter(buf[cursor+3], "null", cursor)
|
return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type floatDecoder struct {
|
type floatDecoder struct {
|
||||||
|
@ -47,7 +49,7 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func floatBytes(s *stream) []byte {
|
func floatBytes(s *Stream) []byte {
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
for {
|
for {
|
||||||
s.cursor++
|
s.cursor++
|
||||||
|
@ -64,7 +66,7 @@ func floatBytes(s *stream) []byte {
|
||||||
return s.buf[start:s.cursor]
|
return s.buf[start:s.cursor]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case ' ', '\n', '\t', '\r':
|
case ' ', '\n', '\t', '\r':
|
||||||
|
@ -87,7 +89,7 @@ func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return nil, errUnexpectedEndOfJSON("float", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("float", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||||
|
@ -111,12 +113,12 @@ func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, erro
|
||||||
cursor += 4
|
cursor += 4
|
||||||
return nil, cursor, nil
|
return nil, cursor, nil
|
||||||
default:
|
default:
|
||||||
return nil, 0, errUnexpectedEndOfJSON("float", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *floatDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
bytes, err := d.decodeStreamByte(s)
|
bytes, err := d.decodeStreamByte(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -127,13 +129,13 @@ func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
||||||
str := *(*string)(unsafe.Pointer(&bytes))
|
str := *(*string)(unsafe.Pointer(&bytes))
|
||||||
f64, err := strconv.ParseFloat(str, 64)
|
f64, err := strconv.ParseFloat(str, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errSyntax(err.Error(), s.totalOffset())
|
return errors.ErrSyntax(err.Error(), s.totalOffset())
|
||||||
}
|
}
|
||||||
d.op(p, f64)
|
d.op(p, f64)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *floatDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *floatDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
bytes, c, err := d.decodeByte(buf, cursor)
|
bytes, c, err := d.decodeByte(buf, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -143,12 +145,12 @@ func (d *floatDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
||||||
}
|
}
|
||||||
cursor = c
|
cursor = c
|
||||||
if !validEndNumberChar[buf[cursor]] {
|
if !validEndNumberChar[buf[cursor]] {
|
||||||
return 0, errUnexpectedEndOfJSON("float", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
|
||||||
}
|
}
|
||||||
s := *(*string)(unsafe.Pointer(&bytes))
|
s := *(*string)(unsafe.Pointer(&bytes))
|
||||||
f64, err := strconv.ParseFloat(s, 64)
|
f64, err := strconv.ParseFloat(s, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errSyntax(err.Error(), cursor)
|
return 0, errors.ErrSyntax(err.Error(), cursor)
|
||||||
}
|
}
|
||||||
d.op(p, f64)
|
d.op(p, f64)
|
||||||
return cursor, nil
|
return cursor, nil
|
|
@ -1,20 +1,23 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type intDecoder struct {
|
type intDecoder struct {
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
kind reflect.Kind
|
kind reflect.Kind
|
||||||
op func(unsafe.Pointer, int64)
|
op func(unsafe.Pointer, int64)
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIntDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
|
func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
|
||||||
return &intDecoder{
|
return &intDecoder{
|
||||||
typ: typ,
|
typ: typ,
|
||||||
kind: typ.Kind(),
|
kind: typ.Kind(),
|
||||||
|
@ -24,10 +27,10 @@ func newIntDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Poin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *intDecoder) typeError(buf []byte, offset int64) *UnmarshalTypeError {
|
func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: fmt.Sprintf("number %s", string(buf)),
|
Value: fmt.Sprintf("number %s", string(buf)),
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Struct: d.structName,
|
Struct: d.structName,
|
||||||
Field: d.fieldName,
|
Field: d.fieldName,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
|
@ -79,7 +82,11 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
var (
|
||||||
|
numZeroBuf = []byte{'0'}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case ' ', '\n', '\t', '\r':
|
case ' ', '\n', '\t', '\r':
|
||||||
|
@ -106,7 +113,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||||
return num, nil
|
return num, nil
|
||||||
case '0':
|
case '0':
|
||||||
s.cursor++
|
s.cursor++
|
||||||
return []byte{'0'}, nil
|
return numZeroBuf, nil
|
||||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
for {
|
for {
|
||||||
|
@ -138,7 +145,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return nil, errUnexpectedEndOfJSON("number(integer)", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||||
|
@ -150,7 +157,7 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
|
||||||
continue
|
continue
|
||||||
case '0':
|
case '0':
|
||||||
cursor++
|
cursor++
|
||||||
return []byte{'0'}, cursor, nil
|
return numZeroBuf, cursor, nil
|
||||||
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
start := cursor
|
start := cursor
|
||||||
cursor++
|
cursor++
|
||||||
|
@ -171,7 +178,7 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *intDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
bytes, err := d.decodeStreamByte(s)
|
bytes, err := d.decodeStreamByte(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -202,7 +209,7 @@ func (d *intDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *intDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *intDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
bytes, c, err := d.decodeByte(buf, cursor)
|
bytes, c, err := d.decodeByte(buf, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
|
@ -1,14 +1,18 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding"
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type interfaceDecoder struct {
|
type interfaceDecoder struct {
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
sliceDecoder *sliceDecoder
|
sliceDecoder *sliceDecoder
|
||||||
|
@ -26,7 +30,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
|
||||||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
|
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
stringDecoder: newStringDecoder(structName, fieldName),
|
stringDecoder: newStringDecoder(structName, fieldName),
|
||||||
|
@ -49,7 +53,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
|
||||||
return ifaceDecoder
|
return ifaceDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder {
|
func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
|
||||||
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
|
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
|
||||||
stringDecoder := newStringDecoder(structName, fieldName)
|
stringDecoder := newStringDecoder(structName, fieldName)
|
||||||
return &interfaceDecoder{
|
return &interfaceDecoder{
|
||||||
|
@ -74,31 +78,31 @@ func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDec
|
||||||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
|
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
}),
|
}),
|
||||||
stringDecoder: stringDecoder,
|
stringDecoder: stringDecoder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *interfaceDecoder) numDecoder(s *stream) decoder {
|
func (d *interfaceDecoder) numDecoder(s *Stream) Decoder {
|
||||||
if s.useNumber {
|
if s.UseNumber {
|
||||||
return d.numberDecoder
|
return d.numberDecoder
|
||||||
}
|
}
|
||||||
return d.floatDecoder
|
return d.floatDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
emptyInterfaceType = type2rtype(reflect.TypeOf((*interface{})(nil)).Elem())
|
emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||||
interfaceMapType = type2rtype(
|
interfaceMapType = runtime.Type2RType(
|
||||||
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
|
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
|
||||||
)
|
)
|
||||||
stringType = type2rtype(
|
stringType = runtime.Type2RType(
|
||||||
reflect.TypeOf(""),
|
reflect.TypeOf(""),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) error {
|
func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
if err := s.skipValue(depth); err != nil {
|
if err := s.skipValue(depth); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -113,7 +117,7 @@ func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler) (int64, error) {
|
func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) {
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
start := cursor
|
start := cursor
|
||||||
end, err := skipValue(buf, cursor, depth)
|
end, err := skipValue(buf, cursor, depth)
|
||||||
|
@ -130,7 +134,7 @@ func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler)
|
||||||
return end, nil
|
return end, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeStreamTextUnmarshaler(s *stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error {
|
func decodeStreamTextUnmarshaler(s *Stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error {
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
if err := s.skipValue(depth); err != nil {
|
if err := s.skipValue(depth); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -171,14 +175,14 @@ func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding
|
||||||
return end, nil
|
return end, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case '{':
|
case '{':
|
||||||
var v map[string]interface{}
|
var v map[string]interface{}
|
||||||
ptr := unsafe.Pointer(&v)
|
ptr := unsafe.Pointer(&v)
|
||||||
if err := d.mapDecoder.decodeStream(s, depth, ptr); err != nil {
|
if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
|
@ -186,13 +190,13 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
||||||
case '[':
|
case '[':
|
||||||
var v []interface{}
|
var v []interface{}
|
||||||
ptr := unsafe.Pointer(&v)
|
ptr := unsafe.Pointer(&v)
|
||||||
if err := d.sliceDecoder.decodeStream(s, depth, ptr); err != nil {
|
if err := d.sliceDecoder.DecodeStream(s, depth, ptr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*(*interface{})(p) = v
|
*(*interface{})(p) = v
|
||||||
return nil
|
return nil
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
return d.numDecoder(s).decodeStream(s, depth, p)
|
return d.numDecoder(s).DecodeStream(s, depth, p)
|
||||||
case '"':
|
case '"':
|
||||||
s.cursor++
|
s.cursor++
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
|
@ -211,7 +215,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
||||||
if s.read() {
|
if s.read() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("string", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
}
|
}
|
||||||
s.cursor++
|
s.cursor++
|
||||||
}
|
}
|
||||||
|
@ -240,17 +244,22 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return errNotAtBeginningOfValue(s.totalOffset())
|
return errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
type emptyInterface struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
ptr unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
|
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
|
||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: p,
|
ptr: p,
|
||||||
}))
|
}))
|
||||||
rv := reflect.ValueOf(runtimeInterfaceValue)
|
rv := reflect.ValueOf(runtimeInterfaceValue)
|
||||||
if rv.NumMethod() > 0 && rv.CanInterface() {
|
if rv.NumMethod() > 0 && rv.CanInterface() {
|
||||||
if u, ok := rv.Interface().(Unmarshaler); ok {
|
if u, ok := rv.Interface().(json.Unmarshaler); ok {
|
||||||
return decodeStreamUnmarshaler(s, depth, u)
|
return decodeStreamUnmarshaler(s, depth, u)
|
||||||
}
|
}
|
||||||
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
|
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
|
||||||
|
@ -284,15 +293,15 @@ func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer
|
||||||
*(*interface{})(p) = nil
|
*(*interface{})(p) = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
decoder, err := decodeCompileToGetDecoder(typ)
|
decoder, err := CompileToGetDecoder(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return decoder.decodeStream(s, depth, ifaceHeader.ptr)
|
return decoder.DecodeStream(s, depth, ifaceHeader.ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *UnmarshalTypeError {
|
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: typ.String(),
|
Value: typ.String(),
|
||||||
Type: typ,
|
Type: typ,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
|
@ -301,14 +310,14 @@ func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *Unm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *interfaceDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
|
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
|
||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: p,
|
ptr: p,
|
||||||
}))
|
}))
|
||||||
rv := reflect.ValueOf(runtimeInterfaceValue)
|
rv := reflect.ValueOf(runtimeInterfaceValue)
|
||||||
if rv.NumMethod() > 0 && rv.CanInterface() {
|
if rv.NumMethod() > 0 && rv.CanInterface() {
|
||||||
if u, ok := rv.Interface().(Unmarshaler); ok {
|
if u, ok := rv.Interface().(json.Unmarshaler); ok {
|
||||||
return decodeUnmarshaler(buf, cursor, depth, u)
|
return decodeUnmarshaler(buf, cursor, depth, u)
|
||||||
}
|
}
|
||||||
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
|
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
|
||||||
|
@ -345,11 +354,11 @@ func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Poin
|
||||||
**(**interface{})(unsafe.Pointer(&p)) = nil
|
**(**interface{})(unsafe.Pointer(&p)) = nil
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
decoder, err := decodeCompileToGetDecoder(typ)
|
decoder, err := CompileToGetDecoder(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return decoder.decode(buf, cursor, depth, ifaceHeader.ptr)
|
return decoder.Decode(buf, cursor, depth, ifaceHeader.ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
|
@ -358,7 +367,7 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
||||||
case '{':
|
case '{':
|
||||||
var v map[string]interface{}
|
var v map[string]interface{}
|
||||||
ptr := unsafe.Pointer(&v)
|
ptr := unsafe.Pointer(&v)
|
||||||
cursor, err := d.mapDecoder.decode(buf, cursor, depth, ptr)
|
cursor, err := d.mapDecoder.Decode(buf, cursor, depth, ptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -367,18 +376,18 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
||||||
case '[':
|
case '[':
|
||||||
var v []interface{}
|
var v []interface{}
|
||||||
ptr := unsafe.Pointer(&v)
|
ptr := unsafe.Pointer(&v)
|
||||||
cursor, err := d.sliceDecoder.decode(buf, cursor, depth, ptr)
|
cursor, err := d.sliceDecoder.Decode(buf, cursor, depth, ptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
**(**interface{})(unsafe.Pointer(&p)) = v
|
**(**interface{})(unsafe.Pointer(&p)) = v
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
return d.floatDecoder.decode(buf, cursor, depth, p)
|
return d.floatDecoder.Decode(buf, cursor, depth, p)
|
||||||
case '"':
|
case '"':
|
||||||
var v string
|
var v string
|
||||||
ptr := unsafe.Pointer(&v)
|
ptr := unsafe.Pointer(&v)
|
||||||
cursor, err := d.stringDecoder.decode(buf, cursor, depth, ptr)
|
cursor, err := d.stringDecoder.Decode(buf, cursor, depth, ptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -406,5 +415,5 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
||||||
**(**interface{})(unsafe.Pointer(&p)) = nil
|
**(**interface{})(unsafe.Pointer(&p)) = nil
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
return cursor, errNotAtBeginningOfValue(cursor)
|
return cursor, errors.ErrNotAtBeginningOfValue(cursor)
|
||||||
}
|
}
|
|
@ -1,20 +1,23 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mapDecoder struct {
|
type mapDecoder struct {
|
||||||
mapType *rtype
|
mapType *runtime.Type
|
||||||
keyType *rtype
|
keyType *runtime.Type
|
||||||
valueType *rtype
|
valueType *runtime.Type
|
||||||
keyDecoder decoder
|
keyDecoder Decoder
|
||||||
valueDecoder decoder
|
valueDecoder Decoder
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapDecoder(mapType *rtype, keyType *rtype, keyDec decoder, valueType *rtype, valueDec decoder, structName, fieldName string) *mapDecoder {
|
func newMapDecoder(mapType *runtime.Type, keyType *runtime.Type, keyDec Decoder, valueType *runtime.Type, valueDec Decoder, structName, fieldName string) *mapDecoder {
|
||||||
return &mapDecoder{
|
return &mapDecoder{
|
||||||
mapType: mapType,
|
mapType: mapType,
|
||||||
keyDecoder: keyDec,
|
keyDecoder: keyDec,
|
||||||
|
@ -27,16 +30,16 @@ func newMapDecoder(mapType *rtype, keyType *rtype, keyDec decoder, valueType *rt
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname makemap reflect.makemap
|
//go:linkname makemap reflect.makemap
|
||||||
func makemap(*rtype, int) unsafe.Pointer
|
func makemap(*runtime.Type, int) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname mapassign reflect.mapassign
|
//go:linkname mapassign reflect.mapassign
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
|
func mapassign(t *runtime.Type, m unsafe.Pointer, key, val unsafe.Pointer)
|
||||||
|
|
||||||
func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
|
@ -49,7 +52,7 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
||||||
return nil
|
return nil
|
||||||
case '{':
|
case '{':
|
||||||
default:
|
default:
|
||||||
return errExpected("{ character for map value", s.totalOffset())
|
return errors.ErrExpected("{ character for map value", s.totalOffset())
|
||||||
}
|
}
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
mapValue := *(*unsafe.Pointer)(p)
|
mapValue := *(*unsafe.Pointer)(p)
|
||||||
|
@ -64,16 +67,16 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
||||||
for {
|
for {
|
||||||
s.cursor++
|
s.cursor++
|
||||||
k := unsafe_New(d.keyType)
|
k := unsafe_New(d.keyType)
|
||||||
if err := d.keyDecoder.decodeStream(s, depth, k); err != nil {
|
if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
if !s.equalChar(':') {
|
if !s.equalChar(':') {
|
||||||
return errExpected("colon after object key", s.totalOffset())
|
return errors.ErrExpected("colon after object key", s.totalOffset())
|
||||||
}
|
}
|
||||||
s.cursor++
|
s.cursor++
|
||||||
v := unsafe_New(d.valueType)
|
v := unsafe_New(d.valueType)
|
||||||
if err := d.valueDecoder.decodeStream(s, depth, v); err != nil {
|
if err := d.valueDecoder.DecodeStream(s, depth, v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mapassign(d.mapType, mapValue, k, v)
|
mapassign(d.mapType, mapValue, k, v)
|
||||||
|
@ -84,21 +87,21 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !s.equalChar(',') {
|
if !s.equalChar(',') {
|
||||||
return errExpected("comma after object value", s.totalOffset())
|
return errors.ErrExpected("comma after object value", s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *mapDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
buflen := int64(len(buf))
|
buflen := int64(len(buf))
|
||||||
if buflen < 2 {
|
if buflen < 2 {
|
||||||
return 0, errExpected("{} for map", cursor)
|
return 0, errors.ErrExpected("{} for map", cursor)
|
||||||
}
|
}
|
||||||
switch buf[cursor] {
|
switch buf[cursor] {
|
||||||
case 'n':
|
case 'n':
|
||||||
|
@ -110,7 +113,7 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
case '{':
|
case '{':
|
||||||
default:
|
default:
|
||||||
return 0, errExpected("{ character for map value", cursor)
|
return 0, errors.ErrExpected("{ character for map value", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
@ -125,17 +128,17 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
k := unsafe_New(d.keyType)
|
k := unsafe_New(d.keyType)
|
||||||
keyCursor, err := d.keyDecoder.decode(buf, cursor, depth, k)
|
keyCursor, err := d.keyDecoder.Decode(buf, cursor, depth, k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
cursor = skipWhiteSpace(buf, keyCursor)
|
cursor = skipWhiteSpace(buf, keyCursor)
|
||||||
if buf[cursor] != ':' {
|
if buf[cursor] != ':' {
|
||||||
return 0, errExpected("colon after object key", cursor)
|
return 0, errors.ErrExpected("colon after object key", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
v := unsafe_New(d.valueType)
|
v := unsafe_New(d.valueType)
|
||||||
valueCursor, err := d.valueDecoder.decode(buf, cursor, depth, v)
|
valueCursor, err := d.valueDecoder.Decode(buf, cursor, depth, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -147,7 +150,7 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
if buf[cursor] != ',' {
|
if buf[cursor] != ',' {
|
||||||
return 0, errExpected("comma after object value", cursor)
|
return 0, errors.ErrExpected("comma after object value", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
|
@ -1,18 +1,21 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type numberDecoder struct {
|
type numberDecoder struct {
|
||||||
stringDecoder *stringDecoder
|
stringDecoder *stringDecoder
|
||||||
op func(unsafe.Pointer, Number)
|
op func(unsafe.Pointer, json.Number)
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, Number)) *numberDecoder {
|
func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder {
|
||||||
return &numberDecoder{
|
return &numberDecoder{
|
||||||
stringDecoder: newStringDecoder(structName, fieldName),
|
stringDecoder: newStringDecoder(structName, fieldName),
|
||||||
op: op,
|
op: op,
|
||||||
|
@ -21,34 +24,34 @@ func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, Numb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *numberDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
bytes, err := d.decodeStreamByte(s)
|
bytes, err := d.decodeStreamByte(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
|
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
|
||||||
return errSyntax(err.Error(), s.totalOffset())
|
return errors.ErrSyntax(err.Error(), s.totalOffset())
|
||||||
}
|
}
|
||||||
d.op(p, Number(string(bytes)))
|
d.op(p, json.Number(string(bytes)))
|
||||||
s.reset()
|
s.reset()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *numberDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *numberDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
bytes, c, err := d.decodeByte(buf, cursor)
|
bytes, c, err := d.decodeByte(buf, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
|
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
|
||||||
return 0, errSyntax(err.Error(), c)
|
return 0, errors.ErrSyntax(err.Error(), c)
|
||||||
}
|
}
|
||||||
cursor = c
|
cursor = c
|
||||||
s := *(*string)(unsafe.Pointer(&bytes))
|
s := *(*string)(unsafe.Pointer(&bytes))
|
||||||
d.op(p, Number(s))
|
d.op(p, json.Number(s))
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case ' ', '\n', '\t', '\r':
|
case ' ', '\n', '\t', '\r':
|
||||||
|
@ -73,7 +76,7 @@ func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return nil, errUnexpectedEndOfJSON("json.Number", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||||
|
@ -99,7 +102,7 @@ func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
||||||
case '"':
|
case '"':
|
||||||
return d.stringDecoder.decodeByte(buf, cursor)
|
return d.stringDecoder.decodeByte(buf, cursor)
|
||||||
default:
|
default:
|
||||||
return nil, 0, errUnexpectedEndOfJSON("json.Number", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,17 +1,19 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ptrDecoder struct {
|
type ptrDecoder struct {
|
||||||
dec decoder
|
dec Decoder
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPtrDecoder(dec decoder, typ *rtype, structName, fieldName string) *ptrDecoder {
|
func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder {
|
||||||
return &ptrDecoder{
|
return &ptrDecoder{
|
||||||
dec: dec,
|
dec: dec,
|
||||||
typ: typ,
|
typ: typ,
|
||||||
|
@ -20,7 +22,7 @@ func newPtrDecoder(dec decoder, typ *rtype, structName, fieldName string) *ptrDe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ptrDecoder) contentDecoder() decoder {
|
func (d *ptrDecoder) contentDecoder() Decoder {
|
||||||
dec, ok := d.dec.(*ptrDecoder)
|
dec, ok := d.dec.(*ptrDecoder)
|
||||||
if !ok {
|
if !ok {
|
||||||
return d.dec
|
return d.dec
|
||||||
|
@ -30,9 +32,9 @@ func (d *ptrDecoder) contentDecoder() decoder {
|
||||||
|
|
||||||
//nolint:golint
|
//nolint:golint
|
||||||
//go:linkname unsafe_New reflect.unsafe_New
|
//go:linkname unsafe_New reflect.unsafe_New
|
||||||
func unsafe_New(*rtype) unsafe.Pointer
|
func unsafe_New(*runtime.Type) unsafe.Pointer
|
||||||
|
|
||||||
func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
if s.char() == nul {
|
if s.char() == nul {
|
||||||
s.read()
|
s.read()
|
||||||
|
@ -51,13 +53,13 @@ func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
||||||
} else {
|
} else {
|
||||||
newptr = *(*unsafe.Pointer)(p)
|
newptr = *(*unsafe.Pointer)(p)
|
||||||
}
|
}
|
||||||
if err := d.dec.decodeStream(s, depth, newptr); err != nil {
|
if err := d.dec.DecodeStream(s, depth, newptr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *ptrDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
if buf[cursor] == 'n' {
|
if buf[cursor] == 'n' {
|
||||||
if err := validateNull(buf, cursor); err != nil {
|
if err := validateNull(buf, cursor); err != nil {
|
||||||
|
@ -76,7 +78,7 @@ func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
||||||
} else {
|
} else {
|
||||||
newptr = *(*unsafe.Pointer)(p)
|
newptr = *(*unsafe.Pointer)(p)
|
||||||
}
|
}
|
||||||
c, err := d.dec.decode(buf, cursor, depth, newptr)
|
c, err := d.dec.Decode(buf, cursor, depth, newptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
|
@ -1,15 +1,18 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sliceDecoder struct {
|
type sliceDecoder struct {
|
||||||
elemType *rtype
|
elemType *runtime.Type
|
||||||
isElemPointerType bool
|
isElemPointerType bool
|
||||||
valueDecoder decoder
|
valueDecoder Decoder
|
||||||
size uintptr
|
size uintptr
|
||||||
arrayPool sync.Pool
|
arrayPool sync.Pool
|
||||||
structName string
|
structName string
|
||||||
|
@ -29,7 +32,7 @@ const (
|
||||||
defaultSliceCapacity = 2
|
defaultSliceCapacity = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func newSliceDecoder(dec decoder, elemType *rtype, size uintptr, structName, fieldName string) *sliceDecoder {
|
func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder {
|
||||||
return &sliceDecoder{
|
return &sliceDecoder{
|
||||||
valueDecoder: dec,
|
valueDecoder: dec,
|
||||||
elemType: elemType,
|
elemType: elemType,
|
||||||
|
@ -71,28 +74,28 @@ func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname copySlice reflect.typedslicecopy
|
//go:linkname copySlice reflect.typedslicecopy
|
||||||
func copySlice(elemType *rtype, dst, src sliceHeader) int
|
func copySlice(elemType *runtime.Type, dst, src sliceHeader) int
|
||||||
|
|
||||||
//go:linkname newArray reflect.unsafe_NewArray
|
//go:linkname newArray reflect.unsafe_NewArray
|
||||||
func newArray(*rtype, int) unsafe.Pointer
|
func newArray(*runtime.Type, int) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname typedmemmove reflect.typedmemmove
|
//go:linkname typedmemmove reflect.typedmemmove
|
||||||
func typedmemmove(t *rtype, dst, src unsafe.Pointer)
|
func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer)
|
||||||
|
|
||||||
func (d *sliceDecoder) errNumber(offset int64) *UnmarshalTypeError {
|
func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError {
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: "number",
|
Value: "number",
|
||||||
Type: reflect.SliceOf(rtype2type(d.elemType)),
|
Type: reflect.SliceOf(runtime.RType2Type(d.elemType)),
|
||||||
Struct: d.structName,
|
Struct: d.structName,
|
||||||
Field: d.fieldName,
|
Field: d.fieldName,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -144,7 +147,7 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.valueDecoder.decodeStream(s, depth, ep); err != nil {
|
if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
|
@ -194,13 +197,13 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return errUnexpectedEndOfJSON("slice", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *sliceDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -251,7 +254,7 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
||||||
typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
|
typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c, err := d.valueDecoder.decode(buf, cursor, depth, ep)
|
c, err := d.valueDecoder.Decode(buf, cursor, depth, ep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -278,14 +281,14 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
||||||
slice.cap = capacity
|
slice.cap = capacity
|
||||||
slice.data = data
|
slice.data = data
|
||||||
d.releaseSlice(slice)
|
d.releaseSlice(slice)
|
||||||
return 0, errInvalidCharacter(buf[cursor], "slice", cursor)
|
return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
return 0, d.errNumber(cursor)
|
return 0, d.errNumber(cursor)
|
||||||
default:
|
default:
|
||||||
return 0, errUnexpectedEndOfJSON("slice", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,16 +1,20 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
initBufSize = 512
|
initBufSize = 512
|
||||||
)
|
)
|
||||||
|
|
||||||
type stream struct {
|
type Stream struct {
|
||||||
buf []byte
|
buf []byte
|
||||||
bufSize int64
|
bufSize int64
|
||||||
length int64
|
length int64
|
||||||
|
@ -19,19 +23,23 @@ type stream struct {
|
||||||
cursor int64
|
cursor int64
|
||||||
filledBuffer bool
|
filledBuffer bool
|
||||||
allRead bool
|
allRead bool
|
||||||
useNumber bool
|
UseNumber bool
|
||||||
disallowUnknownFields bool
|
DisallowUnknownFields bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStream(r io.Reader) *stream {
|
func NewStream(r io.Reader) *Stream {
|
||||||
return &stream{
|
return &Stream{
|
||||||
r: r,
|
r: r,
|
||||||
bufSize: initBufSize,
|
bufSize: initBufSize,
|
||||||
buf: []byte{nul},
|
buf: []byte{nul},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) buffered() io.Reader {
|
func (s *Stream) TotalOffset() int64 {
|
||||||
|
return s.totalOffset()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) Buffered() io.Reader {
|
||||||
buflen := int64(len(s.buf))
|
buflen := int64(len(s.buf))
|
||||||
for i := s.cursor; i < buflen; i++ {
|
for i := s.cursor; i < buflen; i++ {
|
||||||
if s.buf[i] == nul {
|
if s.buf[i] == nul {
|
||||||
|
@ -41,15 +49,35 @@ func (s *stream) buffered() io.Reader {
|
||||||
return bytes.NewReader(s.buf[s.cursor:])
|
return bytes.NewReader(s.buf[s.cursor:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) totalOffset() int64 {
|
func (s *Stream) PrepareForDecode() error {
|
||||||
|
for {
|
||||||
|
switch s.char() {
|
||||||
|
case ' ', '\t', '\r', '\n':
|
||||||
|
s.cursor++
|
||||||
|
continue
|
||||||
|
case ',', ':':
|
||||||
|
s.cursor++
|
||||||
|
return nil
|
||||||
|
case nul:
|
||||||
|
if s.read() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) totalOffset() int64 {
|
||||||
return s.offset + s.cursor
|
return s.offset + s.cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) char() byte {
|
func (s *Stream) char() byte {
|
||||||
return s.buf[s.cursor]
|
return s.buf[s.cursor]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) equalChar(c byte) bool {
|
func (s *Stream) equalChar(c byte) bool {
|
||||||
cur := s.buf[s.cursor]
|
cur := s.buf[s.cursor]
|
||||||
if cur == nul {
|
if cur == nul {
|
||||||
s.read()
|
s.read()
|
||||||
|
@ -58,23 +86,100 @@ func (s *stream) equalChar(c byte) bool {
|
||||||
return cur == c
|
return cur == c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) stat() ([]byte, int64, unsafe.Pointer) {
|
func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) {
|
||||||
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
|
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
|
func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
|
||||||
s.cursor-- // for retry ( because caller progress cursor position in each loop )
|
s.cursor-- // for retry ( because caller progress cursor position in each loop )
|
||||||
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
|
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) reset() {
|
func (s *Stream) Reset() {
|
||||||
|
s.reset()
|
||||||
|
s.bufSize = initBufSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) More() bool {
|
||||||
|
for {
|
||||||
|
switch s.char() {
|
||||||
|
case ' ', '\n', '\r', '\t':
|
||||||
|
s.cursor++
|
||||||
|
continue
|
||||||
|
case '}', ']':
|
||||||
|
return false
|
||||||
|
case nul:
|
||||||
|
if s.read() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) Token() (interface{}, error) {
|
||||||
|
for {
|
||||||
|
c := s.char()
|
||||||
|
switch c {
|
||||||
|
case ' ', '\n', '\r', '\t':
|
||||||
|
s.cursor++
|
||||||
|
case '{', '[', ']', '}':
|
||||||
|
s.cursor++
|
||||||
|
return json.Delim(c), nil
|
||||||
|
case ',', ':':
|
||||||
|
s.cursor++
|
||||||
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
bytes := floatBytes(s)
|
||||||
|
s := *(*string)(unsafe.Pointer(&bytes))
|
||||||
|
f64, err := strconv.ParseFloat(s, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return f64, nil
|
||||||
|
case '"':
|
||||||
|
bytes, err := stringBytes(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return string(bytes), nil
|
||||||
|
case 't':
|
||||||
|
if err := trueBytes(s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
case 'f':
|
||||||
|
if err := falseBytes(s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
case 'n':
|
||||||
|
if err := nullBytes(s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
case nul:
|
||||||
|
if s.read() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
goto END
|
||||||
|
default:
|
||||||
|
return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END:
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) reset() {
|
||||||
s.offset += s.cursor
|
s.offset += s.cursor
|
||||||
s.buf = s.buf[s.cursor:]
|
s.buf = s.buf[s.cursor:]
|
||||||
s.length -= s.cursor
|
s.length -= s.cursor
|
||||||
s.cursor = 0
|
s.cursor = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) readBuf() []byte {
|
func (s *Stream) readBuf() []byte {
|
||||||
if s.filledBuffer {
|
if s.filledBuffer {
|
||||||
s.bufSize *= 2
|
s.bufSize *= 2
|
||||||
remainBuf := s.buf
|
remainBuf := s.buf
|
||||||
|
@ -92,7 +197,7 @@ func (s *stream) readBuf() []byte {
|
||||||
return s.buf[s.cursor+remainNotNulCharNum:]
|
return s.buf[s.cursor+remainNotNulCharNum:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) read() bool {
|
func (s *Stream) read() bool {
|
||||||
if s.allRead {
|
if s.allRead {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -114,7 +219,7 @@ func (s *stream) read() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) skipWhiteSpace() {
|
func (s *Stream) skipWhiteSpace() {
|
||||||
LOOP:
|
LOOP:
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case ' ', '\n', '\t', '\r':
|
case ' ', '\n', '\t', '\r':
|
||||||
|
@ -127,7 +232,7 @@ LOOP:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) skipObject(depth int64) error {
|
func (s *Stream) skipObject(depth int64) error {
|
||||||
braceCount := 1
|
braceCount := 1
|
||||||
_, cursor, p := s.stat()
|
_, cursor, p := s.stat()
|
||||||
for {
|
for {
|
||||||
|
@ -136,7 +241,7 @@ func (s *stream) skipObject(depth int64) error {
|
||||||
braceCount++
|
braceCount++
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
case '}':
|
case '}':
|
||||||
braceCount--
|
braceCount--
|
||||||
|
@ -148,7 +253,7 @@ func (s *stream) skipObject(depth int64) error {
|
||||||
case '[':
|
case '[':
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
case ']':
|
case ']':
|
||||||
depth--
|
depth--
|
||||||
|
@ -164,7 +269,7 @@ func (s *stream) skipObject(depth int64) error {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.statForRetry()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
case '"':
|
case '"':
|
||||||
goto SWITCH_OUT
|
goto SWITCH_OUT
|
||||||
|
@ -174,7 +279,7 @@ func (s *stream) skipObject(depth int64) error {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.statForRetry()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case nul:
|
case nul:
|
||||||
|
@ -183,14 +288,14 @@ func (s *stream) skipObject(depth int64) error {
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("object of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("object of object", cursor)
|
||||||
}
|
}
|
||||||
SWITCH_OUT:
|
SWITCH_OUT:
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) skipArray(depth int64) error {
|
func (s *Stream) skipArray(depth int64) error {
|
||||||
bracketCount := 1
|
bracketCount := 1
|
||||||
_, cursor, p := s.stat()
|
_, cursor, p := s.stat()
|
||||||
for {
|
for {
|
||||||
|
@ -199,7 +304,7 @@ func (s *stream) skipArray(depth int64) error {
|
||||||
bracketCount++
|
bracketCount++
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
case ']':
|
case ']':
|
||||||
bracketCount--
|
bracketCount--
|
||||||
|
@ -211,7 +316,7 @@ func (s *stream) skipArray(depth int64) error {
|
||||||
case '{':
|
case '{':
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
case '}':
|
case '}':
|
||||||
depth--
|
depth--
|
||||||
|
@ -227,7 +332,7 @@ func (s *stream) skipArray(depth int64) error {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.statForRetry()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
case '"':
|
case '"':
|
||||||
goto SWITCH_OUT
|
goto SWITCH_OUT
|
||||||
|
@ -237,7 +342,7 @@ func (s *stream) skipArray(depth int64) error {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.statForRetry()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case nul:
|
case nul:
|
||||||
|
@ -246,14 +351,14 @@ func (s *stream) skipArray(depth int64) error {
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("array of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("array of object", cursor)
|
||||||
}
|
}
|
||||||
SWITCH_OUT:
|
SWITCH_OUT:
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stream) skipValue(depth int64) error {
|
func (s *Stream) skipValue(depth int64) error {
|
||||||
_, cursor, p := s.stat()
|
_, cursor, p := s.stat()
|
||||||
for {
|
for {
|
||||||
switch char(p, cursor) {
|
switch char(p, cursor) {
|
||||||
|
@ -266,7 +371,7 @@ func (s *stream) skipValue(depth int64) error {
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("value of object", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset())
|
||||||
case '{':
|
case '{':
|
||||||
s.cursor = cursor + 1
|
s.cursor = cursor + 1
|
||||||
return s.skipObject(depth + 1)
|
return s.skipObject(depth + 1)
|
||||||
|
@ -285,7 +390,7 @@ func (s *stream) skipValue(depth int64) error {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.statForRetry()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("value of string", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||||
}
|
}
|
||||||
case '"':
|
case '"':
|
||||||
s.cursor = cursor + 1
|
s.cursor = cursor + 1
|
||||||
|
@ -296,7 +401,7 @@ func (s *stream) skipValue(depth int64) error {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.statForRetry()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errUnexpectedEndOfJSON("value of string", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
@ -338,7 +443,7 @@ func (s *stream) skipValue(depth int64) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nullBytes(s *stream) error {
|
func nullBytes(s *Stream) error {
|
||||||
// current cursor's character is 'n'
|
// current cursor's character is 'n'
|
||||||
s.cursor++
|
s.cursor++
|
||||||
if s.char() != 'u' {
|
if s.char() != 'u' {
|
||||||
|
@ -362,14 +467,14 @@ func nullBytes(s *stream) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func retryReadNull(s *stream) error {
|
func retryReadNull(s *Stream) error {
|
||||||
if s.char() == nul && s.read() {
|
if s.char() == nul && s.read() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errInvalidCharacter(s.char(), "null", s.totalOffset())
|
return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func trueBytes(s *stream) error {
|
func trueBytes(s *Stream) error {
|
||||||
// current cursor's character is 't'
|
// current cursor's character is 't'
|
||||||
s.cursor++
|
s.cursor++
|
||||||
if s.char() != 'r' {
|
if s.char() != 'r' {
|
||||||
|
@ -393,14 +498,14 @@ func trueBytes(s *stream) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func retryReadTrue(s *stream) error {
|
func retryReadTrue(s *Stream) error {
|
||||||
if s.char() == nul && s.read() {
|
if s.char() == nul && s.read() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
|
return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func falseBytes(s *stream) error {
|
func falseBytes(s *Stream) error {
|
||||||
// current cursor's character is 'f'
|
// current cursor's character is 'f'
|
||||||
s.cursor++
|
s.cursor++
|
||||||
if s.char() != 'a' {
|
if s.char() != 'a' {
|
||||||
|
@ -430,9 +535,9 @@ func falseBytes(s *stream) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func retryReadFalse(s *stream) error {
|
func retryReadFalse(s *Stream) error {
|
||||||
if s.char() == nul && s.read() {
|
if s.char() == nul && s.read() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
|
return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -6,6 +6,8 @@ import (
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stringDecoder struct {
|
type stringDecoder struct {
|
||||||
|
@ -20,8 +22,8 @@ func newStringDecoder(structName, fieldName string) *stringDecoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *UnmarshalTypeError {
|
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError {
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: typeName,
|
Value: typeName,
|
||||||
Type: reflect.TypeOf(""),
|
Type: reflect.TypeOf(""),
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
|
@ -30,7 +32,7 @@ func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *Unmarsh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *stringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *stringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
bytes, err := d.decodeStreamByte(s)
|
bytes, err := d.decodeStreamByte(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -43,7 +45,7 @@ func (d *stringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *stringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *stringDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
bytes, c, err := d.decodeByte(buf, cursor)
|
bytes, c, err := d.decodeByte(buf, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -91,13 +93,13 @@ func unicodeToRune(code []byte) rune {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeUnicodeRune(s *stream) (rune, int64, error) {
|
func decodeUnicodeRune(s *Stream) (rune, int64, error) {
|
||||||
const defaultOffset = 5
|
const defaultOffset = 5
|
||||||
const surrogateOffset = 11
|
const surrogateOffset = 11
|
||||||
|
|
||||||
if s.cursor+defaultOffset >= s.length {
|
if s.cursor+defaultOffset >= s.length {
|
||||||
if !s.read() {
|
if !s.read() {
|
||||||
return rune(0), 0, errInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
return rune(0), 0, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +119,7 @@ func decodeUnicodeRune(s *stream) (rune, int64, error) {
|
||||||
return r, defaultOffset, nil
|
return r, defaultOffset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeUnicode(s *stream) error {
|
func decodeUnicode(s *Stream) error {
|
||||||
const backSlashAndULen = 2 // length of \u
|
const backSlashAndULen = 2 // length of \u
|
||||||
|
|
||||||
r, offset, err := decodeUnicodeRune(s)
|
r, offset, err := decodeUnicodeRune(s)
|
||||||
|
@ -133,7 +135,7 @@ func decodeUnicode(s *stream) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeEscapeString(s *stream) error {
|
func decodeEscapeString(s *Stream) error {
|
||||||
s.cursor++
|
s.cursor++
|
||||||
RETRY:
|
RETRY:
|
||||||
switch s.buf[s.cursor] {
|
switch s.buf[s.cursor] {
|
||||||
|
@ -157,11 +159,11 @@ RETRY:
|
||||||
return decodeUnicode(s)
|
return decodeUnicode(s)
|
||||||
case nul:
|
case nul:
|
||||||
if !s.read() {
|
if !s.read() {
|
||||||
return errInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
return errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||||
}
|
}
|
||||||
goto RETRY
|
goto RETRY
|
||||||
default:
|
default:
|
||||||
return errUnexpectedEndOfJSON("string", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
}
|
}
|
||||||
s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...)
|
s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...)
|
||||||
s.length--
|
s.length--
|
||||||
|
@ -174,7 +176,7 @@ var (
|
||||||
runeErrBytesLen = int64(len(runeErrBytes))
|
runeErrBytesLen = int64(len(runeErrBytes))
|
||||||
)
|
)
|
||||||
|
|
||||||
func stringBytes(s *stream) ([]byte, error) {
|
func stringBytes(s *Stream) ([]byte, error) {
|
||||||
_, cursor, p := s.stat()
|
_, cursor, p := s.stat()
|
||||||
cursor++ // skip double quote char
|
cursor++ // skip double quote char
|
||||||
start := cursor
|
start := cursor
|
||||||
|
@ -245,10 +247,10 @@ func stringBytes(s *stream) ([]byte, error) {
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
ERROR:
|
ERROR:
|
||||||
return nil, errUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
func (d *stringDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case ' ', '\n', '\t', '\r':
|
case ' ', '\n', '\t', '\r':
|
||||||
|
@ -274,7 +276,7 @@ func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return nil, errNotAtBeginningOfValue(s.totalOffset())
|
return nil, errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||||
|
@ -324,13 +326,13 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
||||||
case 'u':
|
case 'u':
|
||||||
buflen := int64(len(buf))
|
buflen := int64(len(buf))
|
||||||
if cursor+5 >= buflen {
|
if cursor+5 >= buflen {
|
||||||
return nil, 0, errUnexpectedEndOfJSON("escaped string", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
||||||
}
|
}
|
||||||
code := unicodeToRune(buf[cursor+1 : cursor+5])
|
code := unicodeToRune(buf[cursor+1 : cursor+5])
|
||||||
unicode := []byte(string(code))
|
unicode := []byte(string(code))
|
||||||
buf = append(append(buf[:cursor-1], unicode...), buf[cursor+5:]...)
|
buf = append(append(buf[:cursor-1], unicode...), buf[cursor+5:]...)
|
||||||
default:
|
default:
|
||||||
return nil, 0, errUnexpectedEndOfJSON("escaped string", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
case '"':
|
case '"':
|
||||||
|
@ -338,7 +340,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
||||||
cursor++
|
cursor++
|
||||||
return literal, cursor, nil
|
return literal, cursor, nil
|
||||||
case nul:
|
case nul:
|
||||||
return nil, 0, errUnexpectedEndOfJSON("string", cursor)
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
|
@ -349,7 +351,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
||||||
cursor += 4
|
cursor += 4
|
||||||
return nil, cursor, nil
|
return nil, cursor, nil
|
||||||
default:
|
default:
|
||||||
return nil, 0, errNotAtBeginningOfValue(cursor)
|
return nil, 0, errors.ErrNotAtBeginningOfValue(cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -9,10 +9,12 @@ import (
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type structFieldSet struct {
|
type structFieldSet struct {
|
||||||
dec decoder
|
dec Decoder
|
||||||
offset uintptr
|
offset uintptr
|
||||||
isTaggedKey bool
|
isTaggedKey bool
|
||||||
key string
|
key string
|
||||||
|
@ -30,7 +32,7 @@ type structDecoder struct {
|
||||||
keyBitmapUint16 [][256]uint16
|
keyBitmapUint16 [][256]uint16
|
||||||
sortedFieldSets []*structFieldSet
|
sortedFieldSets []*structFieldSet
|
||||||
keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
|
keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
|
||||||
keyStreamDecoder func(*structDecoder, *stream) (*structFieldSet, string, error)
|
keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -201,7 +203,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
|
||||||
cursor++
|
cursor++
|
||||||
return cursor, nil, nil
|
return cursor, nil, nil
|
||||||
case nul:
|
case nul:
|
||||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||||
}
|
}
|
||||||
keyIdx := 0
|
keyIdx := 0
|
||||||
bitmap := d.keyBitmapUint8
|
bitmap := d.keyBitmapUint8
|
||||||
|
@ -220,7 +222,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
|
||||||
}
|
}
|
||||||
return cursor, field, nil
|
return cursor, field, nil
|
||||||
case nul:
|
case nul:
|
||||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||||
case '\\':
|
case '\\':
|
||||||
cursor++
|
cursor++
|
||||||
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
|
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
|
||||||
|
@ -242,7 +244,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return cursor, nil, errNotAtBeginningOfValue(cursor)
|
return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +266,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
|
||||||
cursor++
|
cursor++
|
||||||
return cursor, nil, nil
|
return cursor, nil, nil
|
||||||
case nul:
|
case nul:
|
||||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||||
}
|
}
|
||||||
keyIdx := 0
|
keyIdx := 0
|
||||||
bitmap := d.keyBitmapUint16
|
bitmap := d.keyBitmapUint16
|
||||||
|
@ -283,7 +285,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
|
||||||
}
|
}
|
||||||
return cursor, field, nil
|
return cursor, field, nil
|
||||||
case nul:
|
case nul:
|
||||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||||
case '\\':
|
case '\\':
|
||||||
cursor++
|
cursor++
|
||||||
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
|
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
|
||||||
|
@ -305,7 +307,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return cursor, nil, errNotAtBeginningOfValue(cursor)
|
return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,10 +322,10 @@ func decodeKeyNotFound(b unsafe.Pointer, cursor int64) (int64, *structFieldSet,
|
||||||
case '\\':
|
case '\\':
|
||||||
cursor++
|
cursor++
|
||||||
if char(b, cursor) == nul {
|
if char(b, cursor) == nul {
|
||||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||||
}
|
}
|
||||||
case nul:
|
case nul:
|
||||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,7 +344,7 @@ func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldS
|
||||||
return cursor, field, nil
|
return cursor, field, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
|
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
|
||||||
var (
|
var (
|
||||||
curBit uint8 = math.MaxUint8
|
curBit uint8 = math.MaxUint8
|
||||||
)
|
)
|
||||||
|
@ -357,7 +359,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
case '"':
|
case '"':
|
||||||
cursor++
|
cursor++
|
||||||
FIRST_CHAR:
|
FIRST_CHAR:
|
||||||
|
@ -373,7 +375,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
goto FIRST_CHAR
|
goto FIRST_CHAR
|
||||||
}
|
}
|
||||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
}
|
}
|
||||||
keyIdx := 0
|
keyIdx := 0
|
||||||
bitmap := d.keyBitmapUint8
|
bitmap := d.keyBitmapUint8
|
||||||
|
@ -397,7 +399,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
case '\\':
|
case '\\':
|
||||||
s.cursor = cursor + 1 // skip '\' char
|
s.cursor = cursor + 1 // skip '\' char
|
||||||
chars, err := decodeKeyCharByEscapeCharStream(s)
|
chars, err := decodeKeyCharByEscapeCharStream(s)
|
||||||
|
@ -424,12 +426,12 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
|
func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
|
||||||
var (
|
var (
|
||||||
curBit uint16 = math.MaxUint16
|
curBit uint16 = math.MaxUint16
|
||||||
)
|
)
|
||||||
|
@ -444,7 +446,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
case '"':
|
case '"':
|
||||||
cursor++
|
cursor++
|
||||||
FIRST_CHAR:
|
FIRST_CHAR:
|
||||||
|
@ -460,7 +462,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
goto FIRST_CHAR
|
goto FIRST_CHAR
|
||||||
}
|
}
|
||||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
}
|
}
|
||||||
keyIdx := 0
|
keyIdx := 0
|
||||||
bitmap := d.keyBitmapUint16
|
bitmap := d.keyBitmapUint16
|
||||||
|
@ -484,7 +486,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
||||||
_, cursor, p = s.stat()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
case '\\':
|
case '\\':
|
||||||
s.cursor = cursor + 1 // skip '\' char
|
s.cursor = cursor + 1 // skip '\' char
|
||||||
chars, err := decodeKeyCharByEscapeCharStream(s)
|
chars, err := decodeKeyCharByEscapeCharStream(s)
|
||||||
|
@ -511,19 +513,19 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode from '\uXXXX'
|
// decode from '\uXXXX'
|
||||||
func decodeKeyCharByUnicodeRuneStream(s *stream) ([]byte, error) {
|
func decodeKeyCharByUnicodeRuneStream(s *Stream) ([]byte, error) {
|
||||||
const defaultOffset = 4
|
const defaultOffset = 4
|
||||||
const surrogateOffset = 6
|
const surrogateOffset = 6
|
||||||
|
|
||||||
if s.cursor+defaultOffset >= s.length {
|
if s.cursor+defaultOffset >= s.length {
|
||||||
if !s.read() {
|
if !s.read() {
|
||||||
return nil, errInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset())
|
return nil, errors.ErrInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,7 +549,7 @@ func decodeKeyCharByUnicodeRuneStream(s *stream) ([]byte, error) {
|
||||||
return []byte(string(r)), nil
|
return []byte(string(r)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeKeyCharByEscapeCharStream(s *stream) ([]byte, error) {
|
func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) {
|
||||||
c := s.buf[s.cursor]
|
c := s.buf[s.cursor]
|
||||||
s.cursor++
|
s.cursor++
|
||||||
RETRY:
|
RETRY:
|
||||||
|
@ -572,15 +574,15 @@ RETRY:
|
||||||
return decodeKeyCharByUnicodeRuneStream(s)
|
return decodeKeyCharByUnicodeRuneStream(s)
|
||||||
case nul:
|
case nul:
|
||||||
if !s.read() {
|
if !s.read() {
|
||||||
return nil, errInvalidCharacter(s.char(), "escaped char", s.totalOffset())
|
return nil, errors.ErrInvalidCharacter(s.char(), "escaped char", s.totalOffset())
|
||||||
}
|
}
|
||||||
goto RETRY
|
goto RETRY
|
||||||
default:
|
default:
|
||||||
return nil, errUnexpectedEndOfJSON("struct field", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("struct field", s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeKeyNotFoundStream(s *stream, start int64) (*structFieldSet, string, error) {
|
func decodeKeyNotFoundStream(s *Stream, start int64) (*structFieldSet, string, error) {
|
||||||
buf, cursor, p := s.stat()
|
buf, cursor, p := s.stat()
|
||||||
for {
|
for {
|
||||||
cursor++
|
cursor++
|
||||||
|
@ -596,21 +598,21 @@ func decodeKeyNotFoundStream(s *stream, start int64) (*structFieldSet, string, e
|
||||||
if char(p, cursor) == nul {
|
if char(p, cursor) == nul {
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if !s.read() {
|
if !s.read() {
|
||||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
}
|
}
|
||||||
buf, cursor, p = s.statForRetry()
|
buf, cursor, p = s.statForRetry()
|
||||||
}
|
}
|
||||||
case nul:
|
case nul:
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if !s.read() {
|
if !s.read() {
|
||||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
}
|
}
|
||||||
buf, cursor, p = s.statForRetry()
|
buf, cursor, p = s.statForRetry()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
|
func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
|
||||||
key, err := d.stringDecoder.decodeStreamByte(s)
|
key, err := d.stringDecoder.decodeStreamByte(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
|
@ -619,10 +621,10 @@ func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, erro
|
||||||
return d.fieldMap[k], k, nil
|
return d.fieldMap[k], k, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return errExceededMaxDepth(s.char(), s.cursor)
|
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
|
@ -636,7 +638,7 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
||||||
s.read()
|
s.read()
|
||||||
default:
|
default:
|
||||||
if s.char() != '{' {
|
if s.char() != '{' {
|
||||||
return errNotAtBeginningOfValue(s.totalOffset())
|
return errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.cursor++
|
s.cursor++
|
||||||
|
@ -653,22 +655,22 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
||||||
}
|
}
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
if s.char() != ':' {
|
if s.char() != ':' {
|
||||||
return errExpected("colon after object key", s.totalOffset())
|
return errors.ErrExpected("colon after object key", s.totalOffset())
|
||||||
}
|
}
|
||||||
s.cursor++
|
s.cursor++
|
||||||
if s.char() == nul {
|
if s.char() == nul {
|
||||||
if !s.read() {
|
if !s.read() {
|
||||||
return errExpected("object value after colon", s.totalOffset())
|
return errors.ErrExpected("object value after colon", s.totalOffset())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if field != nil {
|
if field != nil {
|
||||||
if field.err != nil {
|
if field.err != nil {
|
||||||
return field.err
|
return field.err
|
||||||
}
|
}
|
||||||
if err := field.dec.decodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
|
if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if s.disallowUnknownFields {
|
} else if s.DisallowUnknownFields {
|
||||||
return fmt.Errorf("json: unknown field %q", key)
|
return fmt.Errorf("json: unknown field %q", key)
|
||||||
} else {
|
} else {
|
||||||
if err := s.skipValue(depth); err != nil {
|
if err := s.skipValue(depth); err != nil {
|
||||||
|
@ -682,16 +684,16 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if c != ',' {
|
if c != ',' {
|
||||||
return errExpected("comma after object element", s.totalOffset())
|
return errors.ErrExpected("comma after object element", s.totalOffset())
|
||||||
}
|
}
|
||||||
s.cursor++
|
s.cursor++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *structDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
depth++
|
depth++
|
||||||
if depth > maxDecodeNestingDepth {
|
if depth > maxDecodeNestingDepth {
|
||||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
buflen := int64(len(buf))
|
buflen := int64(len(buf))
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
@ -705,7 +707,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
case '{':
|
case '{':
|
||||||
default:
|
default:
|
||||||
return 0, errNotAtBeginningOfValue(cursor)
|
return 0, errors.ErrNotAtBeginningOfValue(cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
@ -720,17 +722,17 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
|
||||||
}
|
}
|
||||||
cursor = skipWhiteSpace(buf, c)
|
cursor = skipWhiteSpace(buf, c)
|
||||||
if char(b, cursor) != ':' {
|
if char(b, cursor) != ':' {
|
||||||
return 0, errExpected("colon after object key", cursor)
|
return 0, errors.ErrExpected("colon after object key", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
if cursor >= buflen {
|
if cursor >= buflen {
|
||||||
return 0, errExpected("object value after colon", cursor)
|
return 0, errors.ErrExpected("object value after colon", cursor)
|
||||||
}
|
}
|
||||||
if field != nil {
|
if field != nil {
|
||||||
if field.err != nil {
|
if field.err != nil {
|
||||||
return 0, field.err
|
return 0, field.err
|
||||||
}
|
}
|
||||||
c, err := field.dec.decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
|
c, err := field.dec.Decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -748,7 +750,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
if char(b, cursor) != ',' {
|
if char(b, cursor) != ',' {
|
||||||
return 0, errExpected("comma after object element", cursor)
|
return 0, errors.ErrExpected("comma after object element", cursor)
|
||||||
}
|
}
|
||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package decoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Decoder interface {
|
||||||
|
Decode([]byte, int64, int64, unsafe.Pointer) (int64, error)
|
||||||
|
DecodeStream(*Stream, int64, unsafe.Pointer) error
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
nul = '\000'
|
||||||
|
maxDecodeNestingDepth = 10000
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
unmarshalJSONType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||||
|
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||||
|
)
|
|
@ -1,20 +1,23 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type uintDecoder struct {
|
type uintDecoder struct {
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
kind reflect.Kind
|
kind reflect.Kind
|
||||||
op func(unsafe.Pointer, uint64)
|
op func(unsafe.Pointer, uint64)
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUintDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
|
func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
|
||||||
return &uintDecoder{
|
return &uintDecoder{
|
||||||
typ: typ,
|
typ: typ,
|
||||||
kind: typ.Kind(),
|
kind: typ.Kind(),
|
||||||
|
@ -24,10 +27,10 @@ func newUintDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Poi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *uintDecoder) typeError(buf []byte, offset int64) *UnmarshalTypeError {
|
func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: fmt.Sprintf("number %s", string(buf)),
|
Value: fmt.Sprintf("number %s", string(buf)),
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +57,7 @@ func (d *uintDecoder) parseUint(b []byte) (uint64, error) {
|
||||||
return sum, nil
|
return sum, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||||
for {
|
for {
|
||||||
switch s.char() {
|
switch s.char() {
|
||||||
case ' ', '\n', '\t', '\r':
|
case ' ', '\n', '\t', '\r':
|
||||||
|
@ -62,7 +65,7 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||||
continue
|
continue
|
||||||
case '0':
|
case '0':
|
||||||
s.cursor++
|
s.cursor++
|
||||||
return []byte{'0'}, nil
|
return numZeroBuf, nil
|
||||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
for {
|
for {
|
||||||
|
@ -93,7 +96,7 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return nil, errUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
|
||||||
|
@ -104,7 +107,7 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
|
||||||
continue
|
continue
|
||||||
case '0':
|
case '0':
|
||||||
cursor++
|
cursor++
|
||||||
return []byte{'0'}, cursor, nil
|
return numZeroBuf, cursor, nil
|
||||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
start := cursor
|
start := cursor
|
||||||
cursor++
|
cursor++
|
||||||
|
@ -125,7 +128,7 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
bytes, err := d.decodeStreamByte(s)
|
bytes, err := d.decodeStreamByte(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -155,7 +158,7 @@ func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *uintDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *uintDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
bytes, c, err := d.decodeByte(buf, cursor)
|
bytes, c, err := d.decodeByte(buf, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
|
@ -1,16 +1,20 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type unmarshalJSONDecoder struct {
|
type unmarshalJSONDecoder struct {
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUnmarshalJSONDecoder(typ *rtype, structName, fieldName string) *unmarshalJSONDecoder {
|
func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
|
||||||
return &unmarshalJSONDecoder{
|
return &unmarshalJSONDecoder{
|
||||||
typ: typ,
|
typ: typ,
|
||||||
structName: structName,
|
structName: structName,
|
||||||
|
@ -20,15 +24,15 @@ func newUnmarshalJSONDecoder(typ *rtype, structName, fieldName string) *unmarsha
|
||||||
|
|
||||||
func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
|
func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case *UnmarshalTypeError:
|
case *errors.UnmarshalTypeError:
|
||||||
e.Struct = d.structName
|
e.Struct = d.structName
|
||||||
e.Field = d.fieldName
|
e.Field = d.fieldName
|
||||||
case *SyntaxError:
|
case *errors.SyntaxError:
|
||||||
e.Offset = cursor
|
e.Offset = cursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *unmarshalJSONDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
if err := s.skipValue(depth); err != nil {
|
if err := s.skipValue(depth); err != nil {
|
||||||
|
@ -42,14 +46,14 @@ func (d *unmarshalJSONDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: p,
|
ptr: p,
|
||||||
}))
|
}))
|
||||||
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||||
d.annotateError(s.cursor, err)
|
d.annotateError(s.cursor, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *unmarshalJSONDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *unmarshalJSONDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
start := cursor
|
start := cursor
|
||||||
end, err := skipValue(buf, cursor, depth)
|
end, err := skipValue(buf, cursor, depth)
|
||||||
|
@ -64,7 +68,7 @@ func (d *unmarshalJSONDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
|
||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: p,
|
ptr: p,
|
||||||
}))
|
}))
|
||||||
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||||
d.annotateError(cursor, err)
|
d.annotateError(cursor, err)
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -7,15 +7,18 @@ import (
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type unmarshalTextDecoder struct {
|
type unmarshalTextDecoder struct {
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarshalTextDecoder {
|
func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder {
|
||||||
return &unmarshalTextDecoder{
|
return &unmarshalTextDecoder{
|
||||||
typ: typ,
|
typ: typ,
|
||||||
structName: structName,
|
structName: structName,
|
||||||
|
@ -25,10 +28,10 @@ func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarsha
|
||||||
|
|
||||||
func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) {
|
func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) {
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case *UnmarshalTypeError:
|
case *errors.UnmarshalTypeError:
|
||||||
e.Struct = d.structName
|
e.Struct = d.structName
|
||||||
e.Field = d.fieldName
|
e.Field = d.fieldName
|
||||||
case *SyntaxError:
|
case *errors.SyntaxError:
|
||||||
e.Offset = cursor
|
e.Offset = cursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +40,7 @@ var (
|
||||||
nullbytes = []byte(`null`)
|
nullbytes = []byte(`null`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *unmarshalTextDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
s.skipWhiteSpace()
|
s.skipWhiteSpace()
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
if err := s.skipValue(depth); err != nil {
|
if err := s.skipValue(depth); err != nil {
|
||||||
|
@ -47,21 +50,21 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
||||||
if len(src) > 0 {
|
if len(src) > 0 {
|
||||||
switch src[0] {
|
switch src[0] {
|
||||||
case '[':
|
case '[':
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: "array",
|
Value: "array",
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: s.totalOffset(),
|
Offset: s.totalOffset(),
|
||||||
}
|
}
|
||||||
case '{':
|
case '{':
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: "object",
|
Value: "object",
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: s.totalOffset(),
|
Offset: s.totalOffset(),
|
||||||
}
|
}
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
return &UnmarshalTypeError{
|
return &errors.UnmarshalTypeError{
|
||||||
Value: "number",
|
Value: "number",
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: s.totalOffset(),
|
Offset: s.totalOffset(),
|
||||||
}
|
}
|
||||||
case 'n':
|
case 'n':
|
||||||
|
@ -88,7 +91,7 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *unmarshalTextDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *unmarshalTextDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
cursor = skipWhiteSpace(buf, cursor)
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
start := cursor
|
start := cursor
|
||||||
end, err := skipValue(buf, cursor, depth)
|
end, err := skipValue(buf, cursor, depth)
|
||||||
|
@ -99,21 +102,21 @@ func (d *unmarshalTextDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
|
||||||
if len(src) > 0 {
|
if len(src) > 0 {
|
||||||
switch src[0] {
|
switch src[0] {
|
||||||
case '[':
|
case '[':
|
||||||
return 0, &UnmarshalTypeError{
|
return 0, &errors.UnmarshalTypeError{
|
||||||
Value: "array",
|
Value: "array",
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: start,
|
Offset: start,
|
||||||
}
|
}
|
||||||
case '{':
|
case '{':
|
||||||
return 0, &UnmarshalTypeError{
|
return 0, &errors.UnmarshalTypeError{
|
||||||
Value: "object",
|
Value: "object",
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: start,
|
Offset: start,
|
||||||
}
|
}
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
return 0, &UnmarshalTypeError{
|
return 0, &errors.UnmarshalTypeError{
|
||||||
Value: "number",
|
Value: "number",
|
||||||
Type: rtype2type(d.typ),
|
Type: runtime.RType2Type(d.typ),
|
||||||
Offset: start,
|
Offset: start,
|
||||||
}
|
}
|
||||||
case 'n':
|
case 'n':
|
|
@ -1,20 +1,22 @@
|
||||||
package json
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wrappedStringDecoder struct {
|
type wrappedStringDecoder struct {
|
||||||
typ *rtype
|
typ *runtime.Type
|
||||||
dec decoder
|
dec Decoder
|
||||||
stringDecoder *stringDecoder
|
stringDecoder *stringDecoder
|
||||||
structName string
|
structName string
|
||||||
fieldName string
|
fieldName string
|
||||||
isPtrType bool
|
isPtrType bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWrappedStringDecoder(typ *rtype, dec decoder, structName, fieldName string) *wrappedStringDecoder {
|
func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) *wrappedStringDecoder {
|
||||||
return &wrappedStringDecoder{
|
return &wrappedStringDecoder{
|
||||||
typ: typ,
|
typ: typ,
|
||||||
dec: dec,
|
dec: dec,
|
||||||
|
@ -25,7 +27,7 @@ func newWrappedStringDecoder(typ *rtype, dec decoder, structName, fieldName stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *wrappedStringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
func (d *wrappedStringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
bytes, err := d.stringDecoder.decodeStreamByte(s)
|
bytes, err := d.stringDecoder.decodeStreamByte(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -38,13 +40,13 @@ func (d *wrappedStringDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
||||||
}
|
}
|
||||||
b := make([]byte, len(bytes)+1)
|
b := make([]byte, len(bytes)+1)
|
||||||
copy(b, bytes)
|
copy(b, bytes)
|
||||||
if _, err := d.dec.decode(b, 0, depth, p); err != nil {
|
if _, err := d.dec.Decode(b, 0, depth, p); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *wrappedStringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
func (d *wrappedStringDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
|
||||||
bytes, c, err := d.stringDecoder.decodeByte(buf, cursor)
|
bytes, c, err := d.stringDecoder.decodeByte(buf, cursor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -56,7 +58,7 @@ func (d *wrappedStringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
bytes = append(bytes, nul)
|
bytes = append(bytes, nul)
|
||||||
if _, err := d.dec.decode(bytes, 0, depth, p); err != nil {
|
if _, err := d.dec.Decode(bytes, 0, depth, p); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
27
rtype.go
27
rtype.go
|
@ -1,27 +0,0 @@
|
||||||
package json
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
type rtype = runtime.Type
|
|
||||||
|
|
||||||
type emptyInterface struct {
|
|
||||||
typ *rtype
|
|
||||||
ptr unsafe.Pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
func rtype_ptrTo(t *rtype) *rtype {
|
|
||||||
return runtime.PtrTo(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rtype2type(t *rtype) reflect.Type {
|
|
||||||
return runtime.RType2Type(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func type2rtype(t reflect.Type) *rtype {
|
|
||||||
return runtime.Type2RType(t)
|
|
||||||
}
|
|
Loading…
Reference in New Issue