podman

Форк
0
885 строк · 23.8 Кб
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 encoder
18

19
import (
20
    `fmt`
21
    `reflect`
22
    `strconv`
23
    `strings`
24
    `unsafe`
25

26
    `github.com/bytedance/sonic/internal/resolver`
27
    `github.com/bytedance/sonic/internal/rt`
28
    `github.com/bytedance/sonic/option`
29
)
30

31
type _Op uint8
32

33
const (
34
    _OP_null _Op = iota + 1
35
    _OP_empty_arr
36
    _OP_empty_obj
37
    _OP_bool
38
    _OP_i8
39
    _OP_i16
40
    _OP_i32
41
    _OP_i64
42
    _OP_u8
43
    _OP_u16
44
    _OP_u32
45
    _OP_u64
46
    _OP_f32
47
    _OP_f64
48
    _OP_str
49
    _OP_bin
50
    _OP_quote
51
    _OP_number
52
    _OP_eface
53
    _OP_iface
54
    _OP_byte
55
    _OP_text
56
    _OP_deref
57
    _OP_index
58
    _OP_load
59
    _OP_save
60
    _OP_drop
61
    _OP_drop_2
62
    _OP_recurse
63
    _OP_is_nil
64
    _OP_is_nil_p1
65
    _OP_is_zero_1
66
    _OP_is_zero_2
67
    _OP_is_zero_4
68
    _OP_is_zero_8
69
    _OP_is_zero_map
70
    _OP_goto
71
    _OP_map_iter
72
    _OP_map_stop
73
    _OP_map_check_key
74
    _OP_map_write_key
75
    _OP_map_value_next
76
    _OP_slice_len
77
    _OP_slice_next
78
    _OP_marshal
79
    _OP_marshal_p
80
    _OP_marshal_text
81
    _OP_marshal_text_p
82
    _OP_cond_set
83
    _OP_cond_testc
84
)
85

86
const (
87
    _INT_SIZE = 32 << (^uint(0) >> 63)
88
    _PTR_SIZE = 32 << (^uintptr(0) >> 63)
89
    _PTR_BYTE = unsafe.Sizeof(uintptr(0))
90
)
91

92
const (
93
    _MAX_ILBUF = 100000     // cutoff at 100k of IL instructions
94
    _MAX_FIELDS = 50        // cutoff at 50 fields struct
95
)
96

97
var _OpNames = [256]string {
98
    _OP_null           : "null",
99
    _OP_empty_arr      : "empty_arr",
100
    _OP_empty_obj      : "empty_obj",
101
    _OP_bool           : "bool",
102
    _OP_i8             : "i8",
103
    _OP_i16            : "i16",
104
    _OP_i32            : "i32",
105
    _OP_i64            : "i64",
106
    _OP_u8             : "u8",
107
    _OP_u16            : "u16",
108
    _OP_u32            : "u32",
109
    _OP_u64            : "u64",
110
    _OP_f32            : "f32",
111
    _OP_f64            : "f64",
112
    _OP_str            : "str",
113
    _OP_bin            : "bin",
114
    _OP_quote          : "quote",
115
    _OP_number         : "number",
116
    _OP_eface          : "eface",
117
    _OP_iface          : "iface",
118
    _OP_byte           : "byte",
119
    _OP_text           : "text",
120
    _OP_deref          : "deref",
121
    _OP_index          : "index",
122
    _OP_load           : "load",
123
    _OP_save           : "save",
124
    _OP_drop           : "drop",
125
    _OP_drop_2         : "drop_2",
126
    _OP_recurse        : "recurse",
127
    _OP_is_nil         : "is_nil",
128
    _OP_is_nil_p1      : "is_nil_p1",
129
    _OP_is_zero_1      : "is_zero_1",
130
    _OP_is_zero_2      : "is_zero_2",
131
    _OP_is_zero_4      : "is_zero_4",
132
    _OP_is_zero_8      : "is_zero_8",
133
    _OP_is_zero_map    : "is_zero_map",
134
    _OP_goto           : "goto",
135
    _OP_map_iter       : "map_iter",
136
    _OP_map_stop       : "map_stop",
137
    _OP_map_check_key  : "map_check_key",
138
    _OP_map_write_key  : "map_write_key",
139
    _OP_map_value_next : "map_value_next",
140
    _OP_slice_len      : "slice_len",
141
    _OP_slice_next     : "slice_next",
142
    _OP_marshal        : "marshal",
143
    _OP_marshal_p      : "marshal_p",
144
    _OP_marshal_text   : "marshal_text",
145
    _OP_marshal_text_p : "marshal_text_p",
146
    _OP_cond_set       : "cond_set",
147
    _OP_cond_testc     : "cond_testc",
148
}
149

150
func (self _Op) String() string {
151
    if ret := _OpNames[self]; ret != "" {
152
        return ret
153
    } else {
154
        return "<invalid>"
155
    }
156
}
157

158
func _OP_int() _Op {
159
    switch _INT_SIZE {
160
        case 32: return _OP_i32
161
        case 64: return _OP_i64
162
        default: panic("unsupported int size")
163
    }
164
}
165

166
func _OP_uint() _Op {
167
    switch _INT_SIZE {
168
        case 32: return _OP_u32
169
        case 64: return _OP_u64
170
        default: panic("unsupported uint size")
171
    }
172
}
173

174
func _OP_uintptr() _Op {
175
    switch _PTR_SIZE {
176
        case 32: return _OP_u32
177
        case 64: return _OP_u64
178
        default: panic("unsupported pointer size")
179
    }
180
}
181

182
func _OP_is_zero_ints() _Op {
183
    switch _INT_SIZE {
184
        case 32: return _OP_is_zero_4
185
        case 64: return _OP_is_zero_8
186
        default: panic("unsupported integer size")
187
    }
188
}
189

190
type _Instr struct {
191
    u uint64            // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
192
    p unsafe.Pointer    // maybe GoString.Ptr, or *GoType
193
}
194

195
func packOp(op _Op) uint64 {
196
    return uint64(op) << 56
197
}
198

199
func newInsOp(op _Op) _Instr {
200
    return _Instr{u: packOp(op)}
201
}
202

203
func newInsVi(op _Op, vi int) _Instr {
204
    return _Instr{u: packOp(op) | rt.PackInt(vi)}
205
}
206

207
func newInsVs(op _Op, vs string) _Instr {
208
    return _Instr {
209
        u: packOp(op) | rt.PackInt(len(vs)),
210
        p: (*rt.GoString)(unsafe.Pointer(&vs)).Ptr,
211
    }
212
}
213

214
func newInsVt(op _Op, vt reflect.Type) _Instr {
215
    return _Instr {
216
        u: packOp(op),
217
        p: unsafe.Pointer(rt.UnpackType(vt)),
218
    }
219
}
220

221
func newInsVp(op _Op, vt reflect.Type, pv bool) _Instr {
222
    i := 0
223
    if pv {
224
        i = 1
225
    }
226
    return _Instr {
227
        u: packOp(op) | rt.PackInt(i),
228
        p: unsafe.Pointer(rt.UnpackType(vt)),
229
    }
230
}
231

232
func (self _Instr) op() _Op {
233
    return _Op(self.u >> 56)
234
}
235

236
func (self _Instr) vi() int {
237
    return rt.UnpackInt(self.u)
238
}
239

240
func (self _Instr) vf() uint8 {
241
    return (*rt.GoType)(self.p).KindFlags
242
}
243

244
func (self _Instr) vs() (v string) {
245
    (*rt.GoString)(unsafe.Pointer(&v)).Ptr = self.p
246
    (*rt.GoString)(unsafe.Pointer(&v)).Len = self.vi()
247
    return
248
}
249

250
func (self _Instr) vk() reflect.Kind {
251
    return (*rt.GoType)(self.p).Kind()
252
}
253

254
func (self _Instr) vt() reflect.Type {
255
    return (*rt.GoType)(self.p).Pack()
256
}
257

258
func (self _Instr) vp() (vt reflect.Type, pv bool) {
259
    return (*rt.GoType)(self.p).Pack(), rt.UnpackInt(self.u) == 1
260
}
261

262
func (self _Instr) i64() int64 {
263
    return int64(self.vi())
264
}
265

266
func (self _Instr) vlen() int {
267
    return int((*rt.GoType)(self.p).Size)
268
}
269

270
func (self _Instr) isBranch() bool {
271
    switch self.op() {
272
        case _OP_goto          : fallthrough
273
        case _OP_is_nil        : fallthrough
274
        case _OP_is_nil_p1     : fallthrough
275
        case _OP_is_zero_1     : fallthrough
276
        case _OP_is_zero_2     : fallthrough
277
        case _OP_is_zero_4     : fallthrough
278
        case _OP_is_zero_8     : fallthrough
279
        case _OP_map_check_key : fallthrough
280
        case _OP_map_write_key : fallthrough
281
        case _OP_slice_next    : fallthrough
282
        case _OP_cond_testc    : return true
283
        default                : return false
284
    }
285
}
286

287
func (self _Instr) disassemble() string {
288
    switch self.op() {
289
        case _OP_byte           : return fmt.Sprintf("%-18s%s", self.op().String(), strconv.QuoteRune(rune(self.vi())))
290
        case _OP_text           : return fmt.Sprintf("%-18s%s", self.op().String(), strconv.Quote(self.vs()))
291
        case _OP_index          : return fmt.Sprintf("%-18s%d", self.op().String(), self.vi())
292
        case _OP_recurse        : fallthrough
293
        case _OP_map_iter       : fallthrough
294
        case _OP_marshal        : fallthrough
295
        case _OP_marshal_p      : fallthrough
296
        case _OP_marshal_text   : fallthrough
297
        case _OP_marshal_text_p : return fmt.Sprintf("%-18s%s", self.op().String(), self.vt())
298
        case _OP_goto           : fallthrough
299
        case _OP_is_nil         : fallthrough
300
        case _OP_is_nil_p1      : fallthrough
301
        case _OP_is_zero_1      : fallthrough
302
        case _OP_is_zero_2      : fallthrough
303
        case _OP_is_zero_4      : fallthrough
304
        case _OP_is_zero_8      : fallthrough
305
        case _OP_is_zero_map    : fallthrough
306
        case _OP_cond_testc     : fallthrough
307
        case _OP_map_check_key  : fallthrough
308
        case _OP_map_write_key  : return fmt.Sprintf("%-18sL_%d", self.op().String(), self.vi())
309
        case _OP_slice_next     : return fmt.Sprintf("%-18sL_%d, %s", self.op().String(), self.vi(), self.vt())
310
        default                 : return self.op().String()
311
    }
312
}
313

314
type (
315
	_Program []_Instr
316
)
317

318
func (self _Program) pc() int {
319
    return len(self)
320
}
321

322
func (self _Program) tag(n int) {
323
    if n >= _MaxStack {
324
        panic("type nesting too deep")
325
    }
326
}
327

328
func (self _Program) pin(i int) {
329
    v := &self[i]
330
    v.u &= 0xffff000000000000
331
    v.u |= rt.PackInt(self.pc())
332
}
333

334
func (self _Program) rel(v []int) {
335
    for _, i := range v {
336
        self.pin(i)
337
    }
338
}
339

340
func (self *_Program) add(op _Op) {
341
    *self = append(*self, newInsOp(op))
342
}
343

344
func (self *_Program) key(op _Op) {
345
    *self = append(*self,
346
        newInsVi(_OP_byte, '"'),
347
        newInsOp(op),
348
        newInsVi(_OP_byte, '"'),
349
    )
350
}
351

352
func (self *_Program) int(op _Op, vi int) {
353
    *self = append(*self, newInsVi(op, vi))
354
}
355

356
func (self *_Program) str(op _Op, vs string) {
357
    *self = append(*self, newInsVs(op, vs))
358
}
359

360
func (self *_Program) rtt(op _Op, vt reflect.Type) {
361
    *self = append(*self, newInsVt(op, vt))
362
}
363

364
func (self *_Program) vp(op _Op, vt reflect.Type, pv bool) {
365
    *self = append(*self, newInsVp(op, vt, pv))
366
}
367

368
func (self _Program) disassemble() string {
369
    nb  := len(self)
370
    tab := make([]bool, nb + 1)
371
    ret := make([]string, 0, nb + 1)
372

373
    /* prescan to get all the labels */
374
    for _, ins := range self {
375
        if ins.isBranch() {
376
            tab[ins.vi()] = true
377
        }
378
    }
379

380
    /* disassemble each instruction */
381
    for i, ins := range self {
382
        if !tab[i] {
383
            ret = append(ret, "\t" + ins.disassemble())
384
        } else {
385
            ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.disassemble()))
386
        }
387
    }
388

389
    /* add the last label, if needed */
390
    if tab[nb] {
391
        ret = append(ret, fmt.Sprintf("L_%d:", nb))
392
    }
393

394
    /* add an "end" indicator, and join all the strings */
395
    return strings.Join(append(ret, "\tend"), "\n")
396
}
397

398
type _Compiler struct {
399
    opts option.CompileOptions
400
    pv   bool
401
    tab  map[reflect.Type]bool
402
    rec  map[reflect.Type]uint8
403
}
404

405
func newCompiler() *_Compiler {
406
    return &_Compiler {
407
        opts: option.DefaultCompileOptions(),
408
        tab: map[reflect.Type]bool{},
409
        rec: map[reflect.Type]uint8{},
410
    }
411
}
412

413
func (self *_Compiler) apply(opts option.CompileOptions) *_Compiler {
414
    self.opts = opts
415
    if self.opts.RecursiveDepth > 0 {
416
        self.rec = map[reflect.Type]uint8{}
417
    }
418
    return self
419
}
420

421
func (self *_Compiler) rescue(ep *error) {
422
    if val := recover(); val != nil {
423
        if err, ok := val.(error); ok {
424
            *ep = err
425
        } else {
426
            panic(val)
427
        }
428
    }
429
}
430

431
func (self *_Compiler) compile(vt reflect.Type, pv bool) (ret _Program, err error) {
432
    defer self.rescue(&err)
433
    self.compileOne(&ret, 0, vt, pv)
434
    return
435
}
436

437
func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type, pv bool) {
438
    if self.tab[vt] {
439
        p.vp(_OP_recurse, vt, pv)
440
    } else {
441
        self.compileRec(p, sp, vt, pv)
442
    }
443
}
444

445
func (self *_Compiler) compileRec(p *_Program, sp int, vt reflect.Type, pv bool) {
446
    pr := self.pv
447
    pt := reflect.PtrTo(vt)
448

449
    /* check for addressable `json.Marshaler` with pointer receiver */
450
    if pv && pt.Implements(jsonMarshalerType) {
451
        p.rtt(_OP_marshal_p, pt)
452
        return
453
    }
454

455
    /* check for `json.Marshaler` */
456
    if vt.Implements(jsonMarshalerType) {
457
        self.compileMarshaler(p, _OP_marshal, vt, jsonMarshalerType)
458
        return
459
    }
460

461
    /* check for addressable `encoding.TextMarshaler` with pointer receiver */
462
    if pv && pt.Implements(encodingTextMarshalerType) {
463
        p.rtt(_OP_marshal_text_p, pt)
464
        return
465
    }
466

467
    /* check for `encoding.TextMarshaler` */
468
    if vt.Implements(encodingTextMarshalerType) {
469
        self.compileMarshaler(p, _OP_marshal_text, vt, encodingTextMarshalerType)
470
        return
471
    }
472

473
    /* enter the recursion, and compile the type */
474
    self.pv = pv
475
    self.tab[vt] = true
476
    self.compileOps(p, sp, vt)
477

478
    /* exit the recursion */
479
    self.pv = pr
480
    delete(self.tab, vt)
481
}
482

483
func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
484
    switch vt.Kind() {
485
        case reflect.Bool      : p.add(_OP_bool)
486
        case reflect.Int       : p.add(_OP_int())
487
        case reflect.Int8      : p.add(_OP_i8)
488
        case reflect.Int16     : p.add(_OP_i16)
489
        case reflect.Int32     : p.add(_OP_i32)
490
        case reflect.Int64     : p.add(_OP_i64)
491
        case reflect.Uint      : p.add(_OP_uint())
492
        case reflect.Uint8     : p.add(_OP_u8)
493
        case reflect.Uint16    : p.add(_OP_u16)
494
        case reflect.Uint32    : p.add(_OP_u32)
495
        case reflect.Uint64    : p.add(_OP_u64)
496
        case reflect.Uintptr   : p.add(_OP_uintptr())
497
        case reflect.Float32   : p.add(_OP_f32)
498
        case reflect.Float64   : p.add(_OP_f64)
499
        case reflect.String    : self.compileString    (p, vt)
500
        case reflect.Array     : self.compileArray     (p, sp, vt.Elem(), vt.Len())
501
        case reflect.Interface : self.compileInterface (p, vt)
502
        case reflect.Map       : self.compileMap       (p, sp, vt)
503
        case reflect.Ptr       : self.compilePtr       (p, sp, vt.Elem())
504
        case reflect.Slice     : self.compileSlice     (p, sp, vt.Elem())
505
        case reflect.Struct    : self.compileStruct    (p, sp, vt)
506
        default                : panic                 (error_type(vt))
507
    }
508
}
509

510
func (self *_Compiler) compileNil(p *_Program, sp int, vt reflect.Type, nil_op _Op, fn func(*_Program, int, reflect.Type)) {
511
    x := p.pc()
512
    p.add(_OP_is_nil)
513
    fn(p, sp, vt)
514
    e := p.pc()
515
    p.add(_OP_goto)
516
    p.pin(x)
517
    p.add(nil_op)
518
    p.pin(e)
519
}
520

521
func (self *_Compiler) compilePtr(p *_Program, sp int, vt reflect.Type) {
522
    self.compileNil(p, sp, vt, _OP_null, self.compilePtrBody)
523
}
524

525
func (self *_Compiler) compilePtrBody(p *_Program, sp int, vt reflect.Type) {
526
    p.tag(sp)
527
    p.add(_OP_save)
528
    p.add(_OP_deref)
529
    self.compileOne(p, sp + 1, vt, true)
530
    p.add(_OP_drop)
531
}
532

533
func (self *_Compiler) compileMap(p *_Program, sp int, vt reflect.Type) {
534
    self.compileNil(p, sp, vt, _OP_empty_obj, self.compileMapBody)
535
}
536

537
func (self *_Compiler) compileMapBody(p *_Program, sp int, vt reflect.Type) {
538
    p.tag(sp + 1)
539
    p.int(_OP_byte, '{')
540
    p.add(_OP_save)
541
    p.rtt(_OP_map_iter, vt)
542
    p.add(_OP_save)
543
    i := p.pc()
544
    p.add(_OP_map_check_key)
545
    u := p.pc()
546
    p.add(_OP_map_write_key)
547
    self.compileMapBodyKey(p, vt.Key())
548
    p.pin(u)
549
    p.int(_OP_byte, ':')
550
    p.add(_OP_map_value_next)
551
    self.compileOne(p, sp + 2, vt.Elem(), false)
552
    j := p.pc()
553
    p.add(_OP_map_check_key)
554
    p.int(_OP_byte, ',')
555
    v := p.pc()
556
    p.add(_OP_map_write_key)
557
    self.compileMapBodyKey(p, vt.Key())
558
    p.pin(v)
559
    p.int(_OP_byte, ':')
560
    p.add(_OP_map_value_next)
561
    self.compileOne(p, sp + 2, vt.Elem(), false)
562
    p.int(_OP_goto, j)
563
    p.pin(i)
564
    p.pin(j)
565
    p.add(_OP_map_stop)
566
    p.add(_OP_drop_2)
567
    p.int(_OP_byte, '}')
568
}
569

570
func (self *_Compiler) compileMapBodyKey(p *_Program, vk reflect.Type) {
571
    if !vk.Implements(encodingTextMarshalerType) {
572
        self.compileMapBodyTextKey(p, vk)
573
    } else {
574
        self.compileMapBodyUtextKey(p, vk)
575
    }
576
}
577

578
func (self *_Compiler) compileMapBodyTextKey(p *_Program, vk reflect.Type) {
579
    switch vk.Kind() {
580
        case reflect.Invalid : panic("map key is nil")
581
        case reflect.Bool    : p.key(_OP_bool)
582
        case reflect.Int     : p.key(_OP_int())
583
        case reflect.Int8    : p.key(_OP_i8)
584
        case reflect.Int16   : p.key(_OP_i16)
585
        case reflect.Int32   : p.key(_OP_i32)
586
        case reflect.Int64   : p.key(_OP_i64)
587
        case reflect.Uint    : p.key(_OP_uint())
588
        case reflect.Uint8   : p.key(_OP_u8)
589
        case reflect.Uint16  : p.key(_OP_u16)
590
        case reflect.Uint32  : p.key(_OP_u32)
591
        case reflect.Uint64  : p.key(_OP_u64)
592
        case reflect.Uintptr : p.key(_OP_uintptr())
593
        case reflect.Float32 : p.key(_OP_f32)
594
        case reflect.Float64 : p.key(_OP_f64)
595
        case reflect.String  : self.compileString(p, vk)
596
        default              : panic(error_type(vk))
597
    }
598
}
599

600
func (self *_Compiler) compileMapBodyUtextKey(p *_Program, vk reflect.Type) {
601
    if vk.Kind() != reflect.Ptr {
602
        p.rtt(_OP_marshal_text, vk)
603
    } else {
604
        self.compileMapBodyUtextPtr(p, vk)
605
    }
606
}
607

608
func (self *_Compiler) compileMapBodyUtextPtr(p *_Program, vk reflect.Type) {
609
    i := p.pc()
610
    p.add(_OP_is_nil)
611
    p.rtt(_OP_marshal_text, vk)
612
    j := p.pc()
613
    p.add(_OP_goto)
614
    p.pin(i)
615
    p.str(_OP_text, "\"\"")
616
    p.pin(j)
617
}
618

619
func (self *_Compiler) compileSlice(p *_Program, sp int, vt reflect.Type) {
620
    self.compileNil(p, sp, vt, _OP_empty_arr, self.compileSliceBody)
621
}
622

623
func (self *_Compiler) compileSliceBody(p *_Program, sp int, vt reflect.Type) {
624
    if isSimpleByte(vt) {
625
        p.add(_OP_bin)
626
    } else {
627
        self.compileSliceArray(p, sp, vt)
628
    }
629
}
630

631
func (self *_Compiler) compileSliceArray(p *_Program, sp int, vt reflect.Type) {
632
    p.tag(sp)
633
    p.int(_OP_byte, '[')
634
    p.add(_OP_save)
635
    p.add(_OP_slice_len)
636
    i := p.pc()
637
    p.rtt(_OP_slice_next, vt)
638
    self.compileOne(p, sp + 1, vt, true)
639
    j := p.pc()
640
    p.rtt(_OP_slice_next, vt)
641
    p.int(_OP_byte, ',')
642
    self.compileOne(p, sp + 1, vt, true)
643
    p.int(_OP_goto, j)
644
    p.pin(i)
645
    p.pin(j)
646
    p.add(_OP_drop)
647
    p.int(_OP_byte, ']')
648
}
649

650
func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type, nb int) {
651
    p.tag(sp)
652
    p.int(_OP_byte, '[')
653
    p.add(_OP_save)
654

655
    /* first item */
656
    if nb != 0 {
657
        self.compileOne(p, sp + 1, vt, self.pv)
658
        p.add(_OP_load)
659
    }
660

661
    /* remaining items */
662
    for i := 1; i < nb; i++ {
663
        p.int(_OP_byte, ',')
664
        p.int(_OP_index, i * int(vt.Size()))
665
        self.compileOne(p, sp + 1, vt, self.pv)
666
        p.add(_OP_load)
667
    }
668

669
    /* end of array */
670
    p.add(_OP_drop)
671
    p.int(_OP_byte, ']')
672
}
673

674
func (self *_Compiler) compileString(p *_Program, vt reflect.Type) {
675
    if vt != jsonNumberType {
676
        p.add(_OP_str)
677
    } else {
678
        p.add(_OP_number)
679
    }
680
}
681

682
func (self *_Compiler) compileStruct(p *_Program, sp int, vt reflect.Type) {
683
    if sp >= self.opts.MaxInlineDepth || p.pc() >= _MAX_ILBUF || (sp > 0 && vt.NumField() >= _MAX_FIELDS) {
684
        p.vp(_OP_recurse, vt, self.pv)
685
        if self.opts.RecursiveDepth > 0 {
686
            if self.pv {
687
                self.rec[vt] = 1
688
            } else {
689
                self.rec[vt] = 0
690
            }
691
        }
692
    } else {
693
        self.compileStructBody(p, sp, vt)
694
    }
695
}
696

697
func (self *_Compiler) compileStructBody(p *_Program, sp int, vt reflect.Type) {
698
    p.tag(sp)
699
    p.int(_OP_byte, '{')
700
    p.add(_OP_save)
701
    p.add(_OP_cond_set)
702

703
    /* compile each field */
704
    for _, fv := range resolver.ResolveStruct(vt) {
705
        var s []int
706
        var o resolver.Offset
707

708
        /* "omitempty" for arrays */
709
        if fv.Type.Kind() == reflect.Array {
710
            if fv.Type.Len() == 0 && (fv.Opts & resolver.F_omitempty) != 0 {
711
                continue
712
            }
713
        }
714

715
        /* index to the field */
716
        for _, o = range fv.Path {
717
            if p.int(_OP_index, int(o.Size)); o.Kind == resolver.F_deref {
718
                s = append(s, p.pc())
719
                p.add(_OP_is_nil)
720
                p.add(_OP_deref)
721
            }
722
        }
723

724
        /* check for "omitempty" option */
725
        if fv.Type.Kind() != reflect.Struct && fv.Type.Kind() != reflect.Array && (fv.Opts & resolver.F_omitempty) != 0 {
726
            s = append(s, p.pc())
727
            self.compileStructFieldZero(p, fv.Type)
728
        }
729

730
        /* add the comma if not the first element */
731
        i := p.pc()
732
        p.add(_OP_cond_testc)
733
        p.int(_OP_byte, ',')
734
        p.pin(i)
735

736
        /* compile the key and value */
737
        ft := fv.Type
738
        p.str(_OP_text, Quote(fv.Name) + ":")
739

740
        /* check for "stringnize" option */
741
        if (fv.Opts & resolver.F_stringize) == 0 {
742
            self.compileOne(p, sp + 1, ft, self.pv)
743
        } else {
744
            self.compileStructFieldStr(p, sp + 1, ft)
745
        }
746

747
        /* patch the skipping jumps and reload the struct pointer */
748
        p.rel(s)
749
        p.add(_OP_load)
750
    }
751

752
    /* end of object */
753
    p.add(_OP_drop)
754
    p.int(_OP_byte, '}')
755
}
756

757
func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Type) {
758
    pc := -1
759
    ft := vt
760
    sv := false
761

762
    /* dereference the pointer if needed */
763
    if ft.Kind() == reflect.Ptr {
764
        ft = ft.Elem()
765
    }
766

767
    /* check if it can be stringized */
768
    switch ft.Kind() {
769
        case reflect.Bool    : sv = true
770
        case reflect.Int     : sv = true
771
        case reflect.Int8    : sv = true
772
        case reflect.Int16   : sv = true
773
        case reflect.Int32   : sv = true
774
        case reflect.Int64   : sv = true
775
        case reflect.Uint    : sv = true
776
        case reflect.Uint8   : sv = true
777
        case reflect.Uint16  : sv = true
778
        case reflect.Uint32  : sv = true
779
        case reflect.Uint64  : sv = true
780
        case reflect.Uintptr : sv = true
781
        case reflect.Float32 : sv = true
782
        case reflect.Float64 : sv = true
783
        case reflect.String  : sv = true
784
    }
785

786
    /* if it's not, ignore the "string" and follow the regular path */
787
    if !sv {
788
        self.compileOne(p, sp, vt, self.pv)
789
        return
790
    }
791

792
    /* dereference the pointer */
793
    if vt.Kind() == reflect.Ptr {
794
        pc = p.pc()
795
        vt = vt.Elem()
796
        p.add(_OP_is_nil)
797
        p.add(_OP_deref)
798
    }
799

800
    /* special case of a double-quoted string */
801
    if ft != jsonNumberType && ft.Kind() == reflect.String {
802
        p.add(_OP_quote)
803
    } else {
804
        self.compileStructFieldQuoted(p, sp, vt)
805
    }
806

807
    /* the "null" case of the pointer */
808
    if pc != -1 {
809
        e := p.pc()
810
        p.add(_OP_goto)
811
        p.pin(pc)
812
        p.add(_OP_null)
813
        p.pin(e)
814
    }
815
}
816

817
func (self *_Compiler) compileStructFieldZero(p *_Program, vt reflect.Type) {
818
    switch vt.Kind() {
819
        case reflect.Bool      : p.add(_OP_is_zero_1)
820
        case reflect.Int       : p.add(_OP_is_zero_ints())
821
        case reflect.Int8      : p.add(_OP_is_zero_1)
822
        case reflect.Int16     : p.add(_OP_is_zero_2)
823
        case reflect.Int32     : p.add(_OP_is_zero_4)
824
        case reflect.Int64     : p.add(_OP_is_zero_8)
825
        case reflect.Uint      : p.add(_OP_is_zero_ints())
826
        case reflect.Uint8     : p.add(_OP_is_zero_1)
827
        case reflect.Uint16    : p.add(_OP_is_zero_2)
828
        case reflect.Uint32    : p.add(_OP_is_zero_4)
829
        case reflect.Uint64    : p.add(_OP_is_zero_8)
830
        case reflect.Uintptr   : p.add(_OP_is_nil)
831
        case reflect.Float32   : p.add(_OP_is_zero_4)
832
        case reflect.Float64   : p.add(_OP_is_zero_8)
833
        case reflect.String    : p.add(_OP_is_nil_p1)
834
        case reflect.Interface : p.add(_OP_is_nil_p1)
835
        case reflect.Map       : p.add(_OP_is_zero_map)
836
        case reflect.Ptr       : p.add(_OP_is_nil)
837
        case reflect.Slice     : p.add(_OP_is_nil_p1)
838
        default                : panic(error_type(vt))
839
    }
840
}
841

842
func (self *_Compiler) compileStructFieldQuoted(p *_Program, sp int, vt reflect.Type) {
843
    p.int(_OP_byte, '"')
844
    self.compileOne(p, sp, vt, self.pv)
845
    p.int(_OP_byte, '"')
846
}
847

848
func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
849
    x := p.pc()
850
    p.add(_OP_is_nil_p1)
851

852
    /* iface and efaces are different */
853
    if vt.NumMethod() == 0 {
854
        p.add(_OP_eface)
855
    } else {
856
        p.add(_OP_iface)
857
    }
858

859
    /* the "null" value */
860
    e := p.pc()
861
    p.add(_OP_goto)
862
    p.pin(x)
863
    p.add(_OP_null)
864
    p.pin(e)
865
}
866

867
func (self *_Compiler) compileMarshaler(p *_Program, op _Op, vt reflect.Type, mt reflect.Type) {
868
    pc := p.pc()
869
    vk := vt.Kind()
870

871
    /* direct receiver */
872
    if vk != reflect.Ptr {
873
        p.rtt(op, vt)
874
        return
875
    }
876

877
    /* value receiver with a pointer type, check for nil before calling the marshaler */
878
    p.add(_OP_is_nil)
879
    p.rtt(op, vt)
880
    i := p.pc()
881
    p.add(_OP_goto)
882
    p.pin(pc)
883
    p.add(_OP_null)
884
    p.pin(i)
885
}
886

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.