diff --git a/src/bytes/buffer.go b/src/bytes/buffer.go index 9684513942da88..2ad4b430870dd0 100644 --- a/src/bytes/buffer.go +++ b/src/bytes/buffer.go @@ -77,6 +77,16 @@ func (b *Buffer) String() string { return string(b.buf[b.off:]) } +// Peek returns the next n bytes without advancing the buffer. +// If there are fewer than n bytes in the buffer, it returns error [io.EOF]. +// The slice is only valid until the next buffer modification. +func (b *Buffer) Peek(n int) ([]byte, error) { + if b.Len() < n { + return b.buf[b.off:], io.EOF + } + return b.buf[b.off:n], nil +} + // empty reports whether the unread portion of the buffer is empty. func (b *Buffer) empty() bool { return len(b.buf) <= b.off } diff --git a/src/bytes/buffer_test.go b/src/bytes/buffer_test.go index b46ba1204eb806..98cfbab096f43d 100644 --- a/src/bytes/buffer_test.go +++ b/src/bytes/buffer_test.go @@ -531,6 +531,31 @@ func TestReadString(t *testing.T) { } } +var peekTests = []struct{ + buffer string + n int + expected string + err error +}{ + {"", 0, "", nil}, + {"aaa", 3, "aaa", nil}, + {"foobar", 2, "fo", nil}, + {"a", 2, "a", io.EOF}, +} + +func TestPeek(t *testing.T) { + for _, test := range peekTests { + buf := NewBufferString(test.buffer) + bytes, err := buf.Peek(test.n) + if string(bytes) != test.expected { + t.Errorf("expected %q, got %q", test.expected, bytes) + } + if err != test.err { + t.Errorf("expected error %v, got %v", test.err, err) + } + } +} + func BenchmarkReadString(b *testing.B) { const n = 32 << 10