Browse Source

added implementation registry

Shelikhoo 4 years ago
parent
commit
1e562e7dd5

+ 9 - 0
common/registry/errors.generated.go

@@ -0,0 +1,9 @@
+package registry
+
+import "github.com/v2fly/v2ray-core/v4/common/errors"
+
+type errPathObjHolder struct{}
+
+func newError(values ...interface{}) *errors.Error {
+	return errors.New(values...).WithPathObj(errPathObjHolder{})
+}

+ 39 - 0
common/registry/implementation_set.go

@@ -0,0 +1,39 @@
+package registry
+
+import "github.com/v2fly/v2ray-core/v4/common/protoext"
+
+//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
+
+type implementationSet struct {
+	AliasLookup map[string]*implementation
+}
+
+type implementation struct {
+	FullName string
+	Alias    []string
+}
+
+func (i *implementationSet) RegisterImplementation(name string, opt *protoext.MessageOpt) {
+	alias := opt.GetShortName()
+
+	impl := &implementation{
+		FullName: name,
+		Alias:    alias,
+	}
+
+	for _, aliasName := range alias {
+		i.AliasLookup[aliasName] = impl
+	}
+}
+
+func (i *implementationSet) FindImplementationByAlias(alias string) (string, error) {
+	impl, found := i.AliasLookup[alias]
+	if found {
+		return impl.FullName, nil
+	}
+	return "", newError("cannot find implementation by alias")
+}
+
+func newImplementationSet() *implementationSet {
+	return &implementationSet{AliasLookup: map[string]*implementation{}}
+}

+ 49 - 0
common/registry/registry.go

@@ -0,0 +1,49 @@
+package registry
+
+import (
+	"github.com/v2fly/v2ray-core/v4/common/protoext"
+	"google.golang.org/protobuf/proto"
+)
+
+type implementationRegistry struct {
+	implSet map[string]*implementationSet
+}
+
+func (i *implementationRegistry) RegisterImplementation(name string, opt *protoext.MessageOpt) {
+	interfaceType := opt.GetType()[0]
+	implSet, found := i.implSet[interfaceType]
+	if !found {
+		implSet = newImplementationSet()
+		i.implSet[interfaceType] = implSet
+	}
+	implSet.RegisterImplementation(name, opt)
+}
+
+func (i *implementationRegistry) FindImplementationByAlias(interfaceType, alias string) (string, error) {
+	implSet, found := i.implSet[interfaceType]
+	if !found {
+		return "", newError("cannot find implemention unknown interface type")
+	}
+	return implSet.FindImplementationByAlias(alias)
+}
+
+func newImplementationRegistry() *implementationRegistry {
+	return &implementationRegistry{implSet: map[string]*implementationSet{}}
+}
+
+var globalImplementationRegistry = newImplementationRegistry()
+
+func RegisterImplementation(proto proto.Message) error {
+	msgDesc := proto.ProtoReflect().Type().Descriptor()
+	fullName := string(msgDesc.FullName())
+	msgOpts, err := protoext.GetMessageOptions(msgDesc)
+	if err != nil {
+		return newError("unable to find message options").Base(err)
+	}
+	globalImplementationRegistry.RegisterImplementation(fullName, msgOpts)
+	return nil
+}
+
+func FindImplementationByAlias(interfaceType, alias string) (string, error) {
+	return globalImplementationRegistry.FindImplementationByAlias(interfaceType, alias)
+}