fox/processor/processor.go
2025-05-29 22:30:49 +08:00

80 lines
1.8 KiB
Go

package processor
import (
"fmt"
"github.com/fox/fox/log"
"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)
log.DebugF("processor register message %v", cmd)
}
func (h *Processor) UnregisterMessage(cmd int32) {
delete(h.types, cmd)
delete(h.delegates, cmd)
log.DebugF("processor unregister message %v", cmd)
}
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
}