github.com/avicd/go-utilx@v0.1.0/goid/reflect.go (about) 1 package goid 2 3 import ( 4 "reflect" 5 "unsafe" 6 ) 7 8 // iface The interface struct. 9 type iface struct { 10 tab unsafe.Pointer 11 data unsafe.Pointer 12 } 13 14 // typelinks returns a slice of the sections in each module, and a slice of *rtype offsets in each module. The types in each module are sorted by string. 15 // 16 //go:linkname typelinks reflect.typelinks 17 func typelinks() (sections []unsafe.Pointer, offset [][]int32) 18 19 // resolveTypeOff resolves an *rtype offset from a base type. 20 // 21 //go:linkname resolveTypeOff reflect.resolveTypeOff 22 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer 23 24 // typeByString returns the type whose 'String' property equals to the given string, or nil if not found. 25 func typeByString(str string) reflect.Type { 26 // The s is search target 27 s := str 28 if len(str) == 0 || str[0] != '*' { 29 s = "*" + s 30 } 31 // The typ is a struct iface{tab(ptr->reflect.Type), dsx(ptr->rtype)} 32 typ := reflect.TypeOf(0) 33 face := (*iface)(unsafe.Pointer(&typ)) 34 // Find the specified target through binary search algorithm 35 sections, offset := typelinks() 36 for offsI, offs := range offset { 37 section := sections[offsI] 38 // We are looking for the first index i where the string becomes >= s. 39 // This is a copy of sort.Search, with f(h) replaced by (*typ[h].String() >= s). 40 i, j := 0, len(offs) 41 for i < j { 42 h := i + (j-i)/2 // avoid overflow when computing h 43 // i ≤ h < j 44 face.data = resolveTypeOff(section, offs[h]) 45 if !(typ.String() >= s) { 46 i = h + 1 // preserves f(i-1) == false 47 } else { 48 j = h // preserves f(j) == true 49 } 50 } 51 // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i. 52 // Having found the first, linear scan forward to find the last. 53 // We could do a second binary search, but the caller is going 54 // to do a linear scan anyway. 55 if i < len(offs) { 56 face.data = resolveTypeOff(section, offs[i]) 57 if typ.Kind() == reflect.Ptr { 58 if typ.String() == str { 59 return typ 60 } 61 elem := typ.Elem() 62 if elem.String() == str { 63 return elem 64 } 65 } 66 } 67 } 68 return nil 69 }