github.com/traefik/yaegi@v0.15.1/internal/unsafe2/unsafe.go (about) 1 // Package unsafe2 provides helpers to generate recursive struct types. 2 package unsafe2 3 4 import ( 5 "reflect" 6 "unsafe" 7 ) 8 9 type dummy struct{} 10 11 // DummyType represents a stand-in for a recursive type. 12 var DummyType = reflect.TypeOf(dummy{}) 13 14 // the following type sizes must match their original definition in Go src/reflect/type.go. 15 16 type rtype struct { 17 _ uintptr 18 _ uintptr 19 _ uint32 20 _ uint32 21 _ uintptr 22 _ uintptr 23 _ uint32 24 _ uint32 25 } 26 27 type emptyInterface struct { 28 typ *rtype 29 _ unsafe.Pointer 30 } 31 32 type structField struct { 33 _ uintptr 34 typ *rtype 35 _ uintptr 36 } 37 38 type structType struct { 39 rtype 40 _ uintptr 41 fields []structField 42 } 43 44 // SetFieldType sets the type of the struct field at the given index, to the given type. 45 // 46 // The struct type must have been created at runtime. This is very unsafe. 47 func SetFieldType(s reflect.Type, idx int, t reflect.Type) { 48 if s.Kind() != reflect.Struct || idx >= s.NumField() { 49 return 50 } 51 52 rtyp := unpackType(s) 53 styp := (*structType)(unsafe.Pointer(rtyp)) 54 f := styp.fields[idx] 55 f.typ = unpackType(t) 56 styp.fields[idx] = f 57 } 58 59 func unpackType(t reflect.Type) *rtype { 60 v := reflect.New(t).Elem().Interface() 61 return (*emptyInterface)(unsafe.Pointer(&v)).typ 62 }