go-json/internal/decoder/interface.go

420 lines
10 KiB
Go
Raw Normal View History

2021-06-03 12:49:01 +03:00
package decoder
2020-05-08 09:13:30 +03:00
import (
2021-02-16 19:51:42 +03:00
"bytes"
2021-01-22 07:28:03 +03:00
"encoding"
2021-06-03 12:49:01 +03:00
"encoding/json"
2020-05-08 09:13:30 +03:00
"reflect"
"unsafe"
2021-06-03 12:49:01 +03:00
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
2020-05-08 09:13:30 +03:00
)
type interfaceDecoder struct {
2021-06-03 12:49:01 +03:00
typ *runtime.Type
structName string
fieldName string
sliceDecoder *sliceDecoder
mapDecoder *mapDecoder
floatDecoder *floatDecoder
numberDecoder *numberDecoder
stringDecoder *stringDecoder
}
func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
ifaceDecoder := &interfaceDecoder{
typ: emptyInterfaceType,
structName: structName,
fieldName: fieldName,
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*interface{})(p) = v
}),
2021-06-03 12:49:01 +03:00
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*interface{})(p) = v
}),
stringDecoder: newStringDecoder(structName, fieldName),
}
ifaceDecoder.sliceDecoder = newSliceDecoder(
ifaceDecoder,
emptyInterfaceType,
emptyInterfaceType.Size(),
structName, fieldName,
)
ifaceDecoder.mapDecoder = newMapDecoder(
interfaceMapType,
stringType,
ifaceDecoder.stringDecoder,
interfaceMapType.Elem(),
ifaceDecoder,
structName,
fieldName,
)
return ifaceDecoder
2020-05-08 09:13:30 +03:00
}
2021-06-03 12:49:01 +03:00
func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
stringDecoder := newStringDecoder(structName, fieldName)
2020-08-11 12:04:32 +03:00
return &interfaceDecoder{
typ: typ,
structName: structName,
fieldName: fieldName,
sliceDecoder: newSliceDecoder(
emptyIfaceDecoder,
emptyInterfaceType,
emptyInterfaceType.Size(),
structName, fieldName,
),
mapDecoder: newMapDecoder(
interfaceMapType,
stringType,
stringDecoder,
interfaceMapType.Elem(),
emptyIfaceDecoder,
structName,
fieldName,
),
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*interface{})(p) = v
}),
2021-06-03 12:49:01 +03:00
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*interface{})(p) = v
}),
stringDecoder: stringDecoder,
2020-08-11 12:04:32 +03:00
}
}
2021-06-03 12:49:01 +03:00
func (d *interfaceDecoder) numDecoder(s *Stream) decoder {
if s.UseNumber {
return d.numberDecoder
2020-08-11 12:04:32 +03:00
}
return d.floatDecoder
2020-05-08 09:13:30 +03:00
}
var (
2021-06-03 12:49:01 +03:00
emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
interfaceMapType = runtime.Type2RType(
2020-08-25 05:17:38 +03:00
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
2020-05-08 09:13:30 +03:00
)
2021-06-03 12:49:01 +03:00
stringType = runtime.Type2RType(
2020-12-22 15:55:59 +03:00
reflect.TypeOf(""),
)
2020-05-08 09:13:30 +03:00
)
2021-06-03 12:49:01 +03:00
func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
2021-01-22 07:28:03 +03:00
start := s.cursor
if err := s.skipValue(depth); err != nil {
2021-01-22 07:28:03 +03:00
return err
}
src := s.buf[start:s.cursor]
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalJSON(dst); err != nil {
return err
}
return nil
}
2021-06-03 12:49:01 +03:00
func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) {
2021-02-16 19:51:42 +03:00
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
2021-02-16 19:51:42 +03:00
if err != nil {
return 0, err
}
src := buf[start:end]
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalJSON(dst); err != nil {
return 0, err
}
return end, nil
}
2021-06-03 12:49:01 +03:00
func decodeStreamTextUnmarshaler(s *Stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error {
2021-01-22 07:28:03 +03:00
start := s.cursor
if err := s.skipValue(depth); err != nil {
2021-01-22 07:28:03 +03:00
return err
}
src := s.buf[start:s.cursor]
2021-02-16 19:51:42 +03:00
if bytes.Equal(src, nullbytes) {
*(*unsafe.Pointer)(p) = nil
return nil
}
2021-01-22 07:28:03 +03:00
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalText(dst); err != nil {
return err
}
return nil
}
func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) (int64, error) {
2021-02-16 19:51:42 +03:00
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
2021-02-16 19:51:42 +03:00
if err != nil {
return 0, err
}
src := buf[start:end]
if bytes.Equal(src, nullbytes) {
*(*unsafe.Pointer)(p) = nil
return end, nil
}
if s, ok := unquoteBytes(src); ok {
src = s
}
if err := unmarshaler.UnmarshalText(src); err != nil {
return 0, err
}
return end, nil
}
2021-06-03 12:49:01 +03:00
func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error {
2020-07-30 16:41:53 +03:00
s.skipWhiteSpace()
2020-07-31 11:10:03 +03:00
for {
switch s.char() {
case '{':
2020-08-25 05:17:38 +03:00
var v map[string]interface{}
2020-07-31 11:10:03 +03:00
ptr := unsafe.Pointer(&v)
2021-06-03 12:49:01 +03:00
if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil {
2020-07-31 11:10:03 +03:00
return err
}
2020-12-05 16:27:33 +03:00
*(*interface{})(p) = v
2020-07-31 11:10:03 +03:00
return nil
case '[':
var v []interface{}
ptr := unsafe.Pointer(&v)
2021-06-03 12:49:01 +03:00
if err := d.sliceDecoder.DecodeStream(s, depth, ptr); err != nil {
2020-07-31 11:10:03 +03:00
return err
}
2020-12-05 16:27:33 +03:00
*(*interface{})(p) = v
2020-07-31 11:10:03 +03:00
return nil
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
2021-06-03 12:49:01 +03:00
return d.numDecoder(s).DecodeStream(s, depth, p)
2020-07-31 11:10:03 +03:00
case '"':
s.cursor++
start := s.cursor
for {
switch s.char() {
case '\\':
2020-08-14 10:00:07 +03:00
if err := decodeEscapeString(s); err != nil {
return err
}
2020-07-31 11:10:03 +03:00
case '"':
literal := s.buf[start:s.cursor]
s.cursor++
2020-12-05 16:27:33 +03:00
*(*interface{})(p) = string(literal)
2020-07-31 11:10:03 +03:00
return nil
case nul:
if s.read() {
continue
}
2021-06-03 12:49:01 +03:00
return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
2020-07-31 11:10:03 +03:00
}
s.cursor++
}
case 't':
if err := trueBytes(s); err != nil {
return err
}
**(**interface{})(unsafe.Pointer(&p)) = true
2020-07-31 11:10:03 +03:00
return nil
case 'f':
if err := falseBytes(s); err != nil {
return err
}
**(**interface{})(unsafe.Pointer(&p)) = false
2020-07-31 11:10:03 +03:00
return nil
case 'n':
if err := nullBytes(s); err != nil {
return err
}
2020-12-05 16:27:33 +03:00
*(*interface{})(p) = nil
2020-07-31 11:10:03 +03:00
return nil
case nul:
if s.read() {
continue
2020-07-30 16:41:53 +03:00
}
}
2020-07-31 11:10:03 +03:00
break
2020-07-30 16:41:53 +03:00
}
2021-06-03 12:49:01 +03:00
return errors.ErrNotAtBeginningOfValue(s.totalOffset())
}
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
2020-07-30 16:41:53 +03:00
}
2021-06-03 12:49:01 +03:00
func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
2021-03-13 08:12:31 +03:00
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
2021-02-09 15:37:18 +03:00
typ: d.typ,
ptr: p,
}))
rv := reflect.ValueOf(runtimeInterfaceValue)
if rv.NumMethod() > 0 && rv.CanInterface() {
2021-06-03 12:49:01 +03:00
if u, ok := rv.Interface().(json.Unmarshaler); ok {
return decodeStreamUnmarshaler(s, depth, u)
2021-02-09 15:37:18 +03:00
}
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
return decodeStreamTextUnmarshaler(s, depth, u, p)
2021-02-09 15:37:18 +03:00
}
s.skipWhiteSpace()
if s.char() == 'n' {
if err := nullBytes(s); err != nil {
return err
}
*(*interface{})(p) = nil
return nil
}
return d.errUnmarshalType(rv.Type(), s.totalOffset())
2021-02-09 15:37:18 +03:00
}
iface := rv.Interface()
2021-03-13 08:12:31 +03:00
ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
2021-02-09 15:37:18 +03:00
typ := ifaceHeader.typ
if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
2021-02-09 15:37:18 +03:00
// concrete type is empty interface
return d.decodeStreamEmptyInterface(s, depth, p)
2021-02-09 16:13:58 +03:00
}
if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
return d.decodeStreamEmptyInterface(s, depth, p)
2021-02-09 16:13:58 +03:00
}
2021-02-16 19:51:42 +03:00
s.skipWhiteSpace()
2021-02-09 16:13:58 +03:00
if s.char() == 'n' {
if err := nullBytes(s); err != nil {
return err
}
*(*interface{})(p) = nil
return nil
2021-02-09 15:37:18 +03:00
}
2021-06-03 12:49:01 +03:00
decoder, err := CompileToGetDecoder(typ)
2021-02-09 15:37:18 +03:00
if err != nil {
return err
}
2021-06-03 12:49:01 +03:00
return decoder.DecodeStream(s, depth, ifaceHeader.ptr)
2021-02-09 15:37:18 +03:00
}
2021-06-03 12:49:01 +03:00
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
return &errors.UnmarshalTypeError{
Value: typ.String(),
Type: typ,
Offset: offset,
Struct: d.structName,
Field: d.fieldName,
}
}
2021-06-03 12:49:01 +03:00
func (d *interfaceDecoder) Decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
2021-03-13 08:12:31 +03:00
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
2021-02-09 16:13:58 +03:00
typ: d.typ,
ptr: p,
}))
rv := reflect.ValueOf(runtimeInterfaceValue)
2021-02-16 19:51:42 +03:00
if rv.NumMethod() > 0 && rv.CanInterface() {
2021-06-03 12:49:01 +03:00
if u, ok := rv.Interface().(json.Unmarshaler); ok {
return decodeUnmarshaler(buf, cursor, depth, u)
2021-02-16 19:51:42 +03:00
}
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
return decodeTextUnmarshaler(buf, cursor, depth, u, p)
2021-02-16 19:51:42 +03:00
}
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == 'n' {
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = nil
return cursor, nil
}
return 0, d.errUnmarshalType(rv.Type(), cursor)
2021-02-16 19:51:42 +03:00
}
2021-02-09 16:13:58 +03:00
iface := rv.Interface()
2021-03-13 08:12:31 +03:00
ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
2021-02-09 16:13:58 +03:00
typ := ifaceHeader.typ
if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
2021-02-09 16:13:58 +03:00
// concrete type is empty interface
return d.decodeEmptyInterface(buf, cursor, depth, p)
2021-02-09 16:13:58 +03:00
}
if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
return d.decodeEmptyInterface(buf, cursor, depth, p)
2021-02-09 16:13:58 +03:00
}
2021-02-16 19:51:42 +03:00
cursor = skipWhiteSpace(buf, cursor)
2021-02-09 16:13:58 +03:00
if buf[cursor] == 'n' {
if err := validateNull(buf, cursor); err != nil {
return 0, err
2021-02-09 16:13:58 +03:00
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = nil
return cursor, nil
}
2021-06-03 12:49:01 +03:00
decoder, err := CompileToGetDecoder(typ)
2021-02-09 16:13:58 +03:00
if err != nil {
return 0, err
}
2021-06-03 12:49:01 +03:00
return decoder.Decode(buf, cursor, depth, ifaceHeader.ptr)
2021-02-09 16:13:58 +03:00
}
func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
2020-05-08 09:13:30 +03:00
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] {
case '{':
2020-08-25 05:17:38 +03:00
var v map[string]interface{}
2020-05-08 09:13:30 +03:00
ptr := unsafe.Pointer(&v)
2021-06-03 12:49:01 +03:00
cursor, err := d.mapDecoder.Decode(buf, cursor, depth, ptr)
2020-05-08 09:13:30 +03:00
if err != nil {
return 0, err
}
**(**interface{})(unsafe.Pointer(&p)) = v
2020-05-08 09:13:30 +03:00
return cursor, nil
case '[':
var v []interface{}
ptr := unsafe.Pointer(&v)
2021-06-03 12:49:01 +03:00
cursor, err := d.sliceDecoder.Decode(buf, cursor, depth, ptr)
2020-05-08 09:13:30 +03:00
if err != nil {
return 0, err
}
**(**interface{})(unsafe.Pointer(&p)) = v
2020-05-08 09:13:30 +03:00
return cursor, nil
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
2021-06-03 12:49:01 +03:00
return d.floatDecoder.Decode(buf, cursor, depth, p)
2020-05-08 09:13:30 +03:00
case '"':
var v string
ptr := unsafe.Pointer(&v)
2021-06-03 12:49:01 +03:00
cursor, err := d.stringDecoder.Decode(buf, cursor, depth, ptr)
if err != nil {
return 0, err
2020-05-08 09:13:30 +03:00
}
**(**interface{})(unsafe.Pointer(&p)) = v
return cursor, nil
2020-05-08 09:13:30 +03:00
case 't':
2021-05-08 21:05:36 +03:00
if err := validateTrue(buf, cursor); err != nil {
return 0, err
2020-05-08 09:13:30 +03:00
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = true
2020-05-08 09:13:30 +03:00
return cursor, nil
case 'f':
2021-05-08 21:05:36 +03:00
if err := validateFalse(buf, cursor); err != nil {
return 0, err
2020-05-08 09:13:30 +03:00
}
cursor += 5
**(**interface{})(unsafe.Pointer(&p)) = false
2020-05-08 09:13:30 +03:00
return cursor, nil
case 'n':
2021-05-08 21:05:36 +03:00
if err := validateNull(buf, cursor); err != nil {
return 0, err
2020-05-08 09:13:30 +03:00
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = nil
2020-05-08 09:13:30 +03:00
return cursor, nil
}
2021-06-03 12:49:01 +03:00
return cursor, errors.ErrNotAtBeginningOfValue(cursor)
2020-05-08 09:13:30 +03:00
}