2020-04-22 07:06:52 +03:00
|
|
|
package json
|
|
|
|
|
|
|
|
import (
|
2021-06-12 11:06:26 +03:00
|
|
|
"context"
|
2021-04-10 12:44:43 +03:00
|
|
|
"fmt"
|
2020-04-22 07:06:52 +03:00
|
|
|
"io"
|
|
|
|
"reflect"
|
|
|
|
"unsafe"
|
|
|
|
|
2021-06-03 12:49:01 +03:00
|
|
|
"github.com/goccy/go-json/internal/decoder"
|
2021-06-03 12:59:52 +03:00
|
|
|
"github.com/goccy/go-json/internal/errors"
|
2021-06-03 12:49:01 +03:00
|
|
|
"github.com/goccy/go-json/internal/runtime"
|
|
|
|
)
|
2020-04-23 19:39:20 +03:00
|
|
|
|
2020-04-22 07:06:52 +03:00
|
|
|
type Decoder struct {
|
2021-06-03 12:49:01 +03:00
|
|
|
s *decoder.Stream
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-07-31 11:10:03 +03:00
|
|
|
const (
|
2021-06-03 12:49:01 +03:00
|
|
|
nul = '\000'
|
2020-07-31 11:10:03 +03:00
|
|
|
)
|
|
|
|
|
2021-06-03 12:49:01 +03:00
|
|
|
type emptyInterface struct {
|
|
|
|
typ *runtime.Type
|
|
|
|
ptr unsafe.Pointer
|
|
|
|
}
|
|
|
|
|
2021-06-04 18:27:02 +03:00
|
|
|
func unmarshal(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
2021-02-10 18:45:38 +03:00
|
|
|
src := make([]byte, len(data)+1) // append nul byte to the end
|
|
|
|
copy(src, data)
|
2020-04-22 07:06:52 +03:00
|
|
|
|
2021-03-13 08:12:31 +03:00
|
|
|
header := (*emptyInterface)(unsafe.Pointer(&v))
|
2021-02-10 19:15:31 +03:00
|
|
|
|
|
|
|
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-06-03 12:49:01 +03:00
|
|
|
dec, err := decoder.CompileToGetDecoder(header.typ)
|
2021-02-10 19:15:31 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-06-04 19:08:27 +03:00
|
|
|
ctx := decoder.TakeRuntimeContext()
|
|
|
|
ctx.Buf = src
|
2021-06-12 11:06:26 +03:00
|
|
|
ctx.Option.Flags = 0
|
2021-06-04 19:08:27 +03:00
|
|
|
for _, optFunc := range optFuncs {
|
|
|
|
optFunc(ctx.Option)
|
|
|
|
}
|
|
|
|
cursor, err := dec.Decode(ctx, 0, 0, header.ptr)
|
2021-04-10 12:44:43 +03:00
|
|
|
if err != nil {
|
2021-06-04 19:08:27 +03:00
|
|
|
decoder.ReleaseRuntimeContext(ctx)
|
2021-02-10 19:15:31 +03:00
|
|
|
return err
|
|
|
|
}
|
2021-06-04 19:08:27 +03:00
|
|
|
decoder.ReleaseRuntimeContext(ctx)
|
2021-04-10 12:44:43 +03:00
|
|
|
return validateEndBuf(src, cursor)
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
2021-06-12 11:06:26 +03:00
|
|
|
func unmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
|
|
|
src := make([]byte, len(data)+1) // append nul byte to the end
|
|
|
|
copy(src, data)
|
|
|
|
|
|
|
|
header := (*emptyInterface)(unsafe.Pointer(&v))
|
|
|
|
|
|
|
|
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
dec, err := decoder.CompileToGetDecoder(header.typ)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
rctx := decoder.TakeRuntimeContext()
|
|
|
|
rctx.Buf = src
|
|
|
|
rctx.Option.Flags = 0
|
|
|
|
rctx.Option.Flags |= decoder.ContextOption
|
|
|
|
rctx.Option.Context = ctx
|
|
|
|
for _, optFunc := range optFuncs {
|
|
|
|
optFunc(rctx.Option)
|
|
|
|
}
|
|
|
|
cursor, err := dec.Decode(rctx, 0, 0, header.ptr)
|
|
|
|
if err != nil {
|
|
|
|
decoder.ReleaseRuntimeContext(rctx)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
decoder.ReleaseRuntimeContext(rctx)
|
|
|
|
return validateEndBuf(src, cursor)
|
|
|
|
}
|
|
|
|
|
2022-11-28 21:55:56 +03:00
|
|
|
var (
|
|
|
|
pathDecoder = decoder.NewPathDecoder()
|
|
|
|
)
|
|
|
|
|
|
|
|
func extractFromPath(path *Path, data []byte, optFuncs ...DecodeOptionFunc) ([][]byte, error) {
|
|
|
|
src := make([]byte, len(data)+1) // append nul byte to the end
|
|
|
|
copy(src, data)
|
|
|
|
|
|
|
|
ctx := decoder.TakeRuntimeContext()
|
|
|
|
ctx.Buf = src
|
|
|
|
ctx.Option.Flags = 0
|
|
|
|
ctx.Option.Flags |= decoder.PathOption
|
|
|
|
ctx.Option.Path = path.path
|
|
|
|
for _, optFunc := range optFuncs {
|
|
|
|
optFunc(ctx.Option)
|
|
|
|
}
|
|
|
|
paths, cursor, err := pathDecoder.DecodePath(ctx, 0, 0)
|
|
|
|
if err != nil {
|
|
|
|
decoder.ReleaseRuntimeContext(ctx)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
decoder.ReleaseRuntimeContext(ctx)
|
|
|
|
if err := validateEndBuf(src, cursor); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return paths, nil
|
|
|
|
}
|
|
|
|
|
2021-06-04 19:08:27 +03:00
|
|
|
func unmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
2021-02-10 18:45:38 +03:00
|
|
|
src := make([]byte, len(data)+1) // append nul byte to the end
|
|
|
|
copy(src, data)
|
|
|
|
|
2021-03-13 08:12:31 +03:00
|
|
|
header := (*emptyInterface)(unsafe.Pointer(&v))
|
2020-05-08 19:07:33 +03:00
|
|
|
|
2021-02-10 19:15:31 +03:00
|
|
|
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
|
2020-05-08 19:07:33 +03:00
|
|
|
return err
|
|
|
|
}
|
2021-06-03 12:49:01 +03:00
|
|
|
dec, err := decoder.CompileToGetDecoder(header.typ)
|
2021-02-04 12:00:08 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
2021-06-04 19:08:27 +03:00
|
|
|
|
|
|
|
ctx := decoder.TakeRuntimeContext()
|
|
|
|
ctx.Buf = src
|
2021-06-12 11:06:26 +03:00
|
|
|
ctx.Option.Flags = 0
|
2021-06-04 19:08:27 +03:00
|
|
|
for _, optFunc := range optFuncs {
|
|
|
|
optFunc(ctx.Option)
|
|
|
|
}
|
|
|
|
cursor, err := dec.Decode(ctx, 0, 0, noescape(header.ptr))
|
2021-04-10 12:44:43 +03:00
|
|
|
if err != nil {
|
2021-06-04 19:08:27 +03:00
|
|
|
decoder.ReleaseRuntimeContext(ctx)
|
2020-04-22 07:06:52 +03:00
|
|
|
return err
|
|
|
|
}
|
2021-06-04 19:08:27 +03:00
|
|
|
decoder.ReleaseRuntimeContext(ctx)
|
2021-04-10 12:44:43 +03:00
|
|
|
return validateEndBuf(src, cursor)
|
|
|
|
}
|
|
|
|
|
|
|
|
func validateEndBuf(src []byte, cursor int64) error {
|
|
|
|
for {
|
|
|
|
switch src[cursor] {
|
|
|
|
case ' ', '\t', '\n', '\r':
|
|
|
|
cursor++
|
|
|
|
continue
|
|
|
|
case nul:
|
|
|
|
return nil
|
|
|
|
}
|
2021-06-03 12:59:52 +03:00
|
|
|
return errors.ErrSyntax(
|
2021-04-10 12:44:43 +03:00
|
|
|
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
|
|
|
|
cursor+1,
|
|
|
|
)
|
|
|
|
}
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
2021-02-10 19:21:35 +03:00
|
|
|
//nolint:staticcheck
|
2021-02-10 19:15:31 +03:00
|
|
|
//go:nosplit
|
|
|
|
func noescape(p unsafe.Pointer) unsafe.Pointer {
|
|
|
|
x := uintptr(p)
|
|
|
|
return unsafe.Pointer(x ^ 0)
|
|
|
|
}
|
|
|
|
|
2021-06-03 12:49:01 +03:00
|
|
|
func validateType(typ *runtime.Type, p uintptr) error {
|
2021-02-18 10:42:38 +03:00
|
|
|
if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
|
2021-06-03 12:49:01 +03:00
|
|
|
return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)}
|
2021-02-10 18:45:38 +03:00
|
|
|
}
|
|
|
|
return nil
|
2020-04-24 15:57:11 +03:00
|
|
|
}
|
|
|
|
|
2021-02-10 18:45:38 +03:00
|
|
|
// NewDecoder returns a new decoder that reads from r.
|
|
|
|
//
|
|
|
|
// The decoder introduces its own buffering and may
|
|
|
|
// read data from r beyond the JSON values requested.
|
|
|
|
func NewDecoder(r io.Reader) *Decoder {
|
2021-06-03 12:49:01 +03:00
|
|
|
s := decoder.NewStream(r)
|
2021-02-10 18:45:38 +03:00
|
|
|
return &Decoder{
|
|
|
|
s: s,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 {
|
2021-06-03 12:49:01 +03:00
|
|
|
return d.s.Buffered()
|
2020-05-24 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2020-04-25 13:55:05 +03:00
|
|
|
// Decode reads the next JSON-encoded value from its
|
|
|
|
// input and stores it in the value pointed to by v.
|
|
|
|
//
|
|
|
|
// See the documentation for Unmarshal for details about
|
|
|
|
// the conversion of JSON into a Go value.
|
2020-04-22 07:06:52 +03:00
|
|
|
func (d *Decoder) Decode(v interface{}) error {
|
2021-06-06 05:24:56 +03:00
|
|
|
return d.DecodeWithOption(v)
|
|
|
|
}
|
|
|
|
|
2021-06-12 11:06:26 +03:00
|
|
|
// DecodeContext reads the next JSON-encoded value from its
|
|
|
|
// input and stores it in the value pointed to by v with context.Context.
|
|
|
|
func (d *Decoder) DecodeContext(ctx context.Context, v interface{}) error {
|
|
|
|
d.s.Option.Flags |= decoder.ContextOption
|
|
|
|
d.s.Option.Context = ctx
|
|
|
|
return d.DecodeWithOption(v)
|
|
|
|
}
|
|
|
|
|
2021-06-06 05:24:56 +03:00
|
|
|
func (d *Decoder) DecodeWithOption(v interface{}, optFuncs ...DecodeOptionFunc) error {
|
2021-03-13 08:12:31 +03:00
|
|
|
header := (*emptyInterface)(unsafe.Pointer(&v))
|
2020-04-24 14:23:26 +03:00
|
|
|
typ := header.typ
|
2020-05-08 19:07:33 +03:00
|
|
|
ptr := uintptr(header.ptr)
|
2020-05-06 16:22:13 +03:00
|
|
|
typeptr := uintptr(unsafe.Pointer(typ))
|
2020-05-08 19:07:33 +03:00
|
|
|
// noescape trick for header.typ ( reflect.*rtype )
|
2021-06-03 12:49:01 +03:00
|
|
|
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
2020-05-08 19:07:33 +03:00
|
|
|
|
2021-02-10 18:45:38 +03:00
|
|
|
if err := validateType(copiedType, ptr); err != nil {
|
2020-05-08 19:07:33 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-06-03 12:49:01 +03:00
|
|
|
dec, err := decoder.CompileToGetDecoder(typ)
|
2021-02-04 12:00:08 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
2021-06-03 12:49:01 +03:00
|
|
|
if err := d.s.PrepareForDecode(); err != nil {
|
2020-05-24 15:31:10 +03:00
|
|
|
return err
|
2020-04-25 16:48:16 +03:00
|
|
|
}
|
2020-05-24 15:31:10 +03:00
|
|
|
s := d.s
|
2021-06-06 05:24:56 +03:00
|
|
|
for _, optFunc := range optFuncs {
|
|
|
|
optFunc(s.Option)
|
|
|
|
}
|
2021-06-03 12:49:01 +03:00
|
|
|
if err := dec.DecodeStream(s, 0, header.ptr); err != nil {
|
2020-05-24 15:31:10 +03:00
|
|
|
return err
|
2020-04-25 16:48:16 +03:00
|
|
|
}
|
2021-06-03 12:49:01 +03:00
|
|
|
s.Reset()
|
2020-05-24 15:31:10 +03:00
|
|
|
return nil
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-05-24 15:31:10 +03:00
|
|
|
func (d *Decoder) More() bool {
|
2021-06-03 12:49:01 +03:00
|
|
|
return d.s.More()
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-05-24 15:31:10 +03:00
|
|
|
func (d *Decoder) Token() (Token, error) {
|
2021-06-03 12:49:01 +03:00
|
|
|
return d.s.Token()
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-04-25 13:55:05 +03:00
|
|
|
// 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.
|
2020-04-22 07:06:52 +03:00
|
|
|
func (d *Decoder) DisallowUnknownFields() {
|
2021-06-03 12:49:01 +03:00
|
|
|
d.s.DisallowUnknownFields = true
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Decoder) InputOffset() int64 {
|
2021-06-03 12:49:01 +03:00
|
|
|
return d.s.TotalOffset()
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-04-25 13:55:05 +03:00
|
|
|
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
|
|
|
// Number instead of as a float64.
|
2020-04-22 07:06:52 +03:00
|
|
|
func (d *Decoder) UseNumber() {
|
2021-06-03 12:49:01 +03:00
|
|
|
d.s.UseNumber = true
|
2020-04-22 07:06:52 +03:00
|
|
|
}
|