|
|
package codec
|
|
|
|
|
|
import (
|
|
|
ctxpkg "github.com/noahlann/nnet/pkg/context"
|
|
|
protocolpkg "github.com/noahlann/nnet/pkg/protocol"
|
|
|
)
|
|
|
|
|
|
// Resolver Codec解析器接口
|
|
|
// 每个Resolver负责一种Codec选择策略,支持双向解析(解码和编码)
|
|
|
type Resolver interface {
|
|
|
// ResolveForDecode 解析用于解码的Codec(数据流入)
|
|
|
// registry: 编解码器注册表(可以动态注册codec)
|
|
|
// ctx: 请求上下文
|
|
|
// raw: 原始数据
|
|
|
// header: 协议帧头(如果有)
|
|
|
// 返回: 解析到的Codec,如果无法解析返回nil和nil错误(继续下一个resolver)
|
|
|
// 注意:resolver可以将解析到的codec注册到registry中,供后续使用
|
|
|
ResolveForDecode(registry Registry, ctx ctxpkg.Context, raw []byte, header protocolpkg.FrameHeader) (Codec, error)
|
|
|
|
|
|
// ResolveForEncode 解析用于编码的Codec(数据流出)
|
|
|
// registry: 编解码器注册表(可以动态注册codec)
|
|
|
// ctx: 请求上下文
|
|
|
// data: 要编码的数据(Go对象)
|
|
|
// header: 协议帧头(如果有)
|
|
|
// 返回: 解析到的Codec,如果无法解析返回nil和nil错误(继续下一个resolver)
|
|
|
// 注意:通常流入时已经将codec注册到registry,这里可以直接获取
|
|
|
ResolveForEncode(registry Registry, ctx ctxpkg.Context, data interface{}, header protocolpkg.FrameHeader) (Codec, error)
|
|
|
}
|
|
|
|
|
|
// ResolverChain Codec解析器链
|
|
|
// 按顺序尝试每个Resolver,直到找到可用的Codec
|
|
|
type ResolverChain struct {
|
|
|
resolvers []Resolver
|
|
|
registry Registry
|
|
|
defaultName string
|
|
|
}
|
|
|
|
|
|
// NewResolverChain 创建解析器链
|
|
|
func NewResolverChain(registry Registry, defaultName string) *ResolverChain {
|
|
|
return &ResolverChain{
|
|
|
resolvers: make([]Resolver, 0),
|
|
|
registry: registry,
|
|
|
defaultName: defaultName,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Add 添加解析器到链中
|
|
|
func (c *ResolverChain) Add(resolver Resolver) *ResolverChain {
|
|
|
c.resolvers = append(c.resolvers, resolver)
|
|
|
return c
|
|
|
}
|
|
|
|
|
|
// ResolveForDecode 执行解析器链用于解码,返回第一个成功解析的Codec
|
|
|
// 如果所有resolver都无法解析,返回默认Codec
|
|
|
func (c *ResolverChain) ResolveForDecode(ctx ctxpkg.Context, raw []byte, header protocolpkg.FrameHeader) (Codec, error) {
|
|
|
// 按顺序尝试每个resolver
|
|
|
for _, resolver := range c.resolvers {
|
|
|
codec, err := resolver.ResolveForDecode(c.registry, ctx, raw, header)
|
|
|
if err != nil {
|
|
|
// 如果resolver返回错误,继续下一个
|
|
|
continue
|
|
|
}
|
|
|
if codec != nil {
|
|
|
return codec, nil
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 所有resolver都无法解析,使用默认
|
|
|
if c.defaultName != "" {
|
|
|
if codec, err := c.registry.Get(c.defaultName); err == nil {
|
|
|
return codec, nil
|
|
|
}
|
|
|
}
|
|
|
return c.registry.Default(), nil
|
|
|
}
|
|
|
|
|
|
// ResolveForEncode 执行解析器链用于编码,返回第一个成功解析的Codec
|
|
|
// 如果所有resolver都无法解析,返回默认Codec
|
|
|
func (c *ResolverChain) ResolveForEncode(ctx ctxpkg.Context, data interface{}, header protocolpkg.FrameHeader) (Codec, error) {
|
|
|
// 按顺序尝试每个resolver
|
|
|
for _, resolver := range c.resolvers {
|
|
|
codec, err := resolver.ResolveForEncode(c.registry, ctx, data, header)
|
|
|
if err != nil {
|
|
|
// 如果resolver返回错误,继续下一个
|
|
|
continue
|
|
|
}
|
|
|
if codec != nil {
|
|
|
return codec, nil
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 所有resolver都无法解析,使用默认
|
|
|
if c.defaultName != "" {
|
|
|
if codec, err := c.registry.Get(c.defaultName); err == nil {
|
|
|
return codec, nil
|
|
|
}
|
|
|
}
|
|
|
return c.registry.Default(), nil
|
|
|
}
|
|
|
|