summary refs log tree commit diff stats
path: root/internal/buffer/buffer.go
blob: 055bf7fcf8bc4c72195d635c02f96f0bdbdf449b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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]
}