123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528 |
- 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 *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
- }),
- 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
- }
- func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
- emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
- stringDecoder := newStringDecoder(structName, fieldName)
- 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
- }),
- 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 {
- return d.numberDecoder
- }
- return d.floatDecoder
- }
- var (
- emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
- EmptyInterfaceType = emptyInterfaceType
- interfaceMapType = runtime.Type2RType(
- reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
- )
- stringType = runtime.Type2RType(
- reflect.TypeOf(""),
- )
- )
- func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
- start := s.cursor
- if err := s.skipValue(depth); err != nil {
- 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
- }
- func decodeStreamUnmarshalerContext(s *Stream, depth int64, unmarshaler unmarshalerContext) error {
- start := s.cursor
- if err := s.skipValue(depth); err != nil {
- return err
- }
- src := s.buf[start:s.cursor]
- dst := make([]byte, len(src))
- copy(dst, src)
- if err := unmarshaler.UnmarshalJSON(s.Option.Context, dst); err != nil {
- return err
- }
- return nil
- }
- func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) {
- cursor = skipWhiteSpace(buf, cursor)
- start := cursor
- end, err := skipValue(buf, cursor, depth)
- 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
- }
- func decodeUnmarshalerContext(ctx *RuntimeContext, buf []byte, cursor, depth int64, unmarshaler unmarshalerContext) (int64, error) {
- cursor = skipWhiteSpace(buf, cursor)
- start := cursor
- end, err := skipValue(buf, cursor, depth)
- if err != nil {
- return 0, err
- }
- src := buf[start:end]
- dst := make([]byte, len(src))
- copy(dst, src)
- if err := unmarshaler.UnmarshalJSON(ctx.Option.Context, dst); err != nil {
- return 0, err
- }
- return end, nil
- }
- 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
- }
- src := s.buf[start:s.cursor]
- if bytes.Equal(src, nullbytes) {
- *(*unsafe.Pointer)(p) = nil
- return nil
- }
- 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) {
- cursor = skipWhiteSpace(buf, cursor)
- start := cursor
- end, err := skipValue(buf, cursor, depth)
- 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
- }
- func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error {
- c := s.skipWhiteSpace()
- for {
- switch c {
- case '{':
- var v map[string]interface{}
- ptr := unsafe.Pointer(&v)
- if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil {
- return err
- }
- *(*interface{})(p) = v
- return nil
- case '[':
- var v []interface{}
- ptr := unsafe.Pointer(&v)
- 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)
- case '"':
- s.cursor++
- start := s.cursor
- for {
- switch s.char() {
- case '\\':
- if _, err := decodeEscapeString(s, nil); err != nil {
- return err
- }
- case '"':
- literal := s.buf[start:s.cursor]
- s.cursor++
- *(*interface{})(p) = string(literal)
- return nil
- case nul:
- if s.read() {
- continue
- }
- return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
- }
- s.cursor++
- }
- case 't':
- if err := trueBytes(s); err != nil {
- return err
- }
- **(**interface{})(unsafe.Pointer(&p)) = true
- return nil
- case 'f':
- if err := falseBytes(s); err != nil {
- return err
- }
- **(**interface{})(unsafe.Pointer(&p)) = false
- return nil
- case 'n':
- if err := nullBytes(s); err != nil {
- return err
- }
- *(*interface{})(p) = nil
- return nil
- case nul:
- if s.read() {
- c = s.char()
- continue
- }
- }
- break
- }
- return errors.ErrInvalidBeginningOfValue(c, s.totalOffset())
- }
- 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().(unmarshalerContext); ok {
- return decodeStreamUnmarshalerContext(s, depth, u)
- }
- if u, ok := rv.Interface().(json.Unmarshaler); ok {
- return decodeStreamUnmarshaler(s, depth, u)
- }
- if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
- return decodeStreamTextUnmarshaler(s, depth, u, p)
- }
- if s.skipWhiteSpace() == 'n' {
- if err := nullBytes(s); err != nil {
- return err
- }
- *(*interface{})(p) = nil
- return nil
- }
- return d.errUnmarshalType(rv.Type(), s.totalOffset())
- }
- iface := rv.Interface()
- ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
- typ := ifaceHeader.typ
- if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
- // concrete type is empty interface
- return d.decodeStreamEmptyInterface(s, depth, p)
- }
- if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
- return d.decodeStreamEmptyInterface(s, depth, p)
- }
- if s.skipWhiteSpace() == 'n' {
- if err := nullBytes(s); err != nil {
- return err
- }
- *(*interface{})(p) = nil
- return nil
- }
- decoder, err := CompileToGetDecoder(typ)
- if err != nil {
- return err
- }
- return decoder.DecodeStream(s, depth, ifaceHeader.ptr)
- }
- 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,
- }
- }
- func (d *interfaceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
- buf := ctx.Buf
- 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().(unmarshalerContext); ok {
- return decodeUnmarshalerContext(ctx, buf, cursor, depth, u)
- }
- if u, ok := rv.Interface().(json.Unmarshaler); ok {
- return decodeUnmarshaler(buf, cursor, depth, u)
- }
- if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
- return decodeTextUnmarshaler(buf, cursor, depth, u, p)
- }
- 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)
- }
- iface := rv.Interface()
- ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
- typ := ifaceHeader.typ
- if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
- // concrete type is empty interface
- return d.decodeEmptyInterface(ctx, cursor, depth, p)
- }
- if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
- return d.decodeEmptyInterface(ctx, cursor, depth, p)
- }
- 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
- }
- decoder, err := CompileToGetDecoder(typ)
- if err != nil {
- return 0, err
- }
- return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr)
- }
- func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
- buf := ctx.Buf
- cursor = skipWhiteSpace(buf, cursor)
- switch buf[cursor] {
- case '{':
- var v map[string]interface{}
- ptr := unsafe.Pointer(&v)
- cursor, err := d.mapDecoder.Decode(ctx, cursor, depth, ptr)
- if err != nil {
- return 0, err
- }
- **(**interface{})(unsafe.Pointer(&p)) = v
- return cursor, nil
- case '[':
- var v []interface{}
- ptr := unsafe.Pointer(&v)
- cursor, err := d.sliceDecoder.Decode(ctx, 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(ctx, cursor, depth, p)
- case '"':
- var v string
- ptr := unsafe.Pointer(&v)
- cursor, err := d.stringDecoder.Decode(ctx, cursor, depth, ptr)
- if err != nil {
- return 0, err
- }
- **(**interface{})(unsafe.Pointer(&p)) = v
- return cursor, nil
- case 't':
- if err := validateTrue(buf, cursor); err != nil {
- return 0, err
- }
- cursor += 4
- **(**interface{})(unsafe.Pointer(&p)) = true
- return cursor, nil
- case 'f':
- if err := validateFalse(buf, cursor); err != nil {
- return 0, err
- }
- cursor += 5
- **(**interface{})(unsafe.Pointer(&p)) = false
- return cursor, nil
- case 'n':
- if err := validateNull(buf, cursor); err != nil {
- return 0, err
- }
- cursor += 4
- **(**interface{})(unsafe.Pointer(&p)) = nil
- return cursor, nil
- }
- return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
- }
- func NewPathDecoder() Decoder {
- ifaceDecoder := &interfaceDecoder{
- typ: emptyInterfaceType,
- structName: "",
- fieldName: "",
- floatDecoder: newFloatDecoder("", "", func(p unsafe.Pointer, v float64) {
- *(*interface{})(p) = v
- }),
- numberDecoder: newNumberDecoder("", "", func(p unsafe.Pointer, v json.Number) {
- *(*interface{})(p) = v
- }),
- stringDecoder: newStringDecoder("", ""),
- }
- ifaceDecoder.sliceDecoder = newSliceDecoder(
- ifaceDecoder,
- emptyInterfaceType,
- emptyInterfaceType.Size(),
- "", "",
- )
- ifaceDecoder.mapDecoder = newMapDecoder(
- interfaceMapType,
- stringType,
- ifaceDecoder.stringDecoder,
- interfaceMapType.Elem(),
- ifaceDecoder,
- "", "",
- )
- return ifaceDecoder
- }
- var (
- truebytes = []byte("true")
- falsebytes = []byte("false")
- )
- func (d *interfaceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
- buf := ctx.Buf
- cursor = skipWhiteSpace(buf, cursor)
- switch buf[cursor] {
- case '{':
- return d.mapDecoder.DecodePath(ctx, cursor, depth)
- case '[':
- return d.sliceDecoder.DecodePath(ctx, cursor, depth)
- case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
- return d.floatDecoder.DecodePath(ctx, cursor, depth)
- case '"':
- return d.stringDecoder.DecodePath(ctx, cursor, depth)
- case 't':
- if err := validateTrue(buf, cursor); err != nil {
- return nil, 0, err
- }
- cursor += 4
- return [][]byte{truebytes}, cursor, nil
- case 'f':
- if err := validateFalse(buf, cursor); err != nil {
- return nil, 0, err
- }
- cursor += 5
- return [][]byte{falsebytes}, cursor, nil
- case 'n':
- if err := validateNull(buf, cursor); err != nil {
- return nil, 0, err
- }
- cursor += 4
- return [][]byte{nullbytes}, cursor, nil
- }
- return nil, cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
- }
|