116 lines
2.3 KiB
Go
116 lines
2.3 KiB
Go
package blt
|
|
|
|
import (
|
|
"encoding/binary"
|
|
)
|
|
|
|
// buffer is a simple wrapper over a slice of bytes with a cursor. It allows for
|
|
// easy command building and results parsing.
|
|
type buffer struct {
|
|
data []byte
|
|
pos int
|
|
}
|
|
|
|
// skip next n bytes
|
|
func (b *buffer) skip(n int) {
|
|
b.pos += n
|
|
}
|
|
|
|
// advance skips next N bytes and returns them
|
|
func (b *buffer) advance(n int) []byte {
|
|
b.skip(n)
|
|
return b.data[b.pos-n:]
|
|
}
|
|
|
|
// cur returns remaining unread buffer.
|
|
func (b *buffer) cur() []byte {
|
|
return b.data[b.pos:]
|
|
}
|
|
|
|
// newReadBuffer creates a buffer with command output.
|
|
func newReadBuffer(data []byte) *buffer {
|
|
return &buffer{data: data}
|
|
}
|
|
|
|
func (b *buffer) readUint8() uint8 {
|
|
return decodeUint8(b.advance(1))
|
|
}
|
|
|
|
func (b *buffer) readUint16() uint16 {
|
|
return decodeUint16(b.advance(2))
|
|
}
|
|
|
|
func (b *buffer) readUint24() uint32 {
|
|
return decodeUint24(b.advance(3))
|
|
}
|
|
|
|
func (b *buffer) readUint32() uint32 {
|
|
return decodeUint32(b.advance(4))
|
|
}
|
|
|
|
func (b *buffer) readUint48() uint64 {
|
|
return decodeUint48(b.advance(6))
|
|
}
|
|
|
|
func (b *buffer) readUint64() uint64 {
|
|
return decodeUint64(b.advance(8))
|
|
}
|
|
|
|
func (b *buffer) readUintLenEnc() (val uint64, isNull bool) {
|
|
var size int
|
|
val, isNull, size = decodeUintLenEnc(b.cur())
|
|
b.skip(size)
|
|
return
|
|
}
|
|
|
|
func (b *buffer) readStringNullTerm() []byte {
|
|
str := decodeStringNullTerm(b.cur())
|
|
b.skip(len(str) + 1)
|
|
return str
|
|
}
|
|
|
|
func (b *buffer) readStringVarLen(n int) []byte {
|
|
return decodeStringVarLen(b.advance(n), n)
|
|
}
|
|
|
|
func (b *buffer) readStringLenEnc() []byte {
|
|
str, size := decodeStringLenEnc(b.cur())
|
|
b.skip(size)
|
|
return str
|
|
}
|
|
|
|
func (b *buffer) readStringEOF() []byte {
|
|
return decodeStringEOF(b.cur())
|
|
}
|
|
|
|
// Pre-allocate command buffer. First four bytes would be used to set command
|
|
// length and sequence number.
|
|
func newCommandBuffer(size int) *buffer {
|
|
return &buffer{data: make([]byte, size+4), pos: 4}
|
|
}
|
|
|
|
func (b *buffer) writeByte(v byte) {
|
|
b.data[b.pos] = v
|
|
b.pos++
|
|
}
|
|
|
|
func (b *buffer) writeUint16(v uint16) {
|
|
binary.LittleEndian.PutUint16(b.data[b.pos:], v)
|
|
b.pos += 2
|
|
}
|
|
|
|
func (b *buffer) writeUint32(v uint32) {
|
|
binary.LittleEndian.PutUint32(b.data[b.pos:], v)
|
|
b.pos += 4
|
|
}
|
|
|
|
func (b *buffer) writeString(s string) {
|
|
b.data[b.pos] = byte(len(s))
|
|
b.pos++
|
|
b.pos += copy(b.data[b.pos:], s)
|
|
}
|
|
|
|
func (b *buffer) writeStringEOF(s string) {
|
|
b.pos += copy(b.data[b.pos:], s)
|
|
}
|