go-json/decode.go

262 lines
5.3 KiB
Go
Raw Normal View History

2020-04-22 07:06:52 +03:00
package json
import (
2020-05-08 14:22:57 +03:00
"encoding"
"fmt"
2020-04-22 07:06:52 +03:00
"io"
"reflect"
2020-07-30 16:41:53 +03:00
"strconv"
2020-04-22 07:06:52 +03:00
"unsafe"
)
2020-04-23 19:39:20 +03:00
type decoder interface {
decode([]byte, int64, int64, unsafe.Pointer) (int64, error)
decodeStream(*stream, int64, unsafe.Pointer) error
2020-04-23 19:39:20 +03:00
}
2020-04-22 07:06:52 +03:00
type Decoder struct {
2021-02-10 18:45:38 +03:00
s *stream
2020-04-22 07:06:52 +03:00
}
var (
2020-05-08 14:22:57 +03:00
unmarshalJSONType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
2020-04-22 07:06:52 +03:00
)
2020-07-31 11:10:03 +03:00
const (
nul = '\000'
maxDecodeNestingDepth = 10000
2020-07-31 11:10:03 +03:00
)
2021-02-10 18:45:38 +03:00
func unmarshal(data []byte, v interface{}) error {
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
}
dec, err := decodeCompileToGetDecoder(header.typ)
if err != nil {
return err
}
cursor, err := dec.decode(src, 0, 0, header.ptr)
if err != nil {
2021-02-10 19:15:31 +03:00
return err
}
return validateEndBuf(src, cursor)
2020-04-22 07:06:52 +03:00
}
2021-02-10 18:45:38 +03:00
func unmarshalNoEscape(data []byte, v interface{}) error {
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))
2021-02-10 19:15:31 +03:00
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
return err
}
2021-02-10 19:15:31 +03:00
dec, err := decodeCompileToGetDecoder(header.typ)
2021-02-04 12:00:08 +03:00
if err != nil {
return err
2020-04-22 07:06:52 +03:00
}
cursor, err := dec.decode(src, 0, 0, noescape(header.ptr))
if err != nil {
2020-04-22 07:06:52 +03:00
return err
}
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
}
return errSyntax(
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-02-10 18:45:38 +03:00
func validateType(typ *rtype, p uintptr) error {
2021-02-18 10:42:38 +03:00
if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
2021-02-10 18:45:38 +03:00
return &InvalidUnmarshalError{Type: rtype2type(typ)}
}
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 {
s := newStream(r)
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 {
return d.s.buffered()
2020-04-24 15:57:11 +03:00
}
2020-05-24 15:31:10 +03:00
func (d *Decoder) prepareForDecode() error {
s := d.s
2020-07-30 16:41:53 +03:00
for {
2020-05-24 15:31:10 +03:00
switch s.char() {
case ' ', '\t', '\r', '\n':
2020-07-31 11:10:03 +03:00
s.cursor++
2020-05-24 15:31:10 +03:00
continue
case ',', ':':
2020-07-31 11:10:03 +03:00
s.cursor++
2020-05-24 15:31:10 +03:00
return nil
2020-07-31 11:10:03 +03:00
case nul:
if s.read() {
continue
}
return io.EOF
2020-05-24 15:31:10 +03:00
}
break
}
return nil
}
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-03-13 08:12:31 +03:00
header := (*emptyInterface)(unsafe.Pointer(&v))
2020-04-24 14:23:26 +03:00
typ := header.typ
ptr := uintptr(header.ptr)
2020-05-06 16:22:13 +03:00
typeptr := uintptr(unsafe.Pointer(typ))
// noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
2021-02-10 18:45:38 +03:00
if err := validateType(copiedType, ptr); err != nil {
return err
}
2021-02-10 19:15:31 +03:00
dec, err := decodeCompileToGetDecoder(typ)
2021-02-04 12:00:08 +03:00
if err != nil {
return err
2020-04-22 07:06:52 +03:00
}
2020-05-24 15:31:10 +03:00
if err := d.prepareForDecode(); err != nil {
return err
2020-04-25 16:48:16 +03:00
}
2020-05-24 15:31:10 +03:00
s := d.s
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
}
s.reset()
s.bufSize = initBufSize
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 {
s := d.s
2020-07-30 16:41:53 +03:00
for {
2020-05-24 15:31:10 +03:00
switch s.char() {
case ' ', '\n', '\r', '\t':
2020-07-31 11:10:03 +03:00
s.cursor++
continue
case '}', ']':
return false
case nul:
if s.read() {
2020-07-30 16:41:53 +03:00
continue
}
2020-05-24 15:31:10 +03:00
return false
}
br