Merge pull request #238 from goccy/feature/refactor-decoder

Refactor package layout for decoder
This commit is contained in:
Masaaki Goshima 2021-06-03 19:53:50 +09:00 committed by GitHub
commit 7d7af9fb36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 723 additions and 745 deletions

View File

@ -191,7 +191,7 @@ For this reason, to date `reflect.Type` is the same as `*reflect.rtype`.
Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`. Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`.
The technique for working with `*reflect.rtype` directly from `go-json` is implemented at https://github.com/goccy/go-json/blob/master/rtype.go. The technique for working with `*reflect.rtype` directly from `go-json` is implemented at [rtype.go](https://github.com/goccy/go-json/blob/master/internal/runtime/rtype.go)
Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect ) Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect )
@ -352,7 +352,7 @@ However, if there is too much type information, it will use a lot of memory, so
If this approach is not available, it will fall back to the `atomic` based process described above. If this approach is not available, it will fall back to the `atomic` based process described above.
If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/codec.go#L24-L76 ) If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/internal/runtime/type.go#L36-L100)
## Decoder ## Decoder

104
codec.go
View File

@ -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)))
}

View File

@ -1,13 +0,0 @@
// +build go1.16
package json
import (
"testing"
)
func TestTypeAddressAligned32(t *testing.T) {
if typeAddrShift != 5 {
t.Fatalf("unexpected type address shift %d, want 5", typeAddrShift)
}
}

150
decode.go
View File

@ -1,33 +1,29 @@
package json package json
import ( import (
"encoding"
"fmt" "fmt"
"io" "io"
"reflect" "reflect"
"strconv"
"unsafe" "unsafe"
)
type decoder interface { "github.com/goccy/go-json/internal/decoder"
decode([]byte, int64, int64, unsafe.Pointer) (int64, error) "github.com/goccy/go-json/internal/errors"
decodeStream(*stream, int64, unsafe.Pointer) error "github.com/goccy/go-json/internal/runtime"
} )
type Decoder struct { type Decoder struct {
s *stream s *decoder.Stream
} }
var (
unmarshalJSONType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)
const ( const (
nul = '\000' nul = '\000'
maxDecodeNestingDepth = 10000
) )
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
func unmarshal(data []byte, v interface{}) error { func unmarshal(data []byte, v interface{}) error {
src := make([]byte, len(data)+1) // append nul byte to the end src := make([]byte, len(data)+1) // append nul byte to the end
copy(src, data) copy(src, data)
@ -37,11 +33,11 @@ func unmarshal(data []byte, v interface{}) error {
if err := validateType(header.typ, uintptr(header.ptr)); err != nil { if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
return err return err
} }
dec, err := decodeCompileToGetDecoder(header.typ) dec, err := decoder.CompileToGetDecoder(header.typ)
if err != nil { if err != nil {
return err return err
} }
cursor, err := dec.decode(src, 0, 0, header.ptr) cursor, err := dec.Decode(src, 0, 0, header.ptr)
if err != nil { if err != nil {
return err return err
} }
@ -57,11 +53,11 @@ func unmarshalNoEscape(data []byte, v interface{}) error {
if err := validateType(header.typ, uintptr(header.ptr)); err != nil { if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
return err return err
} }
dec, err := decodeCompileToGetDecoder(header.typ) dec, err := decoder.CompileToGetDecoder(header.typ)
if err != nil { if err != nil {
return err return err
} }
cursor, err := dec.decode(src, 0, 0, noescape(header.ptr)) cursor, err := dec.Decode(src, 0, 0, noescape(header.ptr))
if err != nil { if err != nil {
return err return err
} }
@ -77,7 +73,7 @@ func validateEndBuf(src []byte, cursor int64) error {
case nul: case nul:
return nil return nil
} }
return errSyntax( return errors.ErrSyntax(
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]), fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
cursor+1, cursor+1,
) )
@ -91,9 +87,9 @@ func noescape(p unsafe.Pointer) unsafe.Pointer {
return unsafe.Pointer(x ^ 0) return unsafe.Pointer(x ^ 0)
} }
func validateType(typ *rtype, p uintptr) error { func validateType(typ *runtime.Type, p uintptr) error {
if typ == nil || typ.Kind() != reflect.Ptr || p == 0 { if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
return &InvalidUnmarshalError{Type: rtype2type(typ)} return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)}
} }
return nil return nil
} }
@ -103,7 +99,7 @@ func validateType(typ *rtype, p uintptr) error {
// The decoder introduces its own buffering and may // The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested. // read data from r beyond the JSON values requested.
func NewDecoder(r io.Reader) *Decoder { func NewDecoder(r io.Reader) *Decoder {
s := newStream(r) s := decoder.NewStream(r)
return &Decoder{ return &Decoder{
s: s, s: s,
} }
@ -112,28 +108,7 @@ func NewDecoder(r io.Reader) *Decoder {
// Buffered returns a reader of the data remaining in the Decoder's // Buffered returns a reader of the data remaining in the Decoder's
// buffer. The reader is valid until the next call to Decode. // buffer. The reader is valid until the next call to Decode.
func (d *Decoder) Buffered() io.Reader { func (d *Decoder) Buffered() io.Reader {
return d.s.buffered() return d.s.Buffered()
}
func (d *Decoder) prepareForDecode() error {
s := d.s
for {
switch s.char() {
case ' ', '\t', '\r', '\n':
s.cursor++
continue
case ',', ':':
s.cursor++
return nil
case nul:
if s.read() {
continue
}
return io.EOF
}
break
}
return nil
} }
// Decode reads the next JSON-encoded value from its // Decode reads the next JSON-encoded value from its
@ -147,115 +122,48 @@ func (d *Decoder) Decode(v interface{}) error {
ptr := uintptr(header.ptr) ptr := uintptr(header.ptr)
typeptr := uintptr(unsafe.Pointer(typ)) typeptr := uintptr(unsafe.Pointer(typ))
// noescape trick for header.typ ( reflect.*rtype ) // noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**rtype)(unsafe.Pointer(&typeptr)) copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
if err := validateType(copiedType, ptr); err != nil { if err := validateType(copiedType, ptr); err != nil {
return err return err
} }
dec, err := decodeCompileToGetDecoder(typ) dec, err := decoder.CompileToGetDecoder(typ)
if err != nil { if err != nil {
return err return err
} }
if err := d.prepareForDecode(); err != nil { if err := d.s.PrepareForDecode(); err != nil {
return err return err
} }
s := d.s s := d.s
if err := dec.decodeStream(s, 0, header.ptr); err != nil { if err := dec.DecodeStream(s, 0, header.ptr); err != nil {
return err return err
} }
s.reset() s.Reset()
s.bufSize = initBufSize
return nil return nil
} }
func (d *Decoder) More() bool { func (d *Decoder) More() bool {
s := d.s return d.s.More()
for {
switch s.char() {
case ' ', '\n', '\r', '\t':
s.cursor++
continue
case '}', ']':
return false
case nul:
if s.read() {
continue
}
return false
}
break
}
return true
} }
func (d *Decoder) Token() (Token, error) { func (d *Decoder) Token() (Token, error) {
s := d.s return d.s.Token()
for {
c := s.char()
switch c {
case ' ', '\n', '\r', '\t':
s.cursor++
case '{', '[', ']', '}':
s.cursor++
return Delim(c), nil
case ',', ':':
s.cursor++
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
bytes := floatBytes(s)
s := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(s, 64)
if err != nil {
return nil, err
}
return f64, nil
case '"':
bytes, err := stringBytes(s)
if err != nil {
return nil, err
}
return string(bytes), nil
case 't':
if err := trueBytes(s); err != nil {
return nil, err
}
return true, nil
case 'f':
if err := falseBytes(s); err != nil {
return nil, err
}
return false, nil
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case nul:
if s.read() {
continue
}
goto END
default:
return nil, errInvalidCharacter(s.char(), "token", s.totalOffset())
}
}
END:
return nil, io.EOF
} }
// DisallowUnknownFields causes the Decoder to return an error when the destination // DisallowUnknownFields causes the Decoder to return an error when the destination
// is a struct and the input contains object keys which do not match any // is a struct and the input contains object keys which do not match any
// non-ignored, exported fields in the destination. // non-ignored, exported fields in the destination.
func (d *Decoder) DisallowUnknownFields() { func (d *Decoder) DisallowUnknownFields() {
d.s.disallowUnknownFields = true d.s.DisallowUnknownFields = true
} }
func (d *Decoder) InputOffset() int64 { func (d *Decoder) InputOffset() int64 {
return d.s.totalOffset() return d.s.TotalOffset()
} }
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a // UseNumber causes the Decoder to unmarshal a number into an interface{} as a
// Number instead of as a float64. // Number instead of as a float64.
func (d *Decoder) UseNumber() { func (d *Decoder) UseNumber() {
d.s.useNumber = true d.s.UseNumber = true
} }

View File

@ -1,24 +0,0 @@
// +build !race
package json
import "unsafe"
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
typeptr := uintptr(unsafe.Pointer(typ))
if typeptr > maxTypeAddr {
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
}
index := (typeptr - baseTypeAddr) >> typeAddrShift
if dec := cachedDecoder[index]; dec != nil {
return dec, nil
}
dec, err := decodeCompileHead(typ, map[uintptr]decoder{})
if err != nil {
return nil, err
}
cachedDecoder[index] = dec
return dec, nil
}

View File

@ -37,13 +37,3 @@ type UnmarshalTypeError = errors.UnmarshalTypeError
type UnsupportedTypeError = errors.UnsupportedTypeError type UnsupportedTypeError = errors.UnsupportedTypeError
type UnsupportedValueError = errors.UnsupportedValueError type UnsupportedValueError = errors.UnsupportedValueError
var (
errExceededMaxDepth = errors.ErrExceededMaxDepth
errNotAtBeginningOfValue = errors.ErrNotAtBeginningOfValue
errUnexpectedEndOfJSON = errors.ErrUnexpectedEndOfJSON
errExpected = errors.ErrExpected
errInvalidCharacter = errors.ErrInvalidCharacter
errSyntax = errors.ErrSyntax
errMarshaler = errors.ErrMarshaler
)

View File

@ -1,6 +1,10 @@
package json package json
var ( import (
NewSyntaxError = errSyntax "github.com/goccy/go-json/internal/errors"
NewMarshalerError = errMarshaler )
var (
NewSyntaxError = errors.ErrSyntax
NewMarshalerError = errors.ErrMarshaler
) )

View File

@ -1,16 +1,18 @@
package json package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime"
) )
type anonymousFieldDecoder struct { type anonymousFieldDecoder struct {
structType *rtype structType *runtime.Type
offset uintptr offset uintptr
dec decoder dec Decoder
} }
func newAnonymousFieldDecoder(structType *rtype, offset uintptr, dec decoder) *anonymousFieldDecoder { func newAnonymousFieldDecoder(structType *runtime.Type, offset uintptr, dec Decoder) *anonymousFieldDecoder {
return &anonymousFieldDecoder{ return &anonymousFieldDecoder{
structType: structType, structType: structType,
offset: offset, offset: offset,
@ -18,18 +20,18 @@ func newAnonymousFieldDecoder(structType *rtype, offset uintptr, dec decoder) *a
} }
} }
func (d *anonymousFieldDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *anonymousFieldDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
if *(*unsafe.Pointer)(p) == nil { if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe_New(d.structType) *(*unsafe.Pointer)(p) = unsafe_New(d.structType)
} }
p = *(*unsafe.Pointer)(p) p = *(*unsafe.Pointer)(p)
return d.dec.decodeStream(s, depth, unsafe.Pointer(uintptr(p)+d.offset)) return d.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+d.offset))
} }
func (d *anonymousFieldDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *anonymousFieldDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
if *(*unsafe.Pointer)(p) == nil { if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe_New(d.structType) *(*unsafe.Pointer)(p) = unsafe_New(d.structType)
} }
p = *(*unsafe.Pointer)(p) p = *(*unsafe.Pointer)(p)
return d.dec.decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset)) return d.dec.Decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
} }

View File

@ -1,20 +1,23 @@
package json package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type arrayDecoder struct { type arrayDecoder struct {
elemType *rtype elemType *runtime.Type
size uintptr size uintptr
valueDecoder decoder valueDecoder Decoder
alen int alen int
structName string structName string
fieldName string fieldName string
zeroValue unsafe.Pointer zeroValue unsafe.Pointer
} }
func newArrayDecoder(dec decoder, elemType *rtype, alen int, structName, fieldName string) *arrayDecoder { func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType)) zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
return &arrayDecoder{ return &arrayDecoder{
valueDecoder: dec, valueDecoder: dec,
@ -27,10 +30,10 @@ func newArrayDecoder(dec decoder, elemType *rtype, alen int, structName, fieldNa
} }
} }
func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
for { for {
@ -46,7 +49,7 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
for { for {
s.cursor++ s.cursor++
if idx < d.alen { if idx < d.alen {
if err := d.valueDecoder.decodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil { if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
return err return err
} }
} else { } else {
@ -86,13 +89,13 @@ func (d *arrayDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
s.cursor++ s.cursor++
} }
ERROR: ERROR:
return errUnexpectedEndOfJSON("array", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
} }
func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *arrayDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
for { for {
@ -111,7 +114,7 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
for { for {
cursor++ cursor++
if idx < d.alen { if idx < d.alen {
c, err := d.valueDecoder.decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)) c, err := d.valueDecoder.Decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -136,11 +139,11 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
case ',': case ',':
continue continue
default: default:
return 0, errInvalidCharacter(buf[cursor], "array", cursor) return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
} }
} }
default: default:
return 0, errUnexpectedEndOfJSON("array", cursor) return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
} }
} }
} }

View File

@ -1,7 +1,9 @@
package json package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
) )
type boolDecoder struct { type boolDecoder struct {
@ -13,7 +15,7 @@ func newBoolDecoder(structName, fieldName string) *boolDecoder {
return &boolDecoder{structName: structName, fieldName: fieldName} return &boolDecoder{structName: structName, fieldName: fieldName}
} }
func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace() s.skipWhiteSpace()
for { for {
switch s.char() { switch s.char() {
@ -43,10 +45,10 @@ func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
break break
} }
ERROR: ERROR:
return errUnexpectedEndOfJSON("bool", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("bool", s.totalOffset())
} }
func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *boolDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] { switch buf[cursor] {
case 't': case 't':
@ -70,5 +72,5 @@ func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
cursor += 4 cursor += 4
return cursor, nil return cursor, nil
} }
return 0, errUnexpectedEndOfJSON("bool", cursor) return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
} }

View File

@ -1,24 +1,27 @@
package json package decoder
import ( import (
"encoding/base64" "encoding/base64"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type bytesDecoder struct { type bytesDecoder struct {
typ *rtype typ *runtime.Type
sliceDecoder decoder sliceDecoder Decoder
structName string structName string
fieldName string fieldName string
} }
func byteUnmarshalerSliceDecoder(typ *rtype, structName string, fieldName string) decoder { func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder {
var unmarshalDecoder decoder var unmarshalDecoder Decoder
switch { switch {
case rtype_ptrTo(typ).Implements(unmarshalJSONType): case runtime.PtrTo(typ).Implements(unmarshalJSONType):
unmarshalDecoder = newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName) unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
case rtype_ptrTo(typ).Implements(unmarshalTextType): case runtime.PtrTo(typ).Implements(unmarshalTextType):
unmarshalDecoder = newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName) unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
} }
if unmarshalDecoder == nil { if unmarshalDecoder == nil {
return nil return nil
@ -26,7 +29,7 @@ func byteUnmarshalerSliceDecoder(typ *rtype, structName string, fieldName string
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName) return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
} }
func newBytesDecoder(typ *rtype, structName string, fieldName string) *bytesDecoder { func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder {
return &bytesDecoder{ return &bytesDecoder{
typ: typ, typ: typ,
sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName), sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName),
@ -35,7 +38,7 @@ func newBytesDecoder(typ *rtype, structName string, fieldName string) *bytesDeco
} }
} }
func (d *bytesDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *bytesDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamBinary(s, depth, p) bytes, err := d.decodeStreamBinary(s, depth, p)
if err != nil { if err != nil {
return err return err
@ -54,7 +57,7 @@ func (d *bytesDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
return nil return nil
} }
func (d *bytesDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *bytesDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeBinary(buf, cursor, depth, p) bytes, c, err := d.decodeBinary(buf, cursor, depth, p)
if err != nil { if err != nil {
return 0, err return 0, err
@ -73,7 +76,7 @@ func (d *bytesDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
return cursor, nil return cursor, nil
} }
func binaryBytes(s *stream) ([]byte, error) { func binaryBytes(s *Stream) ([]byte, error) {
s.cursor++ s.cursor++
start := s.cursor start := s.cursor
for { for {
@ -91,10 +94,10 @@ func binaryBytes(s *stream) ([]byte, error) {
s.cursor++ s.cursor++
} }
ERROR: ERROR:
return nil, errUnexpectedEndOfJSON("[]byte", s.totalOffset()) return nil, errors.ErrUnexpectedEndOfJSON("[]byte", s.totalOffset())
} }
func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Pointer) ([]byte, error) { func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
for { for {
switch s.char() { switch s.char() {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -109,12 +112,12 @@ func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Point
return nil, nil return nil, nil
case '[': case '[':
if d.sliceDecoder == nil { if d.sliceDecoder == nil {
return nil, &UnmarshalTypeError{ return nil, &errors.UnmarshalTypeError{
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(), Offset: s.totalOffset(),
} }
} }
if err := d.sliceDecoder.decodeStream(s, depth, p); err != nil { if err := d.sliceDecoder.DecodeStream(s, depth, p); err != nil {
return nil, err return nil, err
} }
return nil, nil return nil, nil
@ -125,7 +128,7 @@ func (d *bytesDecoder) decodeStreamBinary(s *stream, depth int64, p unsafe.Point
} }
break break
} }
return nil, errNotAtBeginningOfValue(s.totalOffset()) return nil, errors.ErrNotAtBeginningOfValue(s.totalOffset())
} }
func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) { func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
@ -143,18 +146,18 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Po
cursor++ cursor++
return literal, cursor, nil return literal, cursor, nil
case nul: case nul:
return nil, 0, errUnexpectedEndOfJSON("[]byte", cursor) return nil, 0, errors.ErrUnexpectedEndOfJSON("[]byte", cursor)
} }
cursor++ cursor++
} }
case '[': case '[':
if d.sliceDecoder == nil { if d.sliceDecoder == nil {
return nil, 0, &UnmarshalTypeError{ return nil, 0, &errors.UnmarshalTypeError{
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: cursor, Offset: cursor,
} }
} }
c, err := d.sliceDecoder.decode(buf, cursor, depth, p) c, err := d.sliceDecoder.Decode(buf, cursor, depth, p)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
@ -166,7 +169,7 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Po
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
default: default:
return nil, 0, errNotAtBeginningOfValue(cursor) return nil, 0, errors.ErrNotAtBeginningOfValue(cursor)
} }
} }
} }

View File

@ -1,27 +1,56 @@
package json package decoder
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
"sync/atomic"
"unicode" "unicode"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime" "github.com/goccy/go-json/internal/runtime"
) )
var ( var (
jsonNumberType = reflect.TypeOf(json.Number("")) jsonNumberType = reflect.TypeOf(json.Number(""))
typeAddr *runtime.TypeAddr
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
cachedDecoder []Decoder
) )
func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, error) { func init() {
typeAddr = runtime.AnalyzeTypeAddr()
if typeAddr == nil {
typeAddr = &runtime.TypeAddr{}
}
cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift)
}
func loadDecoderMap() map[uintptr]Decoder {
p := atomic.LoadPointer(&cachedDecoderMap)
return *(*map[uintptr]Decoder)(unsafe.Pointer(&p))
}
func storeDecoder(typ uintptr, dec Decoder, m map[uintptr]Decoder) {
newDecoderMap := make(map[uintptr]Decoder, len(m)+1)
newDecoderMap[typ] = dec
for k, v := range m {
newDecoderMap[k] = v
}
atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap)))
}
func compileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (Decoder, error) {
decoderMap := loadDecoderMap() decoderMap := loadDecoderMap()
if dec, exists := decoderMap[typeptr]; exists { if dec, exists := decoderMap[typeptr]; exists {
return dec, nil return dec, nil
} }
dec, err := decodeCompileHead(typ, map[uintptr]decoder{}) dec, err := compileHead(typ, map[uintptr]Decoder{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -29,84 +58,84 @@ func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, er
return dec, nil return dec, nil
} }
func decodeCompileHead(typ *rtype, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
switch { switch {
case rtype_ptrTo(typ).Implements(unmarshalJSONType): case runtime.PtrTo(typ).Implements(unmarshalJSONType):
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil
case rtype_ptrTo(typ).Implements(unmarshalTextType): case runtime.PtrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil
} }
return decodeCompile(typ.Elem(), "", "", structTypeToDecoder) return compile(typ.Elem(), "", "", structTypeToDecoder)
} }
func decodeCompile(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
switch { switch {
case rtype_ptrTo(typ).Implements(unmarshalJSONType): case runtime.PtrTo(typ).Implements(unmarshalJSONType):
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil
case rtype_ptrTo(typ).Implements(unmarshalTextType): case runtime.PtrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
} }
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
return decodeCompilePtr(typ, structName, fieldName, structTypeToDecoder) return compilePtr(typ, structName, fieldName, structTypeToDecoder)
case reflect.Struct: case reflect.Struct:
return decodeCompileStruct(typ, structName, fieldName, structTypeToDecoder) return compileStruct(typ, structName, fieldName, structTypeToDecoder)
case reflect.Slice: case reflect.Slice:
elem := typ.Elem() elem := typ.Elem()
if elem.Kind() == reflect.Uint8 { if elem.Kind() == reflect.Uint8 {
return decodeCompileBytes(elem, structName, fieldName) return compileBytes(elem, structName, fieldName)
} }
return decodeCompileSlice(typ, structName, fieldName, structTypeToDecoder) return compileSlice(typ, structName, fieldName, structTypeToDecoder)
case reflect.Array: case reflect.Array:
return decodeCompileArray(typ, structName, fieldName, structTypeToDecoder) return compileArray(typ, structName, fieldName, structTypeToDecoder)
case reflect.Map: case reflect.Map:
return decodeCompileMap(typ, structName, fieldName, structTypeToDecoder) return compileMap(typ, structName, fieldName, structTypeToDecoder)
case reflect.Interface: case reflect.Interface:
return decodeCompileInterface(typ, structName, fieldName) return compileInterface(typ, structName, fieldName)
case reflect.Uintptr: case reflect.Uintptr:
return decodeCompileUint(typ, structName, fieldName) return compileUint(typ, structName, fieldName)
case reflect.Int: case reflect.Int:
return decodeCompileInt(typ, structName, fieldName) return compileInt(typ, structName, fieldName)
case reflect.Int8: case reflect.Int8:
return decodeCompileInt8(typ, structName, fieldName) return compileInt8(typ, structName, fieldName)
case reflect.Int16: case reflect.Int16:
return decodeCompileInt16(typ, structName, fieldName) return compileInt16(typ, structName, fieldName)
case reflect.Int32: case reflect.Int32:
return decodeCompileInt32(typ, structName, fieldName) return compileInt32(typ, structName, fieldName)
case reflect.Int64: case reflect.Int64:
return decodeCompileInt64(typ, structName, fieldName) return compileInt64(typ, structName, fieldName)
case reflect.Uint: case reflect.Uint:
return decodeCompileUint(typ, structName, fieldName) return compileUint(typ, structName, fieldName)
case reflect.Uint8: case reflect.Uint8:
return decodeCompileUint8(typ, structName, fieldName) return compileUint8(typ, structName, fieldName)
case reflect.Uint16: case reflect.Uint16:
return decodeCompileUint16(typ, structName, fieldName) return compileUint16(typ, structName, fieldName)
case reflect.Uint32: case reflect.Uint32:
return decodeCompileUint32(typ, structName, fieldName) return compileUint32(typ, structName, fieldName)
case reflect.Uint64: case reflect.Uint64:
return decodeCompileUint64(typ, structName, fieldName) return compileUint64(typ, structName, fieldName)
case reflect.String: case reflect.String:
return decodeCompileString(typ, structName, fieldName) return compileString(typ, structName, fieldName)
case reflect.Bool: case reflect.Bool:
return decodeCompileBool(structName, fieldName) return compileBool(structName, fieldName)
case reflect.Float32: case reflect.Float32:
return decodeCompileFloat32(structName, fieldName) return compileFloat32(structName, fieldName)
case reflect.Float64: case reflect.Float64:
return decodeCompileFloat64(structName, fieldName) return compileFloat64(structName, fieldName)
} }
return nil, &UnmarshalTypeError{ return nil, &errors.UnmarshalTypeError{
Value: "object", Value: "object",
Type: rtype2type(typ), Type: runtime.RType2Type(typ),
Offset: 0, Offset: 0,
} }
} }
func isStringTagSupportedType(typ *rtype) bool { func isStringTagSupportedType(typ *runtime.Type) bool {
switch { switch {
case rtype_ptrTo(typ).Implements(unmarshalJSONType): case runtime.PtrTo(typ).Implements(unmarshalJSONType):
return false return false
case rtype_ptrTo(typ).Implements(unmarshalTextType): case runtime.PtrTo(typ).Implements(unmarshalTextType):
return false return false
} }
switch typ.Kind() { switch typ.Kind() {
@ -124,11 +153,11 @@ func isStringTagSupportedType(typ *rtype) bool {
return true return true
} }
func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
if rtype_ptrTo(typ).Implements(unmarshalTextType) { if runtime.PtrTo(typ).Implements(unmarshalTextType) {
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
} }
dec, err := decodeCompile(typ, structName, fieldName, structTypeToDecoder) dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -145,145 +174,145 @@ func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToD
} }
} }
ERROR: ERROR:
return nil, &UnmarshalTypeError{ return nil, &errors.UnmarshalTypeError{
Value: "object", Value: "object",
Type: rtype2type(typ), Type: runtime.RType2Type(typ),
Offset: 0, Offset: 0,
} }
} }
func decodeCompilePtr(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
dec, err := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder) dec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil
} }
func decodeCompileInt(typ *rtype, structName, fieldName string) (decoder, error) { func compileInt(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int)(p) = int(v) *(*int)(p) = int(v)
}), nil }), nil
} }
func decodeCompileInt8(typ *rtype, structName, fieldName string) (decoder, error) { func compileInt8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int8)(p) = int8(v) *(*int8)(p) = int8(v)
}), nil }), nil
} }
func decodeCompileInt16(typ *rtype, structName, fieldName string) (decoder, error) { func compileInt16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int16)(p) = int16(v) *(*int16)(p) = int16(v)
}), nil }), nil
} }
func decodeCompileInt32(typ *rtype, structName, fieldName string) (decoder, error) { func compileInt32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int32)(p) = int32(v) *(*int32)(p) = int32(v)
}), nil }), nil
} }
func decodeCompileInt64(typ *rtype, structName, fieldName string) (decoder, error) { func compileInt64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int64)(p) = v *(*int64)(p) = v
}), nil }), nil
} }
func decodeCompileUint(typ *rtype, structName, fieldName string) (decoder, error) { func compileUint(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint)(p) = uint(v) *(*uint)(p) = uint(v)
}), nil }), nil
} }
func decodeCompileUint8(typ *rtype, structName, fieldName string) (decoder, error) { func compileUint8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint8)(p) = uint8(v) *(*uint8)(p) = uint8(v)
}), nil }), nil
} }
func decodeCompileUint16(typ *rtype, structName, fieldName string) (decoder, error) { func compileUint16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint16)(p) = uint16(v) *(*uint16)(p) = uint16(v)
}), nil }), nil
} }
func decodeCompileUint32(typ *rtype, structName, fieldName string) (decoder, error) { func compileUint32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint32)(p) = uint32(v) *(*uint32)(p) = uint32(v)
}), nil }), nil
} }
func decodeCompileUint64(typ *rtype, structName, fieldName string) (decoder, error) { func compileUint64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint64)(p) = v *(*uint64)(p) = v
}), nil }), nil
} }
func decodeCompileFloat32(structName, fieldName string) (decoder, error) { func compileFloat32(structName, fieldName string) (Decoder, error) {
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*float32)(p) = float32(v) *(*float32)(p) = float32(v)
}), nil }), nil
} }
func decodeCompileFloat64(structName, fieldName string) (decoder, error) { func compileFloat64(structName, fieldName string) (Decoder, error) {
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*float64)(p) = v *(*float64)(p) = v
}), nil }), nil
} }
func decodeCompileString(typ *rtype, structName, fieldName string) (decoder, error) { func compileString(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
if typ == type2rtype(jsonNumberType) { if typ == runtime.Type2RType(jsonNumberType) {
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) { return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*Number)(p) = v *(*json.Number)(p) = v
}), nil }), nil
} }
return newStringDecoder(structName, fieldName), nil return newStringDecoder(structName, fieldName), nil
} }
func decodeCompileBool(structName, fieldName string) (decoder, error) { func compileBool(structName, fieldName string) (Decoder, error) {
return newBoolDecoder(structName, fieldName), nil return newBoolDecoder(structName, fieldName), nil
} }
func decodeCompileBytes(typ *rtype, structName, fieldName string) (decoder, error) { func compileBytes(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newBytesDecoder(typ, structName, fieldName), nil return newBytesDecoder(typ, structName, fieldName), nil
} }
func decodeCompileSlice(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
elem := typ.Elem() elem := typ.Elem()
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder) decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
} }
func decodeCompileArray(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
elem := typ.Elem() elem := typ.Elem()
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder) decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
} }
func decodeCompileMap(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
keyDec, err := decodeCompileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder) keyDec, err := compileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
valueDec, err := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder) valueDec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil
} }
func decodeCompileInterface(typ *rtype, structName, fieldName string) (decoder, error) { func compileInterface(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newInterfaceDecoder(typ, structName, fieldName), nil return newInterfaceDecoder(typ, structName, fieldName), nil
} }
func decodeRemoveConflictFields(fieldMap map[string]*structFieldSet, conflictedMap map[string]struct{}, dec *structDecoder, field reflect.StructField) { func removeConflictFields(fieldMap map[string]*structFieldSet, conflictedMap map[string]struct{}, dec *structDecoder, field reflect.StructField) {
for k, v := range dec.fieldMap { for k, v := range dec.fieldMap {
if _, exists := conflictedMap[k]; exists { if _, exists := conflictedMap[k]; exists {
// already conflicted key // already conflicted key
@ -338,7 +367,7 @@ func decodeRemoveConflictFields(fieldMap map[string]*structFieldSet, conflictedM
} }
} }
func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) { func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
fieldNum := typ.NumField() fieldNum := typ.NumField()
conflictedMap := map[string]struct{}{} conflictedMap := map[string]struct{}{}
fieldMap := map[string]*structFieldSet{} fieldMap := map[string]*structFieldSet{}
@ -356,17 +385,17 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
} }
isUnexportedField := unicode.IsLower([]rune(field.Name)[0]) isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
tag := runtime.StructTagFromField(field) tag := runtime.StructTagFromField(field)
dec, err := decodeCompile(type2rtype(field.Type), structName, field.Name, structTypeToDecoder) dec, err := compile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if field.Anonymous && !tag.IsTaggedKey { if field.Anonymous && !tag.IsTaggedKey {
if stDec, ok := dec.(*structDecoder); ok { if stDec, ok := dec.(*structDecoder); ok {
if type2rtype(field.Type) == typ { if runtime.Type2RType(field.Type) == typ {
// recursive definition // recursive definition
continue continue
} }
decodeRemoveConflictFields(fieldMap, conflictedMap, stDec, field) removeConflictFields(fieldMap, conflictedMap, stDec, field)
} else if pdec, ok := dec.(*ptrDecoder); ok { } else if pdec, ok := dec.(*ptrDecoder); ok {
contentDec := pdec.contentDecoder() contentDec := pdec.contentDecoder()
if pdec.typ == typ { if pdec.typ == typ {
@ -438,8 +467,8 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
} }
} }
} else { } else {
if tag.IsString && isStringTagSupportedType(type2rtype(field.Type)) { if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
dec = newWrappedStringDecoder(type2rtype(field.Type), dec, structName, field.Name) dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name)
} }
var key string var key string
if tag.Key != "" { if tag.Key != "" {

View File

@ -0,0 +1,28 @@
// +build !race
package decoder
import (
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
typeptr := uintptr(unsafe.Pointer(typ))
if typeptr > typeAddr.MaxTypeAddr {
return compileToGetDecoderSlowPath(typeptr, typ)
}
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
if dec := cachedDecoder[index]; dec != nil {
return dec, nil
}
dec, err := compileHead(typ, map[uintptr]Decoder{})
if err != nil {
return nil, err
}
cachedDecoder[index] = dec
return dec, nil
}

View File

@ -1,21 +1,23 @@
// +build race // +build race
package json package decoder
import ( import (
"sync" "sync"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime"
) )
var decMu sync.RWMutex var decMu sync.RWMutex
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) { func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
typeptr := uintptr(unsafe.Pointer(typ)) typeptr := uintptr(unsafe.Pointer(typ))
if typeptr > maxTypeAddr { if typeptr > typeAddr.MaxTypeAddr {
return decodeCompileToGetDecoderSlowPath(typeptr, typ) return compileToGetDecoderSlowPath(typeptr, typ)
} }
index := (typeptr - baseTypeAddr) >> typeAddrShift index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
decMu.RLock() decMu.RLock()
if dec := cachedDecoder[index]; dec != nil { if dec := cachedDecoder[index]; dec != nil {
decMu.RUnlock() decMu.RUnlock()
@ -23,7 +25,7 @@ func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
} }
decMu.RUnlock() decMu.RUnlock()
dec, err := decodeCompileHead(typ, map[uintptr]decoder{}) dec, err := compileHead(typ, map[uintptr]Decoder{})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,7 +1,9 @@
package json package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
) )
var ( var (
@ -34,7 +36,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
braceCount++ braceCount++
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
case '}': case '}':
depth-- depth--
@ -45,7 +47,7 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
case '[': case '[':
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
case ']': case ']':
depth-- depth--
@ -56,16 +58,16 @@ func skipObject(buf []byte, cursor, depth int64) (int64, error) {
case '\\': case '\\':
cursor++ cursor++
if buf[cursor] == nul { if buf[cursor] == nul {
return 0, errUnexpectedEndOfJSON("string of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
case '"': case '"':
goto SWITCH_OUT goto SWITCH_OUT
case nul: case nul:
return 0, errUnexpectedEndOfJSON("string of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
} }
case nul: case nul:
return 0, errUnexpectedEndOfJSON("object of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
} }
SWITCH_OUT: SWITCH_OUT:
cursor++ cursor++
@ -80,7 +82,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
bracketCount++ bracketCount++
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
case ']': case ']':
bracketCount-- bracketCount--
@ -91,7 +93,7 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
case '{': case '{':
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
case '}': case '}':
depth-- depth--
@ -102,16 +104,16 @@ func skipArray(buf []byte, cursor, depth int64) (int64, error) {
case '\\': case '\\':
cursor++ cursor++
if buf[cursor] == nul { if buf[cursor] == nul {
return 0, errUnexpectedEndOfJSON("string of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
case '"': case '"':
goto SWITCH_OUT goto SWITCH_OUT
case nul: case nul:
return 0, errUnexpectedEndOfJSON("string of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
} }
case nul: case nul:
return 0, errUnexpectedEndOfJSON("array of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
} }
SWITCH_OUT: SWITCH_OUT:
cursor++ cursor++
@ -135,12 +137,12 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
case '\\': case '\\':
cursor++ cursor++
if buf[cursor] == nul { if buf[cursor] == nul {
return 0, errUnexpectedEndOfJSON("string of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
case '"': case '"':
return cursor + 1, nil return cursor + 1, nil
case nul: case nul:
return 0, errUnexpectedEndOfJSON("string of object", cursor) return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
} }
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
@ -171,58 +173,58 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
cursor += 4 cursor += 4
return cursor, nil return cursor, nil
default: default:
return cursor, errUnexpectedEndOfJSON("null", cursor) return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
} }
} }
} }
func validateTrue(buf []byte, cursor int64) error { func validateTrue(buf []byte, cursor int64) error {
if cursor+3 >= int64(len(buf)) { if cursor+3 >= int64(len(buf)) {
return errUnexpectedEndOfJSON("true", cursor) return errors.ErrUnexpectedEndOfJSON("true", cursor)
} }
if buf[cursor+1] != 'r' { if buf[cursor+1] != 'r' {
return errInvalidCharacter(buf[cursor+1], "true", cursor) return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor)
} }
if buf[cursor+2] != 'u' { if buf[cursor+2] != 'u' {
return errInvalidCharacter(buf[cursor+2], "true", cursor) return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
} }
if buf[cursor+3] != 'e' { if buf[cursor+3] != 'e' {
return errInvalidCharacter(buf[cursor+3], "true", cursor) return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
} }
return nil return nil
} }
func validateFalse(buf []byte, cursor int64) error { func validateFalse(buf []byte, cursor int64) error {
if cursor+4 >= int64(len(buf)) { if cursor+4 >= int64(len(buf)) {
return errUnexpectedEndOfJSON("false", cursor) return errors.ErrUnexpectedEndOfJSON("false", cursor)
} }
if buf[cursor+1] != 'a' { if buf[cursor+1] != 'a' {
return errInvalidCharacter(buf[cursor+1], "false", cursor) return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor)
} }
if buf[cursor+2] != 'l' { if buf[cursor+2] != 'l' {
return errInvalidCharacter(buf[cursor+2], "false", cursor) return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
} }
if buf[cursor+3] != 's' { if buf[cursor+3] != 's' {
return errInvalidCharacter(buf[cursor+3], "false", cursor) return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor)
} }
if buf[cursor+4] != 'e' { if buf[cursor+4] != 'e' {
return errInvalidCharacter(buf[cursor+4], "false", cursor) return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
} }
return nil return nil
} }
func validateNull(buf []byte, cursor int64) error { func validateNull(buf []byte, cursor int64) error {
if cursor+3 >= int64(len(buf)) { if cursor+3 >= int64(len(buf)) {
return errUnexpectedEndOfJSON("null", cursor) return errors.ErrUnexpectedEndOfJSON("null", cursor)
} }
if buf[cursor+1] != 'u' { if buf[cursor+1] != 'u' {
return errInvalidCharacter(buf[cursor+1], "null", cursor) return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor)
} }
if buf[cursor+2] != 'l' { if buf[cursor+2] != 'l' {
return errInvalidCharacter(buf[cursor+2], "null", cursor) return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
} }
if buf[cursor+3] != 'l' { if buf[cursor+3] != 'l' {
return errInvalidCharacter(buf[cursor+3], "null", cursor) return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
} }
return nil return nil
} }

View File

@ -1,8 +1,10 @@
package json package decoder
import ( import (
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
) )
type floatDecoder struct { type floatDecoder struct {
@ -47,7 +49,7 @@ var (
} }
) )
func floatBytes(s *stream) []byte { func floatBytes(s *Stream) []byte {
start := s.cursor start := s.cursor
for { for {
s.cursor++ s.cursor++
@ -64,7 +66,7 @@ func floatBytes(s *stream) []byte {
return s.buf[start:s.cursor] return s.buf[start:s.cursor]
} }
func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) { func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for { for {
switch s.char() { switch s.char() {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -87,7 +89,7 @@ func (d *floatDecoder) decodeStreamByte(s *stream) ([]byte, error) {
} }
} }
ERROR: ERROR:
return nil, errUnexpectedEndOfJSON("float", s.totalOffset()) return nil, errors.ErrUnexpectedEndOfJSON("float", s.totalOffset())
} }
func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
@ -111,12 +113,12 @@ func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, erro
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
default: default:
return nil, 0, errUnexpectedEndOfJSON("float", cursor) return nil, 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
} }
} }
} }
func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *floatDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s) bytes, err := d.decodeStreamByte(s)
if err != nil { if err != nil {
return err return err
@ -127,13 +129,13 @@ func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
str := *(*string)(unsafe.Pointer(&bytes)) str := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(str, 64) f64, err := strconv.ParseFloat(str, 64)
if err != nil { if err != nil {
return errSyntax(err.Error(), s.totalOffset()) return errors.ErrSyntax(err.Error(), s.totalOffset())
} }
d.op(p, f64) d.op(p, f64)
return nil return nil
} }
func (d *floatDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *floatDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return 0, err return 0, err
@ -143,12 +145,12 @@ func (d *floatDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
} }
cursor = c cursor = c
if !validEndNumberChar[buf[cursor]] { if !validEndNumberChar[buf[cursor]] {
return 0, errUnexpectedEndOfJSON("float", cursor) return 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
} }
s := *(*string)(unsafe.Pointer(&bytes)) s := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(s, 64) f64, err := strconv.ParseFloat(s, 64)
if err != nil { if err != nil {
return 0, errSyntax(err.Error(), cursor) return 0, errors.ErrSyntax(err.Error(), cursor)
} }
d.op(p, f64) d.op(p, f64)
return cursor, nil return cursor, nil

View File

@ -1,20 +1,23 @@
package json package decoder
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type intDecoder struct { type intDecoder struct {
typ *rtype typ *runtime.Type
kind reflect.Kind kind reflect.Kind
op func(unsafe.Pointer, int64) op func(unsafe.Pointer, int64)
structName string structName string
fieldName string fieldName string
} }
func newIntDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder { func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
return &intDecoder{ return &intDecoder{
typ: typ, typ: typ,
kind: typ.Kind(), kind: typ.Kind(),
@ -24,10 +27,10 @@ func newIntDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Poin
} }
} }
func (d *intDecoder) typeError(buf []byte, offset int64) *UnmarshalTypeError { func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: fmt.Sprintf("number %s", string(buf)), Value: fmt.Sprintf("number %s", string(buf)),
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Struct: d.structName, Struct: d.structName,
Field: d.fieldName, Field: d.fieldName,
Offset: offset, Offset: offset,
@ -79,7 +82,11 @@ var (
} }
) )
func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) { var (
numZeroBuf = []byte{'0'}
)
func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for { for {
switch s.char() { switch s.char() {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -106,7 +113,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
return num, nil return num, nil
case '0': case '0':
s.cursor++ s.cursor++
return []byte{'0'}, nil return numZeroBuf, nil
case '1', '2', '3', '4', '5', '6', '7', '8', '9': case '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := s.cursor start := s.cursor
for { for {
@ -138,7 +145,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) {
} }
} }
ERROR: ERROR:
return nil, errUnexpectedEndOfJSON("number(integer)", s.totalOffset()) return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset())
} }
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
@ -150,7 +157,7 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
continue continue
case '0': case '0':
cursor++ cursor++
return []byte{'0'}, cursor, nil return numZeroBuf, cursor, nil
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor start := cursor
cursor++ cursor++
@ -171,7 +178,7 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
} }
} }
func (d *intDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s) bytes, err := d.decodeStreamByte(s)
if err != nil { if err != nil {
return err return err
@ -202,7 +209,7 @@ func (d *intDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
return nil return nil
} }
func (d *intDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *intDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return 0, err return 0, err

View File

@ -1,14 +1,18 @@
package json package decoder
import ( import (
"bytes" "bytes"
"encoding" "encoding"
"encoding/json"
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type interfaceDecoder struct { type interfaceDecoder struct {
typ *rtype typ *runtime.Type
structName string structName string
fieldName string fieldName string
sliceDecoder *sliceDecoder sliceDecoder *sliceDecoder
@ -26,7 +30,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*interface{})(p) = v *(*interface{})(p) = v
}), }),
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) { numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*interface{})(p) = v *(*interface{})(p) = v
}), }),
stringDecoder: newStringDecoder(structName, fieldName), stringDecoder: newStringDecoder(structName, fieldName),
@ -49,7 +53,7 @@ func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
return ifaceDecoder return ifaceDecoder
} }
func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder { func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName) emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
stringDecoder := newStringDecoder(structName, fieldName) stringDecoder := newStringDecoder(structName, fieldName)
return &interfaceDecoder{ return &interfaceDecoder{
@ -74,31 +78,31 @@ func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDec
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*interface{})(p) = v *(*interface{})(p) = v
}), }),
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) { numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*interface{})(p) = v *(*interface{})(p) = v
}), }),
stringDecoder: stringDecoder, stringDecoder: stringDecoder,
} }
} }
func (d *interfaceDecoder) numDecoder(s *stream) decoder { func (d *interfaceDecoder) numDecoder(s *Stream) Decoder {
if s.useNumber { if s.UseNumber {
return d.numberDecoder return d.numberDecoder
} }
return d.floatDecoder return d.floatDecoder
} }
var ( var (
emptyInterfaceType = type2rtype(reflect.TypeOf((*interface{})(nil)).Elem()) emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
interfaceMapType = type2rtype( interfaceMapType = runtime.Type2RType(
reflect.TypeOf((*map[string]interface{})(nil)).Elem(), reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
) )
stringType = type2rtype( stringType = runtime.Type2RType(
reflect.TypeOf(""), reflect.TypeOf(""),
) )
) )
func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) error { func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
start := s.cursor start := s.cursor
if err := s.skipValue(depth); err != nil { if err := s.skipValue(depth); err != nil {
return err return err
@ -113,7 +117,7 @@ func decodeStreamUnmarshaler(s *stream, depth int64, unmarshaler Unmarshaler) er
return nil return nil
} }
func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler) (int64, error) { func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) {
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
start := cursor start := cursor
end, err := skipValue(buf, cursor, depth) end, err := skipValue(buf, cursor, depth)
@ -130,7 +134,7 @@ func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler Unmarshaler)
return end, nil return end, nil
} }
func decodeStreamTextUnmarshaler(s *stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error { func decodeStreamTextUnmarshaler(s *Stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error {
start := s.cursor start := s.cursor
if err := s.skipValue(depth); err != nil { if err := s.skipValue(depth); err != nil {
return err return err
@ -171,14 +175,14 @@ func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding
return end, nil return end, nil
} }
func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p unsafe.Pointer) error { func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace() s.skipWhiteSpace()
for { for {
switch s.char() { switch s.char() {
case '{': case '{':
var v map[string]interface{} var v map[string]interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
if err := d.mapDecoder.decodeStream(s, depth, ptr); err != nil { if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil {
return err return err
} }
*(*interface{})(p) = v *(*interface{})(p) = v
@ -186,13 +190,13 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
case '[': case '[':
var v []interface{} var v []interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
if err := d.sliceDecoder.decodeStream(s, depth, ptr); err != nil { if err := d.sliceDecoder.DecodeStream(s, depth, ptr); err != nil {
return err return err
} }
*(*interface{})(p) = v *(*interface{})(p) = v
return nil return nil
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return d.numDecoder(s).decodeStream(s, depth, p) return d.numDecoder(s).DecodeStream(s, depth, p)
case '"': case '"':
s.cursor++ s.cursor++
start := s.cursor start := s.cursor
@ -211,7 +215,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
if s.read() { if s.read() {
continue continue
} }
return errUnexpectedEndOfJSON("string", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
} }
s.cursor++ s.cursor++
} }
@ -240,17 +244,22 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
} }
break break
} }
return errNotAtBeginningOfValue(s.totalOffset()) return errors.ErrNotAtBeginningOfValue(s.totalOffset())
} }
func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ, typ: d.typ,
ptr: p, ptr: p,
})) }))
rv := reflect.ValueOf(runtimeInterfaceValue) rv := reflect.ValueOf(runtimeInterfaceValue)
if rv.NumMethod() > 0 && rv.CanInterface() { if rv.NumMethod() > 0 && rv.CanInterface() {
if u, ok := rv.Interface().(Unmarshaler); ok { if u, ok := rv.Interface().(json.Unmarshaler); ok {
return decodeStreamUnmarshaler(s, depth, u) return decodeStreamUnmarshaler(s, depth, u)
} }
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok { if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
@ -284,15 +293,15 @@ func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer
*(*interface{})(p) = nil *(*interface{})(p) = nil
return nil return nil
} }
decoder, err := decodeCompileToGetDecoder(typ) decoder, err := CompileToGetDecoder(typ)
if err != nil { if err != nil {
return err return err
} }
return decoder.decodeStream(s, depth, ifaceHeader.ptr) return decoder.DecodeStream(s, depth, ifaceHeader.ptr)
} }
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *UnmarshalTypeError { func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: typ.String(), Value: typ.String(),
Type: typ, Type: typ,
Offset: offset, Offset: offset,
@ -301,14 +310,14 @@ func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *Unm
} }
} }
func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *interfaceDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ, typ: d.typ,
ptr: p, ptr: p,
})) }))
rv := reflect.ValueOf(runtimeInterfaceValue) rv := reflect.ValueOf(runtimeInterfaceValue)
if rv.NumMethod() > 0 && rv.CanInterface() { if rv.NumMethod() > 0 && rv.CanInterface() {
if u, ok := rv.Interface().(Unmarshaler); ok { if u, ok := rv.Interface().(json.Unmarshaler); ok {
return decodeUnmarshaler(buf, cursor, depth, u) return decodeUnmarshaler(buf, cursor, depth, u)
} }
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok { if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
@ -345,11 +354,11 @@ func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Poin
**(**interface{})(unsafe.Pointer(&p)) = nil **(**interface{})(unsafe.Pointer(&p)) = nil
return cursor, nil return cursor, nil
} }
decoder, err := decodeCompileToGetDecoder(typ) decoder, err := CompileToGetDecoder(typ)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return decoder.decode(buf, cursor, depth, ifaceHeader.ptr) return decoder.Decode(buf, cursor, depth, ifaceHeader.ptr)
} }
func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
@ -358,7 +367,7 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
case '{': case '{':
var v map[string]interface{} var v map[string]interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
cursor, err := d.mapDecoder.decode(buf, cursor, depth, ptr) cursor, err := d.mapDecoder.Decode(buf, cursor, depth, ptr)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -367,18 +376,18 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
case '[': case '[':
var v []interface{} var v []interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
cursor, err := d.sliceDecoder.decode(buf, cursor, depth, ptr) cursor, err := d.sliceDecoder.Decode(buf, cursor, depth, ptr)
if err != nil { if err != nil {
return 0, err return 0, err
} }
**(**interface{})(unsafe.Pointer(&p)) = v **(**interface{})(unsafe.Pointer(&p)) = v
return cursor, nil return cursor, nil
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return d.floatDecoder.decode(buf, cursor, depth, p) return d.floatDecoder.Decode(buf, cursor, depth, p)
case '"': case '"':
var v string var v string
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
cursor, err := d.stringDecoder.decode(buf, cursor, depth, ptr) cursor, err := d.stringDecoder.Decode(buf, cursor, depth, ptr)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -406,5 +415,5 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
**(**interface{})(unsafe.Pointer(&p)) = nil **(**interface{})(unsafe.Pointer(&p)) = nil
return cursor, nil return cursor, nil
} }
return cursor, errNotAtBeginningOfValue(cursor) return cursor, errors.ErrNotAtBeginningOfValue(cursor)
} }

View File

@ -1,20 +1,23 @@
package json package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type mapDecoder struct { type mapDecoder struct {
mapType *rtype mapType *runtime.Type
keyType *rtype keyType *runtime.Type
valueType *rtype valueType *runtime.Type
keyDecoder decoder keyDecoder Decoder
valueDecoder decoder valueDecoder Decoder
structName string structName string
fieldName string fieldName string
} }
func newMapDecoder(mapType *rtype, keyType *rtype, keyDec decoder, valueType *rtype, valueDec decoder, structName, fieldName string) *mapDecoder { func newMapDecoder(mapType *runtime.Type, keyType *runtime.Type, keyDec Decoder, valueType *runtime.Type, valueDec Decoder, structName, fieldName string) *mapDecoder {
return &mapDecoder{ return &mapDecoder{
mapType: mapType, mapType: mapType,
keyDecoder: keyDec, keyDecoder: keyDec,
@ -27,16 +30,16 @@ func newMapDecoder(mapType *rtype, keyType *rtype, keyDec decoder, valueType *rt
} }
//go:linkname makemap reflect.makemap //go:linkname makemap reflect.makemap
func makemap(*rtype, int) unsafe.Pointer func makemap(*runtime.Type, int) unsafe.Pointer
//go:linkname mapassign reflect.mapassign //go:linkname mapassign reflect.mapassign
//go:noescape //go:noescape
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer) func mapassign(t *runtime.Type, m unsafe.Pointer, key, val unsafe.Pointer)
func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
s.skipWhiteSpace() s.skipWhiteSpace()
@ -49,7 +52,7 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
return nil return nil
case '{': case '{':
default: default:
return errExpected("{ character for map value", s.totalOffset()) return errors.ErrExpected("{ character for map value", s.totalOffset())
} }
s.skipWhiteSpace() s.skipWhiteSpace()
mapValue := *(*unsafe.Pointer)(p) mapValue := *(*unsafe.Pointer)(p)
@ -64,16 +67,16 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
for { for {
s.cursor++ s.cursor++
k := unsafe_New(d.keyType) k := unsafe_New(d.keyType)
if err := d.keyDecoder.decodeStream(s, depth, k); err != nil { if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil {
return err return err
} }
s.skipWhiteSpace() s.skipWhiteSpace()
if !s.equalChar(':') { if !s.equalChar(':') {
return errExpected("colon after object key", s.totalOffset()) return errors.ErrExpected("colon after object key", s.totalOffset())
} }
s.cursor++ s.cursor++
v := unsafe_New(d.valueType) v := unsafe_New(d.valueType)
if err := d.valueDecoder.decodeStream(s, depth, v); err != nil { if err := d.valueDecoder.DecodeStream(s, depth, v); err != nil {
return err return err
} }
mapassign(d.mapType, mapValue, k, v) mapassign(d.mapType, mapValue, k, v)
@ -84,21 +87,21 @@ func (d *mapDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
return nil return nil
} }
if !s.equalChar(',') { if !s.equalChar(',') {
return errExpected("comma after object value", s.totalOffset()) return errors.ErrExpected("comma after object value", s.totalOffset())
} }
} }
} }
func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *mapDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
buflen := int64(len(buf)) buflen := int64(len(buf))
if buflen < 2 { if buflen < 2 {
return 0, errExpected("{} for map", cursor) return 0, errors.ErrExpected("{} for map", cursor)
} }
switch buf[cursor] { switch buf[cursor] {
case 'n': case 'n':
@ -110,7 +113,7 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
return cursor, nil return cursor, nil
case '{': case '{':
default: default:
return 0, errExpected("{ character for map value", cursor) return 0, errors.ErrExpected("{ character for map value", cursor)
} }
cursor++ cursor++
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
@ -125,17 +128,17 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
} }
for { for {
k := unsafe_New(d.keyType) k := unsafe_New(d.keyType)
keyCursor, err := d.keyDecoder.decode(buf, cursor, depth, k) keyCursor, err := d.keyDecoder.Decode(buf, cursor, depth, k)
if err != nil { if err != nil {
return 0, err return 0, err
} }
cursor = skipWhiteSpace(buf, keyCursor) cursor = skipWhiteSpace(buf, keyCursor)
if buf[cursor] != ':' { if buf[cursor] != ':' {
return 0, errExpected("colon after object key", cursor) return 0, errors.ErrExpected("colon after object key", cursor)
} }
cursor++ cursor++
v := unsafe_New(d.valueType) v := unsafe_New(d.valueType)
valueCursor, err := d.valueDecoder.decode(buf, cursor, depth, v) valueCursor, err := d.valueDecoder.Decode(buf, cursor, depth, v)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -147,7 +150,7 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
return cursor, nil return cursor, nil
} }
if buf[cursor] != ',' { if buf[cursor] != ',' {
return 0, errExpected("comma after object value", cursor) return 0, errors.ErrExpected("comma after object value", cursor)
} }
cursor++ cursor++
} }

View File

@ -1,18 +1,21 @@
package json package decoder
import ( import (
"encoding/json"
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
) )
type numberDecoder struct { type numberDecoder struct {
stringDecoder *stringDecoder stringDecoder *stringDecoder
op func(unsafe.Pointer, Number) op func(unsafe.Pointer, json.Number)
structName string structName string
fieldName string fieldName string
} }
func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, Number)) *numberDecoder { func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder {
return &numberDecoder{ return &numberDecoder{
stringDecoder: newStringDecoder(structName, fieldName), stringDecoder: newStringDecoder(structName, fieldName),
op: op, op: op,
@ -21,34 +24,34 @@ func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, Numb
} }
} }
func (d *numberDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s) bytes, err := d.decodeStreamByte(s)
if err != nil { if err != nil {
return err return err
} }
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
return errSyntax(err.Error(), s.totalOffset()) return errors.ErrSyntax(err.Error(), s.totalOffset())
} }
d.op(p, Number(string(bytes))) d.op(p, json.Number(string(bytes)))
s.reset() s.reset()
return nil return nil
} }
func (d *numberDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *numberDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return 0, err return 0, err
} }
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
return 0, errSyntax(err.Error(), c) return 0, errors.ErrSyntax(err.Error(), c)
} }
cursor = c cursor = c
s := *(*string)(unsafe.Pointer(&bytes)) s := *(*string)(unsafe.Pointer(&bytes))
d.op(p, Number(s)) d.op(p, json.Number(s))
return cursor, nil return cursor, nil
} }
func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, error) { func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for { for {
switch s.char() { switch s.char() {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -73,7 +76,7 @@ func (d *numberDecoder) decodeStreamByte(s *stream) ([]byte, error) {
} }
} }
ERROR: ERROR:
return nil, errUnexpectedEndOfJSON("json.Number", s.totalOffset()) return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset())
} }
func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
@ -99,7 +102,7 @@ func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
case '"': case '"':
return d.stringDecoder.decodeByte(buf, cursor) return d.stringDecoder.decodeByte(buf, cursor)
default: default:
return nil, 0, errUnexpectedEndOfJSON("json.Number", cursor) return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor)
} }
} }
} }

View File

@ -1,17 +1,19 @@
package json package decoder
import ( import (
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime"
) )
type ptrDecoder struct { type ptrDecoder struct {
dec decoder dec Decoder
typ *rtype typ *runtime.Type
structName string structName string
fieldName string fieldName string
} }
func newPtrDecoder(dec decoder, typ *rtype, structName, fieldName string) *ptrDecoder { func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder {
return &ptrDecoder{ return &ptrDecoder{
dec: dec, dec: dec,
typ: typ, typ: typ,
@ -20,7 +22,7 @@ func newPtrDecoder(dec decoder, typ *rtype, structName, fieldName string) *ptrDe
} }
} }
func (d *ptrDecoder) contentDecoder() decoder { func (d *ptrDecoder) contentDecoder() Decoder {
dec, ok := d.dec.(*ptrDecoder) dec, ok := d.dec.(*ptrDecoder)
if !ok { if !ok {
return d.dec return d.dec
@ -30,9 +32,9 @@ func (d *ptrDecoder) contentDecoder() decoder {
//nolint:golint //nolint:golint
//go:linkname unsafe_New reflect.unsafe_New //go:linkname unsafe_New reflect.unsafe_New
func unsafe_New(*rtype) unsafe.Pointer func unsafe_New(*runtime.Type) unsafe.Pointer
func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace() s.skipWhiteSpace()
if s.char() == nul { if s.char() == nul {
s.read() s.read()
@ -51,13 +53,13 @@ func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
} else { } else {
newptr = *(*unsafe.Pointer)(p) newptr = *(*unsafe.Pointer)(p)
} }
if err := d.dec.decodeStream(s, depth, newptr); err != nil { if err := d.dec.DecodeStream(s, depth, newptr); err != nil {
return err return err
} }
return nil return nil
} }
func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *ptrDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == 'n' { if buf[cursor] == 'n' {
if err := validateNull(buf, cursor); err != nil { if err := validateNull(buf, cursor); err != nil {
@ -76,7 +78,7 @@ func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
} else { } else {
newptr = *(*unsafe.Pointer)(p) newptr = *(*unsafe.Pointer)(p)
} }
c, err := d.dec.decode(buf, cursor, depth, newptr) c, err := d.dec.Decode(buf, cursor, depth, newptr)
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@ -1,15 +1,18 @@
package json package decoder
import ( import (
"reflect" "reflect"
"sync" "sync"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type sliceDecoder struct { type sliceDecoder struct {
elemType *rtype elemType *runtime.Type
isElemPointerType bool isElemPointerType bool
valueDecoder decoder valueDecoder Decoder
size uintptr size uintptr
arrayPool sync.Pool arrayPool sync.Pool
structName string structName string
@ -29,7 +32,7 @@ const (
defaultSliceCapacity = 2 defaultSliceCapacity = 2
) )
func newSliceDecoder(dec decoder, elemType *rtype, size uintptr, structName, fieldName string) *sliceDecoder { func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder {
return &sliceDecoder{ return &sliceDecoder{
valueDecoder: dec, valueDecoder: dec,
elemType: elemType, elemType: elemType,
@ -71,28 +74,28 @@ func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
} }
//go:linkname copySlice reflect.typedslicecopy //go:linkname copySlice reflect.typedslicecopy
func copySlice(elemType *rtype, dst, src sliceHeader) int func copySlice(elemType *runtime.Type, dst, src sliceHeader) int
//go:linkname newArray reflect.unsafe_NewArray //go:linkname newArray reflect.unsafe_NewArray
func newArray(*rtype, int) unsafe.Pointer func newArray(*runtime.Type, int) unsafe.Pointer
//go:linkname typedmemmove reflect.typedmemmove //go:linkname typedmemmove reflect.typedmemmove
func typedmemmove(t *rtype, dst, src unsafe.Pointer) func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer)
func (d *sliceDecoder) errNumber(offset int64) *UnmarshalTypeError { func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError {
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: "number", Value: "number",
Type: reflect.SliceOf(rtype2type(d.elemType)), Type: reflect.SliceOf(runtime.RType2Type(d.elemType)),
Struct: d.structName, Struct: d.structName,
Field: d.fieldName, Field: d.fieldName,
Offset: offset, Offset: offset,
} }
} }
func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
for { for {
@ -144,7 +147,7 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
} }
} }
if err := d.valueDecoder.decodeStream(s, depth, ep); err != nil { if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil {
return err return err
} }
s.skipWhiteSpace() s.skipWhiteSpace()
@ -194,13 +197,13 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er
} }
} }
ERROR: ERROR:
return errUnexpectedEndOfJSON("slice", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset())
} }
func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *sliceDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
for { for {
@ -251,7 +254,7 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
typedmemmove(d.elemType, ep, unsafe_New(d.elemType)) typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
} }
} }
c, err := d.valueDecoder.decode(buf, cursor, depth, ep) c, err := d.valueDecoder.Decode(buf, cursor, depth, ep)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -278,14 +281,14 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
slice.cap = capacity slice.cap = capacity
slice.data = data slice.data = data
d.releaseSlice(slice) d.releaseSlice(slice)
return 0, errInvalidCharacter(buf[cursor], "slice", cursor) return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
} }
cursor++ cursor++
} }
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return 0, d.errNumber(cursor) return 0, d.errNumber(cursor)
default: default:
return 0, errUnexpectedEndOfJSON("slice", cursor) return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
} }
} }
} }

View File

@ -1,16 +1,20 @@
package json package decoder
import ( import (
"bytes" "bytes"
"encoding/json"
"io" "io"
"strconv"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
) )
const ( const (
initBufSize = 512 initBufSize = 512
) )
type stream struct { type Stream struct {
buf []byte buf []byte
bufSize int64 bufSize int64
length int64 length int64
@ -19,19 +23,23 @@ type stream struct {
cursor int64 cursor int64
filledBuffer bool filledBuffer bool
allRead bool allRead bool
useNumber bool UseNumber bool
disallowUnknownFields bool DisallowUnknownFields bool
} }
func newStream(r io.Reader) *stream { func NewStream(r io.Reader) *Stream {
return &stream{ return &Stream{
r: r, r: r,
bufSize: initBufSize, bufSize: initBufSize,
buf: []byte{nul}, buf: []byte{nul},
} }
} }
func (s *stream) buffered() io.Reader { func (s *Stream) TotalOffset() int64 {
return s.totalOffset()
}
func (s *Stream) Buffered() io.Reader {
buflen := int64(len(s.buf)) buflen := int64(len(s.buf))
for i := s.cursor; i < buflen; i++ { for i := s.cursor; i < buflen; i++ {
if s.buf[i] == nul { if s.buf[i] == nul {
@ -41,15 +49,35 @@ func (s *stream) buffered() io.Reader {
return bytes.NewReader(s.buf[s.cursor:]) return bytes.NewReader(s.buf[s.cursor:])
} }
func (s *stream) totalOffset() int64 { func (s *Stream) PrepareForDecode() error {
for {
switch s.char() {
case ' ', '\t', '\r', '\n':
s.cursor++
continue
case ',', ':':
s.cursor++
return nil
case nul:
if s.read() {
continue
}
return io.EOF
}
break
}
return nil
}
func (s *Stream) totalOffset() int64 {
return s.offset + s.cursor return s.offset + s.cursor
} }
func (s *stream) char() byte { func (s *Stream) char() byte {
return s.buf[s.cursor] return s.buf[s.cursor]
} }
func (s *stream) equalChar(c byte) bool { func (s *Stream) equalChar(c byte) bool {
cur := s.buf[s.cursor] cur := s.buf[s.cursor]
if cur == nul { if cur == nul {
s.read() s.read()
@ -58,23 +86,100 @@ func (s *stream) equalChar(c byte) bool {
return cur == c return cur == c
} }
func (s *stream) stat() ([]byte, int64, unsafe.Pointer) { func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) {
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
} }
func (s *stream) statForRetry() ([]byte, int64, unsafe.Pointer) { func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
s.cursor-- // for retry ( because caller progress cursor position in each loop ) s.cursor-- // for retry ( because caller progress cursor position in each loop )
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
} }
func (s *stream) reset() { func (s *Stream) Reset() {
s.reset()
s.bufSize = initBufSize
}
func (s *Stream) More() bool {
for {
switch s.char() {
case ' ', '\n', '\r', '\t':
s.cursor++
continue
case '}', ']':
return false
case nul:
if s.read() {
continue
}
return false
}
break
}
return true
}
func (s *Stream) Token() (interface{}, error) {
for {
c := s.char()
switch c {
case ' ', '\n', '\r', '\t':
s.cursor++
case '{', '[', ']', '}':
s.cursor++
return json.Delim(c), nil
case ',', ':':
s.cursor++
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
bytes := floatBytes(s)
s := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(s, 64)
if err != nil {
return nil, err
}
return f64, nil
case '"':
bytes, err := stringBytes(s)
if err != nil {
return nil, err
}
return string(bytes), nil
case 't':
if err := trueBytes(s); err != nil {
return nil, err
}
return true, nil
case 'f':
if err := falseBytes(s); err != nil {
return nil, err
}
return false, nil
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case nul:
if s.read() {
continue
}
goto END
default:
return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset())
}
}
END:
return nil, io.EOF
}
func (s *Stream) reset() {
s.offset += s.cursor s.offset += s.cursor
s.buf = s.buf[s.cursor:] s.buf = s.buf[s.cursor:]
s.length -= s.cursor s.length -= s.cursor
s.cursor = 0 s.cursor = 0
} }
func (s *stream) readBuf() []byte { func (s *Stream) readBuf() []byte {
if s.filledBuffer { if s.filledBuffer {
s.bufSize *= 2 s.bufSize *= 2
remainBuf := s.buf remainBuf := s.buf
@ -92,7 +197,7 @@ func (s *stream) readBuf() []byte {
return s.buf[s.cursor+remainNotNulCharNum:] return s.buf[s.cursor+remainNotNulCharNum:]
} }
func (s *stream) read() bool { func (s *Stream) read() bool {
if s.allRead { if s.allRead {
return false return false
} }
@ -114,7 +219,7 @@ func (s *stream) read() bool {
return true return true
} }
func (s *stream) skipWhiteSpace() { func (s *Stream) skipWhiteSpace() {
LOOP: LOOP:
switch s.char() { switch s.char() {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -127,7 +232,7 @@ LOOP:
} }
} }
func (s *stream) skipObject(depth int64) error { func (s *Stream) skipObject(depth int64) error {
braceCount := 1 braceCount := 1
_, cursor, p := s.stat() _, cursor, p := s.stat()
for { for {
@ -136,7 +241,7 @@ func (s *stream) skipObject(depth int64) error {
braceCount++ braceCount++
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
case '}': case '}':
braceCount-- braceCount--
@ -148,7 +253,7 @@ func (s *stream) skipObject(depth int64) error {
case '[': case '[':
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
case ']': case ']':
depth-- depth--
@ -164,7 +269,7 @@ func (s *stream) skipObject(depth int64) error {
_, cursor, p = s.statForRetry() _, cursor, p = s.statForRetry()
continue continue
} }
return errUnexpectedEndOfJSON("string of object", cursor) return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
case '"': case '"':
goto SWITCH_OUT goto SWITCH_OUT
@ -174,7 +279,7 @@ func (s *stream) skipObject(depth int64) error {
_, cursor, p = s.statForRetry() _, cursor, p = s.statForRetry()
continue continue
} }
return errUnexpectedEndOfJSON("string of object", cursor) return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
} }
case nul: case nul:
@ -183,14 +288,14 @@ func (s *stream) skipObject(depth int64) error {
_, cursor, p = s.stat() _, cursor, p = s.stat()
continue continue
} }
return errUnexpectedEndOfJSON("object of object", cursor) return errors.ErrUnexpectedEndOfJSON("object of object", cursor)
} }
SWITCH_OUT: SWITCH_OUT:
cursor++ cursor++
} }
} }
func (s *stream) skipArray(depth int64) error { func (s *Stream) skipArray(depth int64) error {
bracketCount := 1 bracketCount := 1
_, cursor, p := s.stat() _, cursor, p := s.stat()
for { for {
@ -199,7 +304,7 @@ func (s *stream) skipArray(depth int64) error {
bracketCount++ bracketCount++
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
case ']': case ']':
bracketCount-- bracketCount--
@ -211,7 +316,7 @@ func (s *stream) skipArray(depth int64) error {
case '{': case '{':
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
case '}': case '}':
depth-- depth--
@ -227,7 +332,7 @@ func (s *stream) skipArray(depth int64) error {
_, cursor, p = s.statForRetry() _, cursor, p = s.statForRetry()
continue continue
} }
return errUnexpectedEndOfJSON("string of object", cursor) return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
case '"': case '"':
goto SWITCH_OUT goto SWITCH_OUT
@ -237,7 +342,7 @@ func (s *stream) skipArray(depth int64) error {
_, cursor, p = s.statForRetry() _, cursor, p = s.statForRetry()
continue continue
} }
return errUnexpectedEndOfJSON("string of object", cursor) return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
} }
} }
case nul: case nul:
@ -246,14 +351,14 @@ func (s *stream) skipArray(depth int64) error {
_, cursor, p = s.stat() _, cursor, p = s.stat()
continue continue
} }
return errUnexpectedEndOfJSON("array of object", cursor) return errors.ErrUnexpectedEndOfJSON("array of object", cursor)
} }
SWITCH_OUT: SWITCH_OUT:
cursor++ cursor++
} }
} }
func (s *stream) skipValue(depth int64) error { func (s *Stream) skipValue(depth int64) error {
_, cursor, p := s.stat() _, cursor, p := s.stat()
for { for {
switch char(p, cursor) { switch char(p, cursor) {
@ -266,7 +371,7 @@ func (s *stream) skipValue(depth int64) error {
_, cursor, p = s.stat() _, cursor, p = s.stat()
continue continue
} }
return errUnexpectedEndOfJSON("value of object", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset())
case '{': case '{':
s.cursor = cursor + 1 s.cursor = cursor + 1
return s.skipObject(depth + 1) return s.skipObject(depth + 1)
@ -285,7 +390,7 @@ func (s *stream) skipValue(depth int64) error {
_, cursor, p = s.statForRetry() _, cursor, p = s.statForRetry()
continue continue
} }
return errUnexpectedEndOfJSON("value of string", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
} }
case '"': case '"':
s.cursor = cursor + 1 s.cursor = cursor + 1
@ -296,7 +401,7 @@ func (s *stream) skipValue(depth int64) error {
_, cursor, p = s.statForRetry() _, cursor, p = s.statForRetry()
continue continue
} }
return errUnexpectedEndOfJSON("value of string", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
} }
} }
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
@ -338,7 +443,7 @@ func (s *stream) skipValue(depth int64) error {
} }
} }
func nullBytes(s *stream) error { func nullBytes(s *Stream) error {
// current cursor's character is 'n' // current cursor's character is 'n'
s.cursor++ s.cursor++
if s.char() != 'u' { if s.char() != 'u' {
@ -362,14 +467,14 @@ func nullBytes(s *stream) error {
return nil return nil
} }
func retryReadNull(s *stream) error { func retryReadNull(s *Stream) error {
if s.char() == nul && s.read() { if s.char() == nul && s.read() {
return nil return nil
} }
return errInvalidCharacter(s.char(), "null", s.totalOffset()) return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset())
} }
func trueBytes(s *stream) error { func trueBytes(s *Stream) error {
// current cursor's character is 't' // current cursor's character is 't'
s.cursor++ s.cursor++
if s.char() != 'r' { if s.char() != 'r' {
@ -393,14 +498,14 @@ func trueBytes(s *stream) error {
return nil return nil
} }
func retryReadTrue(s *stream) error { func retryReadTrue(s *Stream) error {
if s.char() == nul && s.read() { if s.char() == nul && s.read() {
return nil return nil
} }
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset()) return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
} }
func falseBytes(s *stream) error { func falseBytes(s *Stream) error {
// current cursor's character is 'f' // current cursor's character is 'f'
s.cursor++ s.cursor++
if s.char() != 'a' { if s.char() != 'a' {
@ -430,9 +535,9 @@ func falseBytes(s *stream) error {
return nil return nil
} }
func retryReadFalse(s *stream) error { func retryReadFalse(s *Stream) error {
if s.char() == nul && s.read() { if s.char() == nul && s.read() {
return nil return nil
} }
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset()) return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
} }

View File

@ -1,4 +1,4 @@
package json package decoder
import ( import (
"reflect" "reflect"
@ -6,6 +6,8 @@ import (
"unicode/utf16" "unicode/utf16"
"unicode/utf8" "unicode/utf8"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
) )
type stringDecoder struct { type stringDecoder struct {
@ -20,8 +22,8 @@ func newStringDecoder(structName, fieldName string) *stringDecoder {
} }
} }
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *UnmarshalTypeError { func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError {
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: typeName, Value: typeName,
Type: reflect.TypeOf(""), Type: reflect.TypeOf(""),
Offset: offset, Offset: offset,
@ -30,7 +32,7 @@ func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *Unmarsh
} }
} }
func (d *stringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *stringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s) bytes, err := d.decodeStreamByte(s)
if err != nil { if err != nil {
return err return err
@ -43,7 +45,7 @@ func (d *stringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
return nil return nil
} }
func (d *stringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *stringDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return 0, err return 0, err
@ -91,13 +93,13 @@ func unicodeToRune(code []byte) rune {
return r return r
} }
func decodeUnicodeRune(s *stream) (rune, int64, error) { func decodeUnicodeRune(s *Stream) (rune, int64, error) {
const defaultOffset = 5 const defaultOffset = 5
const surrogateOffset = 11 const surrogateOffset = 11
if s.cursor+defaultOffset >= s.length { if s.cursor+defaultOffset >= s.length {
if !s.read() { if !s.read() {
return rune(0), 0, errInvalidCharacter(s.char(), "escaped string", s.totalOffset()) return rune(0), 0, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
} }
} }
@ -117,7 +119,7 @@ func decodeUnicodeRune(s *stream) (rune, int64, error) {
return r, defaultOffset, nil return r, defaultOffset, nil
} }
func decodeUnicode(s *stream) error { func decodeUnicode(s *Stream) error {
const backSlashAndULen = 2 // length of \u const backSlashAndULen = 2 // length of \u
r, offset, err := decodeUnicodeRune(s) r, offset, err := decodeUnicodeRune(s)
@ -133,7 +135,7 @@ func decodeUnicode(s *stream) error {
return nil return nil
} }
func decodeEscapeString(s *stream) error { func decodeEscapeString(s *Stream) error {
s.cursor++ s.cursor++
RETRY: RETRY:
switch s.buf[s.cursor] { switch s.buf[s.cursor] {
@ -157,11 +159,11 @@ RETRY:
return decodeUnicode(s) return decodeUnicode(s)
case nul: case nul:
if !s.read() { if !s.read() {
return errInvalidCharacter(s.char(), "escaped string", s.totalOffset()) return errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
} }
goto RETRY goto RETRY
default: default:
return errUnexpectedEndOfJSON("string", s.totalOffset()) return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
} }
s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...) s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...)
s.length-- s.length--
@ -174,7 +176,7 @@ var (
runeErrBytesLen = int64(len(runeErrBytes)) runeErrBytesLen = int64(len(runeErrBytes))
) )
func stringBytes(s *stream) ([]byte, error) { func stringBytes(s *Stream) ([]byte, error) {
_, cursor, p := s.stat() _, cursor, p := s.stat()
cursor++ // skip double quote char cursor++ // skip double quote char
start := cursor start := cursor
@ -245,10 +247,10 @@ func stringBytes(s *stream) ([]byte, error) {
cursor++ cursor++
} }
ERROR: ERROR:
return nil, errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
} }
func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) { func (d *stringDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for { for {
switch s.char() { switch s.char() {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -274,7 +276,7 @@ func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) {
} }
break break
} }
return nil, errNotAtBeginningOfValue(s.totalOffset()) return nil, errors.ErrNotAtBeginningOfValue(s.totalOffset())
} }
func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
@ -324,13 +326,13 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
case 'u': case 'u':
buflen := int64(len(buf)) buflen := int64(len(buf))
if cursor+5 >= buflen { if cursor+5 >= buflen {
return nil, 0, errUnexpectedEndOfJSON("escaped string", cursor) return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
} }
code := unicodeToRune(buf[cursor+1 : cursor+5]) code := unicodeToRune(buf[cursor+1 : cursor+5])
unicode := []byte(string(code)) unicode := []byte(string(code))
buf = append(append(buf[:cursor-1], unicode...), buf[cursor+5:]...) buf = append(append(buf[:cursor-1], unicode...), buf[cursor+5:]...)
default: default:
return nil, 0, errUnexpectedEndOfJSON("escaped string", cursor) return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
} }
continue continue
case '"': case '"':
@ -338,7 +340,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
cursor++ cursor++
return literal, cursor, nil return literal, cursor, nil
case nul: case nul:
return nil, 0, errUnexpectedEndOfJSON("string", cursor) return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor)
} }
cursor++ cursor++
} }
@ -349,7 +351,7 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
default: default:
return nil, 0, errNotAtBeginningOfValue(cursor) return nil, 0, errors.ErrNotAtBeginningOfValue(cursor)
} }
} }
} }

View File

@ -1,4 +1,4 @@
package json package decoder
import ( import (
"fmt" "fmt"
@ -9,10 +9,12 @@ import (
"unicode" "unicode"
"unicode/utf16" "unicode/utf16"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
) )
type structFieldSet struct { type structFieldSet struct {
dec decoder dec Decoder
offset uintptr offset uintptr
isTaggedKey bool isTaggedKey bool
key string key string
@ -30,7 +32,7 @@ type structDecoder struct {
keyBitmapUint16 [][256]uint16 keyBitmapUint16 [][256]uint16
sortedFieldSets []*structFieldSet sortedFieldSets []*structFieldSet
keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error) keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
keyStreamDecoder func(*structDecoder, *stream) (*structFieldSet, string, error) keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error)
} }
var ( var (
@ -201,7 +203,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++ cursor++
return cursor, nil, nil return cursor, nil, nil
case nul: case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapUint8 bitmap := d.keyBitmapUint8
@ -220,7 +222,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
} }
return cursor, field, nil return cursor, field, nil
case nul: case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
case '\\': case '\\':
cursor++ cursor++
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor) chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
@ -242,7 +244,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++ cursor++
} }
default: default:
return cursor, nil, errNotAtBeginningOfValue(cursor) return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
} }
} }
} }
@ -264,7 +266,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++ cursor++
return cursor, nil, nil return cursor, nil, nil
case nul: case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapUint16 bitmap := d.keyBitmapUint16
@ -283,7 +285,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
} }
return cursor, field, nil return cursor, field, nil
case nul: case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
case '\\': case '\\':
cursor++ cursor++
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor) chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
@ -305,7 +307,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++ cursor++
} }
default: default:
return cursor, nil, errNotAtBeginningOfValue(cursor) return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
} }
} }
} }
@ -320,10 +322,10 @@ func decodeKeyNotFound(b unsafe.Pointer, cursor int64) (int64, *structFieldSet,
case '\\': case '\\':
cursor++ cursor++
if char(b, cursor) == nul { if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
} }
case nul: case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
} }
} }
} }
@ -342,7 +344,7 @@ func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldS
return cursor, field, nil return cursor, field, nil
} }
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) { func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
var ( var (
curBit uint8 = math.MaxUint8 curBit uint8 = math.MaxUint8
) )
@ -357,7 +359,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
_, cursor, p = s.stat() _, cursor, p = s.stat()
continue continue
} }
return nil, "", errNotAtBeginningOfValue(s.totalOffset()) return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
case '"': case '"':
cursor++ cursor++
FIRST_CHAR: FIRST_CHAR:
@ -373,7 +375,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
_, cursor, p = s.stat() _, cursor, p = s.stat()
goto FIRST_CHAR goto FIRST_CHAR
} }
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapUint8 bitmap := d.keyBitmapUint8
@ -397,7 +399,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
_, cursor, p = s.stat() _, cursor, p = s.stat()
continue continue
} }
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
case '\\': case '\\':
s.cursor = cursor + 1 // skip '\' char s.cursor = cursor + 1 // skip '\' char
chars, err := decodeKeyCharByEscapeCharStream(s) chars, err := decodeKeyCharByEscapeCharStream(s)
@ -424,12 +426,12 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
cursor++ cursor++
} }
default: default:
return nil, "", errNotAtBeginningOfValue(s.totalOffset()) return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
} }
} }
} }
func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) { func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
var ( var (
curBit uint16 = math.MaxUint16 curBit uint16 = math.MaxUint16
) )
@ -444,7 +446,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
_, cursor, p = s.stat() _, cursor, p = s.stat()
continue continue
} }
return nil, "", errNotAtBeginningOfValue(s.totalOffset()) return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
case '"': case '"':
cursor++ cursor++
FIRST_CHAR: FIRST_CHAR:
@ -460,7 +462,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
_, cursor, p = s.stat() _, cursor, p = s.stat()
goto FIRST_CHAR goto FIRST_CHAR
} }
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapUint16 bitmap := d.keyBitmapUint16
@ -484,7 +486,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
_, cursor, p = s.stat() _, cursor, p = s.stat()
continue continue
} }
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
case '\\': case '\\':
s.cursor = cursor + 1 // skip '\' char s.cursor = cursor + 1 // skip '\' char
chars, err := decodeKeyCharByEscapeCharStream(s) chars, err := decodeKeyCharByEscapeCharStream(s)
@ -511,19 +513,19 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
cursor++ cursor++
} }
default: default:
return nil, "", errNotAtBeginningOfValue(s.totalOffset()) return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
} }
} }
} }
// decode from '\uXXXX' // decode from '\uXXXX'
func decodeKeyCharByUnicodeRuneStream(s *stream) ([]byte, error) { func decodeKeyCharByUnicodeRuneStream(s *Stream) ([]byte, error) {
const defaultOffset = 4 const defaultOffset = 4
const surrogateOffset = 6 const surrogateOffset = 6
if s.cursor+defaultOffset >= s.length { if s.cursor+defaultOffset >= s.length {
if !s.read() { if !s.read() {
return nil, errInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset()) return nil, errors.ErrInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset())
} }
} }
@ -547,7 +549,7 @@ func decodeKeyCharByUnicodeRuneStream(s *stream) ([]byte, error) {
return []byte(string(r)), nil return []byte(string(r)), nil
} }
func decodeKeyCharByEscapeCharStream(s *stream) ([]byte, error) { func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) {
c := s.buf[s.cursor] c := s.buf[s.cursor]
s.cursor++ s.cursor++
RETRY: RETRY:
@ -572,15 +574,15 @@ RETRY:
return decodeKeyCharByUnicodeRuneStream(s) return decodeKeyCharByUnicodeRuneStream(s)
case nul: case nul:
if !s.read() { if !s.read() {
return nil, errInvalidCharacter(s.char(), "escaped char", s.totalOffset()) return nil, errors.ErrInvalidCharacter(s.char(), "escaped char", s.totalOffset())
} }
goto RETRY goto RETRY
default: default:
return nil, errUnexpectedEndOfJSON("struct field", s.totalOffset()) return nil, errors.ErrUnexpectedEndOfJSON("struct field", s.totalOffset())
} }
} }
func decodeKeyNotFoundStream(s *stream, start int64) (*structFieldSet, string, error) { func decodeKeyNotFoundStream(s *Stream, start int64) (*structFieldSet, string, error) {
buf, cursor, p := s.stat() buf, cursor, p := s.stat()
for { for {
cursor++ cursor++
@ -596,21 +598,21 @@ func decodeKeyNotFoundStream(s *stream, start int64) (*structFieldSet, string, e
if char(p, cursor) == nul { if char(p, cursor) == nul {
s.cursor = cursor s.cursor = cursor
if !s.read() { if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
} }
buf, cursor, p = s.statForRetry() buf, cursor, p = s.statForRetry()
} }
case nul: case nul:
s.cursor = cursor s.cursor = cursor
if !s.read() { if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
} }
buf, cursor, p = s.statForRetry() buf, cursor, p = s.statForRetry()
} }
} }
} }
func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, error) { func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
key, err := d.stringDecoder.decodeStreamByte(s) key, err := d.stringDecoder.decodeStreamByte(s)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
@ -619,10 +621,10 @@ func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, erro
return d.fieldMap[k], k, nil return d.fieldMap[k], k, nil
} }
func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor) return errors.ErrExceededMaxDepth(s.char(), s.cursor)
} }
s.skipWhiteSpace() s.skipWhiteSpace()
@ -636,7 +638,7 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
s.read() s.read()
default: default:
if s.char() != '{' { if s.char() != '{' {
return errNotAtBeginningOfValue(s.totalOffset()) return errors.ErrNotAtBeginningOfValue(s.totalOffset())
} }
} }
s.cursor++ s.cursor++
@ -653,22 +655,22 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
} }
s.skipWhiteSpace() s.skipWhiteSpace()
if s.char() != ':' { if s.char() != ':' {
return errExpected("colon after object key", s.totalOffset()) return errors.ErrExpected("colon after object key", s.totalOffset())
} }
s.cursor++ s.cursor++
if s.char() == nul { if s.char() == nul {
if !s.read() { if !s.read() {
return errExpected("object value after colon", s.totalOffset()) return errors.ErrExpected("object value after colon", s.totalOffset())
} }
} }
if field != nil { if field != nil {
if field.err != nil { if field.err != nil {
return field.err return field.err
} }
if err := field.dec.decodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil { if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
return err return err
} }
} else if s.disallowUnknownFields { } else if s.DisallowUnknownFields {
return fmt.Errorf("json: unknown field %q", key) return fmt.Errorf("json: unknown field %q", key)
} else { } else {
if err := s.skipValue(depth); err != nil { if err := s.skipValue(depth); err != nil {
@ -682,16 +684,16 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
return nil return nil
} }
if c != ',' { if c != ',' {
return errExpected("comma after object element", s.totalOffset()) return errors.ErrExpected("comma after object element", s.totalOffset())
} }
s.cursor++ s.cursor++
} }
} }
func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *structDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
depth++ depth++
if depth > maxDecodeNestingDepth { if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
} }
buflen := int64(len(buf)) buflen := int64(len(buf))
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
@ -705,7 +707,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
return cursor, nil return cursor, nil
case '{': case '{':
default: default:
return 0, errNotAtBeginningOfValue(cursor) return 0, errors.ErrNotAtBeginningOfValue(cursor)
} }
cursor++ cursor++
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
@ -720,17 +722,17 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
} }
cursor = skipWhiteSpace(buf, c) cursor = skipWhiteSpace(buf, c)
if char(b, cursor) != ':' { if char(b, cursor) != ':' {
return 0, errExpected("colon after object key", cursor) return 0, errors.ErrExpected("colon after object key", cursor)
} }
cursor++ cursor++
if cursor >= buflen { if cursor >= buflen {
return 0, errExpected("object value after colon", cursor) return 0, errors.ErrExpected("object value after colon", cursor)
} }
if field != nil { if field != nil {
if field.err != nil { if field.err != nil {
return 0, field.err return 0, field.err
} }
c, err := field.dec.decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset)) c, err := field.dec.Decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -748,7 +750,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
return cursor, nil return cursor, nil
} }
if char(b, cursor) != ',' { if char(b, cursor) != ',' {
return 0, errExpected("comma after object element", cursor) return 0, errors.ErrExpected("comma after object element", cursor)
} }
cursor++ cursor++
} }

23
internal/decoder/type.go Normal file
View File

@ -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()
)

View File

@ -1,20 +1,23 @@
package json package decoder
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type uintDecoder struct { type uintDecoder struct {
typ *rtype typ *runtime.Type
kind reflect.Kind kind reflect.Kind
op func(unsafe.Pointer, uint64) op func(unsafe.Pointer, uint64)
structName string structName string
fieldName string fieldName string
} }
func newUintDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder { func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
return &uintDecoder{ return &uintDecoder{
typ: typ, typ: typ,
kind: typ.Kind(), kind: typ.Kind(),
@ -24,10 +27,10 @@ func newUintDecoder(typ *rtype, structName, fieldName string, op func(unsafe.Poi
} }
} }
func (d *uintDecoder) typeError(buf []byte, offset int64) *UnmarshalTypeError { func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: fmt.Sprintf("number %s", string(buf)), Value: fmt.Sprintf("number %s", string(buf)),
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: offset, Offset: offset,
} }
} }
@ -54,7 +57,7 @@ func (d *uintDecoder) parseUint(b []byte) (uint64, error) {
return sum, nil return sum, nil
} }
func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) { func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for { for {
switch s.char() { switch s.char() {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -62,7 +65,7 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
continue continue
case '0': case '0':
s.cursor++ s.cursor++
return []byte{'0'}, nil return numZeroBuf, nil
case '1', '2', '3', '4', '5', '6', '7', '8', '9': case '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := s.cursor start := s.cursor
for { for {
@ -93,7 +96,7 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
} }
break break
} }
return nil, errUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset()) return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
} }
func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
@ -104,7 +107,7 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
continue continue
case '0': case '0':
cursor++ cursor++
return []byte{'0'}, cursor, nil return numZeroBuf, cursor, nil
case '1', '2', '3', '4', '5', '6', '7', '8', '9': case '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor start := cursor
cursor++ cursor++
@ -125,7 +128,7 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
} }
} }
func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s) bytes, err := d.decodeStreamByte(s)
if err != nil { if err != nil {
return err return err
@ -155,7 +158,7 @@ func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) err
return nil return nil
} }
func (d *uintDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *uintDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return 0, err return 0, err

View File

@ -1,16 +1,20 @@
package json package decoder
import ( import (
"encoding/json"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type unmarshalJSONDecoder struct { type unmarshalJSONDecoder struct {
typ *rtype typ *runtime.Type
structName string structName string
fieldName string fieldName string
} }
func newUnmarshalJSONDecoder(typ *rtype, structName, fieldName string) *unmarshalJSONDecoder { func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
return &unmarshalJSONDecoder{ return &unmarshalJSONDecoder{
typ: typ, typ: typ,
structName: structName, structName: structName,
@ -20,15 +24,15 @@ func newUnmarshalJSONDecoder(typ *rtype, structName, fieldName string) *unmarsha
func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) { func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
switch e := err.(type) { switch e := err.(type) {
case *UnmarshalTypeError: case *errors.UnmarshalTypeError:
e.Struct = d.structName e.Struct = d.structName
e.Field = d.fieldName e.Field = d.fieldName
case *SyntaxError: case *errors.SyntaxError:
e.Offset = cursor e.Offset = cursor
} }
} }
func (d *unmarshalJSONDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace() s.skipWhiteSpace()
start := s.cursor start := s.cursor
if err := s.skipValue(depth); err != nil { if err := s.skipValue(depth); err != nil {
@ -42,14 +46,14 @@ func (d *unmarshalJSONDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
typ: d.typ, typ: d.typ,
ptr: p, ptr: p,
})) }))
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil { if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
d.annotateError(s.cursor, err) d.annotateError(s.cursor, err)
return err return err
} }
return nil return nil
} }
func (d *unmarshalJSONDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *unmarshalJSONDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
start := cursor start := cursor
end, err := skipValue(buf, cursor, depth) end, err := skipValue(buf, cursor, depth)
@ -64,7 +68,7 @@ func (d *unmarshalJSONDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
typ: d.typ, typ: d.typ,
ptr: p, ptr: p,
})) }))
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil { if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
d.annotateError(cursor, err) d.annotateError(cursor, err)
return 0, err return 0, err
} }

View File

@ -1,4 +1,4 @@
package json package decoder
import ( import (
"bytes" "bytes"
@ -7,15 +7,18 @@ import (
"unicode/utf16" "unicode/utf16"
"unicode/utf8" "unicode/utf8"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
) )
type unmarshalTextDecoder struct { type unmarshalTextDecoder struct {
typ *rtype typ *runtime.Type
structName string structName string
fieldName string fieldName string
} }
func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarshalTextDecoder { func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder {
return &unmarshalTextDecoder{ return &unmarshalTextDecoder{
typ: typ, typ: typ,
structName: structName, structName: structName,
@ -25,10 +28,10 @@ func newUnmarshalTextDecoder(typ *rtype, structName, fieldName string) *unmarsha
func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) { func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) {
switch e := err.(type) { switch e := err.(type) {
case *UnmarshalTypeError: case *errors.UnmarshalTypeError:
e.Struct = d.structName e.Struct = d.structName
e.Field = d.fieldName e.Field = d.fieldName
case *SyntaxError: case *errors.SyntaxError:
e.Offset = cursor e.Offset = cursor
} }
} }
@ -37,7 +40,7 @@ var (
nullbytes = []byte(`null`) nullbytes = []byte(`null`)
) )
func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *unmarshalTextDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace() s.skipWhiteSpace()
start := s.cursor start := s.cursor
if err := s.skipValue(depth); err != nil { if err := s.skipValue(depth); err != nil {
@ -47,21 +50,21 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
if len(src) > 0 { if len(src) > 0 {
switch src[0] { switch src[0] {
case '[': case '[':
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: "array", Value: "array",
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(), Offset: s.totalOffset(),
} }
case '{': case '{':
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: "object", Value: "object",
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(), Offset: s.totalOffset(),
} }
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return &UnmarshalTypeError{ return &errors.UnmarshalTypeError{
Value: "number", Value: "number",
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(), Offset: s.totalOffset(),
} }
case 'n': case 'n':
@ -88,7 +91,7 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
return nil return nil
} }
func (d *unmarshalTextDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *unmarshalTextDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
start := cursor start := cursor
end, err := skipValue(buf, cursor, depth) end, err := skipValue(buf, cursor, depth)
@ -99,21 +102,21 @@ func (d *unmarshalTextDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
if len(src) > 0 { if len(src) > 0 {
switch src[0] { switch src[0] {
case '[': case '[':
return 0, &UnmarshalTypeError{ return 0, &errors.UnmarshalTypeError{
Value: "array", Value: "array",
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: start, Offset: start,
} }
case '{': case '{':
return 0, &UnmarshalTypeError{ return 0, &errors.UnmarshalTypeError{
Value: "object", Value: "object",
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: start, Offset: start,
} }
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return 0, &UnmarshalTypeError{ return 0, &errors.UnmarshalTypeError{
Value: "number", Value: "number",
Type: rtype2type(d.typ), Type: runtime.RType2Type(d.typ),
Offset: start, Offset: start,
} }
case 'n': case 'n':

View File

@ -1,20 +1,22 @@
package json package decoder
import ( import (
"reflect" "reflect"
"unsafe" "unsafe"
"github.com/goccy/go-json/internal/runtime"
) )
type wrappedStringDecoder struct { type wrappedStringDecoder struct {
typ *rtype typ *runtime.Type
dec decoder dec Decoder
stringDecoder *stringDecoder stringDecoder *stringDecoder
structName string structName string
fieldName string fieldName string
isPtrType bool isPtrType bool
} }
func newWrappedStringDecoder(typ *rtype, dec decoder, structName, fieldName string) *wrappedStringDecoder { func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) *wrappedStringDecoder {
return &wrappedStringDecoder{ return &wrappedStringDecoder{
typ: typ, typ: typ,
dec: dec, dec: dec,
@ -25,7 +27,7 @@ func newWrappedStringDecoder(typ *rtype, dec decoder, structName, fieldName stri
} }
} }
func (d *wrappedStringDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *wrappedStringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.stringDecoder.decodeStreamByte(s) bytes, err := d.stringDecoder.decodeStreamByte(s)
if err != nil { if err != nil {
return err return err
@ -38,13 +40,13 @@ func (d *wrappedStringDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi
} }
b := make([]byte, len(bytes)+1) b := make([]byte, len(bytes)+1)
copy(b, bytes) copy(b, bytes)
if _, err := d.dec.decode(b, 0, depth, p); err != nil { if _, err := d.dec.Decode(b, 0, depth, p); err != nil {
return err return err
} }
return nil return nil
} }
func (d *wrappedStringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *wrappedStringDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.stringDecoder.decodeByte(buf, cursor) bytes, c, err := d.stringDecoder.decodeByte(buf, cursor)
if err != nil { if err != nil {
return 0, err return 0, err
@ -56,7 +58,7 @@ func (d *wrappedStringDecoder) decode(buf []byte, cursor, depth int64, p unsafe.
return c, nil return c, nil
} }
bytes = append(bytes, nul) bytes = append(bytes, nul)
if _, err := d.dec.decode(bytes, 0, depth, p); err != nil { if _, err := d.dec.Decode(bytes, 0, depth, p); err != nil {
return 0, err return 0, err
} }
return c, nil return c, nil

View File

@ -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)
}