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