go-json/internal/decoder/unmarshal_json.go

100 lines
2.2 KiB
Go
Raw Normal View History

2021-06-03 12:49:01 +03:00
package decoder
2020-05-08 14:22:57 +03:00
import (
"context"
2021-06-03 12:49:01 +03:00
"encoding/json"
2020-05-08 14:22:57 +03:00
"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 14:22:57 +03:00
)
type unmarshalJSONDecoder struct {
2021-06-03 12:49:01 +03:00
typ *runtime.Type
2020-12-15 06:29:19 +03:00
structName string
fieldName string
2020-05-08 14:22:57 +03:00
}
2021-06-03 12:49:01 +03:00
func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
return &unmarshalJSONDecoder{
typ: typ,
structName: structName,
fieldName: fieldName,
}
}
2020-11-27 11:11:53 +03:00
func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
switch e := err.(type) {
2021-06-03 12:49:01 +03:00
case *errors.UnmarshalTypeError:
2020-11-27 11:11:53 +03:00
e.Struct = d.structName
e.Field = d.fieldName
2021-06-03 12:49:01 +03:00
case *errors.SyntaxError:
2020-11-27 11:11:53 +03:00
e.Offset = cursor
}
2020-05-08 14:22:57 +03:00
}
2021-06-03 12:49:01 +03:00
func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
2020-07-30 16:41:53 +03:00
s.skipWhiteSpace()
start := s.cursor
if err := s.skipValue(depth); err != nil {
2020-07-30 16:41:53 +03:00
return err
}
src := s.buf[start:s.cursor]
2020-12-05 16:27:33 +03:00
dst := make([]byte, len(src))
copy(dst, src)
2020-12-07 04:44:24 +03:00
2021-03-13 08:12:31 +03:00
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
2020-12-07 04:44:24 +03:00
typ: d.typ,
ptr: p,
}))
switch v := v.(type) {
case unmarshalerContext:
var ctx context.Context
if (s.Option.Flags & ContextOption) != 0 {
ctx = s.Option.Context
} else {
ctx = context.Background()
}
if err := v.UnmarshalJSON(ctx, dst); err != nil {
d.annotateError(s.cursor, err)
return err
}
case json.Unmarshaler:
if err := v.UnmarshalJSON(dst); err != nil {
d.annotateError(s.cursor, err)
return err
}
2020-07-30 16:41:53 +03:00
}
return nil
}
2021-06-04 19:08:27 +03:00
func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
2020-05-08 14:22:57 +03:00
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
2020-05-08 14:22:57 +03:00
if err != nil {
return 0, err
}
src := buf[start:end]
2021-01-22 08:01:01 +03:00
dst := make([]byte, len(src))
copy(dst, src)
2021-03-13 08:12:31 +03:00
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
2020-12-15 06:29:19 +03:00
typ: d.typ,
ptr: p,
}))
if (ctx.Option.Flags & ContextOption) != 0 {
if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil {
d.annotateError(cursor, err)
return 0, err
}
} else {
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
d.annotateError(cursor, err)
return 0, err
}
2020-05-08 14:22:57 +03:00
}
return end, nil
}