337 lines
8.7 KiB
Go
337 lines
8.7 KiB
Go
package serialize
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/binary"
|
||
"fmt"
|
||
"reflect"
|
||
"strconv"
|
||
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
)
|
||
|
||
// FixedVarDeserializer 定长反序列化器
|
||
type FixedVarDeserializer struct {
|
||
byteOrder binary.ByteOrder
|
||
}
|
||
|
||
// NewFixedVarDeserializer 创建新的反序列化器
|
||
func NewFixedVarDeserializer(order binary.ByteOrder) *FixedVarDeserializer {
|
||
if order == nil {
|
||
order = binary.BigEndian
|
||
}
|
||
return &FixedVarDeserializer{byteOrder: order}
|
||
}
|
||
|
||
// Deserialize 反序列化字节数据到结构体
|
||
func (d *FixedVarDeserializer) Deserialize(data []byte, obj reflect.Value) reflect.Value {
|
||
reader := bytes.NewReader(data)
|
||
g.Dump(obj)
|
||
// 获取传入值的类型并创建新实例
|
||
valType := reflect.TypeOf(obj.Interface())
|
||
newVal := reflect.New(valType).Elem()
|
||
|
||
// 处理指针类型
|
||
if newVal.Kind() == reflect.Ptr {
|
||
newVal = newVal.Elem()
|
||
}
|
||
|
||
// 遍历所有字段进行反序列化
|
||
for i := 0; i < newVal.NumField(); i++ {
|
||
field := newVal.Type().Field(i)
|
||
fieldVal := newVal.Field(i)
|
||
|
||
tag := field.Tag.Get("serialize")
|
||
if tag == "" {
|
||
if err := binary.Read(reader, d.byteOrder, fieldVal.Addr().Interface()); err != nil {
|
||
return newVal
|
||
}
|
||
continue
|
||
}
|
||
|
||
mode, params, err := parseTag(tag)
|
||
if err != nil {
|
||
return newVal
|
||
}
|
||
|
||
switch mode {
|
||
case lengthtype.FIXED_LENGTH:
|
||
if err := d.deserializeFixedField(reader, fieldVal, params); err != nil {
|
||
return newVal
|
||
}
|
||
case lengthtype.LENGTH_FIRST:
|
||
if err := d.deserializeVarWithLenField(reader, fieldVal, params); err != nil {
|
||
return newVal
|
||
}
|
||
default:
|
||
return newVal
|
||
}
|
||
}
|
||
|
||
return newVal
|
||
}
|
||
|
||
// 反序列化值
|
||
|
||
// 反序列化结构体
|
||
func (d *FixedVarDeserializer) deserializeStruct(reader *bytes.Reader, val reflect.Value) error {
|
||
typ := val.Type()
|
||
|
||
for i := 0; i < val.NumField(); i++ {
|
||
field := typ.Field(i)
|
||
fieldVal := val.Field(i)
|
||
|
||
// 跳过未导出字段
|
||
if !field.IsExported() {
|
||
continue
|
||
}
|
||
|
||
// 处理指针类型字段
|
||
if fieldVal.Kind() == reflect.Ptr {
|
||
if fieldVal.IsNil() {
|
||
fieldVal.Set(reflect.New(fieldVal.Type().Elem()))
|
||
}
|
||
fieldVal = fieldVal.Elem()
|
||
}
|
||
|
||
// 解析标签
|
||
tag := field.Tag.Get("serialize")
|
||
if tag == "" {
|
||
// 无标签:按原生类型处理
|
||
if err := d.deserializeValue(reader, fieldVal); err != nil {
|
||
return fmt.Errorf("字段 %s 反序列化失败: %v", field.Name, err)
|
||
}
|
||
continue
|
||
}
|
||
|
||
// 解析模式和参数
|
||
mode, params, err := parseTag(tag)
|
||
if err != nil {
|
||
return fmt.Errorf("字段 %s 标签解析失败: %v", field.Name, err)
|
||
}
|
||
|
||
// 根据模式反序列化
|
||
switch mode {
|
||
case lengthtype.FIXED_LENGTH:
|
||
if err := d.deserializeFixedField(reader, fieldVal, params); err != nil {
|
||
return fmt.Errorf("字段 %s 定长反序列化失败: %v", field.Name, err)
|
||
}
|
||
case lengthtype.LENGTH_FIRST:
|
||
if err := d.deserializeVarWithLenField(reader, fieldVal, params); err != nil {
|
||
return fmt.Errorf("字段 %s 变长反序列化失败: %v", field.Name, err)
|
||
}
|
||
default:
|
||
return fmt.Errorf("字段 %s 不支持的序列化模式: %s", field.Name, mode)
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 反序列化定长字段
|
||
func (d *FixedVarDeserializer) deserializeValue(reader *bytes.Reader, val reflect.Value) error {
|
||
kind := val.Kind()
|
||
|
||
switch kind {
|
||
case reflect.Struct:
|
||
return d.deserializeStruct(reader, val)
|
||
case reflect.Slice:
|
||
return d.deserializeSlice(reader, val)
|
||
default:
|
||
if err := binary.Read(reader, d.byteOrder, val.Addr().Interface()); err != nil {
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
}
|
||
|
||
func (d *FixedVarDeserializer) deserializeFixedField(reader *bytes.Reader, val reflect.Value, lengthStr string) error {
|
||
length, err := strconv.Atoi(lengthStr)
|
||
if err != nil {
|
||
return fmt.Errorf("无效的定长参数: %s", lengthStr)
|
||
}
|
||
|
||
return d.deserializeFixedLengthValue(reader, val, length)
|
||
}
|
||
|
||
// 反序列化带长度前缀的可变长度字段
|
||
func (d *FixedVarDeserializer) deserializeVarWithLenField(reader *bytes.Reader, val reflect.Value, lenBytesStr string) error {
|
||
lenBytes, err := strconv.Atoi(lenBytesStr)
|
||
if err != nil {
|
||
return fmt.Errorf("无效的长度字节数: %s", lenBytesStr)
|
||
}
|
||
|
||
if lenBytes < 1 || lenBytes > 8 {
|
||
return fmt.Errorf("长度字节数需在1-8之间")
|
||
}
|
||
|
||
// 读取长度
|
||
lenData := make([]byte, lenBytes)
|
||
if _, err := reader.Read(lenData); err != nil {
|
||
return err
|
||
}
|
||
|
||
var contentLength uint64
|
||
switch lenBytes {
|
||
case 1:
|
||
contentLength = uint64(lenData[0])
|
||
case 2:
|
||
contentLength = uint64(d.byteOrder.Uint16(lenData))
|
||
case 4:
|
||
contentLength = uint64(d.byteOrder.Uint32(lenData))
|
||
case 8:
|
||
contentLength = d.byteOrder.Uint64(lenData)
|
||
default:
|
||
return fmt.Errorf("不支持的长度字节数: %d", lenBytes)
|
||
}
|
||
|
||
// 读取内容
|
||
contentData := make([]byte, contentLength)
|
||
if _, err := reader.Read(contentData); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 反序列化内容
|
||
contentReader := bytes.NewReader(contentData)
|
||
return d.deserializeValue(contentReader, val)
|
||
}
|
||
|
||
// 反序列化定长值
|
||
func (d *FixedVarDeserializer) deserializeFixedLengthValue(reader *bytes.Reader, val reflect.Value, length int) error {
|
||
kind := val.Kind()
|
||
|
||
if kind == reflect.String {
|
||
// 读取定长字符串
|
||
data := make([]byte, length)
|
||
if _, err := reader.Read(data); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 找到字符串结束位置(去除填充的0)
|
||
var strLen int
|
||
for strLen = 0; strLen < length && data[strLen] != 0; strLen++ {
|
||
}
|
||
fmt.Println(val.CanSet())
|
||
val.SetString(string(data[:strLen]))
|
||
g.Dump(val)
|
||
return nil
|
||
}
|
||
|
||
// 其他类型:读取固定长度字节,然后反序列化
|
||
data := make([]byte, length)
|
||
if _, err := reader.Read(data); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 如果是slice或array,特殊处理
|
||
if kind == reflect.Slice || kind == reflect.Array {
|
||
sliceReader := bytes.NewReader(data)
|
||
return d.deserializeValue(sliceReader, val)
|
||
}
|
||
|
||
// 基本类型
|
||
fieldReader := bytes.NewReader(data)
|
||
return binary.Read(fieldReader, d.byteOrder, val.Addr().Interface())
|
||
}
|
||
|
||
// 反序列化slice
|
||
func (d *FixedVarDeserializer) deserializeSlice(reader *bytes.Reader, val reflect.Value) error {
|
||
// 获取slice元素类型
|
||
elemType := val.Type().Elem()
|
||
|
||
// 检查slice是否有标签
|
||
var tag string
|
||
// 检查slice元素是否为结构体
|
||
if elemType.Kind() == reflect.Struct {
|
||
// 如果元素是结构体,获取结构体的标签
|
||
structType := elemType
|
||
for i := 0; i < structType.NumField(); i++ {
|
||
field := structType.Field(i)
|
||
if tag = field.Tag.Get("serialize"); tag != "" {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
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 d.deserializeFixedSlice(reader, val, maxItems, itemLen)
|
||
}
|
||
}
|
||
|
||
// // 无标签或不定长模式:按原生slice处理(先读长度,再读元素)
|
||
// var count int
|
||
|
||
// // 尝试读取slice长度
|
||
// // 这里假设使用int32作为长度类型,实际应根据序列化逻辑调整
|
||
// var length int32
|
||
// if err := binary.Read(reader, d.byteOrder, &length); err != nil {
|
||
// return err
|
||
// }
|
||
// count = int(length)
|
||
|
||
// // 创建足够容量的slice
|
||
// if val.Kind() == reflect.Slice {
|
||
// val.Set(reflect.MakeSlice(val.Type(), count, count))
|
||
// }
|
||
|
||
// // 读取每个元素
|
||
// for i := 0; i < count; i++ {
|
||
// item := val.Index(i)
|
||
// if err := binary.Read(reader, d.byteOrder, item.Addr().Interface()); err != nil {
|
||
// return err
|
||
// }
|
||
// }
|
||
|
||
return nil
|
||
}
|
||
|
||
// 反序列化定长slice
|
||
func (d *FixedVarDeserializer) deserializeFixedSlice(reader *bytes.Reader, val reflect.Value, maxItems, itemLen int) error {
|
||
// 读取实际元素数量
|
||
countByte, err := reader.ReadByte()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
count := int(countByte)
|
||
|
||
if count > maxItems {
|
||
count = maxItems
|
||
}
|
||
|
||
// 创建slice
|
||
if val.Kind() == reflect.Slice {
|
||
val.Set(reflect.MakeSlice(val.Type(), count, count))
|
||
}
|
||
|
||
// 读取每个元素
|
||
for i := 0; i < maxItems; i++ {
|
||
if i < count {
|
||
item := val.Index(i)
|
||
if err := d.deserializeFixedLengthValue(reader, item, itemLen); err != nil {
|
||
return err
|
||
}
|
||
} else {
|
||
// 跳过填充字节
|
||
if _, err := reader.Seek(int64(itemLen), 1); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|