github.com/goplus/reflectx@v1.2.2/reflectx.go (about) 1 /* 2 Copyright 2020 The GoPlus Authors (goplus.org) 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package reflectx 18 19 import ( 20 "path" 21 "reflect" 22 "strconv" 23 "unicode" 24 "unicode/utf8" 25 "unsafe" 26 ) 27 28 func Field(s reflect.Value, i int) reflect.Value { 29 v := s.Field(i) 30 canSet(&v) 31 return v 32 } 33 34 func FieldByIndex(s reflect.Value, index []int) reflect.Value { 35 v := s.FieldByIndex(index) 36 canSet(&v) 37 return v 38 } 39 40 func FieldByName(s reflect.Value, name string) reflect.Value { 41 v := s.FieldByName(name) 42 canSet(&v) 43 return v 44 } 45 46 func FieldByNameFunc(s reflect.Value, match func(name string) bool) reflect.Value { 47 v := s.FieldByNameFunc(match) 48 canSet(&v) 49 return v 50 } 51 52 func canSet(v *reflect.Value) { 53 (*Value)(unsafe.Pointer(v)).flag &= ^flagRO 54 } 55 56 func CanSet(v reflect.Value) reflect.Value { 57 if !v.CanSet() { 58 (*Value)(unsafe.Pointer(&v)).flag &= ^flagRO 59 } 60 return v 61 } 62 63 func typeName(typ reflect.Type) string { 64 for typ.Kind() == reflect.Ptr { 65 typ = typ.Elem() 66 } 67 return typ.Name() 68 } 69 70 func NamedStructOf(pkgpath string, name string, fields []reflect.StructField) reflect.Type { 71 return Default.NamedStructOf(pkgpath, name, fields) 72 } 73 74 func (ctx *Context) NamedStructOf(pkgpath string, name string, fields []reflect.StructField) reflect.Type { 75 return NamedTypeOf(pkgpath, name, ctx.StructOf(fields)) 76 } 77 78 func SetTypeName(typ reflect.Type, pkgpath string, name string) { 79 setTypeName(totype(typ), pkgpath, name) 80 } 81 82 func setTypeName(t *rtype, pkgpath string, name string) { 83 if pkgpath == "" && name == "" { 84 return 85 } 86 exported := isExported(name) 87 if pkgpath != "" { 88 _, f := path.Split(pkgpath) 89 name = f + "." + name 90 } 91 t.tflag |= tflagNamed | tflagExtraStar 92 t.str = resolveReflectName(newName("*"+name, "", exported)) 93 if t.tflag&tflagUncommon == tflagUncommon { 94 toUncommonType(t).pkgPath = resolveReflectName(newName(pkgpath, "", false)) 95 } 96 switch t.Kind() { 97 case reflect.Struct: 98 st := (*structType)(toKindType(t)) 99 st.pkgPath = newName(pkgpath, "", false) 100 case reflect.Interface: 101 st := (*interfaceType)(toKindType(t)) 102 st.pkgPath = newName(pkgpath, "", false) 103 } 104 } 105 106 func copyType(dst *rtype, src *rtype) { 107 dst.size = src.size 108 dst.kind = src.kind 109 dst.equal = src.equal 110 dst.align = src.align 111 dst.fieldAlign = src.fieldAlign 112 dst.tflag = src.tflag 113 dst.gcdata = src.gcdata 114 dst.ptrdata = src.ptrdata 115 } 116 117 func isExported(name string) bool { 118 ch, _ := utf8.DecodeRuneInString(name) 119 return unicode.IsUpper(ch) 120 } 121 122 func checkFields(t1, t2 reflect.Type) bool { 123 n1 := t1.NumField() 124 n2 := t2.NumField() 125 if n1 != n2 { 126 return false 127 } 128 for i := 0; i < n1; i++ { 129 f1 := t1.Field(i) 130 f2 := t2.Field(i) 131 if f1.Name != f2.Name || 132 f1.PkgPath != f2.PkgPath || 133 f1.Anonymous != f2.Anonymous || 134 f1.Type != f2.Type || 135 f1.Offset != f2.Offset { 136 return false 137 } 138 } 139 return true 140 } 141 142 func StructOf(fields []reflect.StructField) reflect.Type { 143 return Default.StructOf(fields) 144 } 145 146 func (ctx *Context) StructOf(fields []reflect.StructField) reflect.Type { 147 var anonymous []int 148 underscore := make(map[int]name) 149 var underscoreCount int 150 fs := make([]reflect.StructField, len(fields)) 151 for i := 0; i < len(fields); i++ { 152 f := fields[i] 153 if f.Anonymous { 154 anonymous = append(anonymous, i) 155 f.Anonymous = false 156 if f.Name == "" { 157 f.Name = typeName(f.Type) 158 } 159 } else if f.Name == "_" { 160 if underscoreCount > 0 { 161 underscore[i] = newName("_", string(f.Tag), false) 162 f.Name = "_gop_underscore_" + strconv.Itoa(i) 163 } 164 underscoreCount++ 165 } 166 fs[i] = f 167 } 168 typ := reflect.StructOf(fs) 169 rt := totype(typ) 170 st := toStructType(rt) 171 for _, i := range anonymous { 172 setEmbedded(&st.fields[i]) 173 } 174 for i, n := range underscore { 175 st.fields[i].name = n 176 } 177 str := typ.String() 178 if ts, ok := ctx.structLookupCache[str]; ok { 179 for _, t := range ts { 180 if haveIdenticalType(t, typ, true) { 181 return t 182 } 183 } 184 ts = append(ts, typ) 185 } else { 186 ctx.structLookupCache[str] = []reflect.Type{typ} 187 } 188 // fix equal for blank fields and uncomparable type 189 if rt.equal != nil && underscoreCount > 0 { 190 rt.equal = func(p, q unsafe.Pointer) bool { 191 for i, ft := range st.fields { 192 if fields[i].Name == "_" { 193 continue 194 } 195 pi := add(p, ft.offset(), "&x.field safe") 196 qi := add(q, ft.offset(), "&x.field safe") 197 if !ft.typ.equal(pi, qi) { 198 return false 199 } 200 } 201 return true 202 } 203 } 204 205 if rt.tflag == 0 && isRegularMemory(typ) { 206 rt.tflag |= tflagRegularMemory 207 } 208 return typ 209 } 210 211 // fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function. 212 func fnv1(x uint32, list string) uint32 { 213 for _, b := range list { 214 x = x*16777619 ^ uint32(b) 215 } 216 return x 217 } 218 219 func SetValue(v reflect.Value, x reflect.Value) { 220 switch v.Kind() { 221 case reflect.Bool: 222 v.SetBool(x.Bool()) 223 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 224 v.SetInt(x.Int()) 225 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 226 v.SetUint(x.Uint()) 227 case reflect.Uintptr: 228 v.SetUint(x.Uint()) 229 case reflect.Float32, reflect.Float64: 230 v.SetFloat(x.Float()) 231 case reflect.Complex64, reflect.Complex128: 232 v.SetComplex(x.Complex()) 233 case reflect.String: 234 v.SetString(x.String()) 235 case reflect.UnsafePointer: 236 v.SetPointer(unsafe.Pointer(x.Pointer())) 237 default: 238 v.Set(x) 239 } 240 } 241 242 var ( 243 tyEmptyInterface = reflect.TypeOf((*interface{})(nil)).Elem() 244 tyEmptyInterfacePtr = reflect.TypeOf((*interface{})(nil)) 245 tyEmptyStruct = reflect.TypeOf((*struct{})(nil)).Elem() 246 tyErrorInterface = reflect.TypeOf((*error)(nil)).Elem() 247 ) 248 249 func SetElem(typ reflect.Type, elem reflect.Type) { 250 rt := totype(typ) 251 switch typ.Kind() { 252 case reflect.Ptr: 253 st := (*ptrType)(toKindType(rt)) 254 st.elem = totype(elem) 255 case reflect.Slice: 256 st := (*sliceType)(toKindType(rt)) 257 st.elem = totype(elem) 258 case reflect.Array: 259 st := (*arrayType)(toKindType(rt)) 260 st.elem = totype(elem) 261 case reflect.Map: 262 st := (*mapType)(toKindType(rt)) 263 st.elem = totype(elem) 264 case reflect.Chan: 265 st := (*chanType)(toKindType(rt)) 266 st.elem = totype(elem) 267 default: 268 panic("reflect: Elem of invalid type " + typ.String()) 269 } 270 } 271 272 func typeId(typ reflect.Type) string { 273 var id string 274 if path := typ.PkgPath(); path != "" { 275 id = path + "." 276 } 277 return id + typ.Name() 278 } 279 280 type replaceTypeContext struct { 281 checking map[reflect.Type]bool 282 } 283 284 func ReplaceType(pkg string, typ reflect.Type, m map[string]reflect.Type) (rtyp reflect.Type, changed bool) { 285 ctx := &replaceTypeContext{make(map[reflect.Type]bool)} 286 return ctx.replace(pkg, typ, m) 287 } 288 289 func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[string]reflect.Type) (rtyp reflect.Type, changed bool) { 290 if ctx.checking[typ] { 291 return 292 } 293 ctx.checking[typ] = true 294 rt := totype(typ) 295 switch typ.Kind() { 296 case reflect.Struct: 297 if typ.PkgPath() != pkg { 298 return 299 } 300 st := (*structType)(toKindType(rt)) 301 for i := 0; i < len(st.fields); i++ { 302 et := toType(st.fields[i].typ) 303 if t, ok := m[typeId(et)]; ok { 304 st.fields[i].typ = totype(t) 305 changed = true 306 } else { 307 if rtyp, ok := ctx.replace(pkg, et, m); ok { 308 changed = true 309 st.fields[i].typ = totype(rtyp) 310 } 311 } 312 } 313 if changed { 314 return toType(rt), true 315 } 316 case reflect.Ptr: 317 st := (*ptrType)(toKindType(rt)) 318 et := toType(st.elem) 319 if t, ok := m[typeId(et)]; ok { 320 st.elem = totype(t) 321 return reflect.PtrTo(t), true 322 } else { 323 if rtyp, ok := ctx.replace(pkg, et, m); ok { 324 return reflect.PtrTo(rtyp), true 325 } 326 } 327 case reflect.Slice: 328 st := (*sliceType)(toKindType(rt)) 329 et := toType(st.elem) 330 if t, ok := m[typeId(et)]; ok { 331 st.elem = totype(t) 332 return reflect.SliceOf(t), true 333 } else { 334 if rtyp, ok := ctx.replace(pkg, et, m); ok { 335 return reflect.SliceOf(rtyp), true 336 } 337 } 338 case reflect.Array: 339 st := (*arrayType)(toKindType(rt)) 340 et := toType(st.elem) 341 if t, ok := m[typeId(et)]; ok { 342 st.elem = totype(t) 343 return reflect.ArrayOf(int(st.len), t), true 344 } else { 345 if rtyp, ok := ctx.replace(pkg, et, m); ok { 346 return reflect.ArrayOf(int(st.len), rtyp), true 347 } 348 } 349 case reflect.Map: 350 st := (*mapType)(toKindType(rt)) 351 kt := toType(st.key) 352 et := toType(st.elem) 353 if t, ok := m[typeId(kt)]; ok { 354 kt = t 355 changed = true 356 } else { 357 if rtyp, ok := ctx.replace(pkg, kt, m); ok { 358 kt = rtyp 359 changed = true 360 } 361 } 362 if t, ok := m[typeId(et)]; ok { 363 et = t 364 changed = true 365 } else { 366 if rtyp, ok := ctx.replace(pkg, et, m); ok { 367 et = rtyp 368 changed = true 369 } 370 } 371 if changed { 372 return reflect.MapOf(kt, et), true 373 } 374 case reflect.Chan: 375 st := (*chanType)(toKindType(rt)) 376 et := toType(st.elem) 377 if t, ok := m[typeId(et)]; ok { 378 st.elem = totype(t) 379 return reflect.ChanOf(typ.ChanDir(), t), true 380 } else { 381 if rtyp, ok := ctx.replace(pkg, et, m); ok { 382 return reflect.ChanOf(typ.ChanDir(), rtyp), true 383 } 384 } 385 case reflect.Func: 386 st := (*funcType)(toKindType(rt)) 387 in := st.in() 388 out := st.out() 389 for i := 0; i < len(in); i++ { 390 et := toType(in[i]) 391 if t, ok := m[typeId(et)]; ok { 392 in[i] = totype(t) 393 changed = true 394 } else { 395 if rtyp, ok := ctx.replace(pkg, et, m); ok { 396 in[i] = totype(rtyp) 397 changed = true 398 } 399 } 400 } 401 for i := 0; i < len(out); i++ { 402 et := toType(out[i]) 403 if t, ok := m[typeId(et)]; ok { 404 out[i] = totype(t) 405 changed = true 406 } else { 407 if rtyp, ok := ctx.replace(pkg, et, m); ok { 408 out[i] = totype(rtyp) 409 changed = true 410 } 411 } 412 } 413 if changed { 414 ins := make([]reflect.Type, len(in)) 415 for i := 0; i < len(in); i++ { 416 ins[i] = toType(in[i]) 417 } 418 outs := make([]reflect.Type, len(out)) 419 for i := 0; i < len(out); i++ { 420 outs[i] = toType(out[i]) 421 } 422 return reflect.FuncOf(ins, outs, typ.IsVariadic()), true 423 } 424 case reflect.Interface: 425 if typ.PkgPath() != pkg { 426 return 427 } 428 if typ == tyErrorInterface { 429 return 430 } 431 st := (*interfaceType)(toKindType(rt)) 432 for i := 0; i < len(st.methods); i++ { 433 tt := typ.Method(i).Type 434 if t, ok := m[typeId(tt)]; ok { 435 st.methods[i].typ = resolveReflectType(totype(t)) 436 changed = true 437 } else if rtyp, ok := ctx.replace(pkg, tt, m); ok { 438 st.methods[i].typ = resolveReflectType(totype(rtyp)) 439 changed = true 440 } 441 } 442 if changed { 443 return toType(rt), true 444 } 445 } 446 return nil, false 447 }