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 }