github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/server/reflection.go (about) 1 package server 2 3 import ( 4 "context" 5 "github.com/nyan233/littlerpc/core/common/errorhandler" 6 "github.com/nyan233/littlerpc/core/common/metadata" 7 "github.com/nyan233/littlerpc/core/middle/codec" 8 "github.com/nyan233/littlerpc/core/middle/packer" 9 "reflect" 10 _ "unsafe" 11 ) 12 13 var ( 14 //go:linkname codecViewer github.com/nyan233/littlerpc/core/middle/codec.codecCollection 15 codecViewer map[string]codec.Codec 16 //go:linkname packerViewer github.com/nyan233/littlerpc/core/middle/packer.packerCollection 17 packerViewer map[string]packer.Packer 18 ) 19 20 type MethodTable struct { 21 SourceName string 22 Table []string 23 } 24 25 // ArgumentType 参数类型 == map[string]interface{}表示struct,interface{}里的参数也同理 == string时表示其它类型 26 type ArgumentType struct { 27 Kind string `json:"kind"` 28 Type interface{} `json:"type"` 29 } 30 31 // LittleRpcReflection 反射服务 32 type LittleRpcReflection struct { 33 rpcServer *Server 34 } 35 36 func (l *LittleRpcReflection) MethodTable(ctx context.Context, sourceName string) (*MethodTable, error) { 37 source, ok := l.rpcServer.sources.LoadOk(sourceName) 38 if !ok { 39 return nil, errorhandler.ServiceNotfound 40 } 41 mt := &MethodTable{ 42 SourceName: sourceName, 43 Table: nil, 44 } 45 for methodName := range source.ProcessSet { 46 mt.Table = append(mt.Table, methodName) 47 } 48 return mt, nil 49 } 50 51 func (l *LittleRpcReflection) AllInstance(ctx context.Context) (map[string]string, error) { 52 mp := make(map[string]string, 4) 53 l.rpcServer.sources.Range(func(key string, value *metadata.Source) bool { 54 mp[key] = value.InstanceType.Name() 55 return true 56 }) 57 return mp, nil 58 } 59 60 func (l *LittleRpcReflection) AllCodec(ctx context.Context) ([]string, error) { 61 codecSchemeSet := make([]string, 0, len(codecViewer)) 62 for k := range codecViewer { 63 codecSchemeSet = append(codecSchemeSet, k) 64 } 65 return codecSchemeSet, nil 66 } 67 68 func (l *LittleRpcReflection) AllPacker(ctx context.Context) ([]string, error) { 69 packerSchemeSet := make([]string, 0, len(packerViewer)) 70 for k := range packerViewer { 71 packerSchemeSet = append(packerSchemeSet, k) 72 } 73 return packerSchemeSet, nil 74 } 75 76 func (l *LittleRpcReflection) MethodArgumentType(ctx context.Context, serviceName string) ([]ArgumentType, error) { 77 service, ok := l.rpcServer.services.LoadOk(serviceName) 78 if !ok { 79 return nil, errorhandler.ServiceNotfound 80 } 81 argDesc := make([]ArgumentType, 0, 4) 82 typ := service.Value.Type() 83 for i := 0; i < typ.NumIn(); i++ { 84 in := typ.In(i) 85 argDesc = append(argDesc, getArgumentType(in)) 86 } 87 return argDesc, nil 88 } 89 90 func getArgumentType(typ reflect.Type) ArgumentType { 91 switch typ.Kind() { 92 case reflect.Struct: 93 fieldMap := make(map[string]interface{}, typ.NumField()) 94 for i := 0; i < typ.NumField(); i++ { 95 field := typ.Field(i) 96 fieldMap[field.Name] = getArgumentType(field.Type) 97 } 98 return ArgumentType{ 99 Kind: "struct", 100 Type: fieldMap, 101 } 102 case reflect.Interface: 103 return ArgumentType{ 104 Kind: "interface", 105 Type: typ.PkgPath() + "." + typ.Name(), 106 } 107 case reflect.Slice: 108 return ArgumentType{ 109 Kind: "array", 110 Type: getTypeName(typ), 111 } 112 case reflect.Map: 113 return ArgumentType{ 114 Kind: "map", 115 Type: struct { 116 Key string 117 Value string 118 }{ 119 Key: getTypeName(typ.Key()), 120 Value: getTypeName(typ.Elem()), 121 }, 122 } 123 case reflect.String: 124 return ArgumentType{ 125 Kind: "string", 126 Type: typ.Name(), 127 } 128 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int, 129 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 130 return ArgumentType{ 131 Kind: "integer", 132 Type: typ.Name(), 133 } 134 case reflect.Pointer: 135 return getArgumentType(typ.Elem()) 136 default: 137 return ArgumentType{ 138 Kind: "unknown", 139 Type: nil, 140 } 141 } 142 } 143 144 func getTypeName(typ reflect.Type) string { 145 switch typ.Kind() { 146 case reflect.Slice: 147 return "[]" + getTypeName(typ.Elem()) 148 case reflect.Pointer: 149 return "*" + getTypeName(typ.Elem()) 150 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int, 151 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 152 return "integer" 153 case reflect.Interface: 154 return typ.PkgPath() + "." + typ.Name() 155 case reflect.Map: 156 return "Map[" + getTypeName(typ.Key()) + "," + getTypeName(typ.Elem()) + "]" 157 default: 158 return typ.Name() 159 } 160 }