refactor(blazing): 重构项目并优化数据结构

- 更新 LoginUserInfo 结构体,将 uint64 类型改为 uint32
- 调整 ServerInfo 结构体,将 IP 字段从 []byte 改为 string
- 移除未使用的 ArraySerialize 结构体
- 更新 ByteArray 类,修改相关方法名
- 删除未使用的 serialize 相关代码
- 优化模块导入,移除冗余依赖
This commit is contained in:
2025-06-22 12:05:07 +08:00
parent c00a87800a
commit 720294ad27
24 changed files with 631 additions and 395 deletions

View File

@@ -0,0 +1,380 @@
package serialize
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"github.com/gogf/gf/v2/util/gconv"
"github.com/tnnmigga/enum"
)
// DefaultPacketSerializer 默认序列化实现,使用大端序写入数据
func DefaultPacketSerializer[T any]() PacketSerializer[T] {
return func(data T) ([]byte, error) {
var buf bytes.Buffer
if err := binary.Write(&buf, binary.BigEndian, data); err != nil {
return nil, errors.New("binary.Write failed: " + err.Error())
}
// 使用大端序写入数据
// 1. 使用reflect获取结构体类型
// typ := reflect.TypeOf(data)
// fmt.Println("结构体类型名称:", typ.Name())
// fmt.Println("字段数量:", typ.NumField())
// for i := 0; i < typ.NumField(); i++ {
// field := typ.Field(i)
// fmt.Printf("字段名: %s, 类型: %s",
// field.Name, field.Type)
// fmt.Println("字段值:", reflect.ValueOf(data).Field(i).Interface())
// // writedata := reflect.ValueOf(data).Field(i).Interface()
// fmt.Println(field.Type.Kind())
// // serializebase[T](field, &buf, writedata)
// }
return buf.Bytes(), nil
}
}
// DefaultPacketDeserializer 默认反序列化实现,使用大端序读取数据
func DefaultPacketDeserializer[T any]() PacketDeserializer[T] {
return func(data []byte) (T, error) {
var result T
reader := bytes.NewReader(data)
// 使用大端序读取数据
if err := binary.Read(reader, binary.BigEndian, &result); err != nil {
var zero T
return zero, err
}
return result, nil
}
}
// NewDefaultPacketHandler 创建默认的数据包处理句柄
func NewDefaultPacketHandler[T any]() *PacketHandler[T] {
return &PacketHandler[T]{
Serialize: DefaultPacketSerializer[T](),
Deserialize: DefaultPacketDeserializer[T](),
}
}
type SerializeMode int
var lengthtype = enum.New[struct {
LENGTH_FIRST SerializeMode
FIXED_LENGTH SerializeMode
}]()
// PacketSerializer 定义序列化函数类型,将数据转换为字节切片
type PacketSerializer[T any] func(data T) ([]byte, error)
// PacketDeserializer 定义反序列化函数类型,将字节切片转换为数据
type PacketDeserializer[T any] func(data []byte) (T, error)
// PacketHandler 封装序列化和反序列化处理函数
type PacketHandler[T any] struct {
Serialize PacketSerializer[T] // 序列化函数
Deserialize PacketDeserializer[T] // 反序列化函数
}
// 定长序列化器
type FixedVarSerializer struct {
byteOrder binary.ByteOrder
}
// 新建序列化器
func NewFixedVarSerializer(order binary.ByteOrder) *FixedVarSerializer {
if order == nil {
order = binary.BigEndian
}
return &FixedVarSerializer{byteOrder: order}
}
// 序列化任意结构体
func (s *FixedVarSerializer) Serialize(obj interface{}) ([]byte, error) {
var buf bytes.Buffer
err := s.serializeValue(reflect.ValueOf(obj), &buf)
if err != nil {
return nil, fmt.Errorf("序列化失败: %w", err)
}
return buf.Bytes(), nil
}
// 递归序列化值
func (s *FixedVarSerializer) serializeValue(val reflect.Value, buf *bytes.Buffer) error {
kind := val.Kind()
switch kind {
case reflect.Struct:
return s.serializeStruct(val, buf)
case reflect.Slice, reflect.Array:
return s.serializeSlice(val, buf)
default:
if err := binary.Write(buf, s.byteOrder, val.Interface()); err != nil {
return nil
}
return nil
}
}
// 序列化结构体
func (s *FixedVarSerializer) serializeStruct(val reflect.Value, buf *bytes.Buffer) error {
typ := val.Type()
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldVal := val.Field(i)
if !field.IsExported() {
continue
}
// 解析标签格式mode,params 如 fixed:16 或 varlen
tag := field.Tag.Get("serialize")
if tag == "" {
// 未指定标签:按原生类型序列化
err := s.serializeValue(fieldVal, buf)
if err != nil {
return err
}
continue
}
// 解析模式和参数
mode, params, err := parseTag(tag)
if err != nil {
return err
}
// 根据模式序列化
switch mode {
case lengthtype.FIXED_LENGTH:
err = s.serializeFixedField(fieldVal, params, buf)
case lengthtype.LENGTH_FIRST:
err = s.serializeVarWithLenField(fieldVal, params, buf)
default:
return fmt.Errorf("无效的序列化模式: %s", tag)
}
if err != nil {
return err
}
}
return nil
}
// 解析标签格式fixed:N 或 varlen 或 varlen:N
func parseTag(tag string) (SerializeMode, string, error) {
parts := splitTag(tag)
if len(parts) == 0 {
return 0, "", fmt.Errorf("空标签")
}
modeStr := parts[0]
params := ""
if len(parts) > 1 {
params = parts[1]
}
switch modeStr {
case "fixed":
if params == "" {
return 0, "", fmt.Errorf("fixed模式需指定长度")
}
return lengthtype.FIXED_LENGTH, params, nil
case "varlen":
// varlen模式可指定长度字段字节数如varlen:2表示用2字节存长度
if params == "" {
params = "4" // 默认用4字节存长度
}
return lengthtype.LENGTH_FIRST, params, nil
default:
return 0, "", fmt.Errorf("未知模式: %s", modeStr)
}
}
// 定长模式序列化字段
func (s *FixedVarSerializer) serializeFixedField(val reflect.Value, lengthStr string, buf *bytes.Buffer) error {
length, err := strconv.Atoi(lengthStr)
if err != nil {
return fmt.Errorf("无效的定长参数: %s", lengthStr)
}
return s.serializeFixedLengthValue(val, length, buf)
}
// 不定长+长度模式序列化字段
func (s *FixedVarSerializer) serializeVarWithLenField(val reflect.Value, lenBytesStr string, buf *bytes.Buffer) error {
lenBytes, err := strconv.Atoi(lenBytesStr)
if err != nil {
return fmt.Errorf("无效的长度字节数: %s", lenBytesStr)
}
if lenBytes < 1 || lenBytes > 8 {
return fmt.Errorf("长度字节数需在1-8之间")
}
// 先序列化内容到临时缓冲区
var contentBuf bytes.Buffer
err = s.serializeValue(val, &contentBuf)
if err != nil {
return err
}
content := contentBuf.Bytes()
// 写入长度(用指定字节数)
lenBuf := make([]byte, lenBytes)
switch lenBytesStr {
case "4":
s.byteOrder.PutUint32(lenBuf, uint32(len(content)))
case "2":
s.byteOrder.PutUint16(lenBuf, uint16(len(content)))
}
//s.byteOrder.PutUint32(lenBuf, uint32(len(content)))
buf.Write(lenBuf[:lenBytes])
// 写入内容
buf.Write(content)
return nil
}
// 序列化定长值
func (s *FixedVarSerializer) serializeFixedLengthValue(val reflect.Value, length int, buf *bytes.Buffer) error {
kind := val.Kind()
if kind == reflect.String {
str := val.String()
if len(str) > length {
str = str[:length]
}
buf.WriteString(str)
buf.Write(make([]byte, length-len(str)))
return nil
}
var tmpBuf bytes.Buffer
fmt.Println(val)
err := s.serializeValue(val, &tmpBuf)
if err != nil {
return err
}
tmpData := tmpBuf.Bytes()
if len(tmpData) > length {
buf.Write(tmpData[:length])
} else {
buf.Write(tmpData)
buf.Write(make([]byte, length-len(tmpData)))
}
return nil
}
// 序列化slice
func (s *FixedVarSerializer) serializeSlice(val reflect.Value, buf *bytes.Buffer) error {
tempslice := gconv.SliceAny(val)
fmt.Println(val)
//binary.Write(buf, s.byteOrder, val.Bytes())
for i := 0; i < len(tempslice); i++ {
err := s.serializeValue(val.Index(i), buf)
if err != nil {
return err
}
}
// for i := 0; i < len(tempslice); i++ {
// kind := val.Type().Elem().Field(i)
// tag := kind.Tag.Get("serialize")
// // 检查元素是否有标签
// if tag != "" {
// // 元素有标签:按定长模式处理
// mode, params, err := parseTag(tag)
// if err != nil {
// return err
// }
// if mode == lengthtype.FIXED_LENGTH {
// // 定长slice解析maxItems和itemLen
// parts := splitTag(params)
// if len(parts) != 2 {
// return fmt.Errorf("定长slice标签需格式为 fixed:N,M")
// }
// maxItems, _ := strconv.Atoi(parts[0])
// itemLen, _ := strconv.Atoi(parts[1])
// return s.serializeFixedSlice(val, maxItems, itemLen, buf)
// }
// }
// 无标签或不定长模式按原生slice处理先写长度再写元素
// count := val.Len()
// binary.Write(buf, s.byteOrder, int32(len(tempslice)))
// for i := 0; i < count; i++ {
// err := s.serializeValue(val.Index(i), buf)
// if err != nil {
// return err
// }
// }
return nil
//}
return nil
}
// 序列化定长slice
func (s *FixedVarSerializer) serializeFixedSlice(val reflect.Value, maxItems, itemLen int, buf *bytes.Buffer) error {
count := val.Len()
if count > maxItems {
count = maxItems
}
buf.WriteByte(byte(count))
for i := 0; i < maxItems; i++ {
if i < count {
item := val.Index(i)
tmpBuf := &bytes.Buffer{}
err := s.serializeValue(item, tmpBuf)
if err != nil {
return err
}
tmpData := tmpBuf.Bytes()
if len(tmpData) > itemLen {
buf.Write(tmpData[:itemLen])
} else {
buf.Write(tmpData)
buf.Write(make([]byte, itemLen-len(tmpData)))
}
} else {
buf.Write(make([]byte, itemLen))
}
}
return nil
}
// 辅助函数:分割标签参数
func splitTag(tag string) []string {
if tag == "" {
return nil
}
return strings.Split(tag, ":")
}
// 示例结构体(混合模式)
type Address struct {
City string `serialize:"fixed:20"` // 定长模式20字节
Country string `serialize:"varlen"` // 不定长模式先写4字节长度再写内容
}
type Person struct {
Name string `serialize:"fixed:16"` // 定长姓名
Age uint8 // 原生类型
Address Address // 嵌套结构体
Hobbies []string `serialize:"fixed:5,20"` // 定长slice5个元素每个20字节
Friends []Person `serialize:"varlen"` // 不定长slice先写长度再写内容
Metadata []float64 `serialize:"varlen:2"` // 不定长slice用2字节存长度
}