diff --git a/processor/processor.go b/processor/processor.go new file mode 100644 index 0000000..e8243a6 --- /dev/null +++ b/processor/processor.go @@ -0,0 +1,71 @@ +package processor + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "reflect" +) + +type RegisterMetas map[protoreflect.Enum]struct { + Typ any // 请求结构体,注意不能使用指针 + Delegate any // 处理方法 +} + +func NewProcessor() *Processor { + return &Processor{ + types: make(map[int32]reflect.Type), + delegates: make(map[int32]reflect.Value), + } +} + +type Processor struct { + types map[int32]reflect.Type + delegates map[int32]reflect.Value +} + +func (h *Processor) RegisterMessages(metas RegisterMetas) { + for cmd, meta := range metas { + h.RegisterMessage(int32(cmd.Number()), meta.Typ, meta.Delegate) + } +} + +func (h *Processor) RegisterMessage(cmd int32, msg, delegate any) { + h.types[cmd] = reflect.TypeOf(msg) + h.delegates[cmd] = reflect.ValueOf(delegate) +} + +func (h *Processor) GetMessageType(cmd int32) reflect.Type { + return h.types[cmd] +} + +func (h *Processor) Unmarshal(cmd int32, data []byte) (any, error) { + typ := h.GetMessageType(cmd) + if typ == nil { + return nil, fmt.Errorf("invalid cmd: %d", cmd) + } + + v := reflect.New(typ).Interface() + if data == nil { + return v, nil + } + + if err := proto.Unmarshal(data, v.(proto.Message)); err != nil { + return nil, err + } + + return v, nil +} + +func (h *Processor) Dispatch(cmd int32, params ...any) error { + in := make([]reflect.Value, len(params)) + for i, param := range params { + in[i] = reflect.ValueOf(param) + } + delegate, ok := h.delegates[cmd] + if !ok { + return fmt.Errorf("cmd %d delegates not found", cmd) + } + delegate.Call(in) + return nil +}