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.
4
5package zstd
6
7import (
8	"errors"
9	"fmt"
10	"math"
11	"math/bits"
12
13	"github.com/klauspost/compress/huff0"
14)
15
16type blockEnc struct {
17	size       int
18	literals   []byte
19	sequences  []seq
20	coders     seqCoders
21	litEnc     *huff0.Scratch
22	dictLitEnc *huff0.Scratch
23	wr         bitWriter
24
25	extraLits int
26	last      bool
27
28	output            []byte
29	recentOffsets     [3]uint32
30	prevRecentOffsets [3]uint32
31}
32
33// init should be used once the block has been created.
34// If called more than once, the effect is the same as calling reset.
35func (b *blockEnc) init() {
36	if cap(b.literals) < maxCompressedLiteralSize {
37		b.literals = make([]byte, 0, maxCompressedLiteralSize)
38	}
39	const defSeqs = 200
40	b.literals = b.literals[:0]
41	if cap(b.sequences) < defSeqs {
42		b.sequences = make([]seq, 0, defSeqs)
43	}
44	if cap(b.output) < maxCompressedBlockSize {
45		b.output = make([]byte, 0, maxCompressedBlockSize)
46	}
47	if b.coders.mlEnc == nil {
48		b.coders.mlEnc = &fseEncoder{}
49		b.coders.mlPrev = &fseEncoder{}
50		b.coders.ofEnc = &fseEncoder{}
51		b.coders.ofPrev = &fseEncoder{}
52		b.coders.llEnc = &fseEncoder{}
53		b.coders.llPrev = &fseEncoder{}
54	}
55	b.litEnc = &huff0.Scratch{WantLogLess: 4}
56	b.reset(nil)
57}
58
59// initNewEncode can be used to reset offsets and encoders to the initial state.
60func (b *blockEnc) initNewEncode() {
61	b.recentOffsets = [3]uint32{1, 4, 8}
62	b.litEnc.Reuse = huff0.ReusePolicyNone
63	b.coders.setPrev(nil, nil, nil)
64}
65
66// reset will reset the block for a new encode, but in the same stream,
67// meaning that state will be carried over, but the block content is reset.
68// If a previous block is provided, the recent offsets are carried over.
69func (b *blockEnc) reset(prev *blockEnc) {
70	b.extraLits = 0
71	b.literals = b.literals[:0]
72	b.size = 0
73	b.sequences = b.sequences[:0]
74	b.output = b.output[:0]
75	b.last = false
76	if prev != nil {
77		b.recentOffsets = prev.prevRecentOffsets
78	}
79}
80
81// reset will reset the block for a new encode, but in the same stream,
82// meaning that state will be carried over, but the block content is reset.
83// If a previous block is provided, the recent offsets are carried over.
84func (b *blockEnc) swapEncoders(prev *blockEnc) {
85	b.coders.swap(&prev.coders)
86	b.litEnc, prev.litEnc = prev.litEnc, b.litEnc
87}
88
89// blockHeader contains the information for a block header.
90type blockHeader uint32
91
92// setLast sets the 'last' indicator on a block.
93func (h *blockHeader) setLast(b bool) {
94	if b {
95		*h = *h | 1
96	} else {
97		const mask = (1 << 24) - 2
98		*h = *h & mask
99	}
100}
101
102// setSize will store the compressed size of a block.
103func (h *blockHeader) setSize(v uint32) {
104	const mask = 7
105	*h = (*h)&mask | blockHeader(v<<3)
106}
107
108// setType sets the block type.
109func (h *blockHeader) setType(t blockType) {
110	const mask = 1 | (((1 << 24) - 1) ^ 7)
111	*h = (*h & mask) | blockHeader(t<<1)
112}
113
114// appendTo will append the block header to a slice.
115func (h blockHeader) appendTo(b []byte) []byte {
116	return append(b, uint8(h), uint8(h>>8), uint8(h>>16))
117}
118
119// String returns a string representation of the block.
120func (h blockHeader) String() string {
121	return fmt.Sprintf("Type: %d, Size: %d, Last:%t", (h>>1)&3, h>>3, h&1 == 1)
122}
123
124// literalsHeader contains literals header information.
125type literalsHeader uint64
126
127// setType can be used to set the type of literal block.
128func (h *literalsHeader) setType(t literalsBlockType) {
129	const mask = math.MaxUint64 - 3
130	*h = (*h & mask) | literalsHeader(t)
131}
132
133// setSize can be used to set a single size, for uncompressed and RLE content.
134func (h *literalsHeader) setSize(regenLen int) {
135	inBits := bits.Len32(uint32(regenLen))
136	// Only retain 2 bits
137	const mask = 3
138	lh := uint64(*h & mask)
139	switch {
140	case inBits < 5:
141		lh |= (uint64(regenLen) << 3) | (1 << 60)
142		if debug {
143			got := int(lh>>3) & 0xff
144			if got != regenLen {
145				panic(fmt.Sprint("litRegenSize = ", regenLen, "(want) != ", got, "(got)"))
146			}
147		}
148	case inBits < 12:
149		lh |= (1 << 2) | (uint64(regenLen) << 4) | (2 << 60)
150	case inBits < 20:
151		lh |= (3 << 2) | (uint64(regenLen) << 4) | (3 << 60)
152	default:
153		panic(fmt.Errorf("internal error: block too big (%d)", regenLen))
154	}
155	*h = literalsHeader(lh)
156}
157
158// setSizes will set the size of a compressed literals section and the input length.
159func (h *literalsHeader) setSizes(compLen, inLen int, single bool) {
160	compBits, inBits := bits.Len32(uint32(compLen)), bits.Len32(uint32(inLen))
161	// Only retain 2 bits
162	const mask = 3
163	lh := uint64(*h & mask)
164	switch {
165	case compBits <= 10 && inBits <= 10:
166		if !single {
167			lh |= 1 << 2
168		}
169		lh |= (uint64(inLen) << 4) | (uint64(compLen) << (10 + 4)) | (3 << 60)
170		if debug {
171			const mmask = (1 << 24) - 1
172			n := (lh >> 4) & mmask
173			if int(n&1023) != inLen {
174				panic(fmt.Sprint("regensize:", int(n&1023), "!=", inLen, inBits))
175			}
176			if int(n>>10) != compLen {
177				panic(fmt.Sprint("compsize:", int(n>>10), "!=", compLen, compBits))
178			}
179		}
180	case compBits <= 14 && inBits <= 14:
181		lh |= (2 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (14 + 4)) | (4 << 60)
182		if single {
183			panic("single stream used with more than 10 bits length.")
184		}
185	case compBits <= 18 && inBits <= 18:
186		lh |= (3 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (18 + 4)) | (5 << 60)
187		if single {
188			panic("single stream used with more than 10 bits length.")
189		}
190	default:
191		panic("internal error: block too big")
192	}
193	*h = literalsHeader(lh)
194}
195
196// appendTo will append the literals header to a byte slice.
197func (h literalsHeader) appendTo(b []byte) []byte {
198	size := uint8(h >> 60)
199	switch size {
200	case 1:
201		b = append(b, uint8(h))
202	case 2:
203		b = append(b, uint8(h), uint8(h>>8))
204	case 3:
205		b = append(b, uint8(h), uint8(h>>8), uint8(h>>16))
206	case 4:
207		b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24))
208	case 5:
209		b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24), uint8(h>>32))
210	default:
211		panic(fmt.Errorf("internal error: literalsHeader has invalid size (%d)", size))
212	}
213	return b
214}
215
216// size returns the output size with currently set values.
217func (h literalsHeader) size() int {
218	return int(h >> 60)
219}
220
221func (h literalsHeader) String() string {
222	return fmt.Sprintf("Type: %d, SizeFormat: %d, Size: 0x%d, Bytes:%d", literalsBlockType(h&3), (h>>2)&3, h&((1<<60)-1)>>4, h>>60)
223}
224
225// pushOffsets will push the recent offsets to the backup store.
226func (b *blockEnc) pushOffsets() {
227	b.prevRecentOffsets = b.recentOffsets
228}
229
230// pushOffsets will push the recent offsets to the backup store.
231func (b *blockEnc) popOffsets() {
232	b.recentOffsets = b.prevRecentOffsets
233}
234
235// matchOffset will adjust recent offsets and return the adjusted one,
236// if it matches a previous offset.
237func (b *blockEnc) matchOffset(offset, lits uint32) uint32 {
238	// Check if offset is one of the recent offsets.
239	// Adjusts the output offset accordingly.
240	// Gives a tiny bit of compression, typically around 1%.
241	if true {
242		if lits > 0 {
243			switch offset {
244			case b.recentOffsets[0]:
245				offset = 1
246			case b.recentOffsets[1]:
247				b.recentOffsets[1] = b.recentOffsets[0]
248				b.recentOffsets[0] = offset
249				offset = 2
250			case b.recentOffsets[2]:
251				b.recentOffsets[2] = b.recentOffsets[1]
252				b.recentOffsets[1] = b.recentOffsets[0]
253				b.recentOffsets[0] = offset
254				offset = 3
255			default:
256				b.recentOffsets[2] = b.recentOffsets[1]
257				b.recentOffsets[1] = b.recentOffsets[0]
258				b.recentOffsets[0] = offset
259				offset += 3
260			}
261		} else {
262			switch offset {
263			case b.recentOffsets[1]:
264				b.recentOffsets[1] = b.recentOffsets[0]
265				b.recentOffsets[0] = offset
266				offset = 1
267			case b.recentOffsets[2]:
268				b.recentOffsets[2] = b.recentOffsets[1]
269				b.recentOffsets[1] = b.recentOffsets[0]
270				b.recentOffsets[0] = offset
271				offset = 2
272			case b.recentOffsets[0] - 1:
273				b.recentOffsets[2] = b.recentOffsets[1]
274				b.recentOffsets[1] = b.recentOffsets[0]
275				b.recentOffsets[0] = offset
276				offset = 3
277			default:
278				b.recentOffsets[2] = b.recentOffsets[1]
279				b.recentOffsets[1] = b.recentOffsets[0]
280				b.recentOffsets[0] = offset
281				offset += 3
282			}
283		}
284	} else {
285		offset += 3
286	}
287	return offset
288}
289
290// encodeRaw can be used to set the output to a raw representation of supplied bytes.
291func (b *blockEnc) encodeRaw(a []byte) {
292	var bh blockHeader
293	bh.setLast(b.last)
294	bh.setSize(uint32(len(a)))
295	bh.setType(blockTypeRaw)
296	b.output = bh.appendTo(b.output[:0])
297	b.output = append(b.output, a...)
298	if debug {
299		println("Adding RAW block, length", len(a), "last:", b.last)
300	}
301}
302
303// encodeRaw can be used to set the output to a raw representation of supplied bytes.
304func (b *blockEnc) encodeRawTo(dst, src []byte) []byte {
305	var bh blockHeader
306	bh.setLast(b.last)
307	bh.setSize(uint32(len(src)))
308	bh.setType(blockTypeRaw)
309	dst = bh.appendTo(dst)
310	dst = append(dst, src...)
311	if debug {
312		println("Adding RAW block, length", len(src), "last:", b.last)
313	}
314	return dst
315}
316
317// encodeLits can be used if the block is only litLen.
318func (b *blockEnc) encodeLits(lits []byte, raw bool) error {
319	var bh blockHeader
320	bh.setLast(b.last)
321	bh.setSize(uint32(len(lits)))
322
323	// Don't compress extremely small blocks
324	if len(lits) < 8 || (len(lits) < 32 && b.dictLitEnc == nil) || raw {
325		if debug {
326			println("Adding RAW block, length", len(lits), "last:", b.last)
327		}
328		bh.setType(blockTypeRaw)
329		b.output = bh.appendTo(b.output)
330		b.output = append(b.output, lits...)
331		return nil
332	}
333
334	var (
335		out            []byte
336		reUsed, single bool
337		err            error
338	)
339	if b.dictLitEnc != nil {
340		b.litEnc.TransferCTable(b.dictLitEnc)
341		b.litEnc.Reuse = huff0.ReusePolicyAllow
342		b.dictLitEnc = nil
343	}
344	if len(lits) >= 1024 {
345		// Use 4 Streams.
346		out, reUsed, err = huff0.Compress4X(lits, b.litEnc)
347	} else if len(lits) > 32 {
348		// Use 1 stream
349		single = true
350		out, reUsed, err = huff0.Compress1X(lits, b.litEnc)
351	} else {
352		err = huff0.ErrIncompressible
353	}
354
355	switch err {
356	case huff0.ErrIncompressible:
357		if debug {
358			println("Adding RAW block, length", len(lits), "last:", b.last)
359		}
360		bh.setType(blockTypeRaw)
361		b.output = bh.appendTo(b.output)
362		b.output = append(b.output, lits...)
363		return nil
364	case huff0.ErrUseRLE:
365		if debug {
366			println("Adding RLE block, length", len(lits))
367		}
368		bh.setType(blockTypeRLE)
369		b.output = bh.appendTo(b.output)
370		b.output = append(b.output, lits[0])
371		return nil
372	default:
373		return err
374	case nil:
375	}
376	// Compressed...
377	// Now, allow reuse
378	b.litEnc.Reuse = huff0.ReusePolicyAllow
379	bh.setType(blockTypeCompressed)
380	var lh literalsHeader
381	if reUsed {
382		if debug {
383			println("Reused tree, compressed to", len(out))
384		}
385		lh.setType(literalsBlockTreeless)
386	} else {
387		if debug {
388			println("New tree, compressed to", len(out), "tree size:", len(b.litEnc.OutTable))
389		}
390		lh.setType(literalsBlockCompressed)
391	}
392	// Set sizes
393	lh.setSizes(len(out), len(lits), single)
394	bh.setSize(uint32(len(out) + lh.size() + 1))
395
396	// Write block headers.
397	b.output = bh.appendTo(b.output)
398	b.output = lh.appendTo(b.output)
399	// Add compressed data.
400	b.output = append(b.output, out...)
401	// No sequences.
402	b.output = append(b.output, 0)
403	return nil
404}
405
406// fuzzFseEncoder can be used to fuzz the FSE encoder.
407func fuzzFseEncoder(data []byte) int {
408	if len(data) > maxSequences || len(data) < 2 {
409		return 0
410	}
411	enc := fseEncoder{}
412	hist := enc.Histogram()[:256]
413	maxSym := uint8(0)
414	for i, v := range data {
415		v = v & 63
416		data[i] = v
417		hist[v]++
418		if v > maxSym {
419			maxSym = v
420		}
421	}
422	if maxSym == 0 {
423		// All 0
424		return 0
425	}
426	maxCount := func(a []uint32) int {
427		var max uint32
428		for _, v := range a {
429			if v > max {
430				max = v
431			}
432		}
433		return int(max)
434	}
435	cnt := maxCount(hist[:maxSym])
436	if cnt == len(data) {
437		// RLE
438		return 0
439	}
440	enc.HistogramFinished(maxSym, cnt)
441	err := enc.normalizeCount(len(data))
442	if err != nil {
443		return 0
444	}
445	_, err = enc.writeCount(nil)
446	if err != nil {
447		panic(err)
448	}
449	return 1
450}
451
452// encode will encode the block and append the output in b.output.
453// Previous offset codes must be pushed if more blocks are expected.
454func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error {
455	if len(b.sequences) == 0 {
456		return b.encodeLits(b.literals, rawAllLits)
457	}
458	// We want some difference to at least account for the headers.
459	saved := b.size - len(b.literals) - (b.size >> 5)
460	if saved < 16 {
461		if org == nil {
462			return errIncompressible
463		}
464		b.popOffsets()
465		return b.encodeLits(org, rawAllLits)
466	}
467
468	var bh blockHeader
469	var lh literalsHeader
470	bh.setLast(b.last)
471	bh.setType(blockTypeCompressed)
472	// Store offset of the block header. Needed when we know the size.
473	bhOffset := len(b.output)
474	b.output = bh.appendTo(b.output)
475
476	var (
477		out            []byte
478		reUsed, single bool
479		err            error
480	)
481	if b.dictLitEnc != nil {
482		b.litEnc.TransferCTable(b.dictLitEnc)
483		b.litEnc.Reuse = huff0.ReusePolicyAllow
484		b.dictLitEnc = nil
485	}
486	if len(b.literals) >= 1024 && !raw {
487		// Use 4 Streams.
488		out, reUsed, err = huff0.Compress4X(b.literals, b.litEnc)
489	} else if len(b.literals) > 32 && !raw {
490		// Use 1 stream
491		single = true
492		out, reUsed, err = huff0.Compress1X(b.literals, b.litEnc)
493	} else {
494		err = huff0.ErrIncompressible
495	}
496
497	switch err {
498	case huff0.ErrIncompressible:
499		lh.setType(literalsBlockRaw)
500		lh.setSize(len(b.literals))
501		b.output = lh.appendTo(b.output)
502		b.output = append(b.output, b.literals...)
503		if debug {
504			println("Adding literals RAW, length", len(b.literals))
505		}
506	case huff0.ErrUseRLE:
507		lh.setType(literalsBlockRLE)
508		lh.setSize(len(b.literals))
509		b.output = lh.appendTo(b.output)
510		b.output = append(b.output, b.literals[0])
511		if debug {
512			println("Adding literals RLE")
513		}
514	default:
515		if debug {
516			println("Adding literals ERROR:", err)
517		}
518		return err
519	case nil:
520		// Compressed litLen...
521		if reUsed {
522			if debug {
523				println("reused tree")
524			}
525			lh.setType(literalsBlockTreeless)
526		} else {
527			if debug {
528				println("new tree, size:", len(b.litEnc.OutTable))
529			}
530			lh.setType(literalsBlockCompressed)
531			if debug {
532				_, _, err := huff0.ReadTable(out, nil)
533				if err != nil {
534					panic(err)
535				}
536			}
537		}
538		lh.setSizes(len(out), len(b.literals), single)
539		if debug {
540			printf("Compressed %d literals to %d bytes", len(b.literals), len(out))
541			println("Adding literal header:", lh)
542		}
543		b.output = lh.appendTo(b.output)
544		b.output = append(b.output, out...)
545		b.litEnc.Reuse = huff0.ReusePolicyAllow
546		if debug {
547			println("Adding literals compressed")
548		}
549	}
550	// Sequence compression
551
552	// Write the number of sequences
553	switch {
554	case len(b.sequences) < 128:
555		b.output = append(b.output, uint8(len(b.sequences)))
556	case len(b.sequences) < 0x7f00: // TODO: this could be wrong
557		n := len(b.sequences)
558		b.output = append(b.output, 128+uint8(n>>8), uint8(n))
559	default:
560		n := len(b.sequences) - 0x7f00
561		b.output = append(b.output, 255, uint8(n), uint8(n>>8))
562	}
563	if debug {
564		println("Encoding", len(b.sequences), "sequences")
565	}
566	b.genCodes()
567	llEnc := b.coders.llEnc
568	ofEnc := b.coders.ofEnc
569	mlEnc := b.coders.mlEnc
570	err = llEnc.normalizeCount(len(b.sequences))
571	if err != nil {
572		return err
573	}
574	err = ofEnc.normalizeCount(len(b.sequences))
575	if err != nil {
576		return err
577	}
578	err = mlEnc.normalizeCount(len(b.sequences))
579	if err != nil {
580		return err
581	}
582
583	// Choose the best compression mode for each type.
584	// Will evaluate the new vs predefined and previous.
585	chooseComp := func(cur, prev, preDef *fseEncoder) (*fseEncoder, seqCompMode) {
586		// See if predefined/previous is better
587		hist := cur.count[:cur.symbolLen]
588		nSize := cur.approxSize(hist) + cur.maxHeaderSize()
589		predefSize := preDef.approxSize(hist)
590		prevSize := prev.approxSize(hist)
591
592		// Add a small penalty for new encoders.
593		// Don't bother with extremely small (<2 byte gains).
594		nSize = nSize + (nSize+2*8*16)>>4
595		switch {
596		case predefSize <= prevSize && predefSize <= nSize || forcePreDef:
597			if debug {
598				println("Using predefined", predefSize>>3, "<=", nSize>>3)
599			}
600			return preDef, compModePredefined
601		case prevSize <= nSize:
602			if debug {
603				println("Using previous", prevSize>>3, "<=", nSize>>3)
604			}
605			return prev, compModeRepeat
606		default:
607			if debug {
608				println("Using new, predef", predefSize>>3, ". previous:", prevSize>>3, ">", nSize>>3, "header max:", cur.maxHeaderSize()>>3, "bytes")
609				println("tl:", cur.actualTableLog, "symbolLen:", cur.symbolLen, "norm:", cur.norm[:cur.symbolLen], "hist", cur.count[:cur.symbolLen])
610			}
611			return cur, compModeFSE
612		}
613	}
614
615	// Write compression mode
616	var mode uint8
617	if llEnc.useRLE {
618		mode |= uint8(compModeRLE) << 6
619		llEnc.setRLE(b.sequences[0].llCode)
620		if debug {
621			println("llEnc.useRLE")
622		}
623	} else {
624		var m seqCompMode
625		llEnc, m = chooseComp(llEnc, b.coders.llPrev, &fsePredefEnc[tableLiteralLengths])
626		mode |= uint8(m) << 6
627	}
628	if ofEnc.useRLE {
629		mode |= uint8(compModeRLE) << 4
630		ofEnc.setRLE(b.sequences[0].ofCode)
631		if debug {
632			println("ofEnc.useRLE")
633		}
634	} else {
635		var m seqCompMode
636		ofEnc, m = chooseComp(ofEnc, b.coders.ofPrev, &fsePredefEnc[tableOffsets])
637		mode |= uint8(m) << 4
638	}
639
640	if mlEnc.useRLE {
641		mode |= uint8(compModeRLE) << 2
642		mlEnc.setRLE(b.sequences[0].mlCode)
643		if debug {
644			println("mlEnc.useRLE, code: ", b.sequences[0].mlCode, "value", b.sequences[0].matchLen)
645		}
646	} else {
647		var m seqCompMode
648		mlEnc, m = chooseComp(mlEnc, b.coders.mlPrev, &fsePredefEnc[tableMatchLengths])
649		mode |= uint8(m) << 2
650	}
651	b.output = append(b.output, mode)
652	if debug {
653		printf("Compression modes: 0b%b", mode)
654	}
655	b.output, err = llEnc.writeCount(b.output)
656	if err != nil {
657		return err
658	}
659	start := len(b.output)
660	b.output, err = ofEnc.writeCount(b.output)
661	if err != nil {
662		return err
663	}
664	if false {
665		println("block:", b.output[start:], "tablelog", ofEnc.actualTableLog, "maxcount:", ofEnc.maxCount)
666		fmt.Printf("selected TableLog: %d, Symbol length: %d\n", ofEnc.actualTableLog, ofEnc.symbolLen)
667		for i, v := range ofEnc.norm[:ofEnc.symbolLen] {
668			fmt.Printf("%3d: %5d -> %4d \n", i, ofEnc.count[i], v)
669		}
670	}
671	b.output, err = mlEnc.writeCount(b.output)
672	if err != nil {
673		return err
674	}
675
676	// Maybe in block?
677	wr := &b.wr
678	wr.reset(b.output)
679
680	var ll, of, ml cState
681
682	// Current sequence
683	seq := len(b.sequences) - 1
684	s := b.sequences[seq]
685	llEnc.setBits(llBitsTable[:])
686	mlEnc.setBits(mlBitsTable[:])
687	ofEnc.setBits(nil)
688
689	llTT, ofTT, mlTT := llEnc.ct.symbolTT[:256], ofEnc.ct.symbolTT[:256], mlEnc.ct.symbolTT[:256]
690
691	// We have 3 bounds checks here (and in the loop).
692	// Since we are iterating backwards it is kinda hard to avoid.
693	llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
694	ll.init(wr, &llEnc.ct, llB)
695	of.init(wr, &ofEnc.ct, ofB)
696	wr.flush32()
697	ml.init(wr, &mlEnc.ct, mlB)
698
699	// Each of these lookups also generates a bounds check.
700	wr.addBits32NC(s.litLen, llB.outBits)
701	wr.addBits32NC(s.matchLen, mlB.outBits)
702	wr.flush32()
703	wr.addBits32NC(s.offset, ofB.outBits)
704	if debugSequences {
705		println("Encoded seq", seq, s, "codes:", s.llCode, s.mlCode, s.ofCode, "states:", ll.state, ml.state, of.state, "bits:", llB, mlB, ofB)
706	}
707	seq--
708	if llEnc.maxBits+mlEnc.maxBits+ofEnc.maxBits <= 32 {
709		// No need to flush (common)
710		for seq >= 0 {
711			s = b.sequences[seq]
712			wr.flush32()
713			llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
714			// tabelog max is 8 for all.
715			of.encode(ofB)
716			ml.encode(mlB)
717			ll.encode(llB)
718			wr.flush32()
719
720			// We checked that all can stay within 32 bits
721			wr.addBits32NC(s.litLen, llB.outBits)
722			wr.addBits32NC(s.matchLen, mlB.outBits)
723			wr.addBits32NC(s.offset, ofB.outBits)
724
725			if debugSequences {
726				println("Encoded seq", seq, s)
727			}
728
729			seq--
730		}
731	} else {
732		for seq >= 0 {
733			s = b.sequences[seq]
734			wr.flush32()
735			llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
736			// tabelog max is below 8 for each.
737			of.encode(ofB)
738			ml.encode(mlB)
739			ll.encode(llB)
740			wr.flush32()
741
742			// ml+ll = max 32 bits total
743			wr.addBits32NC(s.litLen, llB.outBits)
744			wr.addBits32NC(s.matchLen, mlB.outBits)
745			wr.flush32()
746			wr.addBits32NC(s.offset, ofB.outBits)
747
748			if debugSequences {
749				println("Encoded seq", seq, s)
750			}
751
752			seq--
753		}
754	}
755	ml.flush(mlEnc.actualTableLog)
756	of.flush(ofEnc.actualTableLog)
757	ll.flush(llEnc.actualTableLog)
758	err = wr.close()
759	if err != nil {
760		return err
761	}
762	b.output = wr.out
763
764	if len(b.output)-3-bhOffset >= b.size {
765		// Maybe even add a bigger margin.
766		b.litEnc.Reuse = huff0.ReusePolicyNone
767		return errIncompressible
768	}
769
770	// Size is output minus block header.
771	bh.setSize(uint32(len(b.output)-bhOffset) - 3)
772	if debug {
773		println("Rewriting block header", bh)
774	}
775	_ = bh.appendTo(b.output[bhOffset:bhOffset])
776	b.coders.setPrev(llEnc, mlEnc, ofEnc)
777	return nil
778}
779
780var errIncompressible = errors.New("incompressible")
781
782func (b *blockEnc) genCodes() {
783	if len(b.sequences) == 0 {
784		// nothing to do
785		return
786	}
787
788	if len(b.sequences) > math.MaxUint16 {
789		panic("can only encode up to 64K sequences")
790	}
791	// No bounds checks after here:
792	llH := b.coders.llEnc.Histogram()[:256]
793	ofH := b.coders.ofEnc.Histogram()[:256]
794	mlH := b.coders.mlEnc.Histogram()[:256]
795	for i := range llH {
796		llH[i] = 0
797	}
798	for i := range ofH {
799		ofH[i] = 0
800	}
801	for i := range mlH {
802		mlH[i] = 0
803	}
804
805	var llMax, ofMax, mlMax uint8
806	for i, seq := range b.sequences {
807		v := llCode(seq.litLen)
808		seq.llCode = v
809		llH[v]++
810		if v > llMax {
811			llMax = v
812		}
813
814		v = ofCode(seq.offset)
815		seq.ofCode = v
816		ofH[v]++
817		if v > ofMax {
818			ofMax = v
819		}
820
821		v = mlCode(seq.matchLen)
822		seq.mlCode = v
823		mlH[v]++
824		if v > mlMax {
825			mlMax = v
826			if debugAsserts && mlMax > maxMatchLengthSymbol {
827				panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d), matchlen: %d", mlMax, seq.matchLen))
828			}
829		}
830		b.sequences[i] = seq
831	}
832	maxCount := func(a []uint32) int {
833		var max uint32
834		for _, v := range a {
835			if v > max {
836				max = v
837			}
838		}
839		return int(max)
840	}
841	if debugAsserts && mlMax > maxMatchLengthSymbol {
842		panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d)", mlMax))
843	}
844	if debugAsserts && ofMax > maxOffsetBits {
845		panic(fmt.Errorf("ofMax > maxOffsetBits (%d)", ofMax))
846	}
847	if debugAsserts && llMax > maxLiteralLengthSymbol {
848		panic(fmt.Errorf("llMax > maxLiteralLengthSymbol (%d)", llMax))
849	}
850
851	b.coders.mlEnc.HistogramFinished(mlMax, maxCount(mlH[:mlMax+1]))
852	b.coders.ofEnc.HistogramFinished(ofMax, maxCount(ofH[:ofMax+1]))
853	b.coders.llEnc.HistogramFinished(llMax, maxCount(llH[:llMax+1]))
854}
855