Fix package layout for decoder

This commit is contained in:
Masaaki Goshima 2021-06-03 18:49:01 +09:00
parent 80719cf181
commit 5a024ca2f1
27 changed files with 640 additions and 644 deletions

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

149
decode.go
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,21 +1,50 @@
package json
package decoder
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"sync/atomic"
"unicode"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
var (
jsonNumberType = reflect.TypeOf(json.Number(""))
jsonNumberType = reflect.TypeOf(json.Number(""))
typeAddr *runtime.TypeAddr
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
cachedDecoder []decoder
)
func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, error) {
func init() {
typeAddr = runtime.AnalyzeTypeAddr()
if typeAddr == nil {
typeAddr = &runtime.TypeAddr{}
}
cachedDecoder = make([]decoder, typeAddr.AddrRange>>typeAddr.AddrShift)
}
func loadDecoderMap() map[uintptr]decoder {
p := atomic.LoadPointer(&cachedDecoderMap)
return *(*map[uintptr]decoder)(unsafe.Pointer(&p))
}
func storeDecoder(typ uintptr, dec decoder, m map[uintptr]decoder) {
newDecoderMap := make(map[uintptr]decoder, len(m)+1)
newDecoderMap[typ] = dec
for k, v := range m {
newDecoderMap[k] = v
}
atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap)))
}
func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (decoder, error) {
decoderMap := loadDecoderMap()
if dec, exists := decoderMap[typeptr]; exists {
return dec, nil
@ -29,22 +58,22 @@ func decodeCompileToGetDecoderSlowPath(typeptr uintptr, typ *rtype) (decoder, er
return dec, nil
}
func decodeCompileHead(typ *rtype, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
func decodeCompileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
switch {
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil
case rtype_ptrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil
case runtime.PtrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil
}
return decodeCompile(typ.Elem(), "", "", structTypeToDecoder)
}
func decodeCompile(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
func decodeCompile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
switch {
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil
case rtype_ptrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil
case runtime.PtrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
}
switch typ.Kind() {
@ -95,18 +124,18 @@ func decodeCompile(typ *rtype, structName, fieldName string, structTypeToDecoder
case reflect.Float64:
return decodeCompileFloat64(structName, fieldName)
}
return nil, &UnmarshalTypeError{
return nil, &errors.UnmarshalTypeError{
Value: "object",
Type: rtype2type(typ),
Type: runtime.RType2Type(typ),
Offset: 0,
}
}
func isStringTagSupportedType(typ *rtype) bool {
func isStringTagSupportedType(typ *runtime.Type) bool {
switch {
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
return false
case rtype_ptrTo(typ).Implements(unmarshalTextType):
case runtime.PtrTo(typ).Implements(unmarshalTextType):
return false
}
switch typ.Kind() {
@ -124,9 +153,9 @@ func isStringTagSupportedType(typ *rtype) bool {
return true
}
func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
if rtype_ptrTo(typ).Implements(unmarshalTextType) {
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
func decodeCompileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
if runtime.PtrTo(typ).Implements(unmarshalTextType) {
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
}
dec, err := decodeCompile(typ, structName, fieldName, structTypeToDecoder)
if err != nil {
@ -145,14 +174,14 @@ func decodeCompileMapKey(typ *rtype, structName, fieldName string, structTypeToD
}
}
ERROR:
return nil, &UnmarshalTypeError{
return nil, &errors.UnmarshalTypeError{
Value: "object",
Type: rtype2type(typ),
Type: runtime.RType2Type(typ),
Offset: 0,
}
}
func decodeCompilePtr(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
func decodeCompilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
dec, err := decodeCompile(typ.Elem(), structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
@ -160,61 +189,61 @@ func decodeCompilePtr(typ *rtype, structName, fieldName string, structTypeToDeco
return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil
}
func decodeCompileInt(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileInt(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int)(p) = int(v)
}), nil
}
func decodeCompileInt8(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileInt8(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int8)(p) = int8(v)
}), nil
}
func decodeCompileInt16(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileInt16(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int16)(p) = int16(v)
}), nil
}
func decodeCompileInt32(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileInt32(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int32)(p) = int32(v)
}), nil
}
func decodeCompileInt64(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileInt64(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int64)(p) = v
}), nil
}
func decodeCompileUint(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileUint(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint)(p) = uint(v)
}), nil
}
func decodeCompileUint8(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileUint8(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint8)(p) = uint8(v)
}), nil
}
func decodeCompileUint16(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileUint16(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint16)(p) = uint16(v)
}), nil
}
func decodeCompileUint32(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileUint32(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint32)(p) = uint32(v)
}), nil
}
func decodeCompileUint64(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileUint64(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint64)(p) = v
}), nil
@ -232,10 +261,10 @@ func decodeCompileFloat64(structName, fieldName string) (decoder, error) {
}), nil
}
func decodeCompileString(typ *rtype, structName, fieldName string) (decoder, error) {
if typ == type2rtype(jsonNumberType) {
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) {
*(*Number)(p) = v
func decodeCompileString(typ *runtime.Type, structName, fieldName string) (decoder, error) {
if typ == runtime.Type2RType(jsonNumberType) {
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*json.Number)(p) = v
}), nil
}
return newStringDecoder(structName, fieldName), nil
@ -245,11 +274,11 @@ func decodeCompileBool(structName, fieldName string) (decoder, error) {
return newBoolDecoder(structName, fieldName), nil
}
func decodeCompileBytes(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileBytes(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newBytesDecoder(typ, structName, fieldName), nil
}
func decodeCompileSlice(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
func decodeCompileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
elem := typ.Elem()
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
if err != nil {
@ -258,7 +287,7 @@ func decodeCompileSlice(typ *rtype, structName, fieldName string, structTypeToDe
return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
}
func decodeCompileArray(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
func decodeCompileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
elem := typ.Elem()
decoder, err := decodeCompile(elem, structName, fieldName, structTypeToDecoder)
if err != nil {
@ -267,7 +296,7 @@ func decodeCompileArray(typ *rtype, structName, fieldName string, structTypeToDe
return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
}
func decodeCompileMap(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
func decodeCompileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
keyDec, err := decodeCompileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
@ -279,7 +308,7 @@ func decodeCompileMap(typ *rtype, structName, fieldName string, structTypeToDeco
return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil
}
func decodeCompileInterface(typ *rtype, structName, fieldName string) (decoder, error) {
func decodeCompileInterface(typ *runtime.Type, structName, fieldName string) (decoder, error) {
return newInterfaceDecoder(typ, structName, fieldName), nil
}
@ -338,7 +367,7 @@ func decodeRemoveConflictFields(fieldMap map[string]*structFieldSet, conflictedM
}
}
func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
func decodeCompileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]decoder) (decoder, error) {
fieldNum := typ.NumField()
conflictedMap := map[string]struct{}{}
fieldMap := map[string]*structFieldSet{}
@ -356,13 +385,13 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
}
isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
tag := runtime.StructTagFromField(field)
dec, err := decodeCompile(type2rtype(field.Type), structName, field.Name, structTypeToDecoder)
dec, err := decodeCompile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder)
if err != nil {
return nil, err
}
if field.Anonymous && !tag.IsTaggedKey {
if stDec, ok := dec.(*structDecoder); ok {
if type2rtype(field.Type) == typ {
if runtime.Type2RType(field.Type) == typ {
// recursive definition
continue
}
@ -438,8 +467,8 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD
}
}
} else {
if tag.IsString && isStringTagSupportedType(type2rtype(field.Type)) {
dec = newWrappedStringDecoder(type2rtype(field.Type), dec, structName, field.Name)
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name)
}
var key string
if tag.Key != "" {

View File

@ -1,16 +1,20 @@
// +build !race
package json
package decoder
import "unsafe"
import (
"unsafe"
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
"github.com/goccy/go-json/internal/runtime"
)
func CompileToGetDecoder(typ *runtime.Type) (decoder, error) {
typeptr := uintptr(unsafe.Pointer(typ))
if typeptr > maxTypeAddr {
if typeptr > typeAddr.MaxTypeAddr {
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
}
index := (typeptr - baseTypeAddr) >> typeAddrShift
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
if dec := cachedDecoder[index]; dec != nil {
return dec, nil
}

View File

@ -1,15 +1,17 @@
// +build race
package json
package decoder
import (
"sync"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
var decMu sync.RWMutex
func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
func CompileToGetDecoder(typ *runtime.Type) (decoder, error) {
typeptr := uintptr(unsafe.Pointer(typ))
if typeptr > maxTypeAddr {
return decodeCompileToGetDecoderSlowPath(typeptr, typ)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package json
package decoder
import (
"fmt"
@ -7,6 +7,8 @@ import (
"sort"
"strings"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
type structFieldSet struct {
@ -28,7 +30,7 @@ type structDecoder struct {
keyBitmapUint16 [][256]uint16
sortedFieldSets []*structFieldSet
keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
keyStreamDecoder func(*structDecoder, *stream) (*structFieldSet, string, error)
keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error)
}
var (
@ -154,7 +156,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++
return cursor, field, nil
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
keyIdx := 0
bitmap := d.keyBitmapUint8
@ -173,7 +175,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
}
return cursor, field, nil
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
@ -186,10 +188,10 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
case '\\':
cursor++
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
}
}
@ -198,7 +200,7 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++
}
default:
return cursor, nil, errNotAtBeginningOfValue(cursor)
return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
}
}
}
@ -221,7 +223,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++
return cursor, field, nil
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
keyIdx := 0
bitmap := d.keyBitmapUint16
@ -240,7 +242,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
}
return cursor, field, nil
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
@ -253,10 +255,10 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
case '\\':
cursor++
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
}
}
@ -265,7 +267,7 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
cursor++
}
default:
return cursor, nil, errNotAtBeginningOfValue(cursor)
return cursor, nil, errors.ErrNotAtBeginningOfValue(cursor)
}
}
}
@ -284,7 +286,7 @@ func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldS
return cursor, field, nil
}
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
var (
field *structFieldSet
curBit uint8 = math.MaxUint8
@ -300,7 +302,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
buf, cursor, p = s.stat()
continue
}
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
case '"':
cursor++
FIRST_CHAR:
@ -316,7 +318,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
buf, cursor, p = s.stat()
goto FIRST_CHAR
}
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
keyIdx := 0
bitmap := d.keyBitmapUint8
@ -340,7 +342,7 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
buf, cursor, p = s.stat()
continue
}
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
@ -358,14 +360,14 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
if char(p, cursor) == nul {
s.cursor = cursor
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
buf, cursor, p = s.statForRetry()
}
case nul:
s.cursor = cursor
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
buf, cursor, p = s.statForRetry()
}
@ -376,12 +378,12 @@ func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet,
cursor++
}
default:
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
}
}
}
func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
var (
field *structFieldSet
curBit uint16 = math.MaxUint16
@ -397,7 +399,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
buf, cursor, p = s.stat()
continue
}
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
case '"':
cursor++
FIRST_CHAR:
@ -413,7 +415,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
buf, cursor, p = s.stat()
goto FIRST_CHAR
}
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
keyIdx := 0
bitmap := d.keyBitmapUint16
@ -437,7 +439,7 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
buf, cursor, p = s.stat()
continue
}
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
@ -455,14 +457,14 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
if char(p, cursor) == nul {
s.cursor = cursor
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
buf, cursor, p = s.statForRetry()
}
case nul:
s.cursor = cursor
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
buf, cursor, p = s.statForRetry()
}
@ -473,12 +475,12 @@ func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet
cursor++
}
default:
return nil, "", errNotAtBeginningOfValue(s.totalOffset())
return nil, "", errors.ErrNotAtBeginningOfValue(s.totalOffset())
}
}
}
func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
key, err := d.stringDecoder.decodeStreamByte(s)
if err != nil {
return nil, "", err
@ -487,10 +489,10 @@ func decodeKeyStream(d *structDecoder, s *stream) (*structFieldSet, string, erro
return d.fieldMap[k], k, nil
}
func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++
if depth > maxDecodeNestingDepth {
return errExceededMaxDepth(s.char(), s.cursor)
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
s.skipWhiteSpace()
@ -504,7 +506,7 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
s.read()
default:
if s.char() != '{' {
return errNotAtBeginningOfValue(s.totalOffset())
return errors.ErrNotAtBeginningOfValue(s.totalOffset())
}
}
s.cursor++
@ -521,22 +523,22 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
}
s.skipWhiteSpace()
if s.char() != ':' {
return errExpected("colon after object key", s.totalOffset())
return errors.ErrExpected("colon after object key", s.totalOffset())
}
s.cursor++
if s.char() == nul {
if !s.read() {
return errExpected("object value after colon", s.totalOffset())
return errors.ErrExpected("object value after colon", s.totalOffset())
}
}
if field != nil {
if field.err != nil {
return field.err
}
if err := field.dec.decodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
return err
}
} else if s.disallowUnknownFields {
} else if s.DisallowUnknownFields {
return fmt.Errorf("json: unknown field %q", key)
} else {
if err := s.skipValue(depth); err != nil {
@ -550,16 +552,16 @@ func (d *structDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) e
return nil
}
if c != ',' {
return errExpected("comma after object element", s.totalOffset())
return errors.ErrExpected("comma after object element", s.totalOffset())
}
s.cursor++
}
}
func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
func (d *structDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
depth++
if depth > maxDecodeNestingDepth {
return 0, errExceededMaxDepth(buf[cursor], cursor)
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
buflen := int64(len(buf))
cursor = skipWhiteSpace(buf, cursor)
@ -573,7 +575,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
return cursor, nil
case '{':
default:
return 0, errNotAtBeginningOfValue(cursor)
return 0, errors.ErrNotAtBeginningOfValue(cursor)
}
cursor++
cursor = skipWhiteSpace(buf, cursor)
@ -588,17 +590,17 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
}
cursor = skipWhiteSpace(buf, c)
if char(b, cursor) != ':' {
return 0, errExpected("colon after object key", cursor)
return 0, errors.ErrExpected("colon after object key", cursor)
}
cursor++
if cursor >= buflen {
return 0, errExpected("object value after colon", cursor)
return 0, errors.ErrExpected("object value after colon", cursor)
}
if field != nil {
if field.err != nil {
return 0, field.err
}
c, err := field.dec.decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
c, err := field.dec.Decode(buf, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
if err != nil {
return 0, err
}
@ -616,7 +618,7 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
return cursor, nil
}
if char(b, cursor) != ',' {
return 0, errExpected("comma after object element", cursor)
return 0, errors.ErrExpected("comma after object element", cursor)
}
cursor++
}

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

View File

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

View File

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

View File

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

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