Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 46f0427

Browse files
committedMar 6, 2025·
vendor the minimal, noasm version of klauspost/compress/zstd.
Signed-off-by: bwplotka <[email protected]>
1 parent 05fcde9 commit 46f0427

32 files changed

+7088
-4
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Copyright (c) 2012 The Go Authors. All rights reserved.
2+
Copyright (c) 2019 Klaus Post. All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are
6+
met:
7+
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
* Redistributions in binary form must reproduce the above
11+
copyright notice, this list of conditions and the following disclaimer
12+
in the documentation and/or other materials provided with the
13+
distribution.
14+
* Neither the name of Google Inc. nor the names of its
15+
contributors may be used to endorse or promote products derived from
16+
this software without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
This source code is a stripped down version of zstd from the https://github.com/klauspost/compress/tree/517288e9a6e1dd4dea10ad42ffe2829c58dadf51/zstd.
2+
3+
Motivation: https://github.com/kubernetes/kubernetes/pull/130569#discussion_r1981503174
4+
5+
Changes:
6+
* Remove all but things necessary to use and create zstd.NewWriter for SpeedFastest mode.
7+
* Use github.com/cespare/xxhash/v2 instead of vendored copy.
8+
9+
The goal is to remove this once stdlib will support zstd.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright 2018 Klaus Post. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
// Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
5+
6+
package fse
7+
8+
import (
9+
"encoding/binary"
10+
"errors"
11+
"io"
12+
)
13+
14+
// bitReader reads a bitstream in reverse.
15+
// The last set bit indicates the start of the stream and is used
16+
// for aligning the input.
17+
type bitReader struct {
18+
in []byte
19+
off uint // next byte to read is at in[off - 1]
20+
value uint64
21+
bitsRead uint8
22+
}
23+
24+
// init initializes and resets the bit reader.
25+
func (b *bitReader) init(in []byte) error {
26+
if len(in) < 1 {
27+
return errors.New("corrupt stream: too short")
28+
}
29+
b.in = in
30+
b.off = uint(len(in))
31+
// The highest bit of the last byte indicates where to start
32+
v := in[len(in)-1]
33+
if v == 0 {
34+
return errors.New("corrupt stream, did not find end of stream")
35+
}
36+
b.bitsRead = 64
37+
b.value = 0
38+
if len(in) >= 8 {
39+
b.fillFastStart()
40+
} else {
41+
b.fill()
42+
b.fill()
43+
}
44+
b.bitsRead += 8 - uint8(highBits(uint32(v)))
45+
return nil
46+
}
47+
48+
// getBits will return n bits. n can be 0.
49+
func (b *bitReader) getBits(n uint8) uint16 {
50+
if n == 0 || b.bitsRead >= 64 {
51+
return 0
52+
}
53+
return b.getBitsFast(n)
54+
}
55+
56+
// getBitsFast requires that at least one bit is requested every time.
57+
// There are no checks if the buffer is filled.
58+
func (b *bitReader) getBitsFast(n uint8) uint16 {
59+
const regMask = 64 - 1
60+
v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask))
61+
b.bitsRead += n
62+
return v
63+
}
64+
65+
// fillFast() will make sure at least 32 bits are available.
66+
// There must be at least 4 bytes available.
67+
func (b *bitReader) fillFast() {
68+
if b.bitsRead < 32 {
69+
return
70+
}
71+
// 2 bounds checks.
72+
v := b.in[b.off-4:]
73+
v = v[:4]
74+
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
75+
b.value = (b.value << 32) | uint64(low)
76+
b.bitsRead -= 32
77+
b.off -= 4
78+
}
79+
80+
// fill() will make sure at least 32 bits are available.
81+
func (b *bitReader) fill() {
82+
if b.bitsRead < 32 {
83+
return
84+
}
85+
if b.off > 4 {
86+
v := b.in[b.off-4:]
87+
v = v[:4]
88+
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
89+
b.value = (b.value << 32) | uint64(low)
90+
b.bitsRead -= 32
91+
b.off -= 4
92+
return
93+
}
94+
for b.off > 0 {
95+
b.value = (b.value << 8) | uint64(b.in[b.off-1])
96+
b.bitsRead -= 8
97+
b.off--
98+
}
99+
}
100+
101+
// fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read.
102+
func (b *bitReader) fillFastStart() {
103+
// Do single re-slice to avoid bounds checks.
104+
b.value = binary.LittleEndian.Uint64(b.in[b.off-8:])
105+
b.bitsRead = 0
106+
b.off -= 8
107+
}
108+
109+
// finished returns true if all bits have been read from the bit stream.
110+
func (b *bitReader) finished() bool {
111+
return b.bitsRead >= 64 && b.off == 0
112+
}
113+
114+
// close the bitstream and returns an error if out-of-buffer reads occurred.
115+
func (b *bitReader) close() error {
116+
// Release reference.
117+
b.in = nil
118+
if b.bitsRead > 64 {
119+
return io.ErrUnexpectedEOF
120+
}
121+
return nil
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// Copyright 2018 Klaus Post. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
// Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
5+
6+
package fse
7+
8+
import "fmt"
9+
10+
// bitWriter will write bits.
11+
// First bit will be LSB of the first byte of output.
12+
type bitWriter struct {
13+
bitContainer uint64
14+
nBits uint8
15+
out []byte
16+
}
17+
18+
// bitMask16 is bitmasks. Has extra to avoid bounds check.
19+
var bitMask16 = [32]uint16{
20+
0, 1, 3, 7, 0xF, 0x1F,
21+
0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
22+
0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF,
23+
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
24+
0xFFFF, 0xFFFF} /* up to 16 bits */
25+
26+
// addBits16NC will add up to 16 bits.
27+
// It will not check if there is space for them,
28+
// so the caller must ensure that it has flushed recently.
29+
func (b *bitWriter) addBits16NC(value uint16, bits uint8) {
30+
b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63)
31+
b.nBits += bits
32+
}
33+
34+
// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
35+
// It will not check if there is space for them, so the caller must ensure that it has flushed recently.
36+
func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
37+
b.bitContainer |= uint64(value) << (b.nBits & 63)
38+
b.nBits += bits
39+
}
40+
41+
// addBits16ZeroNC will add up to 16 bits.
42+
// It will not check if there is space for them,
43+
// so the caller must ensure that it has flushed recently.
44+
// This is fastest if bits can be zero.
45+
func (b *bitWriter) addBits16ZeroNC(value uint16, bits uint8) {
46+
if bits == 0 {
47+
return
48+
}
49+
value <<= (16 - bits) & 15
50+
value >>= (16 - bits) & 15
51+
b.bitContainer |= uint64(value) << (b.nBits & 63)
52+
b.nBits += bits
53+
}
54+
55+
// flush will flush all pending full bytes.
56+
// There will be at least 56 bits available for writing when this has been called.
57+
// Using flush32 is faster, but leaves less space for writing.
58+
func (b *bitWriter) flush() {
59+
v := b.nBits >> 3
60+
switch v {
61+
case 0:
62+
case 1:
63+
b.out = append(b.out,
64+
byte(b.bitContainer),
65+
)
66+
case 2:
67+
b.out = append(b.out,
68+
byte(b.bitContainer),
69+
byte(b.bitContainer>>8),
70+
)
71+
case 3:
72+
b.out = append(b.out,
73+
byte(b.bitContainer),
74+
byte(b.bitContainer>>8),
75+
byte(b.bitContainer>>16),
76+
)
77+
case 4:
78+
b.out = append(b.out,
79+
byte(b.bitContainer),
80+
byte(b.bitContainer>>8),
81+
byte(b.bitContainer>>16),
82+
byte(b.bitContainer>>24),
83+
)
84+
case 5:
85+
b.out = append(b.out,
86+
byte(b.bitContainer),
87+
byte(b.bitContainer>>8),
88+
byte(b.bitContainer>>16),
89+
byte(b.bitContainer>>24),
90+
byte(b.bitContainer>>32),
91+
)
92+
case 6:
93+
b.out = append(b.out,
94+
byte(b.bitContainer),
95+
byte(b.bitContainer>>8),
96+
byte(b.bitContainer>>16),
97+
byte(b.bitContainer>>24),
98+
byte(b.bitContainer>>32),
99+
byte(b.bitContainer>>40),
100+
)
101+
case 7:
102+
b.out = append(b.out,
103+
byte(b.bitContainer),
104+
byte(b.bitContainer>>8),
105+
byte(b.bitContainer>>16),
106+
byte(b.bitContainer>>24),
107+
byte(b.bitContainer>>32),
108+
byte(b.bitContainer>>40),
109+
byte(b.bitContainer>>48),
110+
)
111+
case 8:
112+
b.out = append(b.out,
113+
byte(b.bitContainer),
114+
byte(b.bitContainer>>8),
115+
byte(b.bitContainer>>16),
116+
byte(b.bitContainer>>24),
117+
byte(b.bitContainer>>32),
118+
byte(b.bitContainer>>40),
119+
byte(b.bitContainer>>48),
120+
byte(b.bitContainer>>56),
121+
)
122+
default:
123+
panic(fmt.Errorf("bits (%d) > 64", b.nBits))
124+
}
125+
b.bitContainer >>= v << 3
126+
b.nBits &= 7
127+
}
128+
129+
// flush32 will flush out, so there are at least 32 bits available for writing.
130+
func (b *bitWriter) flush32() {
131+
if b.nBits < 32 {
132+
return
133+
}
134+
b.out = append(b.out,
135+
byte(b.bitContainer),
136+
byte(b.bitContainer>>8),
137+
byte(b.bitContainer>>16),
138+
byte(b.bitContainer>>24))
139+
b.nBits -= 32
140+
b.bitContainer >>= 32
141+
}
142+
143+
// flushAlign will flush remaining full bytes and align to next byte boundary.
144+
func (b *bitWriter) flushAlign() {
145+
nbBytes := (b.nBits + 7) >> 3
146+
for i := uint8(0); i < nbBytes; i++ {
147+
b.out = append(b.out, byte(b.bitContainer>>(i*8)))
148+
}
149+
b.nBits = 0
150+
b.bitContainer = 0
151+
}
152+
153+
// close will write the alignment bit and write the final byte(s)
154+
// to the output.
155+
func (b *bitWriter) close() {
156+
// End mark
157+
b.addBits16Clean(1, 1)
158+
// flush until next byte.
159+
b.flushAlign()
160+
}
161+
162+
// reset and continue writing by appending to out.
163+
func (b *bitWriter) reset(out []byte) {
164+
b.bitContainer = 0
165+
b.nBits = 0
166+
b.out = out
167+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2018 Klaus Post. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
// Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
5+
6+
package fse
7+
8+
// byteReader provides a byte reader that reads
9+
// little endian values from a byte stream.
10+
// The input stream is manually advanced.
11+
// The reader performs no bounds checks.
12+
type byteReader struct {
13+
b []byte
14+
off int
15+
}
16+
17+
// init will initialize the reader and set the input.
18+
func (b *byteReader) init(in []byte) {
19+
b.b = in
20+
b.off = 0
21+
}
22+
23+
// advance the stream b n bytes.
24+
func (b *byteReader) advance(n uint) {
25+
b.off += int(n)
26+
}
27+
28+
// Uint32 returns a little endian uint32 starting at current offset.
29+
func (b byteReader) Uint32() uint32 {
30+
b2 := b.b[b.off:]
31+
b2 = b2[:4]
32+
v3 := uint32(b2[3])
33+
v2 := uint32(b2[2])
34+
v1 := uint32(b2[1])
35+
v0 := uint32(b2[0])
36+
return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)
37+
}
38+
39+
// unread returns the unread portion of the input.
40+
func (b byteReader) unread() []byte {
41+
return b.b[b.off:]
42+
}
43+
44+
// remain will return the number of bytes remaining.
45+
func (b byteReader) remain() int {
46+
return len(b.b) - b.off
47+
}

0 commit comments

Comments
 (0)
Please sign in to comment.