mirror of https://github.com/goccy/go-json.git
Fix package layout for decoder
This commit is contained in:
parent
80719cf181
commit
5a024ca2f1
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)))
|
||||
}
|
147
decode.go
147
decode.go
|
@ -1,33 +1,28 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type decoder interface {
|
||||
decode([]byte, int64, int64, unsafe.Pointer) (int64, error)
|
||||
decodeStream(*stream, int64, unsafe.Pointer) error
|
||||
}
|
||||
"github.com/goccy/go-json/internal/decoder"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type Decoder struct {
|
||||
s *stream
|
||||
s *decoder.Stream
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalJSONType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
||||
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
const (
|
||||
nul = '\000'
|
||||
maxDecodeNestingDepth = 10000
|
||||
)
|
||||
|
||||
type emptyInterface struct {
|
||||
typ *runtime.Type
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
func unmarshal(data []byte, v interface{}) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||
copy(src, data)
|
||||
|
@ -37,11 +32,11 @@ func unmarshal(data []byte, v interface{}) error {
|
|||
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
||||
return err
|
||||
}
|
||||
dec, err := decodeCompileToGetDecoder(header.typ)
|
||||
dec, err := decoder.CompileToGetDecoder(header.typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cursor, err := dec.decode(src, 0, 0, header.ptr)
|
||||
cursor, err := dec.Decode(src, 0, 0, header.ptr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -57,11 +52,11 @@ func unmarshalNoEscape(data []byte, v interface{}) error {
|
|||
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
||||
return err
|
||||
}
|
||||
dec, err := decodeCompileToGetDecoder(header.typ)
|
||||
dec, err := decoder.CompileToGetDecoder(header.typ)
|
||||
if err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
@ -91,9 +86,9 @@ func noescape(p unsafe.Pointer) unsafe.Pointer {
|
|||
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 {
|
||||
return &InvalidUnmarshalError{Type: rtype2type(typ)}
|
||||
return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -103,7 +98,7 @@ func validateType(typ *rtype, p uintptr) error {
|
|||
// The decoder introduces its own buffering and may
|
||||
// read data from r beyond the JSON values requested.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
s := newStream(r)
|
||||
s := decoder.NewStream(r)
|
||||
return &Decoder{
|
||||
s: s,
|
||||
}
|
||||
|
@ -112,28 +107,7 @@ func NewDecoder(r io.Reader) *Decoder {
|
|||
// Buffered returns a reader of the data remaining in the Decoder's
|
||||
// buffer. The reader is valid until the next call to Decode.
|
||||
func (d *Decoder) Buffered() io.Reader {
|
||||
return d.s.buffered()
|
||||
}
|
||||
|
||||
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
|
||||
return d.s.Buffered()
|
||||
}
|
||||
|
||||
// Decode reads the next JSON-encoded value from its
|
||||
|
@ -147,115 +121,48 @@ func (d *Decoder) Decode(v interface{}) error {
|
|||
ptr := uintptr(header.ptr)
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
|
||||
dec, err := decodeCompileToGetDecoder(typ)
|
||||
dec, err := decoder.CompileToGetDecoder(typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.prepareForDecode(); err != nil {
|
||||
if err := d.s.PrepareForDecode(); err != nil {
|
||||
return err
|
||||
}
|
||||
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
|
||||
}
|
||||
s.reset()
|
||||
s.bufSize = initBufSize
|
||||
s.Reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) More() bool {
|
||||
s := d.s
|
||||
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
|
||||
return d.s.More()
|
||||
}
|
||||
|
||||
func (d *Decoder) Token() (Token, error) {
|
||||
s := d.s
|
||||
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
|
||||
return d.s.Token()
|
||||
}
|
||||
|
||||
// DisallowUnknownFields causes the Decoder to return an error when the destination
|
||||
// is a struct and the input contains object keys which do not match any
|
||||
// non-ignored, exported fields in the destination.
|
||||
func (d *Decoder) DisallowUnknownFields() {
|
||||
d.s.disallowUnknownFields = true
|
||||
d.s.DisallowUnknownFields = true
|
||||
}
|
||||
|
||||
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
|
||||
// Number instead of as a float64.
|
||||
func (d *Decoder) UseNumber() {
|
||||
d.s.useNumber = true
|
||||
d.s.UseNumber = true
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package json
|
||||
|
||||
var (
|
||||
NewSyntaxError = errSyntax
|
||||
NewMarshalerError = errMarshaler
|
||||
import (
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
NewSyntaxError = errors.ErrSyntax
|
||||
NewMarshalerError = errors.ErrMarshaler
|
||||
)
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type anonymousFieldDecoder struct {
|
||||
structType *rtype
|
||||
structType *runtime.Type
|
||||
offset uintptr
|
||||
dec decoder
|
||||
}
|
||||
|
||||
func newAnonymousFieldDecoder(structType *rtype, offset uintptr, dec decoder) *anonymousFieldDecoder {
|
||||
func newAnonymousFieldDecoder(structType *runtime.Type, offset uintptr, dec decoder) *anonymousFieldDecoder {
|
||||
return &anonymousFieldDecoder{
|
||||
structType: structType,
|
||||
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 {
|
||||
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
|
||||
}
|
||||
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 {
|
||||
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
|
||||
}
|
||||
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,11 +1,14 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type arrayDecoder struct {
|
||||
elemType *rtype
|
||||
elemType *runtime.Type
|
||||
size uintptr
|
||||
valueDecoder decoder
|
||||
alen int
|
||||
|
@ -14,7 +17,7 @@ type arrayDecoder struct {
|
|||
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))
|
||||
return &arrayDecoder{
|
||||
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++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
for {
|
||||
|
@ -46,7 +49,7 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
for {
|
||||
s.cursor++
|
||||
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
|
||||
}
|
||||
} else {
|
||||
|
@ -86,13 +89,13 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
s.cursor++
|
||||
}
|
||||
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++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
|
||||
for {
|
||||
|
@ -111,7 +114,7 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
for {
|
||||
cursor++
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -136,11 +139,11 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
case ',':
|
||||
continue
|
||||
default:
|
||||
return 0, errInvalidCharacter(buf[cursor], "array", cursor)
|
||||
return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return 0, errUnexpectedEndOfJSON("array", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type boolDecoder struct {
|
||||
|
@ -13,7 +15,7 @@ func newBoolDecoder(structName, fieldName string) *boolDecoder {
|
|||
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()
|
||||
for {
|
||||
switch s.char() {
|
||||
|
@ -43,10 +45,10 @@ func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
|
|||
break
|
||||
}
|
||||
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)
|
||||
switch buf[cursor] {
|
||||
case 't':
|
||||
|
@ -70,5 +72,5 @@ func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
cursor += 4
|
||||
return cursor, nil
|
||||
}
|
||||
return 0, errUnexpectedEndOfJSON("bool", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
|
||||
}
|
|
@ -1,24 +1,27 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type bytesDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
sliceDecoder decoder
|
||||
structName 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
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
unmarshalDecoder = newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName)
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
unmarshalDecoder = newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName)
|
||||
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||
unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
|
||||
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||
unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
|
||||
}
|
||||
if unmarshalDecoder == nil {
|
||||
return nil
|
||||
|
@ -26,7 +29,7 @@ func byteUnmarshalerSliceDecoder(typ *rtype, structName string, fieldName string
|
|||
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{
|
||||
typ: typ,
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -54,7 +57,7 @@ func (d *bytesDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
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)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -73,7 +76,7 @@ func (d *bytesDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
return cursor, nil
|
||||
}
|
||||
|
||||
func binaryBytes(s *stream) ([]byte, error) {
|
||||
func binaryBytes(s *Stream) ([]byte, error) {
|
||||
s.cursor++
|
||||
start := s.cursor
|
||||
for {
|
||||
|
@ -91,10 +94,10 @@ func binaryBytes(s *stream) ([]byte, error) {
|
|||
s.cursor++
|
||||
}
|
||||
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 {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
@ -109,12 +112,12 @@ func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Point
|
|||
return nil, nil
|
||||
case '[':
|
||||
if d.sliceDecoder == nil {
|
||||
return nil, &UnmarshalTypeError{
|
||||
Type: rtype2type(d.typ),
|
||||
return nil, &errors.UnmarshalTypeError{
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
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, nil
|
||||
|
@ -125,7 +128,7 @@ func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Point
|
|||
}
|
||||
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) {
|
||||
|
@ -143,18 +146,18 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Po
|
|||
cursor++
|
||||
return literal, cursor, nil
|
||||
case nul:
|
||||
return nil, 0, errUnexpectedEndOfJSON("[]byte", cursor)
|
||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("[]byte", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
case '[':
|
||||
if d.sliceDecoder == nil {
|
||||
return nil, 0, &UnmarshalTypeError{
|
||||
Type: rtype2type(d.typ),
|
||||
return nil, 0, &errors.UnmarshalTypeError{
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: cursor,
|
||||
}
|
||||
}
|
||||
c, err := d.sliceDecoder.decode(buf, cursor, depth, p)
|
||||
c, err := d.sliceDecoder.Decode(buf, cursor, depth, p)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
@ -166,7 +169,7 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Po
|
|||
cursor += 4
|
||||
return nil, cursor, nil
|
||||
default:
|
||||
return nil, 0, errNotAtBeginningOfValue(cursor)
|
||||
return nil, 0, errors.ErrNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,50 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"unicode"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
typeAddr *runtime.TypeAddr
|
||||
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
|
||||
cachedDecoder []decoder
|
||||
)
|
||||
|
||||
func 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 decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (decoder, error) {
|
||||
decoderMap := loadDecoderMap()
|
||||
if dec, exists := decoderMap[typeptr]; exists {
|
||||
return dec, nil
|
||||
|
@ -29,22 +58,22 @@ func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, er
|
|||
return dec, nil
|
||||
}
|
||||
|
||||
func decodeCompileHead(typ *rtype, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func decodeCompileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil
|
||||
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil
|
||||
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||
return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil
|
||||
}
|
||||
return decodeCompile(typ.Elem(), "", "", structTypeToDecoder)
|
||||
}
|
||||
|
||||
func decodeCompile(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func decodeCompile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
||||
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
||||
}
|
||||
|
||||
switch typ.Kind() {
|
||||
|
@ -95,18 +124,18 @@ func decodeCompile(typ *rtype, structName, fieldName string, structTypeToDecoder
|
|||
case reflect.Float64:
|
||||
return decodeCompileFloat64(structName, fieldName)
|
||||
}
|
||||
return nil, &UnmarshalTypeError{
|
||||
return nil, &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(typ),
|
||||
Type: runtime.RType2Type(typ),
|
||||
Offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func isStringTagSupportedType(typ *rtype) bool {
|
||||
func isStringTagSupportedType(typ *runtime.Type) bool {
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
|
||||
return false
|
||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||
case runtime.PtrTo(typ).Implements(unmarshalTextType):
|
||||
return false
|
||||
}
|
||||
switch typ.Kind() {
|
||||
|
@ -124,9 +153,9 @@ func isStringTagSupportedType(typ *rtype) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
if rtype_ptrTo(typ).Implements(unmarshalTextType) {
|
||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||
func decodeCompileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
if runtime.PtrTo(typ).Implements(unmarshalTextType) {
|
||||
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
|
||||
}
|
||||
dec, err := decodeCompile(typ, structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
|
@ -145,14 +174,14 @@ func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToD
|
|||
}
|
||||
}
|
||||
ERROR:
|
||||
return nil, &UnmarshalTypeError{
|
||||
return nil, &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(typ),
|
||||
Type: runtime.RType2Type(typ),
|
||||
Offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func decodeCompilePtr(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func decodeCompilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
dec, err := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -160,61 +189,61 @@ func decodeCompilePtr(typ *rtype, structName, fieldName string, structTypeToDeco
|
|||
return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileInt(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileInt(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||
*(*int)(p) = int(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileInt8(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileInt8(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||
*(*int8)(p) = int8(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileInt16(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileInt16(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||
*(*int16)(p) = int16(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileInt32(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileInt32(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||
*(*int32)(p) = int32(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileInt64(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileInt64(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
|
||||
*(*int64)(p) = v
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileUint(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileUint(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||
*(*uint)(p) = uint(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileUint8(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileUint8(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||
*(*uint8)(p) = uint8(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileUint16(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileUint16(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||
*(*uint16)(p) = uint16(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileUint32(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileUint32(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||
*(*uint32)(p) = uint32(v)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileUint64(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileUint64(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
|
||||
*(*uint64)(p) = v
|
||||
}), nil
|
||||
|
@ -232,10 +261,10 @@ func decodeCompileFloat64(structName, fieldName string) (decoder, error) {
|
|||
}), nil
|
||||
}
|
||||
|
||||
func decodeCompileString(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
if typ == type2rtype(jsonNumberType) {
|
||||
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
|
||||
*(*Number)(p) = v
|
||||
func decodeCompileString(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
if typ == runtime.Type2RType(jsonNumberType) {
|
||||
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
|
||||
*(*json.Number)(p) = v
|
||||
}), nil
|
||||
}
|
||||
return newStringDecoder(structName, fieldName), nil
|
||||
|
@ -245,11 +274,11 @@ func decodeCompileBool(structName, fieldName string) (decoder, error) {
|
|||
return newBoolDecoder(structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileBytes(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileBytes(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newBytesDecoder(typ, structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileSlice(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func decodeCompileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
elem := typ.Elem()
|
||||
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
|
@ -258,7 +287,7 @@ func decodeCompileSlice(typ *rtype, structName, fieldName string, structTypeToDe
|
|||
return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileArray(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func decodeCompileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
elem := typ.Elem()
|
||||
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
|
@ -267,7 +296,7 @@ func decodeCompileArray(typ *rtype, structName, fieldName string, structTypeToDe
|
|||
return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileMap(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
func decodeCompileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
keyDec, err := decodeCompileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -279,7 +308,7 @@ func decodeCompileMap(typ *rtype, structName, fieldName string, structTypeToDeco
|
|||
return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil
|
||||
}
|
||||
|
||||
func decodeCompileInterface(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||
func decodeCompileInterface(typ *runtime.Type, structName, fieldName string) (decoder, error) {
|
||||
return newInterfaceDecoder(typ, structName, fieldName), nil
|
||||
}
|
||||
|
||||
|
@ -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 decodeCompileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
|
||||
fieldNum := typ.NumField()
|
||||
conflictedMap := map[string]struct{}{}
|
||||
fieldMap := map[string]*structFieldSet{}
|
||||
|
@ -356,13 +385,13 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
|
|||
}
|
||||
isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
|
||||
tag := runtime.StructTagFromField(field)
|
||||
dec, err := decodeCompile(type2rtype(field.Type), structName, field.Name, structTypeToDecoder)
|
||||
dec, err := decodeCompile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if field.Anonymous && !tag.IsTaggedKey {
|
||||
if stDec, ok := dec.(*structDecoder); ok {
|
||||
if type2rtype(field.Type) == typ {
|
||||
if runtime.Type2RType(field.Type) == typ {
|
||||
// recursive definition
|
||||
continue
|
||||
}
|
||||
|
@ -438,8 +467,8 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if tag.IsString && isStringTagSupportedType(type2rtype(field.Type)) {
|
||||
dec = newWrappedStringDecoder(type2rtype(field.Type), dec, structName, field.Name)
|
||||
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
|
||||
dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name)
|
||||
}
|
||||
var key string
|
||||
if tag.Key != "" {
|
|
@ -1,16 +1,20 @@
|
|||
// +build !race
|
||||
|
||||
package json
|
||||
package decoder
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
func CompileToGetDecoder(typ *runtime.Type) (decoder, error) {
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
if typeptr > maxTypeAddr {
|
||||
if typeptr > typeAddr.MaxTypeAddr {
|
||||
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
|
||||
}
|
||||
|
||||
index := (typeptr - baseTypeAddr) >> typeAddrShift
|
||||
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
|
||||
if dec := cachedDecoder[index]; dec != nil {
|
||||
return dec, nil
|
||||
}
|
|
@ -1,15 +1,17 @@
|
|||
// +build race
|
||||
|
||||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
var decMu sync.RWMutex
|
||||
|
||||
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
|
||||
func CompileToGetDecoder(typ *runtime.Type) (decoder, error) {
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
if typeptr > maxTypeAddr {
|
||||
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
|
|
@ -1,7 +1,9 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -34,7 +36,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
|||
braceCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case '}':
|
||||
depth--
|
||||
|
@ -45,7 +47,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '[':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case ']':
|
||||
depth--
|
||||
|
@ -56,16 +58,16 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '\\':
|
||||
cursor++
|
||||
if buf[cursor] == nul {
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("object of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
|
@ -80,7 +82,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
|||
bracketCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case ']':
|
||||
bracketCount--
|
||||
|
@ -91,7 +93,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '{':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
case '}':
|
||||
depth--
|
||||
|
@ -102,16 +104,16 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '\\':
|
||||
cursor++
|
||||
if buf[cursor] == nul {
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
return 0, errUnexpectedEndOfJSON("array of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
|
@ -135,12 +137,12 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
|
|||
case '\\':
|
||||
cursor++
|
||||
if buf[cursor] == nul {
|
||||
return 0, errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
return cursor + 1, nil
|
||||
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':
|
||||
|
@ -171,58 +173,58 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
|
|||
cursor += 4
|
||||
return cursor, nil
|
||||
default:
|
||||
return cursor, errUnexpectedEndOfJSON("null", cursor)
|
||||
return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func validateTrue(buf []byte, cursor int64) error {
|
||||
if cursor+3 >= int64(len(buf)) {
|
||||
return errUnexpectedEndOfJSON("true", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("true", cursor)
|
||||
}
|
||||
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' {
|
||||
return errInvalidCharacter(buf[cursor+2], "true", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
|
||||
}
|
||||
if buf[cursor+3] != 'e' {
|
||||
return errInvalidCharacter(buf[cursor+3], "true", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateFalse(buf []byte, cursor int64) error {
|
||||
if cursor+4 >= int64(len(buf)) {
|
||||
return errUnexpectedEndOfJSON("false", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("false", cursor)
|
||||
}
|
||||
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' {
|
||||
return errInvalidCharacter(buf[cursor+2], "false", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
|
||||
}
|
||||
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' {
|
||||
return errInvalidCharacter(buf[cursor+4], "false", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateNull(buf []byte, cursor int64) error {
|
||||
if cursor+3 >= int64(len(buf)) {
|
||||
return errUnexpectedEndOfJSON("null", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("null", cursor)
|
||||
}
|
||||
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' {
|
||||
return errInvalidCharacter(buf[cursor+2], "null", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
|
||||
}
|
||||
if buf[cursor+3] != 'l' {
|
||||
return errInvalidCharacter(buf[cursor+3], "null", cursor)
|
||||
return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type floatDecoder struct {
|
||||
|
@ -47,7 +49,7 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func floatBytes(s *stream) []byte {
|
||||
func floatBytes(s *Stream) []byte {
|
||||
start := s.cursor
|
||||
for {
|
||||
s.cursor++
|
||||
|
@ -64,7 +66,7 @@ func floatBytes(s *stream) []byte {
|
|||
return s.buf[start:s.cursor]
|
||||
}
|
||||
|
||||
func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
@ -87,7 +89,7 @@ func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, 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) {
|
||||
|
@ -111,12 +113,12 @@ func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, erro
|
|||
cursor += 4
|
||||
return nil, cursor, nil
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -127,13 +129,13 @@ func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
str := *(*string)(unsafe.Pointer(&bytes))
|
||||
f64, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil {
|
||||
return errSyntax(err.Error(), s.totalOffset())
|
||||
return errors.ErrSyntax(err.Error(), s.totalOffset())
|
||||
}
|
||||
d.op(p, f64)
|
||||
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)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -143,12 +145,12 @@ func (d *floatDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
}
|
||||
cursor = c
|
||||
if !validEndNumberChar[buf[cursor]] {
|
||||
return 0, errUnexpectedEndOfJSON("float", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
|
||||
}
|
||||
s := *(*string)(unsafe.Pointer(&bytes))
|
||||
f64, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return 0, errSyntax(err.Error(), cursor)
|
||||
return 0, errors.ErrSyntax(err.Error(), cursor)
|
||||
}
|
||||
d.op(p, f64)
|
||||
return cursor, nil
|
|
@ -1,20 +1,23 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type intDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
kind reflect.Kind
|
||||
op func(unsafe.Pointer, int64)
|
||||
structName 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{
|
||||
typ: typ,
|
||||
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 {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: fmt.Sprintf("number %s", string(buf)),
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Struct: d.structName,
|
||||
Field: d.fieldName,
|
||||
Offset: offset,
|
||||
|
@ -83,7 +86,7 @@ var (
|
|||
numZeroBuf = []byte{'0'}
|
||||
)
|
||||
|
||||
func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
@ -142,7 +145,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, 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) {
|
||||
|
@ -175,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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -206,7 +209,7 @@ func (d *intDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
|||
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)
|
||||
if err != nil {
|
||||
return 0, err
|
|
@ -1,14 +1,18 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type interfaceDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
structName string
|
||||
fieldName string
|
||||
sliceDecoder *sliceDecoder
|
||||
|
@ -26,7 +30,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
|
|||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||
*(*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
|
||||
}),
|
||||
stringDecoder: newStringDecoder(structName, fieldName),
|
||||
|
@ -49,7 +53,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
|
|||
return ifaceDecoder
|
||||
}
|
||||
|
||||
func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder {
|
||||
func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
|
||||
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
|
||||
stringDecoder := newStringDecoder(structName, fieldName)
|
||||
return &interfaceDecoder{
|
||||
|
@ -74,31 +78,31 @@ func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDec
|
|||
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
|
||||
*(*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
|
||||
}),
|
||||
stringDecoder: stringDecoder,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *interfaceDecoder) numDecoder(s *stream) decoder {
|
||||
if s.useNumber {
|
||||
func (d *interfaceDecoder) numDecoder(s *Stream) decoder {
|
||||
if s.UseNumber {
|
||||
return d.numberDecoder
|
||||
}
|
||||
return d.floatDecoder
|
||||
}
|
||||
|
||||
var (
|
||||
emptyInterfaceType = type2rtype(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||
interfaceMapType = type2rtype(
|
||||
emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||
interfaceMapType = runtime.Type2RType(
|
||||
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
|
||||
)
|
||||
stringType = type2rtype(
|
||||
stringType = runtime.Type2RType(
|
||||
reflect.TypeOf(""),
|
||||
)
|
||||
)
|
||||
|
||||
func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) error {
|
||||
func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
|
||||
start := s.cursor
|
||||
if err := s.skipValue(depth); err != nil {
|
||||
return err
|
||||
|
@ -113,7 +117,7 @@ func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) er
|
|||
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)
|
||||
start := cursor
|
||||
end, err := skipValue(buf, cursor, depth)
|
||||
|
@ -130,7 +134,7 @@ func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler)
|
|||
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
|
||||
if err := s.skipValue(depth); err != nil {
|
||||
return err
|
||||
|
@ -171,14 +175,14 @@ func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding
|
|||
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()
|
||||
for {
|
||||
switch s.char() {
|
||||
case '{':
|
||||
var v map[string]interface{}
|
||||
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
|
||||
}
|
||||
*(*interface{})(p) = v
|
||||
|
@ -186,13 +190,13 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
|||
case '[':
|
||||
var v []interface{}
|
||||
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
|
||||
}
|
||||
*(*interface{})(p) = v
|
||||
return nil
|
||||
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 '"':
|
||||
s.cursor++
|
||||
start := s.cursor
|
||||
|
@ -211,7 +215,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
|||
if s.read() {
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
s.cursor++
|
||||
}
|
||||
|
@ -240,17 +244,22 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
|
|||
}
|
||||
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{
|
||||
typ: d.typ,
|
||||
ptr: p,
|
||||
}))
|
||||
rv := reflect.ValueOf(runtimeInterfaceValue)
|
||||
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)
|
||||
}
|
||||
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
|
||||
return nil
|
||||
}
|
||||
decoder, err := decodeCompileToGetDecoder(typ)
|
||||
decoder, err := CompileToGetDecoder(typ)
|
||||
if err != nil {
|
||||
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 {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: typ.String(),
|
||||
Type: typ,
|
||||
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{
|
||||
typ: d.typ,
|
||||
ptr: p,
|
||||
}))
|
||||
rv := reflect.ValueOf(runtimeInterfaceValue)
|
||||
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)
|
||||
}
|
||||
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
|
||||
return cursor, nil
|
||||
}
|
||||
decoder, err := decodeCompileToGetDecoder(typ)
|
||||
decoder, err := CompileToGetDecoder(typ)
|
||||
if err != nil {
|
||||
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) {
|
||||
|
@ -358,7 +367,7 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
|||
case '{':
|
||||
var v map[string]interface{}
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -367,18 +376,18 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
|||
case '[':
|
||||
var v []interface{}
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
**(**interface{})(unsafe.Pointer(&p)) = v
|
||||
return cursor, nil
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return d.floatDecoder.decode(buf, cursor, depth, p)
|
||||
return d.floatDecoder.Decode(buf, cursor, depth, p)
|
||||
case '"':
|
||||
var v string
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -406,5 +415,5 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
|
|||
**(**interface{})(unsafe.Pointer(&p)) = nil
|
||||
return cursor, nil
|
||||
}
|
||||
return cursor, errNotAtBeginningOfValue(cursor)
|
||||
return cursor, errors.ErrNotAtBeginningOfValue(cursor)
|
||||
}
|
|
@ -1,20 +1,23 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type mapDecoder struct {
|
||||
mapType *rtype
|
||||
keyType *rtype
|
||||
valueType *rtype
|
||||
mapType *runtime.Type
|
||||
keyType *runtime.Type
|
||||
valueType *runtime.Type
|
||||
keyDecoder decoder
|
||||
valueDecoder decoder
|
||||
structName 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{
|
||||
mapType: mapType,
|
||||
keyDecoder: keyDec,
|
||||
|
@ -27,16 +30,16 @@ func newMapDecoder(mapType *rtype, keyType *rtype, keyDec decoder, valueType *rt
|
|||
}
|
||||
|
||||
//go:linkname makemap reflect.makemap
|
||||
func makemap(*rtype, int) unsafe.Pointer
|
||||
func makemap(*runtime.Type, int) unsafe.Pointer
|
||||
|
||||
//go:linkname mapassign reflect.mapassign
|
||||
//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++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
s.skipWhiteSpace()
|
||||
|
@ -49,7 +52,7 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
|||
return nil
|
||||
case '{':
|
||||
default:
|
||||
return errExpected("{ character for map value", s.totalOffset())
|
||||
return errors.ErrExpected("{ character for map value", s.totalOffset())
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
mapValue := *(*unsafe.Pointer)(p)
|
||||
|
@ -64,16 +67,16 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
|||
for {
|
||||
s.cursor++
|
||||
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
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
if !s.equalChar(':') {
|
||||
return errExpected("colon after object key", s.totalOffset())
|
||||
return errors.ErrExpected("colon after object key", s.totalOffset())
|
||||
}
|
||||
s.cursor++
|
||||
v := unsafe_New(d.valueType)
|
||||
if err := d.valueDecoder.decodeStream(s, depth, v); err != nil {
|
||||
if err := d.valueDecoder.DecodeStream(s, depth, v); err != nil {
|
||||
return err
|
||||
}
|
||||
mapassign(d.mapType, mapValue, k, v)
|
||||
|
@ -84,21 +87,21 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
|||
return nil
|
||||
}
|
||||
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++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
buflen := int64(len(buf))
|
||||
if buflen < 2 {
|
||||
return 0, errExpected("{} for map", cursor)
|
||||
return 0, errors.ErrExpected("{} for map", cursor)
|
||||
}
|
||||
switch buf[cursor] {
|
||||
case 'n':
|
||||
|
@ -110,7 +113,7 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
|||
return cursor, nil
|
||||
case '{':
|
||||
default:
|
||||
return 0, errExpected("{ character for map value", cursor)
|
||||
return 0, errors.ErrExpected("{ character for map value", cursor)
|
||||
}
|
||||
cursor++
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
|
@ -125,17 +128,17 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
|||
}
|
||||
for {
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
cursor = skipWhiteSpace(buf, keyCursor)
|
||||
if buf[cursor] != ':' {
|
||||
return 0, errExpected("colon after object key", cursor)
|
||||
return 0, errors.ErrExpected("colon after object key", cursor)
|
||||
}
|
||||
cursor++
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -147,7 +150,7 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
|||
return cursor, nil
|
||||
}
|
||||
if buf[cursor] != ',' {
|
||||
return 0, errExpected("comma after object value", cursor)
|
||||
return 0, errors.ErrExpected("comma after object value", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
|
@ -1,18 +1,21 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type numberDecoder struct {
|
||||
stringDecoder *stringDecoder
|
||||
op func(unsafe.Pointer, Number)
|
||||
op func(unsafe.Pointer, json.Number)
|
||||
structName 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{
|
||||
stringDecoder: newStringDecoder(structName, fieldName),
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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()
|
||||
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)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
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
|
||||
s := *(*string)(unsafe.Pointer(&bytes))
|
||||
d.op(p, Number(s))
|
||||
d.op(p, json.Number(s))
|
||||
return cursor, nil
|
||||
}
|
||||
|
||||
func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
@ -73,7 +76,7 @@ func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, 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) {
|
||||
|
@ -99,7 +102,7 @@ func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||
case '"':
|
||||
return d.stringDecoder.decodeByte(buf, cursor)
|
||||
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 (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type ptrDecoder struct {
|
||||
dec decoder
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
structName 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{
|
||||
dec: dec,
|
||||
typ: typ,
|
||||
|
@ -30,9 +32,9 @@ func (d *ptrDecoder) contentDecoder() decoder {
|
|||
|
||||
//nolint:golint
|
||||
//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()
|
||||
if s.char() == nul {
|
||||
s.read()
|
||||
|
@ -51,13 +53,13 @@ func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
|
|||
} else {
|
||||
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 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)
|
||||
if buf[cursor] == 'n' {
|
||||
if err := validateNull(buf, cursor); err != nil {
|
||||
|
@ -76,7 +78,7 @@ func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
|
|||
} else {
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
|
@ -1,13 +1,16 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type sliceDecoder struct {
|
||||
elemType *rtype
|
||||
elemType *runtime.Type
|
||||
isElemPointerType bool
|
||||
valueDecoder decoder
|
||||
size uintptr
|
||||
|
@ -29,7 +32,7 @@ const (
|
|||
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{
|
||||
valueDecoder: dec,
|
||||
elemType: elemType,
|
||||
|
@ -71,28 +74,28 @@ func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
|
|||
}
|
||||
|
||||
//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
|
||||
func newArray(*rtype, int) unsafe.Pointer
|
||||
func newArray(*runtime.Type, int) unsafe.Pointer
|
||||
|
||||
//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 {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "number",
|
||||
Type: reflect.SliceOf(rtype2type(d.elemType)),
|
||||
Type: reflect.SliceOf(runtime.RType2Type(d.elemType)),
|
||||
Struct: d.structName,
|
||||
Field: d.fieldName,
|
||||
Offset: offset,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
|
||||
func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
s.skipWhiteSpace()
|
||||
|
@ -194,13 +197,13 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
|
|||
}
|
||||
}
|
||||
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++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
c, err := d.valueDecoder.decode(buf, cursor, depth, ep)
|
||||
c, err := d.valueDecoder.Decode(buf, cursor, depth, ep)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -278,14 +281,14 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
|
|||
slice.cap = capacity
|
||||
slice.data = data
|
||||
d.releaseSlice(slice)
|
||||
return 0, errInvalidCharacter(buf[cursor], "slice", cursor)
|
||||
return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return 0, d.errNumber(cursor)
|
||||
default:
|
||||
return 0, errUnexpectedEndOfJSON("slice", cursor)
|
||||
return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,20 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
initBufSize = 512
|
||||
)
|
||||
|
||||
type stream struct {
|
||||
type Stream struct {
|
||||
buf []byte
|
||||
bufSize int64
|
||||
length int64
|
||||
|
@ -19,19 +23,23 @@ type stream struct {
|
|||
cursor int64
|
||||
filledBuffer bool
|
||||
allRead bool
|
||||
useNumber bool
|
||||
disallowUnknownFields bool
|
||||
UseNumber bool
|
||||
DisallowUnknownFields bool
|
||||
}
|
||||
|
||||
func newStream(r io.Reader) *stream {
|
||||
return &stream{
|
||||
func NewStream(r io.Reader) *Stream {
|
||||
return &Stream{
|
||||
r: r,
|
||||
bufSize: initBufSize,
|
||||
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))
|
||||
for i := s.cursor; i < buflen; i++ {
|
||||
if s.buf[i] == nul {
|
||||
|
@ -41,15 +49,35 @@ func (s *stream) buffered() io.Reader {
|
|||
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
|
||||
}
|
||||
|
||||
func (s *stream) char() byte {
|
||||
func (s *Stream) char() byte {
|
||||
return s.buf[s.cursor]
|
||||
}
|
||||
|
||||
func (s *stream) equalChar(c byte) bool {
|
||||
func (s *Stream) equalChar(c byte) bool {
|
||||
cur := s.buf[s.cursor]
|
||||
if cur == nul {
|
||||
s.read()
|
||||
|
@ -58,23 +86,100 @@ func (s *stream) equalChar(c byte) bool {
|
|||
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
|
||||
}
|
||||
|
||||
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 )
|
||||
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.buf = s.buf[s.cursor:]
|
||||
s.length -= s.cursor
|
||||
s.cursor = 0
|
||||
}
|
||||
|
||||
func (s *stream) readBuf() []byte {
|
||||
func (s *Stream) readBuf() []byte {
|
||||
if s.filledBuffer {
|
||||
s.bufSize *= 2
|
||||
remainBuf := s.buf
|
||||
|
@ -92,7 +197,7 @@ func (s *stream) readBuf() []byte {
|
|||
return s.buf[s.cursor+remainNotNulCharNum:]
|
||||
}
|
||||
|
||||
func (s *stream) read() bool {
|
||||
func (s *Stream) read() bool {
|
||||
if s.allRead {
|
||||
return false
|
||||
}
|
||||
|
@ -114,7 +219,7 @@ func (s *stream) read() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *stream) skipWhiteSpace() {
|
||||
func (s *Stream) skipWhiteSpace() {
|
||||
LOOP:
|
||||
switch s.char() {
|
||||
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
|
||||
_, cursor, p := s.stat()
|
||||
for {
|
||||
|
@ -136,7 +241,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
braceCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case '}':
|
||||
braceCount--
|
||||
|
@ -148,7 +253,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
case '[':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case ']':
|
||||
depth--
|
||||
|
@ -164,7 +269,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
|
@ -174,7 +279,7 @@ func (s *stream) skipObject(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
|
@ -183,14 +288,14 @@ func (s *stream) skipObject(depth int64) error {
|
|||
_, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("object of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("object of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) skipArray(depth int64) error {
|
||||
func (s *Stream) skipArray(depth int64) error {
|
||||
bracketCount := 1
|
||||
_, cursor, p := s.stat()
|
||||
for {
|
||||
|
@ -199,7 +304,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
bracketCount++
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case ']':
|
||||
bracketCount--
|
||||
|
@ -211,7 +316,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
case '{':
|
||||
depth++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
case '}':
|
||||
depth--
|
||||
|
@ -227,7 +332,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
case '"':
|
||||
goto SWITCH_OUT
|
||||
|
@ -237,7 +342,7 @@ func (s *stream) skipArray(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("string of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||
}
|
||||
}
|
||||
case nul:
|
||||
|
@ -246,14 +351,14 @@ func (s *stream) skipArray(depth int64) error {
|
|||
_, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("array of object", cursor)
|
||||
return errors.ErrUnexpectedEndOfJSON("array of object", cursor)
|
||||
}
|
||||
SWITCH_OUT:
|
||||
cursor++
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) skipValue(depth int64) error {
|
||||
func (s *Stream) skipValue(depth int64) error {
|
||||
_, cursor, p := s.stat()
|
||||
for {
|
||||
switch char(p, cursor) {
|
||||
|
@ -266,7 +371,7 @@ func (s *stream) skipValue(depth int64) error {
|
|||
_, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("value of object", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset())
|
||||
case '{':
|
||||
s.cursor = cursor + 1
|
||||
return s.skipObject(depth + 1)
|
||||
|
@ -285,7 +390,7 @@ func (s *stream) skipValue(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
continue
|
||||
}
|
||||
return errUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||
}
|
||||
case '"':
|
||||
s.cursor = cursor + 1
|
||||
|
@ -296,7 +401,7 @@ func (s *stream) skipValue(depth int64) error {
|
|||
_, cursor, p = s.statForRetry()
|
||||
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':
|
||||
|
@ -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'
|
||||
s.cursor++
|
||||
if s.char() != 'u' {
|
||||
|
@ -362,14 +467,14 @@ func nullBytes(s *stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func retryReadNull(s *stream) error {
|
||||
func retryReadNull(s *Stream) error {
|
||||
if s.char() == nul && s.read() {
|
||||
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'
|
||||
s.cursor++
|
||||
if s.char() != 'r' {
|
||||
|
@ -393,14 +498,14 @@ func trueBytes(s *stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func retryReadTrue(s *stream) error {
|
||||
func retryReadTrue(s *Stream) error {
|
||||
if s.char() == nul && s.read() {
|
||||
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'
|
||||
s.cursor++
|
||||
if s.char() != 'a' {
|
||||
|
@ -430,9 +535,9 @@ func falseBytes(s *stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func retryReadFalse(s *stream) error {
|
||||
func retryReadFalse(s *Stream) error {
|
||||
if s.char() == nul && s.read() {
|
||||
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 (
|
||||
"reflect"
|
||||
|
@ -6,6 +6,8 @@ import (
|
|||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type stringDecoder struct {
|
||||
|
@ -20,8 +22,8 @@ func newStringDecoder(structName, fieldName string) *stringDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *UnmarshalTypeError {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: typeName,
|
||||
Type: reflect.TypeOf(""),
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -43,7 +45,7 @@ func (d *stringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
|||
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)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -91,13 +93,13 @@ func unicodeToRune(code []byte) rune {
|
|||
return r
|
||||
}
|
||||
|
||||
func decodeUnicodeRune(s *stream) (rune, int64, error) {
|
||||
func decodeUnicodeRune(s *Stream) (rune, int64, error) {
|
||||
const defaultOffset = 5
|
||||
const surrogateOffset = 11
|
||||
|
||||
if s.cursor+defaultOffset >= s.length {
|
||||
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
|
||||
}
|
||||
|
||||
func decodeUnicode(s *stream) error {
|
||||
func decodeUnicode(s *Stream) error {
|
||||
const backSlashAndULen = 2 // length of \u
|
||||
|
||||
r, offset, err := decodeUnicodeRune(s)
|
||||
|
@ -133,7 +135,7 @@ func decodeUnicode(s *stream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func decodeEscapeString(s *stream) error {
|
||||
func decodeEscapeString(s *Stream) error {
|
||||
s.cursor++
|
||||
RETRY:
|
||||
switch s.buf[s.cursor] {
|
||||
|
@ -157,11 +159,11 @@ RETRY:
|
|||
return decodeUnicode(s)
|
||||
case nul:
|
||||
if !s.read() {
|
||||
return errInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||
return errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||
}
|
||||
goto RETRY
|
||||
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.length--
|
||||
|
@ -174,7 +176,7 @@ var (
|
|||
runeErrBytesLen = int64(len(runeErrBytes))
|
||||
)
|
||||
|
||||
func stringBytes(s *stream) ([]byte, error) {
|
||||
func stringBytes(s *Stream) ([]byte, error) {
|
||||
_, cursor, p := s.stat()
|
||||
cursor++ // skip double quote char
|
||||
start := cursor
|
||||
|
@ -245,10 +247,10 @@ func stringBytes(s *stream) ([]byte, error) {
|
|||
cursor++
|
||||
}
|
||||
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 {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
@ -274,7 +276,7 @@ func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
return nil, errNotAtBeginningOfValue(s.totalOffset())
|
||||
return nil, errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||
}
|
||||
|
||||
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':
|
||||
buflen := int64(len(buf))
|
||||
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])
|
||||
unicode := []byte(string(code))
|
||||
buf = append(append(buf[:cursor-1], unicode...), buf[cursor+5:]...)
|
||||
default:
|
||||
return nil, 0, errUnexpectedEndOfJSON("escaped string", cursor)
|
||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
|
||||
}
|
||||
continue
|
||||
case '"':
|
||||
|
@ -338,7 +340,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||
cursor++
|
||||
return literal, cursor, nil
|
||||
case nul:
|
||||
return nil, 0, errUnexpectedEndOfJSON("string", cursor)
|
||||
return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
cursor++
|
||||
}
|
||||
|
@ -349,7 +351,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
|
|||
cursor += 4
|
||||
return nil, cursor, nil
|
||||
default:
|
||||
return nil, 0, errNotAtBeginningOfValue(cursor)
|
||||
return nil, 0, errors.ErrNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -7,6 +7,8 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
)
|
||||
|
||||
type structFieldSet struct {
|
||||
|
@ -28,7 +30,7 @@ type structDecoder struct {
|
|||
keyBitmapUint16 [][256]uint16
|
||||
sortedFieldSets []*structFieldSet
|
||||
keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
|
||||
keyStreamDecoder func(*structDecoder, *stream) (*structFieldSet, string, error)
|
||||
keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error)
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -154,7 +156,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
cursor++
|
||||
return cursor, field, nil
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
keyIdx := 0
|
||||
bitmap := d.keyBitmapUint8
|
||||
|
@ -173,7 +175,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
}
|
||||
return cursor, field, nil
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
|
@ -186,10 +188,10 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
case '\\':
|
||||
cursor++
|
||||
if char(b, cursor) == nul {
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +200,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
cursor++
|
||||
}
|
||||
default:
|
||||
return cursor, nil, errNotAtBeginningOfValue(cursor)
|
||||
return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +223,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
cursor++
|
||||
return cursor, field, nil
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
keyIdx := 0
|
||||
bitmap := d.keyBitmapUint16
|
||||
|
@ -240,7 +242,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
}
|
||||
return cursor, field, nil
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
|
@ -253,10 +255,10 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
case '\\':
|
||||
cursor++
|
||||
if char(b, cursor) == nul {
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
case nul:
|
||||
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
|
||||
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +267,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
|
|||
cursor++
|
||||
}
|
||||
default:
|
||||
return cursor, nil, errNotAtBeginningOfValue(cursor)
|
||||
return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -284,7 +286,7 @@ func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldS
|
|||
return cursor, field, nil
|
||||
}
|
||||
|
||||
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
|
||||
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
|
||||
var (
|
||||
field *structFieldSet
|
||||
curBit uint8 = math.MaxUint8
|
||||
|
@ -300,7 +302,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
|||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
||||
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||
case '"':
|
||||
cursor++
|
||||
FIRST_CHAR:
|
||||
|
@ -316,7 +318,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
|||
buf, cursor, p = s.stat()
|
||||
goto FIRST_CHAR
|
||||
}
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
keyIdx := 0
|
||||
bitmap := d.keyBitmapUint8
|
||||
|
@ -340,7 +342,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
|||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
|
@ -358,14 +360,14 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
|||
if char(p, cursor) == nul {
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
|
@ -376,12 +378,12 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
|
|||
cursor++
|
||||
}
|
||||
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 (
|
||||
field *structFieldSet
|
||||
curBit uint16 = math.MaxUint16
|
||||
|
@ -397,7 +399,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
|||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
||||
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||
case '"':
|
||||
cursor++
|
||||
FIRST_CHAR:
|
||||
|
@ -413,7 +415,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
|||
buf, cursor, p = s.stat()
|
||||
goto FIRST_CHAR
|
||||
}
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
keyIdx := 0
|
||||
bitmap := d.keyBitmapUint16
|
||||
|
@ -437,7 +439,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
|||
buf, cursor, p = s.stat()
|
||||
continue
|
||||
}
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
default:
|
||||
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
|
||||
if curBit == 0 {
|
||||
|
@ -455,14 +457,14 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
|||
if char(p, cursor) == nul {
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
case nul:
|
||||
s.cursor = cursor
|
||||
if !s.read() {
|
||||
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||
}
|
||||
buf, cursor, p = s.statForRetry()
|
||||
}
|
||||
|
@ -473,12 +475,12 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
|
|||
cursor++
|
||||
}
|
||||
default:
|
||||
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
|
||||
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
|
||||
func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
|
||||
key, err := d.stringDecoder.decodeStreamByte(s)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
@ -487,10 +489,10 @@ func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, erro
|
|||
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++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return errExceededMaxDepth(s.char(), s.cursor)
|
||||
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
|
||||
}
|
||||
|
||||
s.skipWhiteSpace()
|
||||
|
@ -504,7 +506,7 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
|||
s.read()
|
||||
default:
|
||||
if s.char() != '{' {
|
||||
return errNotAtBeginningOfValue(s.totalOffset())
|
||||
return errors.ErrNotAtBeginningOfValue(s.totalOffset())
|
||||
}
|
||||
}
|
||||
s.cursor++
|
||||
|
@ -521,22 +523,22 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
|||
}
|
||||
s.skipWhiteSpace()
|
||||
if s.char() != ':' {
|
||||
return errExpected("colon after object key", s.totalOffset())
|
||||
return errors.ErrExpected("colon after object key", s.totalOffset())
|
||||
}
|
||||
s.cursor++
|
||||
if s.char() == nul {
|
||||
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.err != nil {
|
||||
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
|
||||
}
|
||||
} else if s.disallowUnknownFields {
|
||||
} else if s.DisallowUnknownFields {
|
||||
return fmt.Errorf("json: unknown field %q", key)
|
||||
} else {
|
||||
if err := s.skipValue(depth); err != nil {
|
||||
|
@ -550,16 +552,16 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
|
|||
return nil
|
||||
}
|
||||
if c != ',' {
|
||||
return errExpected("comma after object element", s.totalOffset())
|
||||
return errors.ErrExpected("comma after object element", s.totalOffset())
|
||||
}
|
||||
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++
|
||||
if depth > maxDecodeNestingDepth {
|
||||
return 0, errExceededMaxDepth(buf[cursor], cursor)
|
||||
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||
}
|
||||
buflen := int64(len(buf))
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
|
@ -573,7 +575,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
|
|||
return cursor, nil
|
||||
case '{':
|
||||
default:
|
||||
return 0, errNotAtBeginningOfValue(cursor)
|
||||
return 0, errors.ErrNotAtBeginningOfValue(cursor)
|
||||
}
|
||||
cursor++
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
|
@ -588,17 +590,17 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
|
|||
}
|
||||
cursor = skipWhiteSpace(buf, c)
|
||||
if char(b, cursor) != ':' {
|
||||
return 0, errExpected("colon after object key", cursor)
|
||||
return 0, errors.ErrExpected("colon after object key", cursor)
|
||||
}
|
||||
cursor++
|
||||
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.err != nil {
|
||||
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 {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -616,7 +618,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
|
|||
return cursor, nil
|
||||
}
|
||||
if char(b, cursor) != ',' {
|
||||
return 0, errExpected("comma after object element", cursor)
|
||||
return 0, errors.ErrExpected("comma after object element", 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 (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type uintDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
kind reflect.Kind
|
||||
op func(unsafe.Pointer, uint64)
|
||||
structName 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{
|
||||
typ: typ,
|
||||
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 {
|
||||
return &UnmarshalTypeError{
|
||||
func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: fmt.Sprintf("number %s", string(buf)),
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: offset,
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +57,7 @@ func (d *uintDecoder) parseUint(b []byte) (uint64, error) {
|
|||
return sum, nil
|
||||
}
|
||||
|
||||
func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
||||
func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||
for {
|
||||
switch s.char() {
|
||||
case ' ', '\n', '\t', '\r':
|
||||
|
@ -93,7 +96,7 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
|
|||
}
|
||||
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) {
|
||||
|
@ -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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -155,7 +158,7 @@ func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
|
|||
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)
|
||||
if err != nil {
|
||||
return 0, err
|
|
@ -1,16 +1,20 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type unmarshalJSONDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newUnmarshalJSONDecoder(typ *rtype, structName, fieldName string) *unmarshalJSONDecoder {
|
||||
func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
|
||||
return &unmarshalJSONDecoder{
|
||||
typ: typ,
|
||||
structName: structName,
|
||||
|
@ -20,15 +24,15 @@ func newUnmarshalJSONDecoder(typ *rtype, structName, fieldName string) *unmarsha
|
|||
|
||||
func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
|
||||
switch e := err.(type) {
|
||||
case *UnmarshalTypeError:
|
||||
case *errors.UnmarshalTypeError:
|
||||
e.Struct = d.structName
|
||||
e.Field = d.fieldName
|
||||
case *SyntaxError:
|
||||
case *errors.SyntaxError:
|
||||
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()
|
||||
start := s.cursor
|
||||
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,
|
||||
ptr: p,
|
||||
}))
|
||||
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||
d.annotateError(s.cursor, err)
|
||||
return err
|
||||
}
|
||||
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)
|
||||
start := cursor
|
||||
end, err := skipValue(buf, cursor, depth)
|
||||
|
@ -64,7 +68,7 @@ func (d *unmarshalJSONDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
|
|||
typ: d.typ,
|
||||
ptr: p,
|
||||
}))
|
||||
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
|
||||
d.annotateError(cursor, err)
|
||||
return 0, err
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -7,15 +7,18 @@ import (
|
|||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/errors"
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type unmarshalTextDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
structName string
|
||||
fieldName string
|
||||
}
|
||||
|
||||
func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarshalTextDecoder {
|
||||
func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder {
|
||||
return &unmarshalTextDecoder{
|
||||
typ: typ,
|
||||
structName: structName,
|
||||
|
@ -25,10 +28,10 @@ func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarsha
|
|||
|
||||
func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) {
|
||||
switch e := err.(type) {
|
||||
case *UnmarshalTypeError:
|
||||
case *errors.UnmarshalTypeError:
|
||||
e.Struct = d.structName
|
||||
e.Field = d.fieldName
|
||||
case *SyntaxError:
|
||||
case *errors.SyntaxError:
|
||||
e.Offset = cursor
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +40,7 @@ var (
|
|||
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()
|
||||
start := s.cursor
|
||||
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 {
|
||||
switch src[0] {
|
||||
case '[':
|
||||
return &UnmarshalTypeError{
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "array",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: s.totalOffset(),
|
||||
}
|
||||
case '{':
|
||||
return &UnmarshalTypeError{
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: s.totalOffset(),
|
||||
}
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return &UnmarshalTypeError{
|
||||
return &errors.UnmarshalTypeError{
|
||||
Value: "number",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: s.totalOffset(),
|
||||
}
|
||||
case 'n':
|
||||
|
@ -88,7 +91,7 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
|||
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)
|
||||
start := cursor
|
||||
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 {
|
||||
switch src[0] {
|
||||
case '[':
|
||||
return 0, &UnmarshalTypeError{
|
||||
return 0, &errors.UnmarshalTypeError{
|
||||
Value: "array",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: start,
|
||||
}
|
||||
case '{':
|
||||
return 0, &UnmarshalTypeError{
|
||||
return 0, &errors.UnmarshalTypeError{
|
||||
Value: "object",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: start,
|
||||
}
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return 0, &UnmarshalTypeError{
|
||||
return 0, &errors.UnmarshalTypeError{
|
||||
Value: "number",
|
||||
Type: rtype2type(d.typ),
|
||||
Type: runtime.RType2Type(d.typ),
|
||||
Offset: start,
|
||||
}
|
||||
case 'n':
|
|
@ -1,12 +1,14 @@
|
|||
package json
|
||||
package decoder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type wrappedStringDecoder struct {
|
||||
typ *rtype
|
||||
typ *runtime.Type
|
||||
dec decoder
|
||||
stringDecoder *stringDecoder
|
||||
structName string
|
||||
|
@ -14,7 +16,7 @@ type wrappedStringDecoder struct {
|
|||
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{
|
||||
typ: typ,
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -38,13 +40,13 @@ func (d *wrappedStringDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
|
|||
}
|
||||
b := make([]byte, len(bytes)+1)
|
||||
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 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)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -56,7 +58,7 @@ func (d *wrappedStringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
|
|||
return c, nil
|
||||
}
|
||||
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 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