|
|
package unpacker
|
|
|
|
|
|
import (
|
|
|
unpackerpkg "git.noahlan.cn/noahlan/nnet/v2/pkg/unpacker"
|
|
|
)
|
|
|
|
|
|
// fixedLengthUnpacker 固定长度拆包器实现
|
|
|
type fixedLengthUnpacker struct {
|
|
|
length int
|
|
|
buffer []byte
|
|
|
maxBufferSize int
|
|
|
}
|
|
|
|
|
|
// NewFixedLengthUnpacker 创建固定长度拆包器
|
|
|
func NewFixedLengthUnpacker(length int) unpackerpkg.Unpacker {
|
|
|
return NewFixedLengthUnpackerWithMaxBuffer(length, unpackerpkg.DefaultMaxBufferSize)
|
|
|
}
|
|
|
|
|
|
// NewFixedLengthUnpackerWithMaxBuffer 创建固定长度拆包器(指定最大buffer大小)
|
|
|
func NewFixedLengthUnpackerWithMaxBuffer(length int, maxBufferSize int) unpackerpkg.Unpacker {
|
|
|
if length <= 0 {
|
|
|
length = 1024 // 默认长度
|
|
|
}
|
|
|
if maxBufferSize <= 0 {
|
|
|
maxBufferSize = unpackerpkg.DefaultMaxBufferSize
|
|
|
}
|
|
|
return &fixedLengthUnpacker{
|
|
|
length: length,
|
|
|
buffer: make([]byte, 0, length*2), // 预分配初始容量
|
|
|
maxBufferSize: maxBufferSize,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Unpack 拆包
|
|
|
func (u *fixedLengthUnpacker) Unpack(data []byte) ([][]byte, []byte, int, error) {
|
|
|
// 检查buffer大小限制
|
|
|
newSize := len(u.buffer) + len(data)
|
|
|
if newSize > u.maxBufferSize {
|
|
|
return nil, nil, 0, unpackerpkg.NewErrorf("unpacker buffer size exceeded: %d > %d", newSize, u.maxBufferSize)
|
|
|
}
|
|
|
|
|
|
// 优化:如果容量不足,预分配更大的容量(零拷贝优化)
|
|
|
if cap(u.buffer) < newSize {
|
|
|
newCap := cap(u.buffer) * 2
|
|
|
if newCap < newSize {
|
|
|
newCap = newSize
|
|
|
}
|
|
|
if newCap > u.maxBufferSize {
|
|
|
newCap = u.maxBufferSize
|
|
|
}
|
|
|
// 如果现有 buffer 为空,直接分配新 buffer(避免不必要的复制)
|
|
|
if len(u.buffer) == 0 {
|
|
|
u.buffer = make([]byte, 0, newCap)
|
|
|
} else {
|
|
|
newBuffer := make([]byte, len(u.buffer), newCap)
|
|
|
copy(newBuffer, u.buffer)
|
|
|
u.buffer = newBuffer
|
|
|
}
|
|
|
}
|
|
|
|
|
|
u.buffer = append(u.buffer, data...)
|
|
|
|
|
|
var messages [][]byte
|
|
|
|
|
|
for len(u.buffer) >= u.length {
|
|
|
message := make([]byte, u.length)
|
|
|
copy(message, u.buffer[:u.length])
|
|
|
messages = append(messages, message)
|
|
|
|
|
|
// 移除已处理的数据(优化:使用切片操作,避免复制)
|
|
|
u.buffer = u.buffer[u.length:]
|
|
|
|
|
|
// 如果 buffer 太大但剩余数据很少,压缩 buffer(减少内存占用)
|
|
|
// 注意:压缩不会改变buffer的长度,只改变容量
|
|
|
if len(u.buffer) < cap(u.buffer)/4 && cap(u.buffer) > 4096 {
|
|
|
compressed := make([]byte, len(u.buffer), cap(u.buffer)/2)
|
|
|
copy(compressed, u.buffer)
|
|
|
u.buffer = compressed
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 输入字节已经被复制进连接级buffer;调用方应从底层读缓冲中丢弃本次输入,避免重复处理。
|
|
|
return messages, u.buffer, len(data), nil
|
|
|
}
|
|
|
|
|
|
// Pack 打包
|
|
|
func (u *fixedLengthUnpacker) Pack(data []byte) ([]byte, error) {
|
|
|
if len(data) != u.length {
|
|
|
// 如果数据长度不匹配,需要填充或截断
|
|
|
if len(data) < u.length {
|
|
|
// 填充
|
|
|
result := make([]byte, u.length)
|
|
|
copy(result, data)
|
|
|
return result, nil
|
|
|
} else {
|
|
|
// 截断
|
|
|
return data[:u.length], nil
|
|
|
}
|
|
|
}
|
|
|
return data, nil
|
|
|
}
|