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