1
// Copyright 2019+ Klaus Post. All rights reserved.
2
// License information can be found in the LICENSE file.
3
// Based on work by Yann Collet, released under BSD License.
14
"github.com/klauspost/compress/zstd/internal/xxhash"
17
// Decoder provides decoding of zstandard streams.
18
// The decoder has been designed to operate without allocations after a warmup.
19
// This means that you should store the decoder for best performance.
20
// To re-use a stream decoder, use the Reset(r io.Reader) error to switch to another stream.
21
// A decoder can safely be re-used even if the previous stream failed.
22
// To release the resources, you must call the Close() function on a decoder.
26
// Unreferenced decoders, ready for use.
27
decoders chan *blockDec
29
// Current read position used for Reader functionality.
32
// sync stream decoding
42
// Custom dictionaries.
43
// Always uses copies.
46
// streamWg is the waitgroup for all streams
47
streamWg sync.WaitGroup
50
// decoderState is used for maintaining state when the decoder
51
// is used for streaming.
52
type decoderState struct {
53
// current block being written to stream.
56
// output in order to be written to stream.
57
output chan decodeOutput
59
// cancel remaining output.
60
cancel context.CancelFunc
62
// crc of current frame
69
// Check the interfaces we want to support.
70
_ = io.WriterTo(&Decoder{})
71
_ = io.Reader(&Decoder{})
74
// NewReader creates a new decoder.
75
// A nil Reader can be provided in which case Reset can be used to start a decode.
77
// A Decoder can be used in two modes:
80
// 2) For stateless decoding using DecodeAll.
82
// Only a single stream can be decoded concurrently, but the same decoder
83
// can run multiple concurrent stateless decodes. It is even possible to
84
// use stateless decodes while a stream is being decoded.
86
// The Reset function can be used to initiate a new stream, which is will considerably
87
// reduce the allocations normally caused by NewReader.
88
func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) {
92
for _, o := range opts {
98
d.current.crc = xxhash.New()
99
d.current.flushed = true
102
d.current.err = ErrDecoderNilInput
105
// Transfer option dicts.
106
d.dicts = make(map[uint32]dict, len(d.o.dicts))
107
for _, dc := range d.o.dicts {
113
d.decoders = make(chan *blockDec, d.o.concurrent)
114
for i := 0; i < d.o.concurrent; i++ {
115
dec := newBlockDec(d.o.lowMem)
116
dec.localFrame = newFrameDec(d.o)
123
return &d, d.Reset(r)
126
// Read bytes from the decompressed stream into p.
127
// Returns the number of bytes written and any error that occurred.
128
// When the stream is done, io.EOF will be returned.
129
func (d *Decoder) Read(p []byte) (int, error) {
132
if len(d.current.b) > 0 {
133
filled := copy(p, d.current.b)
135
d.current.b = d.current.b[filled:]
141
if len(d.current.b) == 0 {
142
// We have an error and no more data
143
if d.current.err != nil {
146
if !d.nextBlock(n == 0) {
147
return n, d.current.err
151
if len(d.current.b) > 0 {
153
println("returning", n, "still bytes left:", len(d.current.b))
155
// Only return error at end of block
158
if d.current.err != nil {
162
println("returning", n, d.current.err, len(d.decoders))
164
return n, d.current.err
167
// Reset will reset the decoder the supplied stream after the current has finished processing.
168
// Note that this functionality cannot be used after Close has been called.
169
// Reset can be called with a nil reader to release references to the previous reader.
170
// After being called with a nil reader, no other operations than Reset or DecodeAll or Close
172
func (d *Decoder) Reset(r io.Reader) error {
173
if d.current.err == ErrDecoderClosed {
179
d.syncStream.br.r = nil
181
d.current.err = ErrDecoderNilInput
182
if len(d.current.b) > 0 {
183
d.current.b = d.current.b[:0]
185
d.current.flushed = true
189
// If bytes buffer and < 5MB, do sync decoding anyway.
190
if bb, ok := r.(byter); ok && bb.Len() < 5<<20 {
193
println("*bytes.Buffer detected, doing sync decode, len:", bb.Len())
197
if cap(d.current.b) > 0 {
201
dst, err := d.DecodeAll(b, dst[:0])
207
d.current.flushed = true
209
println("sync decode to", len(dst), "bytes, err:", err)
213
// Remove current block.
215
d.current.decodeOutput = decodeOutput{}
217
d.current.flushed = false
220
// Ensure no-one else is still running...
223
d.frame = newFrameDec(d.o)
226
if d.o.concurrent == 1 {
227
return d.startSyncDecoder(r)
230
d.current.output = make(chan decodeOutput, d.o.concurrent)
231
ctx, cancel := context.WithCancel(context.Background())
232
d.current.cancel = cancel
234
go d.startStreamDecoder(ctx, r, d.current.output)
239
// drainOutput will drain the output until errEndOfStream is sent.
240
func (d *Decoder) drainOutput() {
241
if d.current.cancel != nil {
243
println("cancelling current")
246
d.current.cancel = nil
248
if d.current.d != nil {
250
printf("re-adding current decoder %p, decoders: %d", d.current.d, len(d.decoders))
252
d.decoders <- d.current.d
256
if d.current.output == nil || d.current.flushed {
257
println("current already flushed")
260
for v := range d.current.output {
263
printf("re-adding decoder %p", v.d)
268
d.current.output = nil
269
d.current.flushed = true
272
// WriteTo writes data to w until there's no more data to write or when an error occurs.
273
// The return value n is the number of bytes written.
274
// Any error encountered during the write is also returned.
275
func (d *Decoder) WriteTo(w io.Writer) (int64, error) {
278
if len(d.current.b) > 0 {
279
n2, err2 := w.Write(d.current.b)
281
if err2 != nil && (d.current.err == nil || d.current.err == io.EOF) {
283
} else if n2 != len(d.current.b) {
284
d.current.err = io.ErrShortWrite
287
if d.current.err != nil {
302
// DecodeAll allows stateless decoding of a blob of bytes.
303
// Output will be appended to dst, so if the destination size is known
304
// you can pre-allocate the destination slice to avoid allocations.
305
// DecodeAll can be used concurrently.
306
// The Decoder concurrency limits will be respected.
307
func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) {
308
if d.decoders == nil {
309
return dst, ErrDecoderClosed
312
// Grab a block decoder and frame decoder.
313
block := <-d.decoders
314
frame := block.localFrame
317
printf("re-adding decoder: %p", block)
321
if frame.history.decoders.br != nil {
322
frame.history.decoders.br.in = nil
329
frame.history.reset()
330
err := frame.reset(&frame.bBuf)
334
println("frame reset return EOF")
340
if frame.DictionaryID != nil {
341
dict, ok := d.dicts[*frame.DictionaryID]
343
return nil, ErrUnknownDictionary
346
println("setting dict", frame.DictionaryID)
348
frame.history.setDict(&dict)
351
if frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)) {
352
return dst, ErrDecoderSizeExceeded
354
if frame.FrameContentSize > 0 && frame.FrameContentSize < 1<<30 {
355
// Never preallocate more than 1 GB up front.
356
if cap(dst)-len(dst) < int(frame.FrameContentSize) {
357
dst2 := make([]byte, len(dst), len(dst)+int(frame.FrameContentSize))
363
// Allocate len(input) * 2 by default if nothing is provided
364
// and we didn't get frame content size.
365
size := len(input) * 2
370
if uint64(size) > d.o.maxDecodedSize {
371
size = int(d.o.maxDecodedSize)
373
dst = make([]byte, 0, size)
376
dst, err = frame.runDecoder(dst, block)
380
if len(frame.bBuf) == 0 {
382
println("frame dbuf empty")
390
// nextBlock returns the next block.
391
// If an error occurs d.err will be set.
392
// Optionally the function can block for new output.
393
// If non-blocking mode is used the returned boolean will be false
394
// if no data was available without blocking.
395
func (d *Decoder) nextBlock(blocking bool) (ok bool) {
396
if d.current.err != nil {
400
d.current.b = d.current.b[:0]
403
if d.syncStream.enabled {
407
ok = d.nextBlockSync()
417
d.current.decodeOutput, ok = <-d.current.output
420
case d.current.decodeOutput, ok = <-d.current.output:
426
// This should not happen, so signal error state...
427
d.current.err = io.ErrUnexpectedEOF
430
next := d.current.decodeOutput
431
if next.d != nil && next.d.async.newHist != nil {
432
d.current.crc.Reset()
436
binary.LittleEndian.PutUint32(tmp[:], uint32(xxhash.Sum64(next.b)))
437
println("got", len(d.current.b), "bytes, error:", d.current.err, "data crc:", tmp)
441
n, err := d.current.crc.Write(next.b)
443
if n != len(next.b) {
444
d.current.err = io.ErrShortWrite
448
if next.err == nil && next.d != nil && len(next.d.checkCRC) != 0 {
449
got := d.current.crc.Sum64()
451
binary.LittleEndian.PutUint32(tmp[:], uint32(got))
452
if !bytes.Equal(tmp[:], next.d.checkCRC) && !ignoreCRC {
454
println("CRC Check Failed:", tmp[:], " (got) !=", next.d.checkCRC, "(on stream)")
456
d.current.err = ErrCRCMismatch
459
println("CRC ok", tmp[:])
467
func (d *Decoder) nextBlockSync() (ok bool) {
468
if d.current.d == nil {
469
d.current.d = <-d.decoders
471
for len(d.current.b) == 0 {
472
if !d.syncStream.inFrame {
473
d.frame.history.reset()
474
d.current.err = d.frame.reset(&d.syncStream.br)
475
if d.current.err != nil {
478
if d.frame.DictionaryID != nil {
479
dict, ok := d.dicts[*d.frame.DictionaryID]
481
d.current.err = ErrUnknownDictionary
484
d.frame.history.setDict(&dict)
487
if d.frame.WindowSize > d.o.maxDecodedSize || d.frame.WindowSize > d.o.maxWindowSize {
488
d.current.err = ErrDecoderSizeExceeded
492
d.syncStream.decodedFrame = 0
493
d.syncStream.inFrame = true
495
d.current.err = d.frame.next(d.current.d)
496
if d.current.err != nil {
499
d.frame.history.ensureBlock()
501
println("History trimmed:", len(d.frame.history.b), "decoded already:", d.syncStream.decodedFrame)
503
histBefore := len(d.frame.history.b)
504
d.current.err = d.current.d.decodeBuf(&d.frame.history)
506
if d.current.err != nil {
507
println("error after:", d.current.err)
510
d.current.b = d.frame.history.b[histBefore:]
512
println("history after:", len(d.frame.history.b))
515
// Check frame size (before CRC)
516
d.syncStream.decodedFrame += uint64(len(d.current.b))
517
if d.frame.FrameContentSize > 0 && d.syncStream.decodedFrame > d.frame.FrameContentSize {
519
printf("DecodedFrame (%d) > FrameContentSize (%d)\n", d.syncStream.decodedFrame, d.frame.FrameContentSize)
521
d.current.err = ErrFrameSizeExceeded
526
if d.current.d.Last && d.frame.FrameContentSize > 0 && d.syncStream.decodedFrame != d.frame.FrameContentSize {
528
printf("DecodedFrame (%d) != FrameContentSize (%d)\n", d.syncStream.decodedFrame, d.frame.FrameContentSize)
530
d.current.err = ErrFrameSizeMismatch
535
if d.frame.HasCheckSum {
536
d.frame.crc.Write(d.current.b)
537
if d.current.d.Last {
538
d.current.err = d.frame.checkCRC()
539
if d.current.err != nil {
540
println("CRC error:", d.current.err)
545
d.syncStream.inFrame = !d.current.d.Last
550
func (d *Decoder) stashDecoder() {
551
if d.current.d != nil {
553
printf("re-adding current decoder %p", d.current.d)
555
d.decoders <- d.current.d
560
// Close will release all resources.
561
// It is NOT possible to reuse the decoder after this.
562
func (d *Decoder) Close() {
563
if d.current.err == ErrDecoderClosed {
567
if d.current.cancel != nil {
570
d.current.cancel = nil
572
if d.decoders != nil {
574
for dec := range d.decoders {
579
if d.current.d != nil {
583
d.current.err = ErrDecoderClosed
586
// IOReadCloser returns the decoder as an io.ReadCloser for convenience.
587
// Any changes to the decoder will be reflected, so the returned ReadCloser
588
// can be reused along with the decoder.
589
// io.WriterTo is also supported by the returned ReadCloser.
590
func (d *Decoder) IOReadCloser() io.ReadCloser {
591
return closeWrapper{d: d}
594
// closeWrapper wraps a function call as a closer.
595
type closeWrapper struct {
599
// WriteTo forwards WriteTo calls to the decoder.
600
func (c closeWrapper) WriteTo(w io.Writer) (n int64, err error) {
601
return c.d.WriteTo(w)
604
// Read forwards read calls to the decoder.
605
func (c closeWrapper) Read(p []byte) (n int, err error) {
609
// Close closes the decoder.
610
func (c closeWrapper) Close() error {
615
type decodeOutput struct {
621
func (d *Decoder) startSyncDecoder(r io.Reader) error {
622
d.frame.history.reset()
623
d.syncStream.br = readerWrapper{r: r}
624
d.syncStream.inFrame = false
625
d.syncStream.enabled = true
626
d.syncStream.decodedFrame = 0
632
// Spawn 4 go routines.
633
// 0: Read frames and decode blocks.
634
// 1: Decode block and literals. Receives hufftree and seqdecs, returns seqdecs and huff tree.
635
// 2: Wait for recentOffsets if needed. Decode sequences, send recentOffsets.
636
// 3: Wait for stream history, execute sequences, send stream history.
637
func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output chan decodeOutput) {
638
defer d.streamWg.Done()
639
br := readerWrapper{r: r}
641
var seqPrepare = make(chan *blockDec, d.o.concurrent)
642
var seqDecode = make(chan *blockDec, d.o.concurrent)
643
var seqExecute = make(chan *blockDec, d.o.concurrent)
645
// Async 1: Prepare blocks...
649
for block := range seqPrepare {
656
if block.async.newHist != nil {
658
println("Async 1: new history")
661
if block.async.newHist.dict != nil {
662
hist.setDict(block.async.newHist.dict)
665
if block.err != nil || block.Type != blockTypeCompressed {
666
hasErr = block.err != nil
671
remain, err := block.decodeLiterals(block.data, &hist)
673
hasErr = block.err != nil
675
block.async.literals = hist.decoders.literals
676
block.async.seqData = remain
677
} else if debugDecoder {
678
println("decodeLiterals error:", err)
685
// Async 2: Decode sequences...
690
for block := range seqDecode {
697
if block.async.newHist != nil {
699
println("Async 2: new history, recent:", block.async.newHist.recentOffsets)
701
hist.decoders = block.async.newHist.decoders
702
hist.recentOffsets = block.async.newHist.recentOffsets
703
if block.async.newHist.dict != nil {
704
hist.setDict(block.async.newHist.dict)
707
if block.err != nil || block.Type != blockTypeCompressed {
708
hasErr = block.err != nil
713
hist.decoders.literals = block.async.literals
714
block.err = block.prepareSequences(block.async.seqData, &hist)
715
if debugDecoder && block.err != nil {
716
println("prepareSequences returned:", block.err)
718
hasErr = block.err != nil
719
if block.err == nil {
720
block.err = block.decodeSequences(&hist)
721
if debugDecoder && block.err != nil {
722
println("decodeSequences returned:", block.err)
724
hasErr = block.err != nil
725
// block.async.sequence = hist.decoders.seq[:hist.decoders.nSeqs]
726
block.async.seqSize = hist.decoders.seqSize
733
var wg sync.WaitGroup
736
// Async 3: Execute sequences...
737
frameHistCache := d.frame.history.b
740
var decodedFrame uint64
743
for block := range seqExecute {
744
out := decodeOutput{err: block.err, d: block}
745
if block.err != nil || hasErr {
750
if block.async.newHist != nil {
752
println("Async 3: new history")
754
hist.windowSize = block.async.newHist.windowSize
755
hist.allocFrameBuffer = block.async.newHist.allocFrameBuffer
756
if block.async.newHist.dict != nil {
757
hist.setDict(block.async.newHist.dict)
760
if cap(hist.b) < hist.allocFrameBuffer {
761
if cap(frameHistCache) >= hist.allocFrameBuffer {
762
hist.b = frameHistCache
764
hist.b = make([]byte, 0, hist.allocFrameBuffer)
765
println("Alloc history sized", hist.allocFrameBuffer)
769
fcs = block.async.fcs
772
do := decodeOutput{err: block.err, d: block}
776
println("add rle block length:", block.RLESize)
779
if cap(block.dst) < int(block.RLESize) {
781
block.dst = make([]byte, block.RLESize)
783
block.dst = make([]byte, maxBlockSize)
786
block.dst = block.dst[:block.RLESize]
788
for i := range block.dst {
791
hist.append(block.dst)
795
println("add raw block length:", len(block.data))
797
hist.append(block.data)
799
case blockTypeCompressed:
801
println("execute with history length:", len(hist.b), "window:", hist.windowSize)
803
hist.decoders.seqSize = block.async.seqSize
804
hist.decoders.literals = block.async.literals
805
do.err = block.executeSequences(&hist)
806
hasErr = do.err != nil
807
if debugDecoder && hasErr {
808
println("executeSequences returned:", do.err)
813
decodedFrame += uint64(len(do.b))
814
if fcs > 0 && decodedFrame > fcs {
815
println("fcs exceeded", block.Last, fcs, decodedFrame)
816
do.err = ErrFrameSizeExceeded
818
} else if block.Last && fcs > 0 && decodedFrame != fcs {
819
do.err = ErrFrameSizeMismatch
823
println("fcs ok", block.Last, fcs, decodedFrame)
830
frameHistCache = hist.b
833
println("decoder goroutines finished")
841
println("New frame...")
844
frame.history.reset()
845
err := frame.reset(&br)
846
if debugDecoder && err != nil {
847
println("Frame decoder returned", err)
849
if err == nil && frame.DictionaryID != nil {
850
dict, ok := d.dicts[*frame.DictionaryID]
852
err = ErrUnknownDictionary
854
frame.history.setDict(&dict)
857
if err == nil && d.frame.WindowSize > d.o.maxWindowSize {
858
err = ErrDecoderSizeExceeded
863
case dec := <-d.decoders:
870
// Go through all blocks of the frame.
876
case dec = <-d.decoders:
877
// Once we have a decoder, we MUST return it.
879
err := frame.next(dec)
883
println("Alloc History:", h.allocFrameBuffer)
885
dec.async.newHist = &h
886
dec.async.fcs = frame.FrameContentSize
889
dec.async.newHist = nil
891
if debugDecoder && err != nil {
892
println("next block returned error:", err)
896
if dec.Last && frame.HasCheckSum && err == nil {
897
crc, err := frame.rawInput.readSmall(4)
899
println("CRC missing?", err)
904
dec.checkCRC = tmp[:]
906
println("found crc to check:", dec.checkCRC)
922
d.frame.history.b = frameHistCache