1 Star 0 Fork 0

35819194@qq.com/go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
serialize.go 20.74 KB
一键复制 编辑 原始数据 按行查看 历史
35819194@qq.com 提交于 2024-04-24 11:02 . 修改 文件名
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
// serialize
package socks
import (
"bytes"
"encoding/binary"
"fmt"
"hash/crc32"
"log"
"reflect"
"sync"
"unsafe"
)
const cMaxArrSize = 0xFFFFFF
type fieldInfo struct {
offset uintptr
size uint32 // 大小,0 为动态大小需要计算,切片,字符串等
kind reflect.Kind
arrLen uint32 // 数组长度,只有数组才有
elemKind reflect.Kind // 数组和切片的元素类型
elemType reflect.Type // 创建切片的时候要用到
elemSize uint32 // 单个元素的大小,只有切片会用到
tp reflect.Type // 当前字段的类型,创建切片要用到
structInfo *typeInfo // 如果是结构体就指向结构信息
}
type typeInfo struct {
id HashIdType
fields []fieldInfo // 所有字段
tp reflect.Type
dynFields []fieldInfo // 动态大小的字段,如:切片、字符串等
fixedSize uint32 // 固定字段的大小,计算长度只用计算动态字段的长度
crc32 uint32 // 可以识别出字段是否兼容
}
type HashIdType = int32 // =, 用别名,方便兼容
type typeIdHash map[HashIdType]*typeInfo
type typeHash map[reflect.Type]*typeInfo
type Serializer struct {
typeHashTable typeHash
idHashTable typeIdHash
isLikeCRecord bool // 是否跟C++ Record 兼容的方式
mu sync.RWMutex // 读写锁
}
// 方便线程和不同的模式使用 isLikeCStruct 主要是跟 c++、Delphi 类通讯
func New(isLikeCStruct bool, hashTblSize int) *Serializer {
ret := new(Serializer)
ret.idHashTable = make(typeIdHash, hashTblSize)
ret.typeHashTable = make(typeHash, hashTblSize)
ret.isLikeCRecord = isLikeCStruct
return ret
}
// 是否为固定大小的类型
func isFixedSizeKind(kind reflect.Kind) bool {
ret := false
if (kind >= reflect.Bool) && (kind <= reflect.Complex128) {
ret = true
}
return ret
}
type emptyInterface struct {
typ *struct{}
word uintptr
}
func GetValueDataPtr(v *reflect.Value) uintptr {
return (*(*emptyInterface)(unsafe.Pointer(v))).word
}
func (s *Serializer) addType(id HashIdType, tpInfo *typeInfo) bool {
s.mu.Lock()
defer s.mu.Unlock()
if id > 0 {
s.idHashTable[id] = tpInfo
}
s.typeHashTable[tpInfo.tp] = tpInfo
return true
}
func (s *Serializer) idIsExists(id HashIdType) bool {
s.mu.RLock()
defer s.mu.RUnlock()
_, ok := s.idHashTable[id]
return ok
}
func (s *Serializer) regType(id HashIdType, tp reflect.Type) *typeInfo {
//log.Println("type.kind = ", tp.Kind(), tp.Name())
tpInfo := new(typeInfo)
tpInfo.tp = tp
tpInfo.id = id
fldCnt := tp.NumField()
buff := bytes.NewBuffer(nil)
binary.Write(buff, binary.LittleEndian, uint16(fldCnt))
// log.Println("type.kind = ", tp.Kind(), tp.Name(), fldCnt)
for i := 0; i < fldCnt; i++ {
fld := tp.Field(i)
fldInfo := fieldInfo{} // 清空
fldInfo.offset = fld.Offset
fldInfo.kind = fld.Type.Kind()
fldInfo.tp = fld.Type
binary.Write(buff, binary.LittleEndian, uint8(fldInfo.kind))
log.Println("regType: ", i, tp, fld.Type.Kind(), fld.Type, uint8(fldInfo.kind))
if isFixedSizeKind(fldInfo.kind) {
fldInfo.size = uint32(fld.Type.Size()) // 可以直接 copy
} else {
switch fldInfo.kind {
case reflect.Array, reflect.Slice:
fldInfo.elemType = fld.Type.Elem()
fldInfo.elemKind = fldInfo.elemType.Kind()
binary.Write(buff, binary.LittleEndian, fldInfo.elemKind) // 写入元素类型
if isFixedSizeKind(fldInfo.elemKind) {
fldInfo.elemSize = uint32(fldInfo.elemType.Size())
}
if fldInfo.kind == reflect.Array {
fldInfo.arrLen = uint32(fld.Type.Len())
binary.Write(buff, binary.LittleEndian, fldInfo.arrLen) // 数组还要写入长度
if isFixedSizeKind(fldInfo.elemKind) {
fldInfo.size = uint32(fld.Type.Size())
}
}
case reflect.String:
fldInfo.size = 0
case reflect.Struct:
sTpInfo, _ := s.tryGetTypeInfo(fld.Type)
if sTpInfo == nil { // 没找到,直接注册
sTpInfo = s.regType(0, fld.Type)
}
fldInfo.structInfo = sTpInfo
binary.Write(buff, binary.LittleEndian, sTpInfo.crc32) // 结构直接写入crc,子结构变了,本结构也会跟着变,类似区块链
//log.Println("注册结构体: ", *sTpInfo)
default:
log.Panicln("不支持的字段类型,注册失败 ", fldInfo.kind, fld)
return nil
}
}
if fldInfo.size == 0 {
tpInfo.dynFields = append(tpInfo.dynFields, fldInfo) // 请加动态字段
} else {
tpInfo.fixedSize += fldInfo.size // 累加固定大小
}
// log.Println("regType: append ", tp, i, fldInfo.tp, fldInfo.kind)
tpInfo.fields = append(tpInfo.fields, fldInfo)
}
log.Println("regType: crcbits = ", buff.Bytes())
tpInfo.crc32 = crc32.ChecksumIEEE(buff.Bytes())
log.Println("regType: tpinfo = ", tp, ", crc32 = ", tpInfo.crc32)
s.addType(id, tpInfo)
return tpInfo
}
func (s *Serializer) RegisterType(id HashIdType, obj interface{}) bool {
if s.idIsExists(id) {
log.Println("id 重复: ", id)
return false
}
tp := reflect.TypeOf(obj)
if tp.Kind() == reflect.Ptr {
tp = tp.Elem()
}
return s.regType(id, tp) != nil
}
const (
cUint16Tag uint8 = 254
cUint32Tag uint8 = 255
cCRC32Size = uint32(unsafe.Sizeof(uint32(0)))
cMinHeaderSize = cCRC32Size + 1
cMaxUint16 uint32 = 0xFFFF
)
func GetLengthDataLen(avLen uint32) uint32 {
if avLen < uint32(cUint16Tag) {
return 1
} else if avLen <= cMaxUint16 {
return 3
} else {
return 5
}
}
func WiriteLength(bits []byte, aLength uint32) (wirteLen uint32) {
arrLen := len(bits)
if (arrLen >= 1) && (aLength < uint32(cUint16Tag)) {
bits[0] = uint8(aLength)
return 1
} else if (arrLen >= 3) && (aLength <= cMaxUint16) {
bits[0] = cUint16Tag
*(*uint16)(unsafe.Pointer(&bits[1])) = uint16(aLength)
return 3
} else if arrLen >= 5 {
bits[0] = cUint32Tag
*(*uint32)(unsafe.Pointer(&bits[1])) = aLength
return 5
}
return 0 // 写入失败
}
// 获取字符串的写入长度
func getStringWriteLen(str string) uint32 {
l := uint32(len(str))
return l + GetLengthDataLen(l)
}
const cMove16 = uint32(16)
const cMove4 = uint32(4)
func Move(src, dst uintptr, size uint32) {
if (src == dst) || (size == 0) {
return
}
ps := PByteArray(unsafe.Pointer(src))
pd := PByteArray(unsafe.Pointer(dst))
if (src < dst) && (src+uintptr(size) > dst) { // 两块内存有重叠,从左向右复制,要反向操作,先复制尾部的
dis := uint32(dst - src) // 这个速度慢点,但能保证结果正确
idx := size
if (dis >= cMove16) && (idx >= cMove16) {
for {
idx -= cMove16
*(*complex128)(unsafe.Pointer(&(*pd)[idx])) = *(*complex128)(unsafe.Pointer(&(*ps)[idx]))
if idx < cMove16 {
break
}
}
}
if (dis >= cMove4) && (idx >= cMove4) {
for {
idx -= cMove4
*(*uint32)(unsafe.Pointer(&(*pd)[idx])) = *(*uint32)(unsafe.Pointer(&(*ps)[idx]))
if idx < cMove4 {
break
}
}
}
for i := int(idx) - 1; i >= 0; i-- {
(*pd)[i] = (*ps)[i]
}
} else {
copy((*pd)[0:size], (*ps)[0:size])
}
}
func CopyMemory(src, dst []byte) int {
l := len(src)
l2 := len(dst)
if l2 < l {
l = l2
}
Move(uintptr(unsafe.Pointer(&src[0])), uintptr(unsafe.Pointer(&dst[0])), uint32(l))
return l
}
func ReadLength(bits []byte) (lengthValue uint32, readLen uint32) {
bitsLen := len(bits)
if bitsLen >= 1 {
var v uint8 = bits[0]
if v < cUint16Tag {
return uint32(v), 1
} else if (bitsLen >= 3) && (v == cUint16Tag) {
v16 := *(*uint16)(unsafe.Pointer(&bits[1]))
return uint32(v16), 3
} else if bitsLen >= 5 {
v32 := *(*uint32)(unsafe.Pointer(&bits[1]))
return v32, 5
}
}
return 0, 0
}
func ReadString(bits []byte) (str string, readLen uint32) {
bitsLen := uint32(len(bits))
sl, n := ReadLength(bits)
if n > 0 {
idx := uint32(0)
idx += n
if idx+sl <= bitsLen {
str := string(bits[idx : idx+sl])
return str, idx + sl
} else {
log.Println("读取失败内容长度不够", bitsLen, idx+sl)
}
} else {
log.Println("读取字符串长度失败")
}
return "", 0
}
func WriteString(bits []byte, str string) (writeLen uint32) {
bitsLen := uint32(len(bits))
sl := uint32(len(str))
idx := uint32(WiriteLength(bits, sl))
if (sl > 0) && (idx+sl <= bitsLen) {
ps := getSliceDataPtr(uintptr(unsafe.Pointer(&str)))
pd := uintptr(unsafe.Pointer(&bits[idx]))
Move(ps, pd, sl)
idx += sl
}
return idx
}
func writeSlice(bits []byte, slicePtr uintptr, fld *fieldInfo) (writeLen uint32) {
bitsLen := uint32(len(bits))
sliceLen := getSliceLength(slicePtr)
idx := WiriteLength(bits, uint32(sliceLen))
if idx == 0 {
log.Println("切片长度写入失败 ", sliceLen, bitsLen)
return 0
}
if fld.elemSize > 0 { // 可以copy的类型
size := uint32(sliceLen) * fld.elemSize
if idx+size > bitsLen {
log.Println("写入切片固定大小长度不足: ", idx+size, bitsLen)
return 0
}
ps := getSliceDataPtr(slicePtr)
Move(ps, uintptr(unsafe.Pointer(&bits[idx])), size)
idx += size
} else {
switch fld.elemKind {
case reflect.String:
ps := (*[]string)(unsafe.Pointer(slicePtr))
for i := 0; i < sliceLen; i++ {
n := WriteString(bits[idx:], (*ps)[i])
if n == 0 {
log.Println("写入字符串切片失败: ", i, (*ps)[i])
return 0
}
idx += n
}
default:
log.Println("不支持的切片类型写入: ", fld.elemType)
return 0
}
}
return idx
}
func readSlice(bits []byte, slicePtr uintptr, fld *fieldInfo) uint32 {
sliceLen, idx := ReadLength(bits)
if idx == 0 {
log.Println("读取切片长度失败: ", fld)
return 0
}
bitsLen := len(bits)
// 构造 slice 并赋值
// fmt.Println("readSlice: elemType = ", fld.tp, sliceLen)
v := reflect.MakeSlice(fld.tp, int(sliceLen), int(sliceLen))
ps := (*reflect.SliceHeader)(unsafe.Pointer(GetValueDataPtr(&v)))
*(*reflect.SliceHeader)(unsafe.Pointer(slicePtr)) = *ps
if fld.elemSize > 0 { // 可以 copy 的类型
size := fld.elemSize * sliceLen
if size+idx > uint32(bitsLen) {
log.Println("读取slice失败,数据长度不够", size+idx, bitsLen)
return 0
}
pbs := PByteArray(unsafe.Pointer(ps.Data))
copy(pbs[0:size], bits[idx:idx+size])
idx += size
} else {
switch fld.elemKind {
case reflect.String:
pStrs := (PStrArray)(unsafe.Pointer(ps.Data))
for i := 0; i < int(sliceLen); i++ {
str, rLen := ReadString(bits[idx:])
if rLen == 0 {
log.Println("读取切片字符串失败: 长度不够 ", i, idx, bitsLen)
return 0
}
(*pStrs)[i] = str
idx += rLen
}
default:
log.Println("不能支持的切片类型 read : ", fld.elemType)
}
}
return idx
}
func readArray(bits []byte, arrPtr uintptr, fld *fieldInfo) (readLen uint32) {
bitsLen := uint32(len(bits))
idx := uint32(0)
if fld.size > 0 { // 可以直接复制的类型
if bitsLen >= fld.size {
Move(uintptr(unsafe.Pointer(&bits[0])), arrPtr, fld.size)
idx = fld.size
} else {
log.Println("readArray 读取固定大小失败,长度不够 ", fld.size, bitsLen)
return 0
}
} else {
switch fld.elemKind {
case reflect.String:
pStrs := PStrArray(unsafe.Pointer(arrPtr))
for i := 0; i < int(fld.arrLen); i++ {
str, n := ReadString(bits[idx:])
if n == 0 {
log.Println("读取字符串数组失败 ", i, idx)
return 0
}
(*pStrs)[i] = str
idx += n
}
default:
log.Println("readArray 不技能的数组类型 ", fld.elemKind)
return 0
}
}
return idx
}
func writeArray(bits []byte, arrPtr uintptr, fld *fieldInfo) (writeLen uint32) {
bitsLen := uint32(len(bits))
idx := uint32(0)
if fld.size > 0 { // 可以直接复制的类型
if bitsLen >= fld.size {
Move(arrPtr, uintptr(unsafe.Pointer(&bits[0])), fld.size)
idx = fld.size
} else {
log.Println("writeArray 写入固定大小失败,长度不够 ", fld.size, bitsLen)
return 0
}
} else {
switch fld.elemKind {
case reflect.String:
pStrs := PStrArray(unsafe.Pointer(arrPtr))
for i := 0; i < int(fld.arrLen); i++ {
str := (*pStrs)[i]
n := WriteString(bits[idx:], str)
if n == 0 {
log.Println("写入字符串数组失败 ", i, idx)
return 0
}
idx += n
}
default:
log.Println("readArray 不技能的数组类型 ", fld.elemKind)
return 0
}
}
return idx
}
type PByteArray (*[cMaxArrSize]byte)
type PStrArray (*[cMaxArrSize]string)
// 获取切片的长度
func getSliceLength(ptr uintptr) int {
return (*(*reflect.SliceHeader)(unsafe.Pointer(ptr))).Len
}
func getSliceDataPtr(ptr uintptr) uintptr {
return (*(*reflect.SliceHeader)(unsafe.Pointer(ptr))).Data
}
// 计算切片的写入长度
func getSliceWriteLen(ptr uintptr, fld *fieldInfo) uint32 {
len := getSliceLength(ptr)
writeLen := GetLengthDataLen(uint32(len))
if fld.elemSize > 0 {
writeLen += uint32(len) * fld.elemSize
} else {
switch fld.elemKind {
case reflect.String:
ps := (*[]string)(unsafe.Pointer(ptr))
for i := 0; i < len; i++ {
writeLen += getStringWriteLen((*ps)[i])
}
default:
log.Println("不支持的字段切片类型计算长度 ", fld.elemType)
return 0
}
}
return writeLen
}
func getArrayWriteLen(ptr uintptr, fld *fieldInfo) uint32 {
writeLen := uint32(0)
switch fld.elemKind {
case reflect.String:
psArr := (PStrArray)(unsafe.Pointer(ptr))
for i := 0; i < int(fld.arrLen); i++ {
writeLen += getStringWriteLen((*psArr)[i])
}
default:
log.Println("不支持的数组类型计算长度,类型=", fld.elemType)
return 0
}
return writeLen
}
// 计算动态字段的长度
func (pInfo *typeInfo) calcDataSize(valuePtr uintptr) uint32 {
// log.Println("calcDataSize: ", len(pInfo.fields), *pInfo)
fldLen := len(pInfo.dynFields)
var result uint32 = pInfo.fixedSize
for i := 0; i < fldLen; i++ {
fld := &pInfo.dynFields[i]
addr := valuePtr + fld.offset
// log.Println("calcDataSize: ", pInfo.tp, i, fld.kind)
switch fld.kind {
case reflect.String:
result += getStringWriteLen(*(*string)(unsafe.Pointer(addr)))
case reflect.Slice:
result += getSliceWriteLen(addr, fld)
case reflect.Array:
result += getArrayWriteLen(addr, fld)
case reflect.Struct: // 结构递归运算
// log.Println("calcDataSize, offset = ", fld.offset)
result += fld.structInfo.calcDataSize(addr)
default:
log.Println("未处理的类型 ", fld.kind, pInfo.tp.Name())
return 0
}
}
// log.Println("calcDataSize: result = ", result)
return result
}
func (s *Serializer) tryGetTypeInfo(tp reflect.Type) (atpInfo *typeInfo, ret bool) {
s.mu.RLock()
defer s.mu.RUnlock()
tpInfo, ok := s.typeHashTable[tp]
return tpInfo, ok
}
func (s *Serializer) getTypeInfo(tp reflect.Type) (atpInfo *typeInfo, isOk bool) {
tpInfo, ok := s.tryGetTypeInfo(tp)
if ok == false {
tpInfo = s.regType(0, tp) // 找不到就直接注册一个
}
return tpInfo, tpInfo != nil
}
func (s *Serializer) encodeStruct(bits []byte, valuePtr uintptr, tpInfo *typeInfo) uint32 {
// log.Println("encodeStruct: ", valuePtr, bits, *tpInfo)
idx := uint32(0)
for i := 0; i < len(tpInfo.fields); i++ {
fld := &(tpInfo.fields[i])
fldAddr := valuePtr + fld.offset
if fld.size > 0 {
ps := unsafe.Pointer(fldAddr)
pd := unsafe.Pointer(&bits[idx])
switch fld.size { // 下面这种写法能提升10%的速度
case 1:
bits[idx] = *(*uint8)(ps)
case 2:
*(*uint16)(pd) = *(*uint16)(ps)
case 4:
*(*uint32)(pd) = *(*uint32)(ps)
case 8:
*(*uint64)(pd) = *(*uint64)(ps)
case 16:
*(*complex128)(pd) = *(*complex128)(ps)
default:
Move(fldAddr, uintptr(pd), fld.size)
}
idx += fld.size
} else {
switch fld.kind {
case reflect.String:
str := *(*string)(unsafe.Pointer(fldAddr))
n := WriteString(bits[idx:], str)
idx += n
case reflect.Slice:
n := writeSlice(bits[idx:], fldAddr, fld)
idx += n
case reflect.Array:
n := writeArray(bits[idx:], fldAddr, fld)
idx += n
case reflect.Struct:
n := s.encodeStruct(bits[idx:], fldAddr, fld.structInfo)
idx += n
default:
log.Println("EncodeStruct 不支持的字段类型: ", fld.kind)
return 0
}
}
}
// log.Println("encode: len = ", idx)
return idx
}
// 根据注册ID新建结构,方便外面使用
func (s *Serializer) NewStruct(id HashIdType) interface{} {
info, isOk := s.idHashTable[id]
if isOk {
v := reflect.New(info.tp)
return v.Interface()
}
return nil
}
// 这里传指针,加快访问速度
func (s *Serializer) Encode(ptr interface{}) (result []byte, ok bool) {
value := reflect.ValueOf(ptr)
if value.Type().Kind() != reflect.Ptr {
log.Println("编码只能传指针, 为了提高效率", value.Type())
return nil, false
}
value = reflect.Indirect(value)
tpInfo, ok := s.getTypeInfo(value.Type())
if !ok {
log.Println("找不到类型信息,应该没有注册")
return nil, false
}
valuePtr := GetValueDataPtr(&value)
allSize := tpInfo.calcDataSize(valuePtr)
// log.Println("写入结构总长度为: ", allSize)
idx := uint32(0)
var bits []byte
if !s.isLikeCRecord {
n := GetLengthDataLen(allSize)
bits = make([]byte, cCRC32Size+n+allSize) // 开始要写CRC+len
*(*uint32)(unsafe.Pointer(&bits[idx])) = tpInfo.crc32
idx += cCRC32Size
WiriteLength(bits[idx:], allSize) // 写入总长度
idx += n
} else {
bits = make([]byte, allSize)
}
// log.Println("Encode: idx = ", idx)
writeLen := s.encodeStruct(bits[idx:], valuePtr, tpInfo)
// log.Println("Encode: writeLen = ", writeLen, allSize)
if writeLen != allSize {
return nil, false
} else {
return bits, true
}
}
func (s *Serializer) decodeStruct(bits []byte, valuePtr uintptr, tpInfo *typeInfo) uint32 {
bitsLen := uint32(len(bits))
idx := uint32(0)
for i := 0; i < len(tpInfo.fields); i++ {
fld := &(tpInfo.fields[i])
fldAddr := valuePtr + fld.offset
pBytes := PByteArray(unsafe.Pointer(fldAddr))
if fld.size > 0 {
if idx+fld.size > bitsLen {
log.Println("decodeStruct: 读取字段失败 ", i, *fld, *tpInfo)
return 0
}
switch fld.size { // 下面这种写法能提升10%的速度
case 1:
pBytes[0] = bits[idx]
case 2:
*(*uint16)(unsafe.Pointer(pBytes)) = *(*uint16)(unsafe.Pointer(&bits[idx]))
case 4:
*(*uint32)(unsafe.Pointer(pBytes)) = *(*uint32)(unsafe.Pointer(&bits[idx]))
case 8:
*(*uint64)(unsafe.Pointer(pBytes)) = *(*uint64)(unsafe.Pointer(&bits[idx]))
case 16:
*(*complex128)(unsafe.Pointer(pBytes)) = *(*complex128)(unsafe.Pointer(&bits[idx]))
default:
copy(pBytes[0:fld.size], bits[idx:])
}
idx += fld.size
} else {
switch fld.kind {
case reflect.String:
str, n := ReadString(bits[idx:])
if n == 0 {
log.Println("读取字符串字段失败: ", idx, bits, tpInfo.tp, fld)
return 0
}
idx += n
*(*string)(unsafe.Pointer(pBytes)) = str
case reflect.Slice:
n := readSlice(bits[idx:], fldAddr, fld)
if n == 0 {
log.Println("读取Slice字段失败: ", fld)
return 0
}
idx += n
case reflect.Array:
n := readArray(bits[idx:], fldAddr, fld)
if n == 0 {
log.Println("读取array字段失败", fld)
return 0
}
idx += n
case reflect.Struct:
n := s.decodeStruct(bits[idx:], fldAddr, fld.structInfo)
if n == 0 {
log.Println("读取struct字段失败", idx, tpInfo.tp, fld.structInfo)
return 0
}
idx += n
default:
log.Println("DecodeStruct 不支持的字段类型: ", fld.kind)
return 0
}
}
}
return idx
}
func (s *Serializer) Decode(bits []byte, ptr interface{}) bool {
value := reflect.ValueOf(ptr)
tp := value.Type()
if tp.Kind() != reflect.Ptr {
log.Println("解码只能传指针,否则读不到内容 ", tp)
return false
}
value = reflect.Indirect(value) // 指针转值
tp = value.Type()
bitsLen := uint32(len(bits))
var minHeaderSize = cMinHeaderSize
if s.isLikeCRecord {
minHeaderSize = 0
} else if bitsLen < cMinHeaderSize {
log.Println("Decode: 解码长度小于最小头部长度", bitsLen, cMinHeaderSize)
return false
}
tpInfo, ok := s.getTypeInfo(tp)
if !ok {
fmt.Println("找不到类型信息,应该没有注册")
return false
}
if bitsLen < tpInfo.fixedSize+minHeaderSize {
log.Println("bitslen 小于结构体固定大小 ", bitsLen, tpInfo.fixedSize)
return false
}
valuePtr := GetValueDataPtr(&value)
idx := uint32(0)
if !s.isLikeCRecord {
crc32 := *(*uint32)(unsafe.Pointer(&bits[idx]))
idx += cCRC32Size
if crc32 != tpInfo.crc32 {
log.Println("Decode: crc32 不一致 ", crc32, tpInfo.crc32, tpInfo.tp)
return false
}
l, n := ReadLength(bits[idx:])
if n == 0 {
log.Println("Decode: 读取长度失败")
return false
}
idx += n
if idx+l != bitsLen {
log.Println("Decode: all 剩余长度不对: ", idx, l, bitsLen)
return false
}
}
decodeLen := s.decodeStruct(bits[idx:], valuePtr, tpInfo)
// log.Println("Decode: ", decodeLen, bitsLen)
return decodeLen+idx == bitsLen
}
func (s *Serializer) DecodeStruct(id HashIdType, bits []byte) (obj interface{}, isOk bool) {
obj = s.NewStruct(id)
if obj != nil {
if s.Decode(bits, obj) {
return obj, true
}
}
return nil, false
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/cjianwen/go.git
git@gitee.com:cjianwen/go.git
cjianwen
go
go
v1.0.5

搜索帮助

D67c1975 1850385 1daf7b77 1850385