From 5132158ac2dee721790ad4b9f745bb6364406ea0 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Fri, 31 Oct 2025 20:11:04 +0000 Subject: [PATCH] bytes: add Buffer.Peek Fixes #73794 Change-Id: I0a57db05aacfa805213fe8278fc727e76eb8a65e GitHub-Last-Rev: 3494d93f803f21905dfd5a9d593644da69279f16 GitHub-Pull-Request: golang/go#73795 Reviewed-on: https://go-review.googlesource.com/c/go/+/674415 Reviewed-by: Sean Liao LUCI-TryBot-Result: Go LUCI Auto-Submit: Michael Pratt Reviewed-by: Michael Knyszek Reviewed-by: Michael Pratt --- api/next/73794.txt | 1 + doc/next/6-stdlib/99-minor/bytes/73794.md | 2 ++ src/bytes/buffer.go | 12 ++++++++++ src/bytes/buffer_test.go | 28 +++++++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 api/next/73794.txt create mode 100644 doc/next/6-stdlib/99-minor/bytes/73794.md diff --git a/api/next/73794.txt b/api/next/73794.txt new file mode 100644 index 0000000000..4018c149ec --- /dev/null +++ b/api/next/73794.txt @@ -0,0 +1 @@ +pkg bytes, method (*Buffer) Peek(int) ([]uint8, error) #73794 diff --git a/doc/next/6-stdlib/99-minor/bytes/73794.md b/doc/next/6-stdlib/99-minor/bytes/73794.md new file mode 100644 index 0000000000..a44dfc10e6 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/bytes/73794.md @@ -0,0 +1,2 @@ +The new [Buffer.Peek] method returns the next n bytes from the buffer without +advancing it. diff --git a/src/bytes/buffer.go b/src/bytes/buffer.go index 9684513942..3eb5b350c3 100644 --- a/src/bytes/buffer.go +++ b/src/bytes/buffer.go @@ -77,6 +77,18 @@ func (b *Buffer) String() string { return string(b.buf[b.off:]) } +// Peek returns the next n bytes without advancing the buffer. +// If Peek returns fewer than n bytes, it also returns [io.EOF]. +// The slice is only valid until the next call to a read or write method. +// The slice aliases the buffer content at least until the next buffer modification, +// so immediate changes to the slice will affect the result of future reads. +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 b46ba1204e..5f5cc483b0 100644 --- a/src/bytes/buffer_test.go +++ b/src/bytes/buffer_test.go @@ -531,6 +531,34 @@ 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) + } + if buf.Len() != len(test.buffer) { + t.Errorf("bad length after peek: %d, want %d", buf.Len(), len(test.buffer)) + } + } +} + func BenchmarkReadString(b *testing.B) { const n = 32 << 10 -- 2.52.0