89 lines
2.0 KiB
Go
89 lines
2.0 KiB
Go
package mq_coder
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.hpds.cc/Component/mq_coder/encoding"
|
|
)
|
|
|
|
// DecodeState represents the state of decoding
|
|
type DecodeState struct {
|
|
// ConsumedBytes is the bytes consumed by decoder
|
|
ConsumedBytes int
|
|
// SizeL is the bytes length of value
|
|
SizeL int
|
|
}
|
|
|
|
// DecodeToPrimitivePacket parse out whole buffer to a PrimitivePacket
|
|
//
|
|
// Examples:
|
|
// [0x01, 0x01, 0x01] -> Key=0x01, Value=0x01
|
|
// [0x41, 0x06, 0x03, 0x01, 0x61, 0x04, 0x01, 0x62] -> key=0x03, value=0x61; key=0x04, value=0x62
|
|
func DecodeToPrimitivePacket(buf []byte, p *PrimitivePacket) (*DecodeState, error) {
|
|
decoder := &DecodeState{
|
|
ConsumedBytes: 0,
|
|
SizeL: 0,
|
|
}
|
|
|
|
if buf == nil || len(buf) < primitivePacketBufferMinimalLength {
|
|
return decoder, errors.New("invalid packet minimal size")
|
|
}
|
|
|
|
p.packet = &packet{
|
|
valBuf: []byte{},
|
|
buf: &bytes.Buffer{},
|
|
}
|
|
|
|
var pos = 0
|
|
// first byte is `Tag`
|
|
p.tag = NewTag(buf[pos])
|
|
p.buf.WriteByte(buf[pos])
|
|
pos++
|
|
decoder.ConsumedBytes = pos
|
|
|
|
// read `Variant` from buf for `Length of value`
|
|
tmpBuf := buf[pos:]
|
|
var bufLen int32
|
|
codec := encoding.VarCodec{}
|
|
err := codec.DecodePVarInt32(tmpBuf, &bufLen)
|
|
if err != nil {
|
|
return decoder, err
|
|
}
|
|
if codec.Size < 1 {
|
|
return decoder, errors.New("malformed, size of Length can not smaller than 1")
|
|
}
|
|
|
|
// codec.Size describes how many bytes used to represent `Length`
|
|
p.buf.Write(buf[pos : pos+codec.Size])
|
|
pos += codec.Size
|
|
|
|
decoder.ConsumedBytes = pos
|
|
decoder.SizeL = codec.Size
|
|
|
|
// if length<0, error on decoding
|
|
if bufLen < 0 {
|
|
return decoder, errors.New("invalid packet, negative length")
|
|
}
|
|
|
|
// the length of value
|
|
p.length = int(bufLen)
|
|
if p.length == 0 {
|
|
p.valBuf = nil
|
|
return decoder, nil
|
|
}
|
|
|
|
// the next `p.length` bytes store value
|
|
endPos := pos + p.length
|
|
|
|
if pos > endPos || endPos > len(buf) || pos > len(buf) {
|
|
return decoder, fmt.Errorf("beyond the boundary, pos=%v, endPos=%v", pos, endPos)
|
|
}
|
|
p.valBuf = buf[pos:endPos]
|
|
p.buf.Write(buf[pos:endPos])
|
|
|
|
decoder.ConsumedBytes = endPos
|
|
return decoder, nil
|
|
}
|