github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/decoder/assembler_test.go (about) 1 /* 2 * Copyright 2021 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 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 }