1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package reflect
6
7import (
8	"unsafe"
9)
10
11// The compiler uses a compact encoding to store type information. Unlike the
12// main Go compiler, most of the types are stored directly in the type code.
13//
14// Type code bit allocation:
15// xxxxx0: basic types, where xxxxx is the basic type number (never 0).
16//         The higher bits indicate the named type, if any.
17//  nxxx1: complex types, where n indicates whether this is a named type (named
18//         if set) and xxx contains the type kind number:
19//             0 (0001): Chan
20//             1 (0011): Interface
21//             2 (0101): Ptr
22//             3 (0111): Slice
23//             4 (1001): Array
24//             5 (1011): Func
25//             6 (1101): Map
26//             7 (1111): Struct
27//         The higher bits are either the contents of the type depending on the
28//         type (if n is clear) or indicate the number of the named type (if n
29//         is set).
30
31type Kind uintptr
32
33// Copied from reflect/type.go
34// https://golang.org/src/reflect/type.go?s=8302:8316#L217
35const (
36	Invalid Kind = iota
37	Bool
38	Int
39	Int8
40	Int16
41	Int32
42	Int64
43	Uint
44	Uint8
45	Uint16
46	Uint32
47	Uint64
48	Uintptr
49	Float32
50	Float64
51	Complex64
52	Complex128
53	String
54	UnsafePointer
55	Chan
56	Interface
57	Ptr
58	Slice
59	Array
60	Func
61	Map
62	Struct
63)
64
65func (k Kind) String() string {
66	switch k {
67	case Bool:
68		return "bool"
69	case Int:
70		return "int"
71	case Int8:
72		return "int8"
73	case Int16:
74		return "int16"
75	case Int32:
76		return "int32"
77	case Int64:
78		return "int64"
79	case Uint:
80		return "uint"
81	case Uint8:
82		return "uint8"
83	case Uint16:
84		return "uint16"
85	case Uint32:
86		return "uint32"
87	case Uint64:
88		return "uint64"
89	case Uintptr:
90		return "uintptr"
91	case Float32:
92		return "float32"
93	case Float64:
94		return "float64"
95	case Complex64:
96		return "complex64"
97	case Complex128:
98		return "complex128"
99	case String:
100		return "string"
101	case UnsafePointer:
102		return "unsafe.Pointer"
103	case Chan:
104		return "chan"
105	case Interface:
106		return "interface"
107	case Ptr:
108		return "ptr"
109	case Slice:
110		return "slice"
111	case Array:
112		return "array"
113	case Func:
114		return "func"
115	case Map:
116		return "map"
117	case Struct:
118		return "struct"
119	default:
120		return "invalid"
121	}
122}
123
124// basicType returns a new Type for this kind if Kind is a basic type.
125func (k Kind) basicType() Type {
126	return Type(k << 1)
127}
128
129// The typecode as used in an interface{}.
130type Type uintptr
131
132func TypeOf(i interface{}) Type {
133	return ValueOf(i).typecode
134}
135
136func (t Type) String() string {
137	return "T"
138}
139
140func (t Type) Kind() Kind {
141	if t%2 == 0 {
142		// basic type
143		return Kind((t >> 1) % 32)
144	} else {
145		return Kind(t>>1)%8 + 19
146	}
147}
148
149// Elem returns the element type for channel, slice and array types, the
150// pointed-to value for pointer types, and the key type for map types.
151func (t Type) Elem() Type {
152	switch t.Kind() {
153	case Chan, Ptr, Slice:
154		return t.stripPrefix()
155	case Array:
156		index := t.stripPrefix()
157		elem, _ := readVarint(unsafe.Pointer(uintptr(unsafe.Pointer(&arrayTypesSidetable)) + uintptr(index)))
158		return Type(elem)
159	default: // not implemented: Map
160		panic("unimplemented: (reflect.Type).Elem()")
161	}
162}
163
164// stripPrefix removes the "prefix" (the first 5 bytes of the type code) from
165// the type code. If this is a named type, it will resolve the underlying type
166// (which is the data for this named type). If it is not, the lower bits are
167// simply shifted off.
168//
169// The behavior is only defined for non-basic types.
170func (t Type) stripPrefix() Type {
171	// Look at the 'n' bit in the type code (see the top of this file) to see
172	// whether this is a named type.
173	if (t>>4)%2 != 0 {
174		// This is a named type. The data is stored in a sidetable.
175		namedTypeNum := t >> 5
176		n := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&namedNonBasicTypesSidetable)) + uintptr(namedTypeNum)*unsafe.Sizeof(uintptr(0))))
177		return Type(n)
178	}
179	// Not a named type, so the value is stored directly in the type code.
180	return t >> 5
181}
182
183// Field returns the type of the i'th field of this struct type. It panics if t
184// is not a struct type.
185func (t Type) Field(i int) StructField {
186	if t.Kind() != Struct {
187		panic(&TypeError{"Field"})
188	}
189	structIdentifier := t.stripPrefix()
190
191	numField, p := readVarint(unsafe.Pointer(uintptr(unsafe.Pointer(&structTypesSidetable)) + uintptr(structIdentifier)))
192	if uint(i) >= uint(numField) {
193		panic("reflect: field index out of range")
194	}
195
196	// Iterate over every field in the struct and update the StructField each
197	// time, until the target field has been reached. This is very much not
198	// efficient, but it is easy to implement.
199	// Adding a jump table at the start to jump to the field directly would
200	// make this much faster, but that would also impact code size.
201	field := StructField{}
202	offset := uintptr(0)
203	for fieldNum := 0; fieldNum <= i; fieldNum++ {
204		// Read some flags of this field, like whether the field is an
205		// embedded field.
206		flagsByte := *(*uint8)(p)
207		p = unsafe.Pointer(uintptr(p) + 1)
208
209		// Read the type of this struct field.
210		var fieldType uintptr
211		fieldType, p = readVarint(p)
212		field.Type = Type(fieldType)
213
214		// Move Offset forward to align it to this field's alignment.
215		// Assume alignment is a power of two.
216		offset = align(offset, uintptr(field.Type.Align()))
217		field.Offset = offset
218		offset += field.Type.Size() // starting (unaligned) offset for next field
219
220		// Read the field name.
221		var nameNum uintptr
222		nameNum, p = readVarint(p)
223		field.Name = readStringSidetable(unsafe.Pointer(&structNamesSidetable), nameNum)
224
225		// The first bit in the flagsByte indicates whether this is an embedded
226		// field.
227		field.Anonymous = flagsByte&1 != 0
228
229		// The second bit indicates whether there is a tag.
230		if flagsByte&2 != 0 {
231			// There is a tag.
232			var tagNum uintptr
233			tagNum, p = readVarint(p)
234			field.Tag = StructTag(readStringSidetable(unsafe.Pointer(&structNamesSidetable), tagNum))
235		} else {
236			// There is no tag.
237			field.Tag = ""
238		}
239
240		// The third bit indicates whether this field is exported.
241		if flagsByte&4 != 0 {
242			// This field is exported.
243			field.PkgPath = ""
244		} else {
245			// This field is unexported.
246			// TODO: list the real package path here. Storing it should not
247			// significantly impact binary size as there is only a limited
248			// number of packages in any program.
249			field.PkgPath = "<unimplemented>"
250		}
251	}
252
253	return field
254}
255
256// Bits returns the number of bits that this type uses. It is only valid for
257// arithmetic types (integers, floats, and complex numbers). For other types, it
258// will panic.
259func (t Type) Bits() int {
260	kind := t.Kind()
261	if kind >= Int && kind <= Complex128 {
262		return int(t.Size()) * 8
263	}
264	panic(TypeError{"Bits"})
265}
266
267// Len returns the number of elements in this array. It panics of the type kind
268// is not Array.
269func (t Type) Len() int {
270	if t.Kind() != Array {
271		panic(TypeError{"Len"})
272	}
273
274	// skip past the element type
275	arrayIdentifier := t.stripPrefix()
276	_, p := readVarint(unsafe.Pointer(uintptr(unsafe.Pointer(&arrayTypesSidetable)) + uintptr(arrayIdentifier)))
277
278	// Read the array length.
279	arrayLen, _ := readVarint(p)
280	return int(arrayLen)
281}
282
283// NumField returns the number of fields of a struct type. It panics for other
284// type kinds.
285func (t Type) NumField() int {
286	if t.Kind() != Struct {
287		panic(&TypeError{"NumField"})
288	}
289	structIdentifier := t.stripPrefix()
290	n, _ := readVarint(unsafe.Pointer(uintptr(unsafe.Pointer(&structTypesSidetable)) + uintptr(structIdentifier)))
291	return int(n)
292}
293
294// Size returns the size in bytes of a given type. It is similar to
295// unsafe.Sizeof.
296func (t Type) Size() uintptr {
297	switch t.Kind() {
298	case Bool, Int8, Uint8:
299		return 1
300	case Int16, Uint16:
301		return 2
302	case Int32, Uint32:
303		return 4
304	case Int64, Uint64:
305		return 8
306	case Int, Uint:
307		return unsafe.Sizeof(int(0))
308	case Uintptr:
309		return unsafe.Sizeof(uintptr(0))
310	case Float32:
311		return 4
312	case Float64:
313		return 8
314	case Complex64:
315		return 8
316	case Complex128:
317		return 16
318	case String:
319		return unsafe.Sizeof(StringHeader{})
320	case UnsafePointer, Chan, Map, Ptr:
321		return unsafe.Sizeof(uintptr(0))
322	case Slice:
323		return unsafe.Sizeof(SliceHeader{})
324	case Interface:
325		return unsafe.Sizeof(interface{}(nil))
326	case Array:
327		return t.Elem().Size() * uintptr(t.Len())
328	case Struct:
329		numField := t.NumField()
330		if numField == 0 {
331			return 0
332		}
333		lastField := t.Field(numField - 1)
334		return lastField.Offset + lastField.Type.Size()
335	default:
336		panic("unimplemented: size of type")
337	}
338}
339
340// Align returns the alignment of this type. It is similar to calling
341// unsafe.Alignof.
342func (t Type) Align() int {
343	switch t.Kind() {
344	case Bool, Int8, Uint8:
345		return int(unsafe.Alignof(int8(0)))
346	case Int16, Uint16:
347		return int(unsafe.Alignof(int16(0)))
348	case Int32, Uint32:
349		return int(unsafe.Alignof(int32(0)))
350	case Int64, Uint64:
351		return int(unsafe.Alignof(int64(0)))
352	case Int, Uint:
353		return int(unsafe.Alignof(int(0)))
354	case Uintptr:
355		return int(unsafe.Alignof(uintptr(0)))
356	case Float32:
357		return int(unsafe.Alignof(float32(0)))
358	case Float64:
359		return int(unsafe.Alignof(float64(0)))
360	case Complex64:
361		return int(unsafe.Alignof(complex64(0)))
362	case Complex128:
363		return int(unsafe.Alignof(complex128(0)))
364	case String:
365		return int(unsafe.Alignof(StringHeader{}))
366	case UnsafePointer, Chan, Map, Ptr:
367		return int(unsafe.Alignof(uintptr(0)))
368	case Slice:
369		return int(unsafe.Alignof(SliceHeader{}))
370	case Interface:
371		return int(unsafe.Alignof(interface{}(nil)))
372	case Struct:
373		numField := t.NumField()
374		alignment := 1
375		for i := 0; i < numField; i++ {
376			fieldAlignment := t.Field(i).Type.Align()
377			if fieldAlignment > alignment {
378				alignment = fieldAlignment
379			}
380		}
381		return alignment
382	case Array:
383		return t.Elem().Align()
384	default:
385		panic("unimplemented: alignment of type")
386	}
387}
388
389// FieldAlign returns the alignment if this type is used in a struct field. It
390// is currently an alias for Align() but this might change in the future.
391func (t Type) FieldAlign() int {
392	return t.Align()
393}
394
395// AssignableTo returns whether a value of type u can be assigned to a variable
396// of type t.
397func (t Type) AssignableTo(u Type) bool {
398	if t == u {
399		return true
400	}
401	if t.Kind() == Interface {
402		panic("reflect: unimplemented: assigning to interface of different type")
403	}
404	return false
405}
406
407func (t Type) Implements(u Type) bool {
408	if t.Kind() != Interface {
409		panic("reflect: non-interface type passed to Type.Implements")
410	}
411	return u.AssignableTo(t)
412}
413
414// Comparable returns whether values of this type can be compared to each other.
415func (t Type) Comparable() bool {
416	switch t.Kind() {
417	case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
418		return true
419	case Float32, Float64, Complex64, Complex128:
420		return true
421	case String:
422		return true
423	case UnsafePointer:
424		return true
425	case Chan:
426		return true
427	case Interface:
428		return true
429	case Ptr:
430		return true
431	case Slice:
432		return false
433	case Array:
434		return t.Elem().Comparable()
435	case Func:
436		return false
437	case Map:
438		return false
439	case Struct:
440		numField := t.NumField()
441		for i := 0; i < numField; i++ {
442			if !t.Field(i).Type.Comparable() {
443				return false
444			}
445		}
446		return true
447	default:
448		panic(TypeError{"Comparable"})
449	}
450}
451
452func (t Type) ConvertibleTo(u Type) bool {
453	panic("unimplemented: (reflect.Type).ConvertibleTo()")
454}
455
456func (t Type) NumMethod() int {
457	panic("unimplemented: (reflect.Type).NumMethod()")
458}
459
460func (t Type) Name() string {
461	panic("unimplemented: (reflect.Type).Name()")
462}
463
464func (t Type) Key() Type {
465	panic("unimplemented: (reflect.Type).Key()")
466}
467
468// A StructField describes a single field in a struct.
469type StructField struct {
470	// Name indicates the field name.
471	Name string
472
473	// PkgPath is the package path where the struct containing this field is
474	// declared for unexported fields, or the empty string for exported fields.
475	PkgPath string
476
477	Type      Type
478	Tag       StructTag // field tag string
479	Anonymous bool
480	Offset    uintptr
481}
482
483// A StructTag is the tag string in a struct field.
484type StructTag string
485
486// TODO: it would be feasible to do the key/value splitting at compile time,
487// avoiding the code size cost of doing it at runtime
488
489// Get returns the value associated with key in the tag string.
490func (tag StructTag) Get(key string) string {
491	v, _ := tag.Lookup(key)
492	return v
493}
494
495// Lookup returns the value associated with key in the tag string.
496func (tag StructTag) Lookup(key string) (value string, ok bool) {
497	for tag != "" {
498		// Skip leading space.
499		i := 0
500		for i < len(tag) && tag[i] == ' ' {
501			i++
502		}
503		tag = tag[i:]
504		if tag == "" {
505			break
506		}
507
508		// Scan to colon. A space, a quote or a control character is a syntax error.
509		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
510		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
511		// as it is simpler to inspect the tag's bytes than the tag's runes.
512		i = 0
513		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
514			i++
515		}
516		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
517			break
518		}
519		name := string(tag[:i])
520		tag = tag[i+1:]
521
522		// Scan quoted string to find value.
523		i = 1
524		for i < len(tag) && tag[i] != '"' {
525			if tag[i] == '\\' {
526				i++
527			}
528			i++
529		}
530		if i >= len(tag) {
531			break
532		}
533		qvalue := string(tag[:i+1])
534		tag = tag[i+1:]
535
536		if key == name {
537			value, err := unquote(qvalue)
538			if err != nil {
539				break
540			}
541			return value, true
542		}
543	}
544	return "", false
545}
546
547// TypeError is the error that is used in a panic when invoking a method on a
548// type that is not applicable to that type.
549type TypeError struct {
550	Method string
551}
552
553func (e *TypeError) Error() string {
554	return "reflect: call of reflect.Type." + e.Method + " on invalid type"
555}
556
557func align(offset uintptr, alignment uintptr) uintptr {
558	return (offset + alignment - 1) &^ (alignment - 1)
559}
560