summaryrefslogtreecommitdiff
path: root/vendor/github.com/klauspost/compress/zstd/bytebuf.go
blob: 4a8460476845c34f5625993850ec8ce6cb959deb (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2019+ Klaus Post. All rights reserved.
// License information can be found in the LICENSE file.
// Based on work by Yann Collet, released under BSD License.

package zstd

import (
	"fmt"
	"io"
	"io/ioutil"
)

type byteBuffer interface {
	// Read up to 8 bytes.
	// Returns nil if no more input is available.
	readSmall(n int) []byte

	// Read >8 bytes.
	// MAY use the destination slice.
	readBig(n int, dst []byte) ([]byte, error)

	// Read a single byte.
	readByte() (byte, error)

	// Skip n bytes.
	skipN(n int) error
}

// in-memory buffer
type byteBuf []byte

func (b *byteBuf) readSmall(n int) []byte {
	if debug && n > 8 {
		panic(fmt.Errorf("small read > 8 (%d). use readBig", n))
	}
	bb := *b
	if len(bb) < n {
		return nil
	}
	r := bb[:n]
	*b = bb[n:]
	return r
}

func (b *byteBuf) readBig(n int, dst []byte) ([]byte, error) {
	bb := *b
	if len(bb) < n {
		return nil, io.ErrUnexpectedEOF
	}
	r := bb[:n]
	*b = bb[n:]
	return r, nil
}

func (b *byteBuf) remain() []byte {
	return *b
}

func (b *byteBuf) readByte() (byte, error) {
	bb := *b
	if len(bb) < 1 {
		return 0, nil
	}
	r := bb[0]
	*b = bb[1:]
	return r, nil
}

func (b *byteBuf) skipN(n int) error {
	bb := *b
	if len(bb) < n {
		return io.ErrUnexpectedEOF
	}
	*b = bb[n:]
	return nil
}

// wrapper around a reader.
type readerWrapper struct {
	r   io.Reader
	tmp [8]byte
}

func (r *readerWrapper) readSmall(n int) []byte {
	if debug && n > 8 {
		panic(fmt.Errorf("small read > 8 (%d). use readBig", n))
	}
	n2, err := io.ReadFull(r.r, r.tmp[:n])
	// We only really care about the actual bytes read.
	if n2 != n {
		if debug {
			println("readSmall: got", n2, "want", n, "err", err)
		}
		return nil
	}
	return r.tmp[:n]
}

func (r *readerWrapper) readBig(n int, dst []byte) ([]byte, error) {
	if cap(dst) < n {
		dst = make([]byte, n)
	}
	n2, err := io.ReadFull(r.r, dst[:n])
	return dst[:n2], err
}

func (r *readerWrapper) readByte() (byte, error) {
	n2, err := r.r.Read(r.tmp[:1])
	if err != nil {
		return 0, err
	}
	if n2 != 1 {
		return 0, io.ErrUnexpectedEOF
	}
	return r.tmp[0], nil
}

func (r *readerWrapper) skipN(n int) error {
	_, err := io.CopyN(ioutil.Discard, r.r, int64(n))
	return err
}