blob: 3eb3f1c82661a49912b83e44b3b62770eb579000 [file] [log] [blame]
khenaidoo7d3c5582021-08-11 18:09:44 -04001// Package zstd provides decompression of zstandard files.
2//
3// For advanced usage and examples, go to the README: https://github.com/klauspost/compress/tree/master/zstd#zstd
4package zstd
5
6import (
7 "bytes"
8 "encoding/binary"
9 "errors"
10 "log"
11 "math"
12 "math/bits"
13)
14
15// enable debug printing
16const debug = false
17
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053018// enable encoding debug printing
19const debugEncoder = debug
20
21// enable decoding debug printing
22const debugDecoder = debug
23
khenaidoo7d3c5582021-08-11 18:09:44 -040024// Enable extra assertions.
25const debugAsserts = debug || false
26
27// print sequence details
28const debugSequences = false
29
30// print detailed matching information
31const debugMatches = false
32
33// force encoder to use predefined tables.
34const forcePreDef = false
35
36// zstdMinMatch is the minimum zstd match length.
37const zstdMinMatch = 3
38
39// Reset the buffer offset when reaching this.
40const bufferReset = math.MaxInt32 - MaxWindowSize
41
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053042// fcsUnknown is used for unknown frame content size.
43const fcsUnknown = math.MaxUint64
44
khenaidoo7d3c5582021-08-11 18:09:44 -040045var (
46 // ErrReservedBlockType is returned when a reserved block type is found.
47 // Typically this indicates wrong or corrupted input.
48 ErrReservedBlockType = errors.New("invalid input: reserved block type encountered")
49
50 // ErrCompressedSizeTooBig is returned when a block is bigger than allowed.
51 // Typically this indicates wrong or corrupted input.
52 ErrCompressedSizeTooBig = errors.New("invalid input: compressed size too big")
53
54 // ErrBlockTooSmall is returned when a block is too small to be decoded.
55 // Typically returned on invalid input.
56 ErrBlockTooSmall = errors.New("block too small")
57
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053058 // ErrUnexpectedBlockSize is returned when a block has unexpected size.
59 // Typically returned on invalid input.
60 ErrUnexpectedBlockSize = errors.New("unexpected block size")
61
khenaidoo7d3c5582021-08-11 18:09:44 -040062 // ErrMagicMismatch is returned when a "magic" number isn't what is expected.
63 // Typically this indicates wrong or corrupted input.
64 ErrMagicMismatch = errors.New("invalid input: magic number mismatch")
65
66 // ErrWindowSizeExceeded is returned when a reference exceeds the valid window size.
67 // Typically this indicates wrong or corrupted input.
68 ErrWindowSizeExceeded = errors.New("window size exceeded")
69
70 // ErrWindowSizeTooSmall is returned when no window size is specified.
71 // Typically this indicates wrong or corrupted input.
72 ErrWindowSizeTooSmall = errors.New("invalid input: window size was too small")
73
74 // ErrDecoderSizeExceeded is returned if decompressed size exceeds the configured limit.
75 ErrDecoderSizeExceeded = errors.New("decompressed size exceeds configured limit")
76
77 // ErrUnknownDictionary is returned if the dictionary ID is unknown.
78 // For the time being dictionaries are not supported.
79 ErrUnknownDictionary = errors.New("unknown dictionary")
80
81 // ErrFrameSizeExceeded is returned if the stated frame size is exceeded.
82 // This is only returned if SingleSegment is specified on the frame.
83 ErrFrameSizeExceeded = errors.New("frame size exceeded")
84
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053085 // ErrFrameSizeMismatch is returned if the stated frame size does not match the expected size.
86 // This is only returned if SingleSegment is specified on the frame.
87 ErrFrameSizeMismatch = errors.New("frame size does not match size on stream")
88
khenaidoo7d3c5582021-08-11 18:09:44 -040089 // ErrCRCMismatch is returned if CRC mismatches.
90 ErrCRCMismatch = errors.New("CRC check failed")
91
92 // ErrDecoderClosed will be returned if the Decoder was used after
93 // Close has been called.
94 ErrDecoderClosed = errors.New("decoder used after Close")
95
96 // ErrDecoderNilInput is returned when a nil Reader was provided
97 // and an operation other than Reset/DecodeAll/Close was attempted.
98 ErrDecoderNilInput = errors.New("nil input provided as reader")
99)
100
101func println(a ...interface{}) {
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +0530102 if debug || debugDecoder || debugEncoder {
khenaidoo7d3c5582021-08-11 18:09:44 -0400103 log.Println(a...)
104 }
105}
106
107func printf(format string, a ...interface{}) {
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +0530108 if debug || debugDecoder || debugEncoder {
khenaidoo7d3c5582021-08-11 18:09:44 -0400109 log.Printf(format, a...)
110 }
111}
112
khenaidoo7d3c5582021-08-11 18:09:44 -0400113// matchLen returns the maximum length.
114// a must be the shortest of the two.
115// The function also returns whether all bytes matched.
116func matchLen(a, b []byte) int {
117 b = b[:len(a)]
118 for i := 0; i < len(a)-7; i += 8 {
119 if diff := load64(a, i) ^ load64(b, i); diff != 0 {
120 return i + (bits.TrailingZeros64(diff) >> 3)
121 }
122 }
123
124 checked := (len(a) >> 3) << 3
125 a = a[checked:]
126 b = b[checked:]
127 for i := range a {
128 if a[i] != b[i] {
129 return i + checked
130 }
131 }
132 return len(a) + checked
133}
134
135func load3232(b []byte, i int32) uint32 {
136 return binary.LittleEndian.Uint32(b[i:])
137}
138
139func load6432(b []byte, i int32) uint64 {
140 return binary.LittleEndian.Uint64(b[i:])
141}
142
143func load64(b []byte, i int) uint64 {
144 return binary.LittleEndian.Uint64(b[i:])
145}
146
147type byter interface {
148 Bytes() []byte
149 Len() int
150}
151
152var _ byter = &bytes.Buffer{}