about summary refs log tree commit diff stats
path: root/internal/buffer/buffer.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/buffer/buffer.go')
-rw-r--r--internal/buffer/buffer.go95
1 files changed, 95 insertions, 0 deletions
diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go
new file mode 100644
index 0000000..055bf7f
--- /dev/null
+++ b/internal/buffer/buffer.go
@@ -0,0 +1,95 @@
+package buffer
+
+import (
+	"io"
+)
+
+type Buffer struct {
+	buf []byte
+	pos int
+	len int
+}
+
+func NewBuffer(buf []byte) *Buffer {
+	return &Buffer{
+		buf: buf,
+		pos: 0,
+		len: len(buf),
+	}
+}
+
+// Read implements io.Reader's Read method
+func (b *Buffer) Read(p []byte) (int, error) {
+	if b.pos >= b.len {
+		return 0, io.EOF
+	}
+
+	n := len(p)
+	if n > b.len-b.pos {
+		n = b.len - b.pos
+	}
+
+	copy(p[:n], b.buf[b.pos:b.pos+n])
+	b.pos += n
+
+	return n, nil
+}
+
+// Write appends the contents of p to the buffer's data.
+func (b *Buffer) Write(p []byte) (int, error) {
+	if len(b.buf) < b.len+len(p) {
+		newLen := b.len + len(p)
+		if cap(b.buf) >= newLen {
+			b.buf = b.buf[:newLen]
+		} else {
+			newBuf := make([]byte, newLen*2)
+			copy(newBuf, b.buf[:b.len])
+			b.buf = newBuf
+		}
+	}
+
+	copy(b.buf[b.len:], p)
+	b.len += len(p)
+
+	return len(p), nil
+}
+
+func (b *Buffer) Len() int {
+	return b.len
+}
+
+// Reset resets the buffer to be empty. The underlying array is reused if possible.
+func (b *Buffer) Reset() {
+	b.len = 0
+	b.pos = 0
+}
+
+// Seek moves the read position by offset bytes relative to whence (Start, Current, End)
+func (b *Buffer) Seek(offset int64, whence int) (int64, error) {
+	var newpos int
+
+	switch whence {
+	case io.SeekStart:
+		newpos = int(offset)
+	case io.SeekCurrent:
+		newpos = b.pos + int(offset)
+	case io.SeekEnd:
+		newpos = b.len + int(offset)
+	default:
+		return 0, io.EOF
+	}
+
+	if newpos < 0 {
+		newpos = 0
+	} else if newpos > b.len {
+		newpos = b.len
+	}
+
+	b.pos = newpos
+
+	return int64(newpos), nil
+}
+
+func (b *Buffer) Bytes() []byte {
+	return b.buf[:b.len]
+}