ing
This commit is contained in:
parent
392dd3823b
commit
bb77dd1b59
10
registry.go
10
registry.go
|
@ -77,19 +77,21 @@ func (rr *rpcRegistry) Invoke(codec protocol.RegistryCodec) (result interface{},
|
||||||
// Decode the args.
|
// Decode the args.
|
||||||
|
|
||||||
var in []reflect.Value
|
var in []reflect.Value
|
||||||
paramValues, paramInstances := methodSpec.getParams()
|
paramValues := methodSpec.paramValues
|
||||||
|
|
||||||
if nil != paramValues {
|
if nil != paramValues {
|
||||||
in = make([]reflect.Value, len(paramValues)+1)
|
params := methodSpec.getInterfaces()
|
||||||
if errRead := codec.ReadParams(paramInstances); errRead != nil {
|
if errRead := codec.ReadParams(params); errRead != nil {
|
||||||
return nil, errRead
|
return nil, errRead
|
||||||
}
|
}
|
||||||
|
in = make([]reflect.Value, len(paramValues)+1)
|
||||||
for indexI := 0; indexI < len(paramValues); indexI++ {
|
for indexI := 0; indexI < len(paramValues); indexI++ {
|
||||||
in[indexI+1] = paramValues[indexI]
|
in[indexI+1] = paramValues[indexI]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
in = make([]reflect.Value, 1)
|
in = make([]reflect.Value, 1)
|
||||||
}
|
}
|
||||||
in[0] = serviceSpec.rcvr
|
in[0] = serviceSpec.rcvrV
|
||||||
|
|
||||||
// Call the service method.
|
// Call the service method.
|
||||||
returnValues := methodSpec.method.Func.Call(in)
|
returnValues := methodSpec.method.Func.Call(in)
|
||||||
|
|
|
@ -20,29 +20,29 @@ var (
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
name string // name of service
|
name string // name of service
|
||||||
rcvr reflect.Value // receiver of methods for the service
|
rcvrV reflect.Value // receiver of methods for the service
|
||||||
rcvrType reflect.Type // type of the receiver
|
rcvrT reflect.Type // type of the receiver
|
||||||
methods map[string]*serviceMethod // registered methods
|
methods map[string]*serviceMethod // registered methods
|
||||||
}
|
}
|
||||||
|
|
||||||
type serviceMethod struct {
|
type serviceMethod struct {
|
||||||
method reflect.Method // receiver method
|
method reflect.Method // receiver method
|
||||||
paramTypes []reflect.Type // type of the request argument
|
paramTypes []reflect.Type // type of the request argument
|
||||||
|
paramValues []reflect.Value
|
||||||
returnType reflect.Type // type of the response argument
|
returnType reflect.Type // type of the response argument
|
||||||
|
returnValue reflect.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *serviceMethod) getParams() (values []reflect.Value, instances []interface{}) {
|
func (sm *serviceMethod) getInterfaces() (instances []interface{}) {
|
||||||
if nil == sm.paramTypes || 0 == len(sm.paramTypes) {
|
if nil == sm.paramValues || 0 == len(sm.paramValues) {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pCount := len(sm.paramTypes)
|
pCount := len(sm.paramValues)
|
||||||
values = make([]reflect.Value, pCount)
|
|
||||||
instances = make([]interface{}, pCount)
|
instances = make([]interface{}, pCount)
|
||||||
|
|
||||||
for indexI := 0; indexI < pCount; indexI++ {
|
for indexI := 0; indexI < pCount; indexI++ {
|
||||||
values[indexI] = reflect.New(sm.paramTypes[indexI])
|
instances[indexI] = sm.paramValues[indexI].Interface()
|
||||||
instances[indexI] = values[indexI].Interface()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -63,68 +63,76 @@ func (m *serviceMap) register(rcvr interface{}, name string) error {
|
||||||
// Setup service.
|
// Setup service.
|
||||||
s := &service{
|
s := &service{
|
||||||
name: name,
|
name: name,
|
||||||
rcvr: reflect.ValueOf(rcvr),
|
rcvrV: reflect.ValueOf(rcvr),
|
||||||
rcvrType: reflect.TypeOf(rcvr),
|
rcvrT: reflect.TypeOf(rcvr),
|
||||||
methods: make(map[string]*serviceMethod),
|
methods: make(map[string]*serviceMethod),
|
||||||
}
|
}
|
||||||
if name == "" {
|
if name == "" {
|
||||||
s.name = reflect.Indirect(s.rcvr).Type().Name()
|
s.name = reflect.Indirect(s.rcvrV).Type().Name()
|
||||||
if !isExported(s.name) {
|
if !isExported(s.name) {
|
||||||
return fmt.Errorf("rpc: type %q is not exported", s.name)
|
return fmt.Errorf("rpc: type %q is not exported", s.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.name == "" {
|
if s.name == "" {
|
||||||
return fmt.Errorf("rpc: no service name for type %q",
|
return fmt.Errorf("rpc: no service name for type %q",
|
||||||
s.rcvrType.String())
|
s.rcvrT.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
// Setup methods.
|
// Setup methods.
|
||||||
Loop:
|
Loop:
|
||||||
for i := 0; i < s.rcvrType.NumMethod(); i++ {
|
for i := 0; i < s.rcvrT.NumMethod(); i++ {
|
||||||
method := s.rcvrType.Method(i)
|
m := s.rcvrT.Method(i)
|
||||||
mtype := method.Type
|
mt := m.Type
|
||||||
// Method must be exported.
|
// Method must be exported.
|
||||||
if method.PkgPath != "" {
|
if m.PkgPath != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var paramTypes []reflect.Type
|
var paramTypes []reflect.Type
|
||||||
|
var paramValues []reflect.Value
|
||||||
mCount := mtype.NumIn()
|
|
||||||
if 0 < mCount {
|
|
||||||
paramTypes = make([]reflect.Type, mCount)
|
|
||||||
for indexI := 1; indexI < mCount; indexI++ {
|
|
||||||
param := mtype.In(indexI)
|
|
||||||
if !isExportedOrBuiltin(param) {
|
|
||||||
continue Loop
|
|
||||||
}
|
|
||||||
paramTypes[indexI] = param.Elem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var returnType reflect.Type
|
var returnType reflect.Type
|
||||||
switch mtype.NumOut() {
|
var returnValue reflect.Value
|
||||||
|
|
||||||
|
pCount := mt.NumIn() - 1
|
||||||
|
|
||||||
|
if 0 < pCount {
|
||||||
|
paramTypes = make([]reflect.Type, pCount)
|
||||||
|
paramValues = make([]reflect.Value, pCount)
|
||||||
|
|
||||||
|
for indexI := 0; indexI < pCount; indexI++ {
|
||||||
|
if paramTypes[indexI], paramValues[indexI], err = validateType(mt.In(indexI + 1)); nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch mt.NumOut() {
|
||||||
case 1:
|
case 1:
|
||||||
if returnType := mtype.Out(0); returnType != typeOfError {
|
if t := mt.Out(0); t != typeOfError {
|
||||||
continue Loop
|
continue Loop
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
if returnType := mtype.Out(0); !isExportedOrBuiltin(returnType) {
|
if t := mt.Out(0); !isExportedOrBuiltin(t) {
|
||||||
continue Loop
|
continue Loop
|
||||||
}
|
}
|
||||||
|
|
||||||
if returnType := mtype.Out(1); returnType != typeOfError {
|
if t := mt.Out(1); t != typeOfError {
|
||||||
continue Loop
|
continue Loop
|
||||||
}
|
}
|
||||||
returnType = mtype.Out(0).Elem()
|
if returnType, returnValue, err = validateType(mt.Out(0)); nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s.methods[method.Name] = &serviceMethod{
|
s.methods[m.Name] = &serviceMethod{
|
||||||
method: method,
|
method: m,
|
||||||
paramTypes: paramTypes,
|
paramTypes: paramTypes,
|
||||||
|
paramValues: paramValues,
|
||||||
returnType: returnType,
|
returnType: returnType,
|
||||||
|
returnValue: returnValue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(s.methods) == 0 {
|
if len(s.methods) == 0 {
|
||||||
|
@ -142,6 +150,22 @@ Loop:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateType(t reflect.Type) (rt reflect.Type, rv reflect.Value, err error) {
|
||||||
|
if t.Kind() == reflect.Struct {
|
||||||
|
err = fmt.Errorf("Type is Struct. Pass by reference, i.e. %s", t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if t.Kind() == reflect.Ptr {
|
||||||
|
rt = t.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = reflect.New(rt)
|
||||||
|
if rt.Kind() != reflect.Struct {
|
||||||
|
rv = reflect.Indirect(rv)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// get returns a registered service given a method name.
|
// get returns a registered service given a method name.
|
||||||
//
|
//
|
||||||
// The method name uses a dotted notation as in "Service.Method".
|
// The method name uses a dotted notation as in "Service.Method".
|
||||||
|
|
Loading…
Reference in New Issue
Block a user