bug fix
This commit is contained in:
		
							parent
							
								
									b7e43ac8fe
								
							
						
					
					
						commit
						174ae7ae33
					
				|  | @ -1,72 +0,0 @@ | ||||||
| package mq_coder |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"bytes" |  | ||||||
| 	"io" |  | ||||||
| 	"io/ioutil" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type chunkVReader struct { |  | ||||||
| 	src        io.Reader     // the reader parts of V
 |  | ||||||
| 	buf        *bytes.Buffer // the bytes part of V
 |  | ||||||
| 	totalSize  int           // size of whole buffer of this packet
 |  | ||||||
| 	off        int           // last read op
 |  | ||||||
| 	ChunkVSize int           // the size of chunked V
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Read implement io.Reader interface
 |  | ||||||
| func (r *chunkVReader) Read(p []byte) (n int, err error) { |  | ||||||
| 	if r.src == nil { |  | ||||||
| 		return 0, nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if r.off >= r.totalSize { |  | ||||||
| 		return 0, io.EOF |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if r.off < r.totalSize-r.ChunkVSize { |  | ||||||
| 		n, err := r.buf.Read(p) |  | ||||||
| 		r.off += n |  | ||||||
| 		if err != nil { |  | ||||||
| 			if err == io.EOF { |  | ||||||
| 				return n, nil |  | ||||||
| 			} else { |  | ||||||
| 				return 0, err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		return n, nil |  | ||||||
| 	} |  | ||||||
| 	n, err = r.src.Read(p) |  | ||||||
| 	r.off += n |  | ||||||
| 	if err != nil { |  | ||||||
| 		return n, err |  | ||||||
| 	} |  | ||||||
| 	return n, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // WriteTo implement io.WriteTo interface
 |  | ||||||
| func (r *chunkVReader) WriteTo(w io.Writer) (n int64, err error) { |  | ||||||
| 	if r.src == nil { |  | ||||||
| 		return 0, nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// first, write existed buffer
 |  | ||||||
| 	m, err := w.Write(r.buf.Bytes()) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 	n += int64(m) |  | ||||||
| 
 |  | ||||||
| 	// last, write from reader
 |  | ||||||
| 	buf, err := ioutil.ReadAll(r.src) |  | ||||||
| 	if err != nil && err != io.EOF { |  | ||||||
| 		return 0, errWriteFromReader |  | ||||||
| 	} |  | ||||||
| 	m, err = w.Write(buf) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return 0, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	n += int64(m) |  | ||||||
| 	return n, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										54
									
								
								coder.go
								
								
								
								
							
							
						
						
									
										54
									
								
								coder.go
								
								
								
								
							|  | @ -1,54 +0,0 @@ | ||||||
| package mq_coder |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"io" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| var ( |  | ||||||
| 	errBuildIncomplete = errors.New("coder.Encoder: invalid structure of packet") |  | ||||||
| 	errInvalidAdding   = errors.New("coder.Encoder: can not add this Packet after StreamPacket has been add") |  | ||||||
| 	errNonStreamPacket = errors.New("coder.Packet: this packet is not in node mode") |  | ||||||
| 	errWriteFromReader = errors.New("coder.streamV: write from reader error") |  | ||||||
| 	errNotNodeMode     = errors.New("coder.Encoder: packet should be in node mode can be add other packets as child") |  | ||||||
| 	errNilReader       = errors.New("coder.Decoder: nil source reader") |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // Packet 编解码器包
 |  | ||||||
| type Packet interface { |  | ||||||
| 	// SeqId 返回此数据包的序列Id.
 |  | ||||||
| 	SeqId() int |  | ||||||
| 	// Size 返回整个数据包的大小
 |  | ||||||
| 	Size() int |  | ||||||
| 	// VSize 返回V的大小.
 |  | ||||||
| 	VSize() int |  | ||||||
| 	// Bytes 此数据包的全部字节.
 |  | ||||||
| 	Bytes() []byte |  | ||||||
| 	// Reader 返回 io.Reader 字节.
 |  | ||||||
| 	Reader() io.Reader |  | ||||||
| 	// VReader 返回 io.Reader 的 流字节.
 |  | ||||||
| 	VReader() io.Reader |  | ||||||
| 	// IsStreamMode 是否流模式
 |  | ||||||
| 	IsStreamMode() bool |  | ||||||
| 	// IsNodeMode 是否节点模式
 |  | ||||||
| 	IsNodeMode() bool |  | ||||||
| 
 |  | ||||||
| 	// BytesV 返回流字节
 |  | ||||||
| 	BytesV() []byte |  | ||||||
| 	// Utf8StringV 返回流的utf8字符串值
 |  | ||||||
| 	Utf8StringV() string |  | ||||||
| 	// Int32V 返回流的int32值
 |  | ||||||
| 	Int32V() (val int32, err error) |  | ||||||
| 	// UInt32V 返回流的uint32值
 |  | ||||||
| 	UInt32V() (val uint32, err error) |  | ||||||
| 	// Int64V 返回流的int64值
 |  | ||||||
| 	Int64V() (val int64, err error) |  | ||||||
| 	// UInt64V 返回流的uint64值
 |  | ||||||
| 	UInt64V() (val uint64, err error) |  | ||||||
| 	// Float32V 返回流的float32值
 |  | ||||||
| 	Float32V() (val float32, err error) |  | ||||||
| 	// Float64V 返回流的float64值
 |  | ||||||
| 	Float64V() (val float64, err error) |  | ||||||
| 	// BoolV 返回流的bool值
 |  | ||||||
| 	BoolV() (val bool, err error) |  | ||||||
| } |  | ||||||
							
								
								
									
										93
									
								
								decoder.go
								
								
								
								
							
							
						
						
									
										93
									
								
								decoder.go
								
								
								
								
							|  | @ -1,93 +0,0 @@ | ||||||
| package mq_coder |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"bytes" |  | ||||||
| 	"io" |  | ||||||
| 
 |  | ||||||
| 	"git.hpds.cc/Component/mq_coder/spec" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // Decoder is the tool for decoding packet from stream
 |  | ||||||
| type Decoder struct { |  | ||||||
| 	tag spec.T |  | ||||||
| 	len *spec.L |  | ||||||
| 	rd  io.Reader |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // NewDecoder returns a Decoder from an io.Reader
 |  | ||||||
| func NewDecoder(reader io.Reader) *Decoder { |  | ||||||
| 	return &Decoder{ |  | ||||||
| 		rd: reader, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SeqId return the SequenceID of the decoding packet
 |  | ||||||
| func (d *Decoder) SeqId() int { |  | ||||||
| 	return d.tag.Sid() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // UnderlyingReader returns the reader this decoder using
 |  | ||||||
| func (d *Decoder) UnderlyingReader() io.Reader { |  | ||||||
| 	return d.rd |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ReadHeader will block until io.EOF or receive T and L of a packet.
 |  | ||||||
| func (d *Decoder) ReadHeader() error { |  | ||||||
| 	// only read T and L
 |  | ||||||
| 	return d.readTL() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetChunkedPacket will block until io.EOF or receive V of a packet in chunked mode.
 |  | ||||||
| func (d *Decoder) GetChunkedPacket() Packet { |  | ||||||
| 	return &StreamPacket{ |  | ||||||
| 		t:         d.tag, |  | ||||||
| 		l:         *d.len, |  | ||||||
| 		vr:        d.rd, |  | ||||||
| 		chunkMode: true, |  | ||||||
| 		chunkSize: d.len.VSize(), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetFullFilledPacket read full Packet from given io.Reader
 |  | ||||||
| func (d *Decoder) GetFullFilledPacket() (packet Packet, err error) { |  | ||||||
| 	// read V
 |  | ||||||
| 	buf := new(bytes.Buffer) |  | ||||||
| 	total := 0 |  | ||||||
| 	for { |  | ||||||
| 		valBuf := make([]byte, d.len.VSize()) |  | ||||||
| 		n, err := d.rd.Read(valBuf) |  | ||||||
| 		if n > 0 { |  | ||||||
| 			total += n |  | ||||||
| 			buf.Write(valBuf[:n]) |  | ||||||
| 		} |  | ||||||
| 		if total >= d.len.VSize() || err != nil { |  | ||||||
| 			break |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	packet = &StreamPacket{ |  | ||||||
| 		t:         d.tag, |  | ||||||
| 		l:         *d.len, |  | ||||||
| 		vBuf:      buf.Bytes(), |  | ||||||
| 		chunkMode: false, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return packet, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (d *Decoder) readTL() (err error) { |  | ||||||
| 	if d.rd == nil { |  | ||||||
| 		return errNilReader |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// read T
 |  | ||||||
| 	d.tag, err = spec.ReadT(d.rd) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// read L
 |  | ||||||
| 	d.len, err = spec.ReadL(d.rd) |  | ||||||
| 
 |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
							
								
								
									
										187
									
								
								encoder.go
								
								
								
								
							
							
						
						
									
										187
									
								
								encoder.go
								
								
								
								
							|  | @ -2,157 +2,76 @@ package mq_coder | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"io" | 	"fmt" | ||||||
| 
 | 	"git.hpds.cc/Component/mq_coder/encoding" | ||||||
| 	"git.hpds.cc/Component/mq_coder/spec" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Encoder is the tool for creating a packet easily
 | // Encoder will encode object to encoding
 | ||||||
| type Encoder struct { | type encoder struct { | ||||||
| 	tag           spec.T | 	seqID    byte | ||||||
| 	len           *spec.L | 	valbuf   []byte | ||||||
| 	valReader     io.Reader | 	isNode   bool | ||||||
| 	valReaderSize int | 	isArray  bool | ||||||
| 	nodes         map[int]Packet | 	buf      *bytes.Buffer | ||||||
| 	state         int | 	complete bool | ||||||
| 	size          int32 // size of value
 |  | ||||||
| 	isStreamMode  bool |  | ||||||
| 	valBuf        *bytes.Buffer |  | ||||||
| 	done          bool |  | ||||||
| 	seqId         int |  | ||||||
| 	isNodeMode    bool |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SetSeqId set sequenceId of a  packet, if this packet contains other
 | type iEncoder interface { | ||||||
| // packets, isNode should set to true
 | 	Encode() []byte | ||||||
| func (b *Encoder) SetSeqId(seqId int, isNode bool) { |  | ||||||
| 	// init
 |  | ||||||
| 	b.valBuf = new(bytes.Buffer) |  | ||||||
| 	b.nodes = make(map[int]Packet) |  | ||||||
| 	// set seqId
 |  | ||||||
| 	b.seqId = seqId |  | ||||||
| 	b.isNodeMode = isNode |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SetBytesV set bytes type as V
 | func (enc *encoder) GetValBuf() []byte { | ||||||
| func (b *Encoder) SetBytesV(buf []byte) { | 	return enc.valbuf | ||||||
| 	b.size += int32(len(buf)) |  | ||||||
| 	b.valBuf.Write(buf) |  | ||||||
| 	b.isStreamMode = false |  | ||||||
| 	b.state |= 0x04 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SetReaderV set io.Reader type as V
 | func (enc *encoder) IsEmpty() bool { | ||||||
| func (b *Encoder) SetReaderV(r io.Reader, size int) { | 	return len(enc.valbuf) == 0 | ||||||
| 	b.isStreamMode = true |  | ||||||
| 	b.valReader = r |  | ||||||
| 	b.state |= 0x04 |  | ||||||
| 	b.size += int32(size) |  | ||||||
| 	b.valReaderSize = size |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // AddPacket add a Packet child to this packet, this packet must be NodeMode
 | func (enc *encoder) AddBytes(buf []byte) { | ||||||
| func (b *Encoder) AddPacket(child Packet) error { | 	enc.valbuf = append(enc.valbuf, buf...) | ||||||
| 	// only packet is in node mode can add other packets
 | } | ||||||
| 	if !b.isNodeMode { | 
 | ||||||
| 		return errNotNodeMode | func (enc *encoder) addRawPacket(en iEncoder) { | ||||||
|  | 	enc.valbuf = append(enc.valbuf, en.Encode()...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // setTag write tag as seqID
 | ||||||
|  | func (enc *encoder) writeTag() { | ||||||
|  | 	if enc.seqID > 0x3F { | ||||||
|  | 		panic(fmt.Errorf("sid should be in [0..0x3F]")) | ||||||
| 	} | 	} | ||||||
| 
 | 	if enc.isNode { | ||||||
| 	if b.done { | 		enc.seqID = enc.seqID | 0x80 | ||||||
| 		return errInvalidAdding |  | ||||||
| 	} | 	} | ||||||
| 	b.nodes[child.SeqId()] = child | 	if enc.isArray { | ||||||
| 	buf := child.Bytes() | 		enc.seqID = enc.seqID | 0x40 | ||||||
| 	b.SetBytesV(buf) | 	} | ||||||
| 	return nil | 	enc.buf.WriteByte(enc.seqID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // AddStreamPacket will put a StreamPacket in chunked mode to current packet.
 | func (enc *encoder) writeLengthBuf() { | ||||||
| func (b *Encoder) AddStreamPacket(child Packet) (err error) { | 	vallen := len(enc.valbuf) | ||||||
| 	// if this packet is in stream mode, can not add any packets
 | 	size := encoding.SizeOfPVarInt32(int32(vallen)) | ||||||
| 	if b.done { | 	codec := encoding.VarCodec{Size: size} | ||||||
| 		return errInvalidAdding | 	tmp := make([]byte, size) | ||||||
| 	} | 	err := codec.EncodePVarInt32(tmp, int32(vallen)) | ||||||
| 
 |  | ||||||
| 	// only accept packet in stream mode
 |  | ||||||
| 	if !child.IsStreamMode() { |  | ||||||
| 		return errNonStreamPacket |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// set the valReader of this packet to the child's
 |  | ||||||
| 	b.valReader = child.VReader() |  | ||||||
| 
 |  | ||||||
| 	// valReaderSize will be the same as child's
 |  | ||||||
| 	b.valReaderSize = child.VSize() |  | ||||||
| 	// add this child packet
 |  | ||||||
| 	b.nodes[child.SeqId()] = child |  | ||||||
| 	// add the size of child's V to L of this packet
 |  | ||||||
| 	b.size += int32(child.Size()) |  | ||||||
| 	// put the bytes of child to valBuf
 |  | ||||||
| 	buf := child.Bytes() |  | ||||||
| 	b.valBuf.Write(buf) |  | ||||||
| 	// update state
 |  | ||||||
| 	b.state |= 0x04 |  | ||||||
| 	b.isStreamMode = true |  | ||||||
| 	b.done = true |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Packet return a Packet instance.
 |  | ||||||
| func (b *Encoder) Packet() (Packet, error) { |  | ||||||
| 	err := b.generateT() |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		panic(err) | ||||||
| 	} | 	} | ||||||
| 
 | 	enc.buf.Write(tmp) | ||||||
| 	err = b.generateL() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if b.state != 0x07 { |  | ||||||
| 		return nil, errBuildIncomplete |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if b.isStreamMode { |  | ||||||
| 		return &StreamPacket{ |  | ||||||
| 			t:         b.tag, |  | ||||||
| 			l:         *b.len, |  | ||||||
| 			vr:        b.valReader, |  | ||||||
| 			vBuf:      b.valBuf.Bytes(), |  | ||||||
| 			chunkMode: true, |  | ||||||
| 			chunkSize: b.valReaderSize, |  | ||||||
| 		}, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// not streaming mode
 |  | ||||||
| 	return &StreamPacket{ |  | ||||||
| 		t:         b.tag, |  | ||||||
| 		l:         *b.len, |  | ||||||
| 		vBuf:      b.valBuf.Bytes(), |  | ||||||
| 		chunkMode: false, |  | ||||||
| 	}, err |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // will generate T of a TLV.
 | // Encode returns a final Y3 encoded byte slice
 | ||||||
| func (b *Encoder) generateT() error { | func (enc *encoder) Encode() []byte { | ||||||
| 	t, err := spec.NewT(b.seqId) | 	if !enc.complete { | ||||||
| 	t.SetNodeMode(b.isNodeMode) | 		// Tag
 | ||||||
| 	if err != nil { | 		enc.writeTag() | ||||||
| 		return err | 		// Len
 | ||||||
|  | 		enc.writeLengthBuf() | ||||||
|  | 		// Val
 | ||||||
|  | 		enc.buf.Write(enc.valbuf) | ||||||
|  | 		enc.complete = true | ||||||
| 	} | 	} | ||||||
| 	b.tag = t | 	return enc.buf.Bytes() | ||||||
| 	b.state |= 0x01 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // will generate L of a TLV.
 |  | ||||||
| func (b *Encoder) generateL() error { |  | ||||||
| 	l, err := spec.NewL(int(b.size)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	b.len = &l |  | ||||||
| 	b.state |= 0x02 |  | ||||||
| 	return nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,98 +0,0 @@ | ||||||
| package mq_coder |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"git.hpds.cc/Component/mq_coder/encoding" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // SetUtf8StringV set utf-8 string type value as V
 |  | ||||||
| func (b *Encoder) SetUtf8StringV(v string) { |  | ||||||
| 	buf := []byte(v) |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetInt32V set an int32 type value as V
 |  | ||||||
| func (b *Encoder) SetInt32V(v int32) error { |  | ||||||
| 	size := encoding.SizeOfNVarInt32(v) |  | ||||||
| 	codec := encoding.VarCodec{Size: size} |  | ||||||
| 	buf := make([]byte, size) |  | ||||||
| 	err := codec.EncodeNVarInt32(buf, v) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetUInt32V set an uint32 type value as V
 |  | ||||||
| func (b *Encoder) SetUInt32V(v uint32) error { |  | ||||||
| 	size := encoding.SizeOfNVarUInt32(v) |  | ||||||
| 	codec := encoding.VarCodec{Size: size} |  | ||||||
| 	buf := make([]byte, size) |  | ||||||
| 	err := codec.EncodeNVarUInt32(buf, v) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetInt64V set an int64 type value as V
 |  | ||||||
| func (b *Encoder) SetInt64V(v int64) error { |  | ||||||
| 	size := encoding.SizeOfNVarInt64(v) |  | ||||||
| 	codec := encoding.VarCodec{Size: size} |  | ||||||
| 	buf := make([]byte, size) |  | ||||||
| 	err := codec.EncodeNVarInt64(buf, v) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetUInt64V set an uint64 type value as V
 |  | ||||||
| func (b *Encoder) SetUInt64V(v uint64) error { |  | ||||||
| 	size := encoding.SizeOfNVarUInt64(v) |  | ||||||
| 	codec := encoding.VarCodec{Size: size} |  | ||||||
| 	buf := make([]byte, size) |  | ||||||
| 	err := codec.EncodeNVarUInt64(buf, v) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetFloat32V set a float32 type value as V
 |  | ||||||
| func (b *Encoder) SetFloat32V(v float32) error { |  | ||||||
| 	size := encoding.SizeOfVarFloat32(v) |  | ||||||
| 	codec := encoding.VarCodec{Size: size} |  | ||||||
| 	buf := make([]byte, size) |  | ||||||
| 	err := codec.EncodeVarFloat32(buf, v) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetFloat64V set a float64 type value as V
 |  | ||||||
| func (b *Encoder) SetFloat64V(v float64) error { |  | ||||||
| 	size := encoding.SizeOfVarFloat64(v) |  | ||||||
| 	codec := encoding.VarCodec{Size: size} |  | ||||||
| 	buf := make([]byte, size) |  | ||||||
| 	err := codec.EncodeVarFloat64(buf, v) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetBoolV set bool type value as V
 |  | ||||||
| func (b *Encoder) SetBoolV(v bool) { |  | ||||||
| 	var size = encoding.SizeOfPVarUInt32(uint32(1)) |  | ||||||
| 	codec := encoding.VarCodec{Size: size} |  | ||||||
| 	buf := make([]byte, size) |  | ||||||
| 	_ = codec.EncodePVarBool(buf, v) |  | ||||||
| 	b.SetBytesV(buf) |  | ||||||
| } |  | ||||||
|  | @ -0,0 +1,96 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"errors" | ||||||
|  | 
 | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/encoding" | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/utils" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func parsePayload(b []byte) (consumedBytes int, ifNodePacket bool, np *NodePacket, pp *PrimitivePacket, err error) { | ||||||
|  | 	if len(b) == 0 { | ||||||
|  | 		return 0, false, nil, nil, errors.New("parsePacket params can not be nil") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pos := 0 | ||||||
|  | 	// NodePacket
 | ||||||
|  | 	if ok := utils.IsNodePacket(b[pos]); ok { | ||||||
|  | 		np = &NodePacket{} | ||||||
|  | 		endPos, err := DecodeToNodePacket(b, np) | ||||||
|  | 		return endPos, true, np, nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pp = &PrimitivePacket{} | ||||||
|  | 	state, err := DecodeToPrimitivePacket(b, pp) | ||||||
|  | 	return state.ConsumedBytes, false, nil, pp, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DecodeToNodePacket parse out whole buffer to a NodePacket
 | ||||||
|  | func DecodeToNodePacket(buf []byte, pct *NodePacket) (consumedBytes int, err error) { | ||||||
|  | 	if len(buf) == 0 { | ||||||
|  | 		return 0, errors.New("empty buf") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pct.packet = &packet{ | ||||||
|  | 		valBuf: buf, | ||||||
|  | 		buf:    &bytes.Buffer{}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pct.NodePackets = map[byte]NodePacket{} | ||||||
|  | 	pct.PrimitivePackets = map[byte]PrimitivePacket{} | ||||||
|  | 
 | ||||||
|  | 	pos := 0 | ||||||
|  | 
 | ||||||
|  | 	// `Tag`
 | ||||||
|  | 	tag := NewTag(buf[pos]) | ||||||
|  | 	pct.packet.tag = tag | ||||||
|  | 	pct.buf.WriteByte(buf[pos]) | ||||||
|  | 	pos++ | ||||||
|  | 
 | ||||||
|  | 	// `Length`: the type is `varint`
 | ||||||
|  | 	tmpBuf := buf[pos:] | ||||||
|  | 	var valLen int32 | ||||||
|  | 	codec := encoding.VarCodec{} | ||||||
|  | 	err = codec.DecodePVarInt32(tmpBuf, &valLen) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	pct.packet.length = int(valLen) | ||||||
|  | 	pct.buf.Write(buf[pos : pos+codec.Size]) | ||||||
|  | 	pos += codec.Size | ||||||
|  | 	// if `Length` is 0, means empty node packet
 | ||||||
|  | 	if valLen == 0 { | ||||||
|  | 		return pos, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// `Value`
 | ||||||
|  | 	// `raw` is pct.Length() length
 | ||||||
|  | 	vl := int(valLen) | ||||||
|  | 	if vl < 0 { | ||||||
|  | 		return pos, errors.New("found L of V smaller than 0") | ||||||
|  | 	} | ||||||
|  | 	endPos := pos + vl | ||||||
|  | 	pct.packet.valBuf = buf[pos:endPos] | ||||||
|  | 	pct.buf.Write(buf[pos:endPos]) | ||||||
|  | 
 | ||||||
|  | 	// Parse value to Packet
 | ||||||
|  | 	for { | ||||||
|  | 		if pos >= endPos || pos >= len(buf) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		_p, isNode, np, pp, err := parsePayload(buf[pos:endPos]) | ||||||
|  | 		pos += _p | ||||||
|  | 		if err != nil { | ||||||
|  | 			return 0, err | ||||||
|  | 		} | ||||||
|  | 		if isNode { | ||||||
|  | 			pct.NodePackets[np.packet.tag.SeqId()] = *np | ||||||
|  | 		} else { | ||||||
|  | 			pct.PrimitivePackets[byte(pp.SeqId())] = *pp | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	consumedBytes = endPos | ||||||
|  | 	return consumedBytes, nil | ||||||
|  | } | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // NodePacketEncoder used for encode a node packet
 | ||||||
|  | type NodePacketEncoder struct { | ||||||
|  | 	*encoder | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewNodePacketEncoder returns an Encoder for node packet
 | ||||||
|  | func NewNodePacketEncoder(sid byte) *NodePacketEncoder { | ||||||
|  | 	nodeEnc := &NodePacketEncoder{ | ||||||
|  | 		encoder: &encoder{ | ||||||
|  | 			isNode: true, | ||||||
|  | 			buf:    new(bytes.Buffer), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	nodeEnc.seqID = sid | ||||||
|  | 	return nodeEnc | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddNodePacket add new node to this node
 | ||||||
|  | func (enc *NodePacketEncoder) AddNodePacket(np *NodePacketEncoder) { | ||||||
|  | 	enc.addRawPacket(np) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddPrimitivePacket add new primitive to this node
 | ||||||
|  | func (enc *NodePacketEncoder) AddPrimitivePacket(np *PrimitivePacketEncoder) { | ||||||
|  | 	enc.addRawPacket(np) | ||||||
|  | } | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | // NodePacket describes complex values
 | ||||||
|  | type NodePacket struct { | ||||||
|  | 	*packet | ||||||
|  | 	// NodePackets store all the node packets
 | ||||||
|  | 	NodePackets map[byte]NodePacket | ||||||
|  | 	// PrimitivePackets store all the primitive packets
 | ||||||
|  | 	PrimitivePackets map[byte]PrimitivePacket | ||||||
|  | } | ||||||
							
								
								
									
										160
									
								
								packet.go
								
								
								
								
							
							
						
						
									
										160
									
								
								packet.go
								
								
								
								
							|  | @ -2,155 +2,37 @@ package mq_coder | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"io" |  | ||||||
| 
 |  | ||||||
| 	"git.hpds.cc/Component/mq_coder/encoding" |  | ||||||
| 	"git.hpds.cc/Component/mq_coder/spec" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // StreamPacket implement the Packet interface.
 | // packet is the base type of the NodePacket and PrimitivePacket
 | ||||||
| type StreamPacket struct { | type packet struct { | ||||||
| 	t         spec.T | 	tag    *Tag | ||||||
| 	l         spec.L | 	length int | ||||||
| 	vBuf      []byte | 	valBuf []byte | ||||||
| 	vr        io.Reader | 	buf    *bytes.Buffer | ||||||
| 	chunkMode bool |  | ||||||
| 	chunkSize int |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var _ Packet = &StreamPacket{} | // GetRawBytes get all raw bytes of this packet
 | ||||||
| 
 | func (bp *packet) GetRawBytes() []byte { | ||||||
| // SeqId returns the sequenceId of this packet
 | 	return bp.buf.Bytes() | ||||||
| func (p *StreamPacket) SeqId() int { return p.t.Sid() } |  | ||||||
| 
 |  | ||||||
| // Size returns the size of whole packet.
 |  | ||||||
| func (p *StreamPacket) Size() int { |  | ||||||
| 	// T.Size + L.Size + V.Size
 |  | ||||||
| 	return p.t.Size() + p.l.Size() + p.l.VSize() |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // VSize returns the size of V.
 | // Length return the length of Val this packet
 | ||||||
| func (p *StreamPacket) VSize() int { return p.l.VSize() } | func (bp *packet) Length() int { | ||||||
| 
 | 	return bp.length | ||||||
| // Bytes return the raw bytes of this packet. V will be absent if
 |  | ||||||
| // is in chunked mode
 |  | ||||||
| func (p *StreamPacket) Bytes() []byte { |  | ||||||
| 	buf := new(bytes.Buffer) |  | ||||||
| 	// the raw bytes of T and L
 |  | ||||||
| 	p.writeTL(buf) |  | ||||||
| 	// p.valBuf stores the raw bytes of V
 |  | ||||||
| 	buf.Write(p.vBuf) |  | ||||||
| 
 |  | ||||||
| 	return buf.Bytes() |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // VReader return an io.Reader which can be read as the content of V.
 | // SeqId returns Tag of this packet
 | ||||||
| func (p *StreamPacket) VReader() io.Reader { | func (bp *packet) SeqId() byte { | ||||||
| 	if !p.chunkMode { | 	return bp.tag.SeqId() | ||||||
| 		return bytes.NewReader(p.vBuf) |  | ||||||
| 	} |  | ||||||
| 	return p.vr |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Reader return an io.Reader which can be read as the whole bytes of
 | // IsSlice determine if the current node is a Slice
 | ||||||
| // this packet. This function only available if this V of packet is in
 | func (bp *packet) IsSlice() bool { | ||||||
| // chunked mode.
 | 	return bp.tag.IsSlice() | ||||||
| func (p *StreamPacket) Reader() io.Reader { |  | ||||||
| 	if !p.chunkMode { |  | ||||||
| 		buf := new(bytes.Buffer) |  | ||||||
| 		buf.Write(p.t.Bytes()) |  | ||||||
| 		buf.Write(p.l.Bytes()) |  | ||||||
| 		buf.Write(p.vBuf) |  | ||||||
| 		return buf |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	buf := new(bytes.Buffer) |  | ||||||
| 	// T and L of this packet
 |  | ||||||
| 	p.writeTL(buf) |  | ||||||
| 	// V of this packet
 |  | ||||||
| 	buf.Write(p.vBuf) |  | ||||||
| 
 |  | ||||||
| 	return &chunkVReader{ |  | ||||||
| 		buf:        buf, |  | ||||||
| 		src:        p.vr, |  | ||||||
| 		totalSize:  p.Size(), |  | ||||||
| 		ChunkVSize: p.VSize(), |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // IsStreamMode returns a bool value indicates if the V of
 | // GetValBuf get raw buffer of Val of this packet
 | ||||||
| // this packet is in stream mode
 | func (bp *packet) GetValBuf() []byte { | ||||||
| func (p *StreamPacket) IsStreamMode() bool { | 	return bp.valBuf | ||||||
| 	return p.chunkMode |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // IsNodeMode returns a bool value indicates if this packet
 |  | ||||||
| // is node mode
 |  | ||||||
| func (p *StreamPacket) IsNodeMode() bool { |  | ||||||
| 	return p.t.IsNodeMode() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // write the raw bytes of T and L to given buf
 |  | ||||||
| func (p *StreamPacket) writeTL(buf *bytes.Buffer) { |  | ||||||
| 	buf.Write(p.t.Bytes()) |  | ||||||
| 	buf.Write(p.l.Bytes()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // BytesV return V as bytes
 |  | ||||||
| func (p *StreamPacket) BytesV() []byte { |  | ||||||
| 	return p.vBuf |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // UTF8StringV return V as utf-8 string
 |  | ||||||
| func (p *StreamPacket) Utf8StringV() string { |  | ||||||
| 	return string(p.vBuf) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Int32V return V as int32
 |  | ||||||
| func (p *StreamPacket) Int32V() (val int32, err error) { |  | ||||||
| 	codec := encoding.VarCodec{Size: len(p.vBuf)} |  | ||||||
| 	err = codec.DecodeNVarInt32(p.vBuf, &val) |  | ||||||
| 	return val, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // UInt32V return V as uint32
 |  | ||||||
| func (p *StreamPacket) UInt32V() (val uint32, err error) { |  | ||||||
| 	codec := encoding.VarCodec{Size: len(p.vBuf)} |  | ||||||
| 	err = codec.DecodeNVarUInt32(p.vBuf, &val) |  | ||||||
| 	return val, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Int64V return V as int64
 |  | ||||||
| func (p *StreamPacket) Int64V() (val int64, err error) { |  | ||||||
| 	codec := encoding.VarCodec{Size: len(p.vBuf)} |  | ||||||
| 	err = codec.DecodeNVarInt64(p.vBuf, &val) |  | ||||||
| 	return val, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // UInt64V return V as uint64
 |  | ||||||
| func (p *StreamPacket) UInt64V() (val uint64, err error) { |  | ||||||
| 	codec := encoding.VarCodec{Size: len(p.vBuf)} |  | ||||||
| 	err = codec.DecodeNVarUInt64(p.vBuf, &val) |  | ||||||
| 	return val, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Float32V return V as float32
 |  | ||||||
| func (p *StreamPacket) Float32V() (val float32, err error) { |  | ||||||
| 	codec := encoding.VarCodec{Size: len(p.vBuf)} |  | ||||||
| 	err = codec.DecodeVarFloat32(p.vBuf, &val) |  | ||||||
| 	return val, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Float64V return V as float64
 |  | ||||||
| func (p *StreamPacket) Float64V() (val float64, err error) { |  | ||||||
| 	codec := encoding.VarCodec{Size: len(p.vBuf)} |  | ||||||
| 	err = codec.DecodeVarFloat64(p.vBuf, &val) |  | ||||||
| 	return val, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // BoolV return V as bool
 |  | ||||||
| func (p *StreamPacket) BoolV() (val bool, err error) { |  | ||||||
| 	codec := encoding.VarCodec{Size: len(p.vBuf)} |  | ||||||
| 	err = codec.DecodePVarBool(p.vBuf, &val) |  | ||||||
| 	return val, err |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,100 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 
 | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/encoding" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	ErrMalformed = errors.New("coder.ReadPacket: malformed") | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // ReadPacket will try to read encoded packet from the reader
 | ||||||
|  | func ReadPacket(reader io.Reader) ([]byte, error) { | ||||||
|  | 	tag, err := readByte(reader) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	// buf will contain a complete encoded handshakeFrame
 | ||||||
|  | 	buf := bytes.Buffer{} | ||||||
|  | 
 | ||||||
|  | 	// the first byte is coder.Tag
 | ||||||
|  | 	// write coder.Tag bytes
 | ||||||
|  | 	buf.WriteByte(tag) | ||||||
|  | 
 | ||||||
|  | 	// read y3.Length bytes, a varInt format
 | ||||||
|  | 	lenBuf := bytes.Buffer{} | ||||||
|  | 	for { | ||||||
|  | 		b, e := readByte(reader) | ||||||
|  | 		if e != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		lenBuf.WriteByte(b) | ||||||
|  | 		if b&0x80 != 0x80 { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// parse to coder.Length
 | ||||||
|  | 	var length int32 | ||||||
|  | 	codec := encoding.VarCodec{} | ||||||
|  | 	err = codec.DecodePVarInt32(lenBuf.Bytes(), &length) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, ErrMalformed | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// validate len decoded from stream
 | ||||||
|  | 	if length < 0 { | ||||||
|  | 		return nil, fmt.Errorf("coder.ReadPacket() get lenBuf=(%# x), decode len=(%v)", lenBuf.Bytes(), length) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// write coder.Length bytes
 | ||||||
|  | 	buf.Write(lenBuf.Bytes()) | ||||||
|  | 
 | ||||||
|  | 	// read next {len} bytes as coder.Value
 | ||||||
|  | 	valBuf := bytes.Buffer{} | ||||||
|  | 
 | ||||||
|  | 	// every batch read 512 bytes, if next reads < 512, read
 | ||||||
|  | 	var count int | ||||||
|  | 	for { | ||||||
|  | 		batchReadSize := 1024 * 1024 | ||||||
|  | 		var tmpBuf []byte | ||||||
|  | 		if int(length)-count < batchReadSize { | ||||||
|  | 			tmpBuf = make([]byte, int(length)-count) | ||||||
|  | 		} else { | ||||||
|  | 			tmpBuf = make([]byte, batchReadSize) | ||||||
|  | 		} | ||||||
|  | 		p, e := reader.Read(tmpBuf) | ||||||
|  | 		count += p | ||||||
|  | 		if e != nil { | ||||||
|  | 			if e == io.EOF { | ||||||
|  | 				valBuf.Write(tmpBuf[:p]) | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 			return nil, fmt.Errorf("y3 parse valBuf error: %v", err) | ||||||
|  | 		} | ||||||
|  | 		valBuf.Write(tmpBuf[:p]) | ||||||
|  | 		if count == int(length) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if count < int(length) { | ||||||
|  | 		// return nil, fmt.Errorf("[y3] p should == len when getting y3 value buffer, len=%d, p=%d", length, count)
 | ||||||
|  | 		return nil, ErrMalformed | ||||||
|  | 	} | ||||||
|  | 	// write coder.Value bytes
 | ||||||
|  | 	buf.Write(valBuf.Bytes()) | ||||||
|  | 
 | ||||||
|  | 	return buf.Bytes(), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func readByte(reader io.Reader) (byte, error) { | ||||||
|  | 	var b [1]byte | ||||||
|  | 	_, err := reader.Read(b[:]) | ||||||
|  | 	return b[0], err | ||||||
|  | } | ||||||
|  | @ -0,0 +1,88 @@ | ||||||
|  | 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 `Varint` 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 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,112 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 
 | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/encoding" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // PrimitivePacketEncoder used for encode a primitive packet
 | ||||||
|  | type PrimitivePacketEncoder struct { | ||||||
|  | 	*encoder | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewPrimitivePacketEncoder return an Encoder for primitive packet
 | ||||||
|  | func NewPrimitivePacketEncoder(sid byte) *PrimitivePacketEncoder { | ||||||
|  | 	prim := &PrimitivePacketEncoder{ | ||||||
|  | 		encoder: &encoder{ | ||||||
|  | 			isNode: false, | ||||||
|  | 			buf:    new(bytes.Buffer), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	prim.seqID = sid | ||||||
|  | 	return prim | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetInt32Value encode int32 value
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetInt32Value(v int32) { | ||||||
|  | 	size := encoding.SizeOfNVarInt32(v) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	enc.valbuf = make([]byte, size) | ||||||
|  | 	err := codec.EncodeNVarInt32(enc.valbuf, v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetUInt32Value encode uint32 value
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetUInt32Value(v uint32) { | ||||||
|  | 	size := encoding.SizeOfNVarUInt32(v) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	enc.valbuf = make([]byte, size) | ||||||
|  | 	err := codec.EncodeNVarUInt32(enc.valbuf, v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetInt64Value encode int64 value
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetInt64Value(v int64) { | ||||||
|  | 	size := encoding.SizeOfNVarInt64(v) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	enc.valbuf = make([]byte, size) | ||||||
|  | 	err := codec.EncodeNVarInt64(enc.valbuf, v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetUInt64Value encode uint64 value
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetUInt64Value(v uint64) { | ||||||
|  | 	size := encoding.SizeOfNVarUInt64(v) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	enc.valbuf = make([]byte, size) | ||||||
|  | 	err := codec.EncodeNVarUInt64(enc.valbuf, v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetFloat32Value encode float32 value
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetFloat32Value(v float32) { | ||||||
|  | 	var size = encoding.SizeOfVarFloat32(v) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	enc.valbuf = make([]byte, size) | ||||||
|  | 	err := codec.EncodeVarFloat32(enc.valbuf, v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetFloat64Value encode float64 value
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetFloat64Value(v float64) { | ||||||
|  | 	var size = encoding.SizeOfVarFloat64(v) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	enc.valbuf = make([]byte, size) | ||||||
|  | 	err := codec.EncodeVarFloat64(enc.valbuf, v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetBoolValue encode bool value
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetBoolValue(v bool) { | ||||||
|  | 	var size = encoding.SizeOfPVarUInt32(uint32(1)) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	enc.valbuf = make([]byte, size) | ||||||
|  | 	err := codec.EncodePVarBool(enc.valbuf, v) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetStringValue encode string
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetStringValue(v string) { | ||||||
|  | 	enc.valbuf = []byte(v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetBytesValue encode []byte
 | ||||||
|  | func (enc *PrimitivePacketEncoder) SetBytesValue(v []byte) { | ||||||
|  | 	enc.valbuf = v | ||||||
|  | } | ||||||
|  | @ -0,0 +1,100 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/encoding" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // 最小长度为2个字节
 | ||||||
|  | const primitivePacketBufferMinimalLength = 2 | ||||||
|  | 
 | ||||||
|  | // PrimitivePacket describes primitive value type,
 | ||||||
|  | type PrimitivePacket struct { | ||||||
|  | 	*packet | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToInt32 parse raw as int32 value
 | ||||||
|  | func (p *PrimitivePacket) ToInt32() (int32, error) { | ||||||
|  | 	var val int32 | ||||||
|  | 	codec := encoding.VarCodec{Size: len(p.valBuf)} | ||||||
|  | 	err := codec.DecodeNVarInt32(p.packet.valBuf, &val) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToUInt32 parse raw as uint32 value
 | ||||||
|  | func (p *PrimitivePacket) ToUInt32() (uint32, error) { | ||||||
|  | 	var val uint32 | ||||||
|  | 	codec := encoding.VarCodec{Size: len(p.valBuf)} | ||||||
|  | 	err := codec.DecodeNVarUInt32(p.valBuf, &val) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToInt64 parse raw as int64 value
 | ||||||
|  | func (p *PrimitivePacket) ToInt64() (int64, error) { | ||||||
|  | 	var val int64 | ||||||
|  | 	codec := encoding.VarCodec{Size: len(p.valBuf)} | ||||||
|  | 	err := codec.DecodeNVarInt64(p.valBuf, &val) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToUInt64 parse raw as uint64 value
 | ||||||
|  | func (p *PrimitivePacket) ToUInt64() (uint64, error) { | ||||||
|  | 	var val uint64 | ||||||
|  | 	codec := encoding.VarCodec{Size: len(p.valBuf)} | ||||||
|  | 	err := codec.DecodeNVarUInt64(p.valBuf, &val) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToFloat32 parse raw as float32 value
 | ||||||
|  | func (p *PrimitivePacket) ToFloat32() (float32, error) { | ||||||
|  | 	var val float32 | ||||||
|  | 	codec := encoding.VarCodec{Size: len(p.valBuf)} | ||||||
|  | 	err := codec.DecodeVarFloat32(p.valBuf, &val) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToFloat64 parse raw as float64 value
 | ||||||
|  | func (p *PrimitivePacket) ToFloat64() (float64, error) { | ||||||
|  | 	var val float64 | ||||||
|  | 	codec := encoding.VarCodec{Size: len(p.valBuf)} | ||||||
|  | 	err := codec.DecodeVarFloat64(p.valBuf, &val) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToBool parse raw as bool value
 | ||||||
|  | func (p *PrimitivePacket) ToBool() (bool, error) { | ||||||
|  | 	var val bool | ||||||
|  | 	codec := encoding.VarCodec{Size: len(p.valBuf)} | ||||||
|  | 	err := codec.DecodePVarBool(p.valBuf, &val) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToUTF8String parse raw data as string value
 | ||||||
|  | func (p *PrimitivePacket) ToUTF8String() (string, error) { | ||||||
|  | 	return string(p.valBuf), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ToBytes returns raw buffer data
 | ||||||
|  | func (p *PrimitivePacket) ToBytes() []byte { | ||||||
|  | 	return p.valBuf | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								spec/spec.go
								
								
								
								
							
							
						
						
									
										26
									
								
								spec/spec.go
								
								
								
								
							|  | @ -1,26 +0,0 @@ | ||||||
| package spec |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"io" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( |  | ||||||
| 	maxSeqId     = 0x3F |  | ||||||
| 	flagBitNode  = 0x80 |  | ||||||
| 	wipeFlagBits = 0x3F |  | ||||||
| 	msb          = 0x80 |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| var ( |  | ||||||
| 	errInvalidSeqId = errors.New("coder.Builder: SeqId should >= 0 and =< 0x3F") |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func readByte(reader io.Reader) (byte, error) { |  | ||||||
| 	var b [1]byte |  | ||||||
| 	n, err := reader.Read(b[:]) |  | ||||||
| 	if n == 0 { |  | ||||||
| 		return 0x00, err |  | ||||||
| 	} |  | ||||||
| 	return b[0], err |  | ||||||
| } |  | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| @startuml |  | ||||||
| namespace spec { |  | ||||||
|     class L << (S,Aquamarine) >> { |  | ||||||
|         - buf []byte |  | ||||||
|         - size int |  | ||||||
|         - len int |  | ||||||
| 
 |  | ||||||
|         + Bytes() []byte |  | ||||||
|         + Size() int |  | ||||||
|         + VSize() int |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
|     class T << (S,Aquamarine) >> { |  | ||||||
|         + Sid() int |  | ||||||
|         + Bytes() []byte |  | ||||||
|         + IsNodeMode() bool |  | ||||||
|         + SetNodeMode(flag bool) |  | ||||||
|         + Size() int |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
|     class spec.T << (T, #FF7700) >>  { |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| "__builtin__.byte" #.. "spec.T" |  | ||||||
| @enduml |  | ||||||
|  | @ -1,54 +0,0 @@ | ||||||
| package spec |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"io" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // T is the Tag in a TLV structure
 |  | ||||||
| type T byte |  | ||||||
| 
 |  | ||||||
| // NewT returns a T with sequenceID. If this packet contains other
 |  | ||||||
| // packets, this packet will be a "node packet", the T of this packet
 |  | ||||||
| // will set MSB to T.
 |  | ||||||
| func NewT(seqId int) (T, error) { |  | ||||||
| 	if seqId < 0 || seqId > maxSeqId { |  | ||||||
| 		return 0, errInvalidSeqId |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return T(seqId), nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Sid returns the sequenceId of this packet.
 |  | ||||||
| func (t T) Sid() int { |  | ||||||
| 	return int(t & wipeFlagBits) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Bytes returns raw bytes of T.
 |  | ||||||
| func (t T) Bytes() []byte { |  | ||||||
| 	return []byte{byte(t)} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // IsNodeMode will return true if this packet contains other packets.
 |  | ||||||
| // Otherwise, return false.
 |  | ||||||
| func (t T) IsNodeMode() bool { |  | ||||||
| 	return t&flagBitNode == flagBitNode |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SetNodeMode will set T to indicates this packet contains
 |  | ||||||
| // other packets.
 |  | ||||||
| func (t *T) SetNodeMode(flag bool) { |  | ||||||
| 	if flag { |  | ||||||
| 		*t |= flagBitNode |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Size return the size of T raw bytes.
 |  | ||||||
| func (t T) Size() int { |  | ||||||
| 	return 1 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ReadT read T from a bufio.Reader
 |  | ||||||
| func ReadT(rd io.Reader) (T, error) { |  | ||||||
| 	b, err := readByte(rd) |  | ||||||
| 	return T(b), err |  | ||||||
| } |  | ||||||
|  | @ -1,89 +0,0 @@ | ||||||
| package spec |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"bytes" |  | ||||||
| 	"errors" |  | ||||||
| 	"io" |  | ||||||
| 
 |  | ||||||
| 	"git.hpds.cc/Component/mq_coder/encoding" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // L is the Length in a TLV structure
 |  | ||||||
| type L struct { |  | ||||||
| 	buf  []byte |  | ||||||
| 	size int |  | ||||||
| 	len  int |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // NewL will take an int type len as parameter and return L to
 |  | ||||||
| // represent the size of V in a TLV. an integer will be encoded as
 |  | ||||||
| // a PVarInt32 type to represent the value.
 |  | ||||||
| func NewL(len int) (L, error) { |  | ||||||
| 	var l = L{} |  | ||||||
| 	if len < -1 { |  | ||||||
| 		return l, errors.New("y3.L: len can't less than -1") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	valLen := int32(len) |  | ||||||
| 	l.size = encoding.SizeOfPVarInt32(valLen) |  | ||||||
| 	codec := encoding.VarCodec{Size: l.size} |  | ||||||
| 	tmp := make([]byte, l.size) |  | ||||||
| 	err := codec.EncodePVarInt32(tmp, valLen) |  | ||||||
| 	if err != nil { |  | ||||||
| 		panic(err) |  | ||||||
| 	} |  | ||||||
| 	l.buf = make([]byte, l.size) |  | ||||||
| 	copy(l.buf, tmp) |  | ||||||
| 	l.len = len |  | ||||||
| 	return l, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Bytes will return the raw bytes of L.
 |  | ||||||
| func (l L) Bytes() []byte { |  | ||||||
| 	return l.buf |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Size returns how many bytes used to represent this L.
 |  | ||||||
| func (l L) Size() int { |  | ||||||
| 	return l.size |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // VSize returns the size of V.
 |  | ||||||
| func (l L) VSize() int { |  | ||||||
| 	return int(l.len) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ReadL read L from bufio.Reader
 |  | ||||||
| func ReadL(r io.Reader) (*L, error) { |  | ||||||
| 	lenBuf := bytes.Buffer{} |  | ||||||
| 	for { |  | ||||||
| 		b, err := readByte(r) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		lenBuf.WriteByte(b) |  | ||||||
| 		if b&msb != msb { |  | ||||||
| 			break |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	buf := lenBuf.Bytes() |  | ||||||
| 
 |  | ||||||
| 	// decode to L
 |  | ||||||
| 	length, err := decodeL(buf) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return &L{ |  | ||||||
| 		buf:  buf, |  | ||||||
| 		len:  int(length), |  | ||||||
| 		size: len(buf), |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func decodeL(buf []byte) (length int32, err error) { |  | ||||||
| 	codec := encoding.VarCodec{} |  | ||||||
| 	err = codec.DecodePVarInt32(buf, &length) |  | ||||||
| 	return length, err |  | ||||||
| } |  | ||||||
|  | @ -0,0 +1,115 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 
 | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/encoding" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // StreamReader read an coder packet from io.Reader, and return
 | ||||||
|  | // the ValReader after decode out Tag and Len
 | ||||||
|  | type StreamReader struct { | ||||||
|  | 	src io.Reader | ||||||
|  | 	// Tag of a coder packet
 | ||||||
|  | 	Tag byte | ||||||
|  | 	// Len of a coder packet
 | ||||||
|  | 	Len int | ||||||
|  | 	// Val of a coder packet
 | ||||||
|  | 	Val io.Reader | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewStreamParser create a new coder StreamReader
 | ||||||
|  | func NewStreamParser(reader io.Reader) *StreamReader { | ||||||
|  | 	return &StreamReader{ | ||||||
|  | 		src: reader, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (sr *StreamReader) GetValBuffer() ([]byte, error) { | ||||||
|  | 	buf, err := io.ReadAll(sr.Val) | ||||||
|  | 	return buf, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Do must run in a goroutine
 | ||||||
|  | func (sr *StreamReader) Do() error { | ||||||
|  | 	if sr.src == nil { | ||||||
|  | 		return errors.New("coder: nil source reader") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tag, err := readByte(sr.src) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// the first byte is coder.Tag
 | ||||||
|  | 	sr.Tag = tag | ||||||
|  | 
 | ||||||
|  | 	// read coder.Length bytes, a varInt format
 | ||||||
|  | 	lenBuf := bytes.Buffer{} | ||||||
|  | 	for { | ||||||
|  | 		b, e := readByte(sr.src) | ||||||
|  | 		if e != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		lenBuf.WriteByte(b) | ||||||
|  | 		if b&0x80 != 0x80 { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// parse to coder.Length
 | ||||||
|  | 	var length int32 | ||||||
|  | 	codec := encoding.VarCodec{} | ||||||
|  | 	err = codec.DecodePVarInt32(lenBuf.Bytes(), &length) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// validate len decoded from stream
 | ||||||
|  | 	if length < 0 { | ||||||
|  | 		return fmt.Errorf("coder: streamParse() get lenBuf=(%# x), decode len=(%v)", lenBuf.Bytes(), length) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sr.Len = int(length) | ||||||
|  | 
 | ||||||
|  | 	// read next {len} bytes as coder.Value
 | ||||||
|  | 	sr.Val = &valR{ | ||||||
|  | 		length: int(length), | ||||||
|  | 		src:    sr.src, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type valR struct { | ||||||
|  | 	length int | ||||||
|  | 	off    int | ||||||
|  | 	src    io.Reader | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (r *valR) Read(p []byte) (n int, err error) { | ||||||
|  | 	if r.src == nil { | ||||||
|  | 		return 0, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if r.off >= r.length { | ||||||
|  | 		return 0, io.EOF | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bound := len(p) | ||||||
|  | 	if len(p) > r.length-r.off { | ||||||
|  | 		bound = r.length - r.off | ||||||
|  | 	} | ||||||
|  | 	// update read
 | ||||||
|  | 	r.off, err = r.src.Read(p[0:bound]) | ||||||
|  | 	return r.off, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func StreamReadPacket(reader io.Reader) (*StreamReader, error) { | ||||||
|  | 	sp := NewStreamParser(reader) | ||||||
|  | 	err := sp.Do() | ||||||
|  | 	return sp, err | ||||||
|  | } | ||||||
|  | @ -0,0 +1,138 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"io" | ||||||
|  | 
 | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/encoding" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type StreamEncoder struct { | ||||||
|  | 	tag    byte | ||||||
|  | 	buf    *bytes.Buffer | ||||||
|  | 	pBuf   *bytes.Buffer | ||||||
|  | 	len    int | ||||||
|  | 	sLen   int | ||||||
|  | 	reader *yR | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewStreamEncoder(tag byte) *StreamEncoder { | ||||||
|  | 	var se = &StreamEncoder{ | ||||||
|  | 		tag:  tag, | ||||||
|  | 		buf:  new(bytes.Buffer), | ||||||
|  | 		pBuf: new(bytes.Buffer), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return se | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (se *StreamEncoder) AddPacket(packet *PrimitivePacketEncoder) { | ||||||
|  | 	node := packet.Encode() | ||||||
|  | 	se.AddPacketBuffer(node) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (se *StreamEncoder) AddPacketBuffer(buf []byte) { | ||||||
|  | 	se.pBuf.Write(buf) | ||||||
|  | 	se.growLen(len(se.pBuf.Bytes())) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (se *StreamEncoder) AddStreamPacket(tag byte, length int, reader io.Reader) { | ||||||
|  | 	se.sLen = length | ||||||
|  | 	// s-Tag
 | ||||||
|  | 	se.pBuf.WriteByte(tag) | ||||||
|  | 	se.growLen(1) | ||||||
|  | 	// calculate s-Len
 | ||||||
|  | 	size := encoding.SizeOfPVarInt32(int32(length)) | ||||||
|  | 	codec := encoding.VarCodec{Size: size} | ||||||
|  | 	tmp := make([]byte, size) | ||||||
|  | 	err := codec.EncodePVarInt32(tmp, int32(length)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	se.pBuf.Write(tmp) | ||||||
|  | 	se.growLen(size) | ||||||
|  | 
 | ||||||
|  | 	// total buf
 | ||||||
|  | 	se.buf.WriteByte(se.tag) | ||||||
|  | 	se.growLen(length) | ||||||
|  | 	// calculate total Len buf
 | ||||||
|  | 	size = encoding.SizeOfPVarInt32(int32(se.len)) | ||||||
|  | 	codec = encoding.VarCodec{Size: size} | ||||||
|  | 	tmp = make([]byte, size) | ||||||
|  | 	err = codec.EncodePVarInt32(tmp, int32(se.len)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	se.buf.Write(tmp) //lenBuf
 | ||||||
|  | 	se.buf.Write(se.pBuf.Bytes()) | ||||||
|  | 	se.growLen(size) // total length
 | ||||||
|  | 	se.growLen(1)    // parent tag
 | ||||||
|  | 
 | ||||||
|  | 	se.reader = &yR{ | ||||||
|  | 		buf:    se.buf, | ||||||
|  | 		src:    reader, | ||||||
|  | 		length: se.len, | ||||||
|  | 		sLen:   se.sLen, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (se *StreamEncoder) GetReader() io.Reader { | ||||||
|  | 	if se.reader != nil { | ||||||
|  | 		return se.reader | ||||||
|  | 	} | ||||||
|  | 	return new(bytes.Buffer) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Pipe can pipe data to os.StdOut
 | ||||||
|  | func (se *StreamEncoder) Pipe(writer io.Writer) { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (se *StreamEncoder) GetLen() int { | ||||||
|  | 	if se.reader != nil { | ||||||
|  | 		return se.len | ||||||
|  | 	} | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (se *StreamEncoder) growLen(step int) { | ||||||
|  | 	se.len += step | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type yR struct { | ||||||
|  | 	src    io.Reader | ||||||
|  | 	buf    *bytes.Buffer | ||||||
|  | 	length int | ||||||
|  | 	off    int | ||||||
|  | 	sLen   int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (r *yR) Read(p []byte) (n int, err error) { | ||||||
|  | 	if r.src == nil { | ||||||
|  | 		return 0, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if r.off >= r.length { | ||||||
|  | 		return 0, io.EOF | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if r.off < r.length-r.sLen { | ||||||
|  | 		n, err = r.buf.Read(p) | ||||||
|  | 		r.off += n | ||||||
|  | 		if err != nil { | ||||||
|  | 			if err == io.EOF { | ||||||
|  | 				return n, nil | ||||||
|  | 			} else { | ||||||
|  | 				return 0, err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return n, nil | ||||||
|  | 	} else { | ||||||
|  | 		n, err = r.src.Read(p) | ||||||
|  | 		r.off += n | ||||||
|  | 		if err != nil { | ||||||
|  | 			return n, err | ||||||
|  | 		} | ||||||
|  | 		return n, nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,38 @@ | ||||||
|  | package mq_coder | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"git.hpds.cc/Component/mq_coder/utils" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Tag represents the Tag of TLV,
 | ||||||
|  | // MSB used to represent the packet type, 0x80 means a node packet, otherwise is a primitive packet.
 | ||||||
|  | // Low 7 bits represent Sequence ID, like `key` in JSON format
 | ||||||
|  | type Tag struct { | ||||||
|  | 	raw byte | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsNode returns true is MSB is 1.
 | ||||||
|  | func (t *Tag) IsNode() bool { | ||||||
|  | 	return t.raw&utils.MSB == utils.MSB | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsSlice determine if the current node is a Slice
 | ||||||
|  | func (t *Tag) IsSlice() bool { | ||||||
|  | 	return t.raw&utils.SliceFlag == utils.SliceFlag | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SeqId get the sequence ID, as key in JSON format
 | ||||||
|  | func (t *Tag) SeqId() byte { | ||||||
|  | 	//return t.raw & packet utils.DropMSB
 | ||||||
|  | 	return t.raw & utils.DropMSBArrayFlag | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewTag create a NodePacket Tag field
 | ||||||
|  | func NewTag(b byte) *Tag { | ||||||
|  | 	return &Tag{raw: b} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Raw return the original byte
 | ||||||
|  | func (t *Tag) Raw() byte { | ||||||
|  | 	return t.raw | ||||||
|  | } | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | package utils | ||||||
|  | 
 | ||||||
|  | // MSB is `1000 0000` describes this is a node packet, otherwise, is a primitive packet
 | ||||||
|  | const MSB byte = 0x80 | ||||||
|  | 
 | ||||||
|  | // DropMSB is `0111 1111`, used to remove MSB flag bit
 | ||||||
|  | const DropMSB byte = 0x3F | ||||||
|  | 
 | ||||||
|  | // SliceFlag is `0100 0000`, describes this packet is a Slice type
 | ||||||
|  | const SliceFlag byte = 0x40 | ||||||
|  | 
 | ||||||
|  | // DropMSBArrayFlag is `0011 1111`, used to remove MSB and Slice flag bit
 | ||||||
|  | const DropMSBArrayFlag byte = 0x3F | ||||||
|  | 
 | ||||||
|  | // IsNodePacket returns true if the tag represents a node package
 | ||||||
|  | func IsNodePacket(tag byte) bool { | ||||||
|  | 	return tag&MSB == MSB | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue