...
1 package decoder
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "unsafe"
8
9 "github.com/goccy/go-json/internal/errors"
10 "github.com/goccy/go-json/internal/runtime"
11 )
12
13 type unmarshalJSONDecoder struct {
14 typ *runtime.Type
15 structName string
16 fieldName string
17 }
18
19 func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
20 return &unmarshalJSONDecoder{
21 typ: typ,
22 structName: structName,
23 fieldName: fieldName,
24 }
25 }
26
27 func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
28 switch e := err.(type) {
29 case *errors.UnmarshalTypeError:
30 e.Struct = d.structName
31 e.Field = d.fieldName
32 case *errors.SyntaxError:
33 e.Offset = cursor
34 }
35 }
36
37 func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
38 s.skipWhiteSpace()
39 start := s.cursor
40 if err := s.skipValue(depth); err != nil {
41 return err
42 }
43 src := s.buf[start:s.cursor]
44 dst := make([]byte, len(src))
45 copy(dst, src)
46
47 v := *(*interface{})(unsafe.Pointer(&emptyInterface{
48 typ: d.typ,
49 ptr: p,
50 }))
51 switch v := v.(type) {
52 case unmarshalerContext:
53 var ctx context.Context
54 if (s.Option.Flags & ContextOption) != 0 {
55 ctx = s.Option.Context
56 } else {
57 ctx = context.Background()
58 }
59 if err := v.UnmarshalJSON(ctx, dst); err != nil {
60 d.annotateError(s.cursor, err)
61 return err
62 }
63 case json.Unmarshaler:
64 if err := v.UnmarshalJSON(dst); err != nil {
65 d.annotateError(s.cursor, err)
66 return err
67 }
68 }
69 return nil
70 }
71
72 func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
73 buf := ctx.Buf
74 cursor = skipWhiteSpace(buf, cursor)
75 start := cursor
76 end, err := skipValue(buf, cursor, depth)
77 if err != nil {
78 return 0, err
79 }
80 src := buf[start:end]
81 dst := make([]byte, len(src))
82 copy(dst, src)
83
84 v := *(*interface{})(unsafe.Pointer(&emptyInterface{
85 typ: d.typ,
86 ptr: p,
87 }))
88 if (ctx.Option.Flags & ContextOption) != 0 {
89 if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil {
90 d.annotateError(cursor, err)
91 return 0, err
92 }
93 } else {
94 if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
95 d.annotateError(cursor, err)
96 return 0, err
97 }
98 }
99 return end, nil
100 }
101
102 func (d *unmarshalJSONDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
103 return nil, 0, fmt.Errorf("json: unmarshal json decoder does not support decode path")
104 }
105
View as plain text