func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
	b.WindowSize = windowSize
	tmp := br.readSmall(3)
	if tmp == nil {
		if debug {
			println("Reading block header:", io.ErrUnexpectedEOF)
		}
		return io.ErrUnexpectedEOF
	}
	bh := uint32(tmp[0]) | (uint32(tmp[1]) << 8) | (uint32(tmp[2]) << 16)
	b.Last = bh&1 != 0
	b.Type = blockType((bh >> 1) & 3)
	cSize := int(bh >> 3)
	maxSize := maxBlockSize
	switch b.Type {
	case blockTypeReserved:
		return ErrReservedBlockType
	case blockTypeRLE:
		b.RLESize = uint32(cSize)
		if b.lowMem {
			maxSize = cSize
		}
		cSize = 1
	case blockTypeCompressed:
		if debug {
			println("Data size on stream:", cSize)
		}
		b.RLESize = 0
		maxSize = maxCompressedBlockSize
		if windowSize < maxCompressedBlockSize && b.lowMem {
			maxSize = int(windowSize)
		}
		if cSize > maxCompressedBlockSize || uint64(cSize) > b.WindowSize {
			if debug {
				printf("compressed block too big: csize:%d block: %+v\n", uint64(cSize), b)
			}
			return ErrCompressedSizeTooBig
		}
	case blockTypeRaw:
		b.RLESize = 0
		maxSize = -1
	default:
		panic("Invalid block type")
	}
	if cap(b.dataStorage) < cSize {
		if b.lowMem {
			b.dataStorage = make([]byte, 0, cSize)
		} else {
			b.dataStorage = make([]byte, 0, maxBlockSize)
		}
	}
	if cap(b.dst) <= maxSize {
		b.dst = make([]byte, 0, maxSize+1)
	}
	var err error
	b.data, err = br.readBig(cSize, b.dataStorage)
	if err != nil {
		if debug {
			println("Reading block:", err, "(", cSize, ")", len(b.data))
			printf("%T", br)
		}
		return err
	}
	return nil
}
reset will reset the block.
Input must be a start of a block and will be at the end of the block when returned.
package zstd
import (
	"errors"
	"fmt"
	"io"
	"sync"
	"github.com/klauspost/compress/huff0"
	"github.com/klauspost/compress/zstd/internal/xxhash"
)
type blockType uint8
const (
	blockTypeRaw blockType = iota
	blockTypeRLE
	blockTypeCompressed
	blockTypeReserved
)
type literalsBlockType uint8
const (
	literalsBlockRaw literalsBlockType = iota
	literalsBlockRLE
	literalsBlockCompressed
	literalsBlockTreeless
)
const (
	maxCompressedBlockSize = 128 << 10
	maxBlockSize = (1 << 21) - 1
	maxCompressedLiteralSize = 1 << 18
	maxRLELiteralSize        = 1 << 20
	maxMatchLen              = 131074
	maxSequences             = 0x7f00 + 0xffff
	maxOffsetBits = 30
)
var (
	huffDecoderPool = sync.Pool{New: func() interface{} {
		return &huff0.Scratch{}
	}}
	fseDecoderPool = sync.Pool{New: func() interface{} {
		return &fseDecoder{}
	}}
)
type blockDec struct {
	data        []byte
	dataStorage []byte
	dst []byte
	literalBuf []byte
	WindowSize uint64
	history     chan *history
	input       chan struct{}
	result      chan decodeOutput
	sequenceBuf []seq
	err         error
	decWG       sync.WaitGroup
	localFrame *frameDec
	RLESize uint32
	tmp     [4]byte
	Type blockType
	Last bool
	lowMem bool
}
func (b *blockDec) String() string {
	if b == nil {
		return "<nil>"
	}
	return fmt.Sprintf("Steam Size: %d, Type: %v, Last: %t, Window: %d", len(b.data), b.Type, b.Last, b.WindowSize)
}
func newBlockDec(lowMem bool) *blockDec {
	b := blockDec{
		lowMem:  lowMem,
		result:  make(chan decodeOutput, 1),
		input:   make(chan struct{}, 1),
		history: make(chan *history, 1),
	}
	b.decWG.Add(1)
	go b.startDecoder()
	return &b
}