82 lines
2.0 KiB
Go
82 lines
2.0 KiB
Go
package varn
|
|
|
|
import "io"
|
|
|
|
// Buffer is a simple buffer reader that allows reading bytes and
|
|
// variable-length integers. It is not thread-safe and should not be used
|
|
// concurrently.
|
|
type Buffer struct {
|
|
pos *int
|
|
buf []byte
|
|
}
|
|
|
|
// NewBuffer creates a new Buffer instance.
|
|
func NewBuffer(buf []byte) Buffer {
|
|
zero := 0
|
|
return Buffer{&zero, buf}
|
|
}
|
|
|
|
// ReadBytes reads n bytes from the buffer.
|
|
func (buf Buffer) ReadBytes(n int) ([]byte, error) {
|
|
if *buf.pos >= len(buf.buf) {
|
|
return nil, io.EOF
|
|
}
|
|
if *buf.pos+n > len(buf.buf) {
|
|
return nil, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
res := buf.buf[*buf.pos : *buf.pos+n]
|
|
*buf.pos = *buf.pos + n
|
|
return res, nil
|
|
}
|
|
|
|
func (buf Buffer) ReadByte() (byte, error) {
|
|
b, err := buf.ReadBytes(1)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return b[0], nil
|
|
}
|
|
|
|
// ReadVarUint reads a variable-length unsigned integer from the buffer.
|
|
// Returns io.EOF if the end of the buffer is reached before a complete integer
|
|
// is read.
|
|
func (buf Buffer) ReadVarUint() (uint64, error) {
|
|
var value uint64 = 0
|
|
var shift uint64 = 0
|
|
|
|
for {
|
|
b, err := buf.ReadByte()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
value |= (uint64(b) & 0b01111111) << shift
|
|
shift += 7
|
|
if b&0b10000000 == 0 {
|
|
break
|
|
}
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// ReadVarBytes reads a variable-length byte array from the buffer.
|
|
// It first reads a variable-length unsigned integer to determine the length
|
|
// of the byte array, and then reads that many bytes from the buffer.
|
|
// Returns the byte array and an error if any occurs during reading.
|
|
// The function will return io.EOF if the end of the buffer is reached before
|
|
// the specified number of bytes is read.
|
|
// If the length of the byte array is 0, it will return an empty byte slice.
|
|
// If the length is greater than the remaining bytes in the buffer, it will
|
|
// return io.EOF.
|
|
func (buf Buffer) ReadVarBytes() ([]byte, error) {
|
|
v, err := buf.ReadVarUint()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
b, err := buf.ReadBytes(int(v))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return b, nil
|
|
}
|