summaryrefslogtreecommitdiffhomepage
path: root/util/bufiox/bufiox.go
blob: ceea9aefe226ff1cdf1772ffc945d2a44851722a (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
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause

// Package bufiox provides extensions to the standard bufio package.
package bufiox

import "io"

// BufferedReader is an interface for readers that support peeking
// into an internal buffer, like [bufio.Reader].
type BufferedReader interface {
	Peek(n int) ([]byte, error)
	Discard(n int) (discarded int, err error)
}

// ReadFull reads exactly len(buf) bytes from r into buf, like
// [io.ReadFull], but without heap allocations. It uses Peek to
// access the buffered data directly, copies it into buf, then
// discards the consumed bytes. If an error occurs,
// discard is not called and the buffer is left unchanged.
func ReadFull(r BufferedReader, buf []byte) (int, error) {
	b, err := r.Peek(len(buf))
	if err != nil {
		if len(b) > 0 && err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		return 0, err
	}
	defer r.Discard(len(buf))
	return copy(buf, b), nil
}