1 package decoder
2
3 import (
4 "bytes"
5 "fmt"
6 "unsafe"
7
8 "github.com/goccy/go-json/internal/errors"
9 "github.com/goccy/go-json/internal/runtime"
10 )
11
12 type funcDecoder struct {
13 typ *runtime.Type
14 structName string
15 fieldName string
16 }
17
18 func newFuncDecoder(typ *runtime.Type, structName, fieldName string) *funcDecoder {
19 fnDecoder := &funcDecoder{typ, structName, fieldName}
20 return fnDecoder
21 }
22
23 func (d *funcDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
24 s.skipWhiteSpace()
25 start := s.cursor
26 if err := s.skipValue(depth); err != nil {
27 return err
28 }
29 src := s.buf[start:s.cursor]
30 if len(src) > 0 {
31 switch src[0] {
32 case '"':
33 return &errors.UnmarshalTypeError{
34 Value: "string",
35 Type: runtime.RType2Type(d.typ),
36 Offset: s.totalOffset(),
37 }
38 case '[':
39 return &errors.UnmarshalTypeError{
40 Value: "array",
41 Type: runtime.RType2Type(d.typ),
42 Offset: s.totalOffset(),
43 }
44 case '{':
45 return &errors.UnmarshalTypeError{
46 Value: "object",
47 Type: runtime.RType2Type(d.typ),
48 Offset: s.totalOffset(),
49 }
50 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
51 return &errors.UnmarshalTypeError{
52 Value: "number",
53 Type: runtime.RType2Type(d.typ),
54 Offset: s.totalOffset(),
55 }
56 case 'n':
57 if err := nullBytes(s); err != nil {
58 return err
59 }
60 *(*unsafe.Pointer)(p) = nil
61 return nil
62 case 't':
63 if err := trueBytes(s); err == nil {
64 return &errors.UnmarshalTypeError{
65 Value: "boolean",
66 Type: runtime.RType2Type(d.typ),
67 Offset: s.totalOffset(),
68 }
69 }
70 case 'f':
71 if err := falseBytes(s); err == nil {
72 return &errors.UnmarshalTypeError{
73 Value: "boolean",
74 Type: runtime.RType2Type(d.typ),
75 Offset: s.totalOffset(),
76 }
77 }
78 }
79 }
80 return errors.ErrInvalidBeginningOfValue(s.buf[s.cursor], s.totalOffset())
81 }
82
83 func (d *funcDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
84 buf := ctx.Buf
85 cursor = skipWhiteSpace(buf, cursor)
86 start := cursor
87 end, err := skipValue(buf, cursor, depth)
88 if err != nil {
89 return 0, err
90 }
91 src := buf[start:end]
92 if len(src) > 0 {
93 switch src[0] {
94 case '"':
95 return 0, &errors.UnmarshalTypeError{
96 Value: "string",
97 Type: runtime.RType2Type(d.typ),
98 Offset: start,
99 }
100 case '[':
101 return 0, &errors.UnmarshalTypeError{
102 Value: "array",
103 Type: runtime.RType2Type(d.typ),
104 Offset: start,
105 }
106 case '{':
107 return 0, &errors.UnmarshalTypeError{
108 Value: "object",
109 Type: runtime.RType2Type(d.typ),
110 Offset: start,
111 }
112 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
113 return 0, &errors.UnmarshalTypeError{
114 Value: "number",
115 Type: runtime.RType2Type(d.typ),
116 Offset: start,
117 }
118 case 'n':
119 if bytes.Equal(src, nullbytes) {
120 *(*unsafe.Pointer)(p) = nil
121 return end, nil
122 }
123 case 't':
124 if err := validateTrue(buf, start); err == nil {
125 return 0, &errors.UnmarshalTypeError{
126 Value: "boolean",
127 Type: runtime.RType2Type(d.typ),
128 Offset: start,
129 }
130 }
131 case 'f':
132 if err := validateFalse(buf, start); err == nil {
133 return 0, &errors.UnmarshalTypeError{
134 Value: "boolean",
135 Type: runtime.RType2Type(d.typ),
136 Offset: start,
137 }
138 }
139 }
140 }
141 return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
142 }
143
144 func (d *funcDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
145 return nil, 0, fmt.Errorf("json: func decoder does not support decode path")
146 }
147
View as plain text