Source file src/pkg/internal/reflectlite/value.go
1
2
3
4
5 package reflectlite
6
7 import (
8 "runtime"
9 "unsafe"
10 )
11
12 const ptrSize = 4 << (^uintptr(0) >> 63)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 type Value struct {
36
37 typ *rtype
38
39
40
41 ptr unsafe.Pointer
42
43
44
45
46
47
48
49
50
51
52
53
54
55 flag
56
57
58
59
60
61
62 }
63
64 type flag uintptr
65
66 const (
67 flagKindWidth = 5
68 flagKindMask flag = 1<<flagKindWidth - 1
69 flagStickyRO flag = 1 << 5
70 flagEmbedRO flag = 1 << 6
71 flagIndir flag = 1 << 7
72 flagAddr flag = 1 << 8
73 flagMethod flag = 1 << 9
74 flagMethodShift = 10
75 flagRO flag = flagStickyRO | flagEmbedRO
76 )
77
78 func (f flag) kind() Kind {
79 return Kind(f & flagKindMask)
80 }
81
82 func (f flag) ro() flag {
83 if f&flagRO != 0 {
84 return flagStickyRO
85 }
86 return 0
87 }
88
89
90
91 func (v Value) pointer() unsafe.Pointer {
92 if v.typ.size != ptrSize || !v.typ.pointers() {
93 panic("can't call pointer on a non-pointer Value")
94 }
95 if v.flag&flagIndir != 0 {
96 return *(*unsafe.Pointer)(v.ptr)
97 }
98 return v.ptr
99 }
100
101
102 func packEface(v Value) interface{} {
103 t := v.typ
104 var i interface{}
105 e := (*emptyInterface)(unsafe.Pointer(&i))
106
107 switch {
108 case ifaceIndir(t):
109 if v.flag&flagIndir == 0 {
110 panic("bad indir")
111 }
112
113 ptr := v.ptr
114 if v.flag&flagAddr != 0 {
115
116
117 c := unsafe_New(t)
118 typedmemmove(t, c, ptr)
119 ptr = c
120 }
121 e.word = ptr
122 case v.flag&flagIndir != 0:
123
124
125 e.word = *(*unsafe.Pointer)(v.ptr)
126 default:
127
128 e.word = v.ptr
129 }
130
131
132
133
134 e.typ = t
135 return i
136 }
137
138
139 func unpackEface(i interface{}) Value {
140 e := (*emptyInterface)(unsafe.Pointer(&i))
141
142 t := e.typ
143 if t == nil {
144 return Value{}
145 }
146 f := flag(t.Kind())
147 if ifaceIndir(t) {
148 f |= flagIndir
149 }
150 return Value{t, e.word, f}
151 }
152
153
154
155
156 type ValueError struct {
157 Method string
158 Kind Kind
159 }
160
161 func (e *ValueError) Error() string {
162 return "reflect: call of " + e.Method + " on zero Value"
163 }
164
165
166
167 func methodName() string {
168 pc, _, _, _ := runtime.Caller(2)
169 f := runtime.FuncForPC(pc)
170 if f == nil {
171 return "unknown method"
172 }
173 return f.Name()
174 }
175
176
177 type emptyInterface struct {
178 typ *rtype
179 word unsafe.Pointer
180 }
181
182
183 type nonEmptyInterface struct {
184
185 itab *struct {
186 ityp *rtype
187 typ *rtype
188 hash uint32
189 _ [4]byte
190 fun [100000]unsafe.Pointer
191 }
192 word unsafe.Pointer
193 }
194
195
196
197 func (f flag) mustBeExported() {
198 if f == 0 {
199 panic(&ValueError{methodName(), 0})
200 }
201 if f&flagRO != 0 {
202 panic("reflect: " + methodName() + " using value obtained using unexported field")
203 }
204 }
205
206
207
208
209 func (f flag) mustBeAssignable() {
210 if f == 0 {
211 panic(&ValueError{methodName(), Invalid})
212 }
213
214 if f&flagRO != 0 {
215 panic("reflect: " + methodName() + " using value obtained using unexported field")
216 }
217 if f&flagAddr == 0 {
218 panic("reflect: " + methodName() + " using unaddressable value")
219 }
220 }
221
222
223
224
225
226
227 func (v Value) CanSet() bool {
228 return v.flag&(flagAddr|flagRO) == flagAddr
229 }
230
231
232
233
234
235 func (v Value) Elem() Value {
236 k := v.kind()
237 switch k {
238 case Interface:
239 var eface interface{}
240 if v.typ.NumMethod() == 0 {
241 eface = *(*interface{})(v.ptr)
242 } else {
243 eface = (interface{})(*(*interface {
244 M()
245 })(v.ptr))
246 }
247 x := unpackEface(eface)
248 if x.flag != 0 {
249 x.flag |= v.flag.ro()
250 }
251 return x
252 case Ptr:
253 ptr := v.ptr
254 if v.flag&flagIndir != 0 {
255 ptr = *(*unsafe.Pointer)(ptr)
256 }
257
258 if ptr == nil {
259 return Value{}
260 }
261 tt := (*ptrType)(unsafe.Pointer(v.typ))
262 typ := tt.elem
263 fl := v.flag&flagRO | flagIndir | flagAddr
264 fl |= flag(typ.Kind())
265 return Value{typ, ptr, fl}
266 }
267 panic(&ValueError{"reflectlite.Value.Elem", v.kind()})
268 }
269
270 func valueInterface(v Value) interface{} {
271 if v.flag == 0 {
272 panic(&ValueError{"reflectlite.Value.Interface", 0})
273 }
274
275 if v.kind() == Interface {
276
277
278
279 if v.numMethod() == 0 {
280 return *(*interface{})(v.ptr)
281 }
282 return *(*interface {
283 M()
284 })(v.ptr)
285 }
286
287
288 return packEface(v)
289 }
290
291
292
293
294
295
296
297
298 func (v Value) IsNil() bool {
299 k := v.kind()
300 switch k {
301 case Chan, Func, Map, Ptr, UnsafePointer:
302
303
304
305 ptr := v.ptr
306 if v.flag&flagIndir != 0 {
307 ptr = *(*unsafe.Pointer)(ptr)
308 }
309 return ptr == nil
310 case Interface, Slice:
311
312
313 return *(*unsafe.Pointer)(v.ptr) == nil
314 }
315 panic(&ValueError{"reflectlite.Value.IsNil", v.kind()})
316 }
317
318
319
320
321
322
323 func (v Value) IsValid() bool {
324 return v.flag != 0
325 }
326
327
328
329 func (v Value) Kind() Kind {
330 return v.kind()
331 }
332
333
334 func chanlen(unsafe.Pointer) int
335 func maplen(unsafe.Pointer) int
336
337
338
339 func (v Value) Len() int {
340 k := v.kind()
341 switch k {
342 case Array:
343 tt := (*arrayType)(unsafe.Pointer(v.typ))
344 return int(tt.len)
345 case Chan:
346 return chanlen(v.pointer())
347 case Map:
348 return maplen(v.pointer())
349 case Slice:
350
351 return (*sliceHeader)(v.ptr).Len
352 case String:
353
354 return (*stringHeader)(v.ptr).Len
355 }
356 panic(&ValueError{"reflect.Value.Len", v.kind()})
357 }
358
359
360 func (v Value) numMethod() int {
361 if v.typ == nil {
362 panic(&ValueError{"reflectlite.Value.NumMethod", Invalid})
363 }
364 return v.typ.NumMethod()
365 }
366
367
368
369
370 func (v Value) Set(x Value) {
371 v.mustBeAssignable()
372 x.mustBeExported()
373 var target unsafe.Pointer
374 if v.kind() == Interface {
375 target = v.ptr
376 }
377 x = x.assignTo("reflectlite.Set", v.typ, target)
378 if x.flag&flagIndir != 0 {
379 typedmemmove(v.typ, v.ptr, x.ptr)
380 } else {
381 *(*unsafe.Pointer)(v.ptr) = x.ptr
382 }
383 }
384
385
386 func (v Value) Type() Type {
387 f := v.flag
388 if f == 0 {
389 panic(&ValueError{"reflectlite.Value.Type", Invalid})
390 }
391
392 return v.typ
393 }
394
395
396 type stringHeader struct {
397 Data unsafe.Pointer
398 Len int
399 }
400
401
402 type sliceHeader struct {
403 Data unsafe.Pointer
404 Len int
405 Cap int
406 }
407
408
411
412
413 func unsafe_New(*rtype) unsafe.Pointer
414
415
416
417 func ValueOf(i interface{}) Value {
418 if i == nil {
419 return Value{}
420 }
421
422
423
424
425
426 escapes(i)
427
428 return unpackEface(i)
429 }
430
431
432
433
434 func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
435
436
437
438
439 switch {
440 case directlyAssignable(dst, v.typ):
441
442
443 fl := v.flag&(flagAddr|flagIndir) | v.flag.ro()
444 fl |= flag(dst.Kind())
445 return Value{dst, v.ptr, fl}
446
447 case implements(dst, v.typ):
448 if target == nil {
449 target = unsafe_New(dst)
450 }
451 if v.Kind() == Interface && v.IsNil() {
452
453
454
455 return Value{dst, nil, flag(Interface)}
456 }
457 x := valueInterface(v)
458 if dst.NumMethod() == 0 {
459 *(*interface{})(target) = x
460 } else {
461 ifaceE2I(dst, x, target)
462 }
463 return Value{dst, target, flagIndir | flag(Interface)}
464 }
465
466
467 panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
468 }
469
470
471
472
473
474
475
476
477 func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer {
478 return add(p, uintptr(i)*eltSize, "i < len")
479 }
480
481 func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
482
483
484
485 func typedmemmove(t *rtype, dst, src unsafe.Pointer)
486
487
488
489
490 func escapes(x interface{}) {
491 if dummy.b {
492 dummy.x = x
493 }
494 }
495
496 var dummy struct {
497 b bool
498 x interface{}
499 }
500
View as plain text