broker: simplify handler check
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
		| @@ -21,7 +21,7 @@ var ( | |||||||
| 	// ErrInvalidMessage returns when invalid Message passed | 	// ErrInvalidMessage returns when invalid Message passed | ||||||
| 	ErrInvalidMessage = errors.New("invalid message") | 	ErrInvalidMessage = errors.New("invalid message") | ||||||
| 	// ErrInvalidHandler returns when subscriber passed to Subscribe | 	// ErrInvalidHandler returns when subscriber passed to Subscribe | ||||||
| 	ErrInvalidHandler = errors.New("invalid handler") | 	ErrInvalidHandler = errors.New("invalid handler, ony func(Message) error and func([]Message) error supported") | ||||||
| 	// DefaultGracefulTimeout | 	// DefaultGracefulTimeout | ||||||
| 	DefaultGracefulTimeout = 5 * time.Second | 	DefaultGracefulTimeout = 5 * time.Second | ||||||
| ) | ) | ||||||
|   | |||||||
| @@ -1,87 +1,14 @@ | |||||||
| package broker | package broker | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"reflect" |  | ||||||
| 	"unicode" |  | ||||||
| 	"unicode/utf8" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	messageSig  = "func(broker.Message) error" |  | ||||||
| 	messagesSig = "func([]broker.Message) error" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Precompute the reflect type for error. Can't use error directly |  | ||||||
| // because Typeof takes an empty interface value. This is annoying. |  | ||||||
| var typeOfError = reflect.TypeOf((*error)(nil)).Elem() |  | ||||||
|  |  | ||||||
| // Is this an exported - upper case - name? |  | ||||||
| func isExported(name string) bool { |  | ||||||
| 	r, _ := utf8.DecodeRuneInString(name) |  | ||||||
| 	return unicode.IsUpper(r) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Is this type exported or a builtin? |  | ||||||
| func isExportedOrBuiltinType(t reflect.Type) bool { |  | ||||||
| 	for t.Kind() == reflect.Ptr { |  | ||||||
| 		t = t.Elem() |  | ||||||
| 	} |  | ||||||
| 	// PkgPath will be non-empty even for an exported type, |  | ||||||
| 	// so we need to check the type name as well. |  | ||||||
| 	return isExported(t.Name()) || t.PkgPath() == "" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // IsValidHandler func signature | // IsValidHandler func signature | ||||||
| func IsValidHandler(sub interface{}) error { | func IsValidHandler(sub interface{}) error { | ||||||
| 	typ := reflect.TypeOf(sub) | 	switch sub.(type) { | ||||||
| 	var argType reflect.Type |  | ||||||
| 	switch typ.Kind() { |  | ||||||
| 	case reflect.Func: |  | ||||||
| 		name := "Func" |  | ||||||
| 		switch typ.NumIn() { |  | ||||||
| 		case 1: |  | ||||||
| 			argType = typ.In(0) |  | ||||||
| 		default: |  | ||||||
| 			return fmt.Errorf("subscriber %v takes wrong number of args: %v required signature %s", name, typ.NumIn(), messageSig) |  | ||||||
| 		} |  | ||||||
| 		if !isExportedOrBuiltinType(argType) { |  | ||||||
| 			return fmt.Errorf("subscriber %v argument type not exported: %v", name, argType) |  | ||||||
| 		} |  | ||||||
| 		if typ.NumOut() != 1 { |  | ||||||
| 			return fmt.Errorf("subscriber %v has wrong number of return values: %v require signature %s", |  | ||||||
| 				name, typ.NumOut(), messageSig) |  | ||||||
| 		} |  | ||||||
| 		if returnType := typ.Out(0); returnType != typeOfError { |  | ||||||
| 			return fmt.Errorf("subscriber %v returns %v not error", name, returnType.String()) |  | ||||||
| 		} |  | ||||||
| 	default: | 	default: | ||||||
| 		hdlr := reflect.ValueOf(sub) | 		return ErrInvalidHandler | ||||||
| 		name := reflect.Indirect(hdlr).Type().Name() | 	case func(Message) error: | ||||||
|  | 		break | ||||||
| 		for m := 0; m < typ.NumMethod(); m++ { | 	case func([]Message) error: | ||||||
| 			method := typ.Method(m) | 		break | ||||||
| 			switch method.Type.NumIn() { |  | ||||||
| 			case 3: |  | ||||||
| 				argType = method.Type.In(2) |  | ||||||
| 			default: |  | ||||||
| 				return fmt.Errorf("subscriber %v.%v takes wrong number of args: %v required signature %s", |  | ||||||
| 					name, method.Name, method.Type.NumIn(), messageSig) |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if !isExportedOrBuiltinType(argType) { |  | ||||||
| 				return fmt.Errorf("%v argument type not exported: %v", name, argType) |  | ||||||
| 			} |  | ||||||
| 			if method.Type.NumOut() != 1 { |  | ||||||
| 				return fmt.Errorf( |  | ||||||
| 					"subscriber %v.%v has wrong number of return values: %v require signature %s", |  | ||||||
| 					name, method.Name, method.Type.NumOut(), messageSig) |  | ||||||
| 			} |  | ||||||
| 			if returnType := method.Type.Out(0); returnType != typeOfError { |  | ||||||
| 				return fmt.Errorf("subscriber %v.%v returns %v not error", name, method.Name, returnType.String()) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user