1
16
17 package decoder
18
19 import (
20 `encoding/base64`
21 `encoding/json`
22 `reflect`
23 `testing`
24 `unsafe`
25
26 `github.com/bytedance/sonic/internal/caching`
27 `github.com/bytedance/sonic/internal/jit`
28 `github.com/bytedance/sonic/internal/native/types`
29 `github.com/bytedance/sonic/internal/rt`
30 `github.com/stretchr/testify/assert`
31 `github.com/stretchr/testify/require`
32 )
33
34 var utextVar []byte
35 type UtextValue int
36
37 func (UtextValue) UnmarshalText(text []byte) error {
38 utextVar = text
39 return nil
40 }
41
42 var ujsonVar []byte
43 type UjsonValue int
44
45 func (UjsonValue) UnmarshalJSON(json []byte) error {
46 ujsonVar = json
47 return nil
48 }
49
50 type UtextStruct struct {
51 V string
52 }
53
54 func (self *UtextStruct) UnmarshalText(text []byte) error {
55 self.V = string(text)
56 return nil
57 }
58
59 type UjsonStruct struct {
60 V string
61 }
62
63 func (self *UjsonStruct) UnmarshalJSON(v []byte) error {
64 self.V = string(v)
65 return nil
66 }
67
68 const (
69 _OP_dbg_get_sr _Op = 253
70 _OP_dbg_set_sr _Op = 254
71 _OP_dbg_break _Op = 255
72 )
73
74 func (self *_Assembler) _asm_OP_dbg_get_sr(_ *_Instr) {
75 self.Emit("MOVQ", _VAR_sr, _AX)
76 self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0))
77 }
78
79 func (self *_Assembler) _asm_OP_dbg_set_sr(p *_Instr) {
80 self.Emit("MOVQ", jit.Imm(p.i64()), _AX)
81 self.Emit("MOVQ", _AX, _VAR_sr)
82 }
83
84 func (self *_Assembler) _asm_OP_dbg_break(_ *_Instr) {
85 self.Byte(0xcc)
86 }
87
88 func init() {
89 _OpNames[_OP_dbg_get_sr] = "dbg_get_sr"
90 _OpNames[_OP_dbg_set_sr] = "dbg_set_sr"
91 _OpNames[_OP_dbg_break] = "dbg_break"
92 _OpFuncTab[_OP_dbg_get_sr] = (*_Assembler)._asm_OP_dbg_get_sr
93 _OpFuncTab[_OP_dbg_set_sr] = (*_Assembler)._asm_OP_dbg_set_sr
94 _OpFuncTab[_OP_dbg_break] = (*_Assembler)._asm_OP_dbg_break
95 }
96
97 type testOps struct {
98 key string
99 ins _Program
100 src string
101 pos int
102 opt uint64
103 vfn func(i int, v interface{})
104 exp interface{}
105 err error
106 val interface{}
107 }
108
109 func testOpCode(t *testing.T, ops *testOps) {
110 p := ops.ins
111 k := new(_Stack)
112 a := newAssembler(p)
113 f := a.Load()
114 i, e := f(ops.src, ops.pos, rt.UnpackEface(ops.val).Value, k, ops.opt, "", nil)
115 if ops.err != nil {
116 assert.EqualError(t, e, ops.err.Error())
117 } else {
118 assert.NoError(t, e)
119 if ops.vfn != nil {
120 if ops.val == nil {
121 ops.vfn(i, nil)
122 } else {
123 ops.vfn(i, reflect.Indirect(reflect.ValueOf(ops.val)).Interface())
124 }
125 } else {
126 if ops.val == nil {
127 assert.Nil(t, ops.exp)
128 } else {
129 assert.Equal(t, ops.exp, reflect.Indirect(reflect.ValueOf(ops.val)).Interface())
130 }
131 }
132 }
133 }
134
135 func TestAssembler_OpCode(t *testing.T) {
136 tests := []testOps{
137 {
138 key: "_OP_any/stdlib",
139 ins: []_Instr{newInsOp(_OP_any)},
140 src: `{"a": [1, 2, 3]}`,
141 exp: map[string]interface{}{"a": []interface{}{1.0, 2.0, 3.0}},
142 val: new(interface{}),
143 },
144 {
145 key: "_OP_any/use_int64",
146 ins: []_Instr{newInsOp(_OP_any)},
147 src: `{"a": [1, 2, 3]}`,
148 opt: 1 << _F_use_int64,
149 exp: map[string]interface{}{"a": []interface{}{int64(1), int64(2), int64(3)}},
150 val: new(interface{}),
151 },
152 {
153 key: "_OP_any/use_number",
154 ins: []_Instr{newInsOp(_OP_any)},
155 src: `{"a": [1, 2, 3]}`,
156 opt: 1 << _F_use_number,
157 exp: map[string]interface{}{"a": []interface{}{json.Number("1"), json.Number("2"), json.Number("3")}},
158 val: new(interface{}),
159 },
160 {
161 key: "_OP_str/plain",
162 ins: []_Instr{newInsOp(_OP_str)},
163 src: `hello, world"`,
164 exp: "hello, world",
165 val: new(string),
166 }, {
167 key: "_OP_str/unquote",
168 ins: []_Instr{newInsOp(_OP_str)},
169 src: `hello, world \\ \" \/ \b \f \n \r \t \u666f 测试中文 \ud83d\ude00"`,
170 exp: "hello, world \\ \" / \b \f \n \r \t 景 测试中文 😀",
171 val: new(string),
172 }, {
173 key: "_OP_str/unquote_unirep",
174 ins: []_Instr{newInsOp(_OP_str)},
175 src: `hello\ud800world"`,
176 exp: "hello\ufffdworld",
177 val: new(string),
178 }, {
179 key: "_OP_str/error_eof",
180 ins: []_Instr{newInsOp(_OP_str)},
181 src: `12345`,
182 err: SyntaxError{Src: `12345`, Pos: 5, Code: types.ERR_EOF},
183 val: new(string),
184 }, {
185 key: "_OP_str/error_invalid_escape",
186 ins: []_Instr{newInsOp(_OP_str)},
187 src: `12\g345"`,
188 err: SyntaxError{Src: `12\g345"`, Pos: 3, Code: types.ERR_INVALID_ESCAPE},
189 val: new(string),
190 }, {
191 key: "_OP_str/error_invalid_unicode",
192 ins: []_Instr{newInsOp(_OP_str)},
193 src: `hello\ud800world"`,
194 opt: 1 << _F_disable_urc,
195 err: SyntaxError{Src: `hello\ud800world"`, Pos: 7, Code: types.ERR_INVALID_UNICODE},
196 val: new(string),
197 }, {
198 key: "_OP_str/error_invalid_char",
199 ins: []_Instr{newInsOp(_OP_str)},
200 src: `12\u1ggg345"`,
201 err: SyntaxError{Src: `12\u1ggg345"`, Pos: 5, Code: types.ERR_INVALID_CHAR},
202 val: new(string),
203 }, {
204 key: "_OP_bin",
205 ins: []_Instr{newInsOp(_OP_bin)},
206 src: `aGVsbG8sIHdvcmxk"`,
207 exp: []byte("hello, world"),
208 val: new([]byte),
209 }, {
210 key: "_OP_bin/error_eof",
211 ins: []_Instr{newInsOp(_OP_bin)},
212 src: `aGVsbG8sIHdvcmxk`,
213 err: SyntaxError{Src: `aGVsbG8sIHdvcmxk`, Pos: 16, Code: types.ERR_EOF},
214 val: new([]byte),
215 }, {
216 key: "_OP_bin/error_corrupt_input",
217 ins: []_Instr{newInsOp(_OP_bin)},
218 src: `aGVsbG8!sIHdvcmxk"`,
219 err: base64.CorruptInputError(7),
220 val: new([]byte),
221 }, {
222 key: "_OP_bool/true",
223 ins: []_Instr{newInsOp(_OP_bool)},
224 src: "true",
225 exp: true,
226 val: new(bool),
227 },
228 {
229 key: "_OP_bool/skip",
230 ins: []_Instr{newInsOp(_OP_bool)},
231 src: `"true"`,
232 exp: nil,
233 val: new(bool),
234 err: &MismatchTypeError{Src: `"true"`, Pos: 0, Type: reflect.TypeOf(true)},
235 },
236 {
237 key: "_OP_bool/false",
238 ins: []_Instr{newInsOp(_OP_bool)},
239 src: "false",
240 exp: false,
241 val: new(bool),
242 }, {
243 key: "_OP_bool/false_pos",
244 ins: []_Instr{newInsOp(_OP_bool)},
245 src: "false",
246 vfn: func(i int, v interface{}) { require.False(t, v.(bool)); assert.Equal(t, 5, i) },
247 val: new(bool),
248 }, {
249 key: "_OP_bool/error_eof_1",
250 ins: []_Instr{newInsOp(_OP_bool)},
251 src: "tru",
252 err: SyntaxError{Src: `tru`, Pos: 3, Code: types.ERR_EOF},
253 val: new(bool),
254 }, {
255 key: "_OP_bool/error_eof_2",
256 ins: []_Instr{newInsOp(_OP_bool)},
257 src: "fals",
258 err: SyntaxError{Src: `fals`, Pos: 4, Code: types.ERR_EOF},
259 val: new(bool),
260 }, {
261 key: "_OP_bool/error_invalid_char_1",
262 ins: []_Instr{newInsOp(_OP_bool)},
263 src: "falxe",
264 err: SyntaxError{Src: `falxe`, Pos: 3, Code: types.ERR_INVALID_CHAR},
265 val: new(bool),
266 }, {
267 key: "_OP_bool/error_invalid_char_2",
268 ins: []_Instr{newInsOp(_OP_bool)},
269 src: "falsx",
270 err: SyntaxError{Src: `falsx`, Pos: 4, Code: types.ERR_INVALID_CHAR},
271 val: new(bool),
272 },
273 {
274 key: "_OP_num/positive",
275 ins: []_Instr{newInsOp(_OP_num)},
276 src: "1.234e5",
277 exp: json.Number("1.234e5"),
278 val: new(json.Number),
279 }, {
280 key: "_OP_num/negative",
281 ins: []_Instr{newInsOp(_OP_num)},
282 src: "-1.234e5",
283 exp: json.Number("-1.234e5"),
284 val: new(json.Number),
285 }, {
286 key: "_OP_num/error_eof",
287 ins: []_Instr{newInsOp(_OP_num)},
288 src: "-",
289 err: SyntaxError{Src: `-`, Pos: 1, Code: types.ERR_INVALID_CHAR},
290 val: new(json.Number),
291 }, {
292 key: "_OP_num/error_invalid_char",
293 ins: []_Instr{newInsOp(_OP_num)},
294 src: "xxx",
295 err: SyntaxError{Src: `xxx`, Pos: 1, Code: types.ERR_INVALID_CHAR},
296 val: new(json.Number),
297 }, {
298 key: "_OP_i8",
299 ins: []_Instr{newInsOp(_OP_i8)},
300 src: "123",
301 exp: int8(123),
302 val: new(int8),
303 }, {
304 key: "_OP_i8/error_overflow",
305 ins: []_Instr{newInsOp(_OP_i8)},
306 src: "1234",
307 err: error_value("1234", reflect.TypeOf(int8(0))),
308 val: new(int8),
309 },
310 {
311 key: "_OP_i8/error_wrong_type",
312 ins: []_Instr{newInsOp(_OP_i8)},
313 src: "12.34",
314 err: &MismatchTypeError{Src: `12.34`, Pos: 0, Type: int8Type},
315 val: new(int8),
316 }, {
317 key: "_OP_u8",
318 ins: []_Instr{newInsOp(_OP_u8)},
319 src: "234",
320 exp: uint8(234),
321 val: new(uint8),
322 }, {
323 key: "_OP_u8/error_overflow",
324 ins: []_Instr{newInsOp(_OP_u8)},
325 src: "1234",
326 err: error_value("1234", reflect.TypeOf(uint8(0))),
327 val: new(uint8),
328 }, {
329 key: "_OP_u8/error_underflow",
330 ins: []_Instr{newInsOp(_OP_u8)},
331 src: "-123",
332 err: &MismatchTypeError{Src: `-123`, Pos: 0, Type: uint8Type},
333 val: new(uint8),
334 }, {
335 key: "_OP_u8/error_wrong_type",
336 ins: []_Instr{newInsOp(_OP_u8)},
337 src: "12.34",
338 err: &MismatchTypeError{Src: `12.34`, Pos: 0, Type: uint8Type},
339 val: new(uint8),
340 }, {
341 key: "_OP_f32",
342 ins: []_Instr{newInsOp(_OP_f32)},
343 src: "1.25e20",
344 exp: float32(1.25e20),
345 val: new(float32),
346 }, {
347 key: "_OP_f32/overflow",
348 ins: []_Instr{newInsOp(_OP_f32)},
349 src: "1.25e50",
350 err: error_value("1.25e50", reflect.TypeOf(float32(0))),
351 val: new(float32),
352 }, {
353 key: "_OP_f32/underflow",
354 ins: []_Instr{newInsOp(_OP_f32)},
355 src: "-1.25e50",
356 err: error_value("-1.25e50", reflect.TypeOf(float32(0))),
357 val: new(float32),
358 }, {
359 key: "_OP_f64",
360 ins: []_Instr{newInsOp(_OP_f64)},
361 src: "1.25e123",
362 exp: 1.25e123,
363 val: new(float64),
364 }, {
365 key: "_OP_unquote/plain",
366 ins: []_Instr{newInsOp(_OP_unquote)},
367 src: `\"hello, world\""`,
368 exp: "hello, world",
369 val: new(string),
370 }, {
371 key: "_OP_unquote/unquote",
372 ins: []_Instr{newInsOp(_OP_unquote)},
373 src: `\"hello, world \\\\ \\\" \\/ \\b \\f \\n \\r \\t \\u666f 测试中文 \\ud83d\\ude00\""`,
374 exp: "hello, world \\ \" / \b \f \n \r \t 景 测试中文 😀",
375 val: new(string),
376 }, {
377 key: "_OP_unquote/error_invalid_end",
378 ins: []_Instr{newInsOp(_OP_unquote)},
379 src: `\"te\\\"st"`,
380 err: SyntaxError{Src: `\"te\\\"st"`, Pos: 8, Code: types.ERR_INVALID_CHAR},
381 val: new(string),
382 }, {
383 key: "_OP_nil_1",
384 ins: []_Instr{newInsOp(_OP_nil_1)},
385 src: "",
386 exp: 0,
387 val: (func() *int { v := new(int); *v = 123; return v })(),
388 }, {
389 key: "_OP_nil_2",
390 ins: []_Instr{newInsOp(_OP_nil_2)},
391 src: "",
392 exp: error(nil),
393 val: (func() *error { v := new(error); *v = types.ERR_EOF; return v })(),
394 }, {
395 key: "_OP_nil_3",
396 ins: []_Instr{newInsOp(_OP_nil_3)},
397 src: "",
398 exp: []byte(nil),
399 val: &[]byte{1, 2, 3},
400 }, {
401 key: "_OP_deref",
402 ins: []_Instr{newInsVt(_OP_deref, reflect.TypeOf(0))},
403 src: "",
404 vfn: func(_ int, v interface{}) { require.NotNil(t, v); assert.NotNil(t, v.(*int)) },
405 val: new(*int),
406 }, {
407 key: "_OP_map_init",
408 ins: []_Instr{newInsOp(_OP_map_init)},
409 src: "",
410 vfn: func(_ int, v interface{}) { require.NotNil(t, v); assert.NotNil(t, v.(map[string]int)) },
411 val: new(map[string]int),
412 }, {
413 key: "_OP_map_key_i8",
414 ins: []_Instr{newInsVt(_OP_map_key_i8, reflect.TypeOf(map[int8]int{}))},
415 src: `123"`,
416 exp: map[int8]int{123: 0},
417 val: map[int8]int{},
418 }, {
419 key: "_OP_map_key_i32",
420 ins: []_Instr{newInsVt(_OP_map_key_i32, reflect.TypeOf(map[int32]int{}))},
421 src: `123456789"`,
422 exp: map[int32]int{123456789: 0},
423 val: map[int32]int{},
424 }, {
425 key: "_OP_map_key_i64",
426 ins: []_Instr{newInsVt(_OP_map_key_i64, reflect.TypeOf(map[int64]int{}))},
427 src: `123456789123456789"`,
428 exp: map[int64]int{123456789123456789: 0},
429 val: map[int64]int{},
430 }, {
431 key: "_OP_map_key_u8",
432 ins: []_Instr{newInsVt(_OP_map_key_u8, reflect.TypeOf(map[uint8]int{}))},
433 src: `123"`,
434 exp: map[uint8]int{123: 0},
435 val: map[uint8]int{},
436 }, {
437 key: "_OP_map_key_u32",
438 ins: []_Instr{newInsVt(_OP_map_key_u32, reflect.TypeOf(map[uint32]int{}))},
439 src: `123456789"`,
440 exp: map[uint32]int{123456789: 0},
441 val: map[uint32]int{},
442 }, {
443 key: "_OP_map_key_u64",
444 ins: []_Instr{newInsVt(_OP_map_key_u64, reflect.TypeOf(map[uint64]int{}))},
445 src: `123456789123456789"`,
446 exp: map[uint64]int{123456789123456789: 0},
447 val: map[uint64]int{},
448 }, {
449 key: "_OP_map_key_f32",
450 ins: []_Instr{newInsVt(_OP_map_key_f32, reflect.TypeOf(map[float32]int{}))},
451 src: `1.25"`,
452 exp: map[float32]int{1.25: 0},
453 val: map[float32]int{},
454 }, {
455 key: "_OP_map_key_f64",
456 ins: []_Instr{newInsVt(_OP_map_key_f64, reflect.TypeOf(map[float64]int{}))},
457 src: `1.25"`,
458 exp: map[float64]int{1.25: 0},
459 val: map[float64]int{},
460 }, {
461 key: "_OP_map_key_str/plain",
462 ins: []_Instr{newInsVt(_OP_map_key_str, reflect.TypeOf(map[string]int{}))},
463 src: `foo"`,
464 exp: map[string]int{"foo": 0},
465 val: map[string]int{},
466 }, {
467 key: "_OP_map_key_str/unquote",
468 ins: []_Instr{newInsVt(_OP_map_key_str, reflect.TypeOf(map[string]int{}))},
469 src: `foo\nbar"`,
470 exp: map[string]int{"foo\nbar": 0},
471 val: map[string]int{},
472 },
473 {
474 key: "_OP_map_key_utext/value",
475 ins: []_Instr{newInsVt(_OP_map_key_utext, reflect.TypeOf(map[UtextValue]int{}))},
476 src: `foo"`,
477 vfn: func(_ int, v interface{}) {
478 m := v.(map[UtextValue]int)
479 assert.Equal(t, 1, len(m))
480 for k := range m {
481 assert.Equal(t, UtextValue(0), k)
482 }
483 assert.Equal(t, []byte("foo"), utextVar)
484 },
485 val: map[UtextValue]int{},
486 },
487 {
488 key: "_OP_map_key_utext/pointer",
489 ins: []_Instr{newInsVt(_OP_map_key_utext, reflect.TypeOf(map[*UtextStruct]int{}))},
490 src: `foo"`,
491 vfn: func(_ int, v interface{}) {
492 m := v.(map[*UtextStruct]int)
493 assert.Equal(t, 1, len(m))
494 for k := range m {
495 assert.Equal(t, "foo", k.V)
496 }
497 },
498 val: map[*UtextStruct]int{},
499 },
500 {
501 key: "_OP_map_key_utext_p",
502 ins: []_Instr{newInsVt(_OP_map_key_utext_p, reflect.TypeOf(map[UtextStruct]int{}))},
503 src: `foo"`,
504 exp: map[UtextStruct]int{UtextStruct{V: "foo"}: 0},
505 val: map[UtextStruct]int{},
506 },
507 {
508 key: "_OP_array_skip",
509 ins: []_Instr{newInsOp(_OP_array_skip)},
510 src: `[1,2.0,true,false,null,"asdf",{"qwer":[1,2,3,4]}]`,
511 pos: 1,
512 vfn: func(i int, _ interface{}) { assert.Equal(t, 49, i) },
513 val: nil,
514 },{
515 key: "_OP_slice_init",
516 ins: []_Instr{newInsVt(_OP_slice_init, reflect.TypeOf(0))},
517 src: "",
518 vfn: func(_ int, v interface{}) {
519 require.NotNil(t, v)
520 assert.Equal(t, 0, len(v.([]int)))
521 assert.Equal(t, _MinSlice, cap(v.([]int)))
522 },
523 val: new([]int),
524 }, {
525 key: "_OP_slice_append",
526 ins: []_Instr{newInsVt(_OP_slice_append, reflect.TypeOf(0)), newInsOp(_OP_nil_1)},
527 src: "",
528 exp: []int{123, 0},
529 val: &[]int{123},
530 }, {
531 key: "_OP_object_skip",
532 ins: []_Instr{newInsOp(_OP_object_skip)},
533 src: `{"zxcv":[1,2.0],"asdf":[true,false,null,"asdf",{"qwer":345}]}`,
534 pos: 1,
535 vfn: func(i int, _ interface{}) { assert.Equal(t, 61, i) },
536 val: nil,
537 }, {
538 key: "_OP_object_next",
539 ins: []_Instr{newInsOp(_OP_object_next)},
540 src: `{"asdf":[1,2.0,true,false,null,"asdf",{"qwer":345}]}`,
541 vfn: func(i int, _ interface{}) { assert.Equal(t, 52, i) },
542 val: nil,
543 }, {
544 key: "_OP_struct_field",
545 ins: []_Instr{
546 newInsVf(_OP_struct_field, (func() *caching.FieldMap {
547 ret := caching.CreateFieldMap(2)
548 ret.Set("bab", 1)
549 ret.Set("bac", 2)
550 ret.Set("bad", 3)
551 return ret
552 })()),
553 newInsOp(_OP_dbg_get_sr),
554 },
555 src: `bac"`,
556 exp: 2,
557 val: new(int),
558 }, {
559 key: "_OP_struct_field/case_insensitive",
560 ins: []_Instr{
561 newInsVf(_OP_struct_field, (func() *caching.FieldMap {
562 ret := caching.CreateFieldMap(2)
563 ret.Set("Bac", 2)
564 ret.Set("BAC", 1)
565 ret.Set("baC", 3)
566 return ret
567 })()),
568 newInsOp(_OP_dbg_get_sr),
569 },
570 src: `bac"`,
571 exp: 1,
572 val: new(int),
573 }, {
574 key: "_OP_struct_field/not_found",
575 ins: []_Instr{
576 newInsVf(_OP_struct_field, (func() *caching.FieldMap {
577 ret := caching.CreateFieldMap(2)
578 ret.Set("bab", 1)
579 ret.Set("bac", 2)
580 ret.Set("bad", 3)
581 return ret
582 })()),
583 newInsOp(_OP_dbg_get_sr),
584 },
585 src: `bae"`,
586 exp: -1,
587 val: new(int),
588 }, {
589 key: "_OP_unmarshal/value",
590 ins: []_Instr{newInsVt(_OP_unmarshal, reflect.TypeOf(UjsonValue(0)))},
591 src: `{"asdf":[1,2.0,true,false,null,"asdf",{"qwer":345}]}`,
592 vfn: func(_ int, v interface{}) {
593 assert.Equal(t, []byte(`{"asdf":[1,2.0,true,false,null,"asdf",{"qwer":345}]}`), ujsonVar)
594 },
595 val: new(UjsonValue),
596 }, {
597 key: "_OP_unmarshal/pointer",
598 ins: []_Instr{newInsVt(_OP_unmarshal, reflect.TypeOf(new(UjsonStruct)))},
599 src: `{"asdf":[1,2.0,true,false,null,"asdf",{"qwer":345}]}`,
600 exp: &UjsonStruct{V: `{"asdf":[1,2.0,true,false,null,"asdf",{"qwer":345}]}`},
601 val: new(*UjsonStruct),
602 }, {
603 key: "_OP_unmarshal_p",
604 ins: []_Instr{newInsVt(_OP_unmarshal_p, reflect.TypeOf(new(UjsonStruct)))},
605 src: `{"asdf":[1,2.0,true,false,null,"asdf",{"qwer":345}]}`,
606 exp: UjsonStruct{V: `{"asdf":[1,2.0,true,false,null,"asdf",{"qwer":345}]}`},
607 val: new(UjsonStruct),
608 }, {
609 key: "_OP_unmarshal_text/value",
610 ins: []_Instr{newInsVt(_OP_unmarshal_text, reflect.TypeOf(UtextValue(0)))},
611 src: `hello\n\r\tworld"`,
612 vfn: func(_ int, v interface{}) {
613 assert.Equal(t, []byte("hello\n\r\tworld"), utextVar)
614 },
615 val: new(UtextValue),
616 }, {
617 key: "_OP_unmarshal_text/pointer",
618 ins: []_Instr{newInsVt(_OP_unmarshal_text, reflect.TypeOf(new(UtextStruct)))},
619 src: `hello\n\r\tworld"`,
620 exp: &UtextStruct{V: "hello\n\r\tworld"},
621 val: new(*UtextStruct),
622 }, {
623 key: "_OP_unmarshal_text_p",
624 ins: []_Instr{newInsVt(_OP_unmarshal_text_p, reflect.TypeOf(new(UtextStruct)))},
625 src: `hello\n\r\tworld"`,
626 exp: UtextStruct{V: "hello\n\r\tworld"},
627 val: new(UtextStruct),
628 }, {
629 key: "_OP_lspace",
630 ins: []_Instr{newInsOp(_OP_lspace)},
631 src: " \t\r\na",
632 vfn: func(i int, _ interface{}) { assert.Equal(t, 4, i) },
633 val: nil,
634 }, {
635 key: "_OP_lspace/error",
636 ins: []_Instr{newInsOp(_OP_lspace)},
637 src: "",
638 err: SyntaxError{Src: ``, Pos: 0, Code: types.ERR_EOF},
639 val: nil,
640 }, {
641 key: "_OP_match_char/correct",
642 ins: []_Instr{newInsVb(_OP_match_char, 'a')},
643 src: "a",
644 exp: nil,
645 val: nil,
646 }, {
647 key: "_OP_match_char/error",
648 ins: []_Instr{newInsVb(_OP_match_char, 'b')},
649 src: "a",
650 err: SyntaxError{Src: `a`, Pos: 0, Code: types.ERR_INVALID_CHAR},
651 val: nil,
652 }, {
653 key: "_OP_switch",
654 ins: []_Instr{
655 newInsVi(_OP_dbg_set_sr, 1),
656 newInsVs(_OP_switch, []int{4, 6, 8}),
657 newInsOp(_OP_i8),
658 newInsVi(_OP_goto, 9),
659 newInsOp(_OP_i16),
660 newInsVi(_OP_goto, 9),
661 newInsOp(_OP_i32),
662 newInsVi(_OP_goto, 9),
663 newInsOp(_OP_u8),
664 },
665 src: "-1234567",
666 exp: int32(-1234567),
667 val: new(int32),
668 },
669 }
670 for _, tv := range tests {
671 t.Run(tv.key, func(t *testing.T) {
672 println(tv.key)
673 testOpCode(t, &tv)
674 })
675 }
676 }
677
678 type JsonStruct struct {
679 A int
680 B string
681 C map[string]int
682 D []int
683 }
684
685 func TestAssembler_DecodeStruct(t *testing.T) {
686 var v JsonStruct
687 s := `{"A": 123, "B": "asdf", "C": {"qwer": 4567}, "D": [1, 2, 3, 4, 5]}`
688 p, err := newCompiler().compile(reflect.TypeOf(v))
689 require.NoError(t, err)
690 k := new(_Stack)
691 a := newAssembler(p)
692 f := a.Load()
693 pos, err := f(s, 0, unsafe.Pointer(&v), k, 0, "", nil)
694 require.NoError(t, err)
695 assert.Equal(t, len(s), pos)
696 assert.Equal(t, JsonStruct{
697 A: 123,
698 B: "asdf",
699 C: map[string]int{"qwer": 4567},
700 D: []int{1, 2, 3, 4, 5},
701 }, v)
702 }
703
704 func TestAssembler_PrologueAndEpilogue(t *testing.T) {
705 a := newAssembler(nil)
706 _, e := a.Load()("", 0, nil, nil, 0, "", nil)
707 assert.Nil(t, e)
708 }
709
710 type Tx struct {
711 x int
712 }
713
714 func TestAssembler_DecodeStruct_SinglePrivateField(t *testing.T) {
715 var v Tx
716 s := `{"x": 1}`
717 p, err := newCompiler().compile(reflect.TypeOf(v))
718 require.NoError(t, err)
719 k := new(_Stack)
720 a := newAssembler(p)
721 f := a.Load()
722 pos, err := f(s, 0, unsafe.Pointer(&v), k, 0, "", nil)
723 require.NoError(t, err)
724 assert.Equal(t, len(s), pos)
725 assert.Equal(t, Tx{}, v)
726 }
727
728 func TestAssembler_DecodeByteSlice_Bin(t *testing.T) {
729 var v []byte
730 s := `"aGVsbG8sIHdvcmxk"`
731 p, err := newCompiler().compile(reflect.TypeOf(v))
732 require.NoError(t, err)
733 k := new(_Stack)
734 a := newAssembler(p)
735 f := a.Load()
736 pos, err := f(s, 0, unsafe.Pointer(&v), k, 0, "", nil)
737 require.NoError(t, err)
738 assert.Equal(t, len(s), pos)
739 assert.Equal(t, []byte("hello, world"), v)
740 }
741
742 func TestAssembler_DecodeByteSlice_List(t *testing.T) {
743 var v []byte
744 s := `[104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100]`
745 p, err := newCompiler().compile(reflect.TypeOf(v))
746 require.NoError(t, err)
747 k := new(_Stack)
748 a := newAssembler(p)
749 f := a.Load()
750 pos, err := f(s, 0, unsafe.Pointer(&v), k, 0, "", nil)
751 require.NoError(t, err)
752 assert.Equal(t, len(s), pos)
753 assert.Equal(t, []byte("hello, world"), v)
754 }
View as plain text