-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpopulate.go
112 lines (98 loc) · 2.32 KB
/
populate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package magic
import (
"reflect"
"strings"
"unsafe"
)
func (m *Manager) newV(t reflect.Type) reflect.Value {
return reflect.New(t).Elem()
}
func (m *Manager) getI(v reflect.Value) interface{} {
return v.Interface()
}
func (m *Manager) vLen(vg reflect.Value) (len int, dynamicInfer bool) {
if vlen := vg.Len(); vlen != 0 {
return vlen, false
} else if vcap := vg.Cap(); vcap != 0 {
return vcap, false
} else {
return m.ReadInt(), true
}
}
func (m *Manager) pop(t reflect.Type, v reflect.Value, vg reflect.Value) {
switch t.Kind() {
case reflect.Bool:
v.SetBool(m.ReadBool())
case reflect.Int8:
v.SetInt(m.readInt(8))
case reflect.Int16:
v.SetInt(m.readInt(16))
case reflect.Int:
v.SetInt(m.readInt(0))
case reflect.Int32:
v.SetInt(m.readInt(32))
case reflect.Int64:
v.SetInt(m.readInt(64))
case reflect.Uint8:
v.SetUint(m.readUint(8))
case reflect.Uint16:
v.SetUint(m.readUint(16))
case reflect.Uint:
v.SetUint(m.readUint(0))
case reflect.Uint32:
v.SetUint(m.readUint(32))
case reflect.Uint64:
v.SetUint(m.readUint(64))
case reflect.Float32:
v.SetFloat(m.readFloat(32))
case reflect.Float64:
v.SetFloat(m.readFloat(64))
case reflect.Array:
fallthrough
case reflect.Slice:
m.popColl(t, v, vg)
case reflect.Ptr:
ptrv := reflect.New(t.Elem())
m.pop(t.Elem(), ptrv.Elem(), ptrv.Elem())
v.Set(ptrv)
case reflect.String:
v.SetString(m.cursor.next())
case reflect.Struct:
m.popStruct(t, v, vg)
default:
panic("unsupported type: " + t.Name())
}
}
func (m *Manager) popColl(t reflect.Type, v reflect.Value, vg reflect.Value) {
vlen, dynamicInfer := m.vLen(vg)
var s reflect.Value
switch t.Kind() {
case reflect.Array:
s = reflect.New(reflect.ArrayOf(vlen, t.Elem())).Elem()
case reflect.Slice:
s = reflect.MakeSlice(t, vlen, vlen)
}
for idx := 0; idx < vlen; idx++ {
vi := s.Index(idx)
var vgi reflect.Value
if !dynamicInfer {
vgi = vg.Index(idx)
} else {
vgi = s.Index(idx)
}
m.pop(vi.Type(), vi, vgi)
}
v.Set(s)
}
func (m *Manager) popStruct(t reflect.Type, v reflect.Value, vg reflect.Value) {
for idx := 0; idx < t.NumField(); idx++ {
f := t.Field(idx)
if strings.HasPrefix(f.Name, "_") {
continue
}
ft := f.Type
fvPtr := unsafe.Pointer(v.Field(idx).UnsafeAddr())
fv := reflect.NewAt(ft, fvPtr).Elem()
m.pop(ft, fv, vg.Field(idx))
}
}