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 }