You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							2632 lines
						
					
					
						
							68 KiB
						
					
					
				
			
		
		
	
	
							2632 lines
						
					
					
						
							68 KiB
						
					
					
				package brotli
 | 
						|
 | 
						|
/* Copyright 2013 Google Inc. All Rights Reserved.
 | 
						|
 | 
						|
   Distributed under MIT license.
 | 
						|
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
 | 
						|
*/
 | 
						|
 | 
						|
const (
 | 
						|
	decoderResultError           = 0
 | 
						|
	decoderResultSuccess         = 1
 | 
						|
	decoderResultNeedsMoreInput  = 2
 | 
						|
	decoderResultNeedsMoreOutput = 3
 | 
						|
)
 | 
						|
 | 
						|
/**
 | 
						|
 * Error code for detailed logging / production debugging.
 | 
						|
 *
 | 
						|
 * See ::BrotliDecoderGetErrorCode and ::BROTLI_LAST_ERROR_CODE.
 | 
						|
 */
 | 
						|
const (
 | 
						|
	decoderNoError                          = 0
 | 
						|
	decoderSuccess                          = 1
 | 
						|
	decoderNeedsMoreInput                   = 2
 | 
						|
	decoderNeedsMoreOutput                  = 3
 | 
						|
	decoderErrorFormatExuberantNibble       = -1
 | 
						|
	decoderErrorFormatReserved              = -2
 | 
						|
	decoderErrorFormatExuberantMetaNibble   = -3
 | 
						|
	decoderErrorFormatSimpleHuffmanAlphabet = -4
 | 
						|
	decoderErrorFormatSimpleHuffmanSame     = -5
 | 
						|
	decoderErrorFormatClSpace               = -6
 | 
						|
	decoderErrorFormatHuffmanSpace          = -7
 | 
						|
	decoderErrorFormatContextMapRepeat      = -8
 | 
						|
	decoderErrorFormatBlockLength1          = -9
 | 
						|
	decoderErrorFormatBlockLength2          = -10
 | 
						|
	decoderErrorFormatTransform             = -11
 | 
						|
	decoderErrorFormatDictionary            = -12
 | 
						|
	decoderErrorFormatWindowBits            = -13
 | 
						|
	decoderErrorFormatPadding1              = -14
 | 
						|
	decoderErrorFormatPadding2              = -15
 | 
						|
	decoderErrorFormatDistance              = -16
 | 
						|
	decoderErrorDictionaryNotSet            = -19
 | 
						|
	decoderErrorInvalidArguments            = -20
 | 
						|
	decoderErrorAllocContextModes           = -21
 | 
						|
	decoderErrorAllocTreeGroups             = -22
 | 
						|
	decoderErrorAllocContextMap             = -25
 | 
						|
	decoderErrorAllocRingBuffer1            = -26
 | 
						|
	decoderErrorAllocRingBuffer2            = -27
 | 
						|
	decoderErrorAllocBlockTypeTrees         = -30
 | 
						|
	decoderErrorUnreachable                 = -31
 | 
						|
)
 | 
						|
 | 
						|
/**
 | 
						|
 * The value of the last error code, negative integer.
 | 
						|
 *
 | 
						|
 * All other error code values are in the range from ::lastErrorCode
 | 
						|
 * to @c -1. There are also 4 other possible non-error codes @c 0 .. @c 3 in
 | 
						|
 * ::BrotliDecoderErrorCode enumeration.
 | 
						|
 */
 | 
						|
const lastErrorCode = decoderErrorUnreachable
 | 
						|
 | 
						|
/** Options to be used with ::BrotliDecoderSetParameter. */
 | 
						|
const (
 | 
						|
	decoderParamDisableRingBufferReallocation = 0
 | 
						|
	decoderParamLargeWindow                   = 1
 | 
						|
)
 | 
						|
 | 
						|
const huffmanTableBits = 8
 | 
						|
 | 
						|
const huffmanTableMask = 0xFF
 | 
						|
 | 
						|
/* We need the slack region for the following reasons:
 | 
						|
   - doing up to two 16-byte copies for fast backward copying
 | 
						|
   - inserting transformed dictionary word (5 prefix + 24 base + 8 suffix) */
 | 
						|
const kRingBufferWriteAheadSlack uint32 = 42
 | 
						|
 | 
						|
var kCodeLengthCodeOrder = [codeLengthCodes]byte{1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15}
 | 
						|
 | 
						|
/* Static prefix code for the complex code length code lengths. */
 | 
						|
var kCodeLengthPrefixLength = [16]byte{2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4}
 | 
						|
 | 
						|
var kCodeLengthPrefixValue = [16]byte{0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5}
 | 
						|
 | 
						|
func decoderSetParameter(state *Reader, p int, value uint32) bool {
 | 
						|
	if state.state != stateUninited {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	switch p {
 | 
						|
	case decoderParamDisableRingBufferReallocation:
 | 
						|
		if !(value == 0) {
 | 
						|
			state.canny_ringbuffer_allocation = 0
 | 
						|
		} else {
 | 
						|
			state.canny_ringbuffer_allocation = 1
 | 
						|
		}
 | 
						|
		return true
 | 
						|
 | 
						|
	case decoderParamLargeWindow:
 | 
						|
		state.large_window = (!(value == 0))
 | 
						|
		return true
 | 
						|
 | 
						|
	default:
 | 
						|
		return false
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Saves error code and converts it to BrotliDecoderResult. */
 | 
						|
func saveErrorCode(s *Reader, e int) int {
 | 
						|
	s.error_code = int(e)
 | 
						|
	switch e {
 | 
						|
	case decoderSuccess:
 | 
						|
		return decoderResultSuccess
 | 
						|
 | 
						|
	case decoderNeedsMoreInput:
 | 
						|
		return decoderResultNeedsMoreInput
 | 
						|
 | 
						|
	case decoderNeedsMoreOutput:
 | 
						|
		return decoderResultNeedsMoreOutput
 | 
						|
 | 
						|
	default:
 | 
						|
		return decoderResultError
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for "Large Window Brotli".
 | 
						|
   Precondition: bit-reader accumulator has at least 8 bits. */
 | 
						|
func decodeWindowBits(s *Reader, br *bitReader) int {
 | 
						|
	var n uint32
 | 
						|
	var large_window bool = s.large_window
 | 
						|
	s.large_window = false
 | 
						|
	takeBits(br, 1, &n)
 | 
						|
	if n == 0 {
 | 
						|
		s.window_bits = 16
 | 
						|
		return decoderSuccess
 | 
						|
	}
 | 
						|
 | 
						|
	takeBits(br, 3, &n)
 | 
						|
	if n != 0 {
 | 
						|
		s.window_bits = 17 + n
 | 
						|
		return decoderSuccess
 | 
						|
	}
 | 
						|
 | 
						|
	takeBits(br, 3, &n)
 | 
						|
	if n == 1 {
 | 
						|
		if large_window {
 | 
						|
			takeBits(br, 1, &n)
 | 
						|
			if n == 1 {
 | 
						|
				return decoderErrorFormatWindowBits
 | 
						|
			}
 | 
						|
 | 
						|
			s.large_window = true
 | 
						|
			return decoderSuccess
 | 
						|
		} else {
 | 
						|
			return decoderErrorFormatWindowBits
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if n != 0 {
 | 
						|
		s.window_bits = 8 + n
 | 
						|
		return decoderSuccess
 | 
						|
	}
 | 
						|
 | 
						|
	s.window_bits = 17
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */
 | 
						|
func decodeVarLenUint8(s *Reader, br *bitReader, value *uint32) int {
 | 
						|
	var bits uint32
 | 
						|
	switch s.substate_decode_uint8 {
 | 
						|
	case stateDecodeUint8None:
 | 
						|
		if !safeReadBits(br, 1, &bits) {
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
 | 
						|
		if bits == 0 {
 | 
						|
			*value = 0
 | 
						|
			return decoderSuccess
 | 
						|
		}
 | 
						|
		fallthrough
 | 
						|
 | 
						|
		/* Fall through. */
 | 
						|
	case stateDecodeUint8Short:
 | 
						|
		if !safeReadBits(br, 3, &bits) {
 | 
						|
			s.substate_decode_uint8 = stateDecodeUint8Short
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
 | 
						|
		if bits == 0 {
 | 
						|
			*value = 1
 | 
						|
			s.substate_decode_uint8 = stateDecodeUint8None
 | 
						|
			return decoderSuccess
 | 
						|
		}
 | 
						|
 | 
						|
		/* Use output value as a temporary storage. It MUST be persisted. */
 | 
						|
		*value = bits
 | 
						|
		fallthrough
 | 
						|
 | 
						|
		/* Fall through. */
 | 
						|
	case stateDecodeUint8Long:
 | 
						|
		if !safeReadBits(br, *value, &bits) {
 | 
						|
			s.substate_decode_uint8 = stateDecodeUint8Long
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
 | 
						|
		*value = (1 << *value) + bits
 | 
						|
		s.substate_decode_uint8 = stateDecodeUint8None
 | 
						|
		return decoderSuccess
 | 
						|
 | 
						|
	default:
 | 
						|
		return decoderErrorUnreachable
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes a metablock length and flags by reading 2 - 31 bits. */
 | 
						|
func decodeMetaBlockLength(s *Reader, br *bitReader) int {
 | 
						|
	var bits uint32
 | 
						|
	var i int
 | 
						|
	for {
 | 
						|
		switch s.substate_metablock_header {
 | 
						|
		case stateMetablockHeaderNone:
 | 
						|
			if !safeReadBits(br, 1, &bits) {
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			if bits != 0 {
 | 
						|
				s.is_last_metablock = 1
 | 
						|
			} else {
 | 
						|
				s.is_last_metablock = 0
 | 
						|
			}
 | 
						|
			s.meta_block_remaining_len = 0
 | 
						|
			s.is_uncompressed = 0
 | 
						|
			s.is_metadata = 0
 | 
						|
			if s.is_last_metablock == 0 {
 | 
						|
				s.substate_metablock_header = stateMetablockHeaderNibbles
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderEmpty
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockHeaderEmpty:
 | 
						|
			if !safeReadBits(br, 1, &bits) {
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			if bits != 0 {
 | 
						|
				s.substate_metablock_header = stateMetablockHeaderNone
 | 
						|
				return decoderSuccess
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderNibbles
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockHeaderNibbles:
 | 
						|
			if !safeReadBits(br, 2, &bits) {
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			s.size_nibbles = uint(byte(bits + 4))
 | 
						|
			s.loop_counter = 0
 | 
						|
			if bits == 3 {
 | 
						|
				s.is_metadata = 1
 | 
						|
				s.substate_metablock_header = stateMetablockHeaderReserved
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderSize
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockHeaderSize:
 | 
						|
			i = s.loop_counter
 | 
						|
 | 
						|
			for ; i < int(s.size_nibbles); i++ {
 | 
						|
				if !safeReadBits(br, 4, &bits) {
 | 
						|
					s.loop_counter = i
 | 
						|
					return decoderNeedsMoreInput
 | 
						|
				}
 | 
						|
 | 
						|
				if uint(i+1) == s.size_nibbles && s.size_nibbles > 4 && bits == 0 {
 | 
						|
					return decoderErrorFormatExuberantNibble
 | 
						|
				}
 | 
						|
 | 
						|
				s.meta_block_remaining_len |= int(bits << uint(i*4))
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderUncompressed
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockHeaderUncompressed:
 | 
						|
			if s.is_last_metablock == 0 {
 | 
						|
				if !safeReadBits(br, 1, &bits) {
 | 
						|
					return decoderNeedsMoreInput
 | 
						|
				}
 | 
						|
 | 
						|
				if bits != 0 {
 | 
						|
					s.is_uncompressed = 1
 | 
						|
				} else {
 | 
						|
					s.is_uncompressed = 0
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			s.meta_block_remaining_len++
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderNone
 | 
						|
			return decoderSuccess
 | 
						|
 | 
						|
		case stateMetablockHeaderReserved:
 | 
						|
			if !safeReadBits(br, 1, &bits) {
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			if bits != 0 {
 | 
						|
				return decoderErrorFormatReserved
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderBytes
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockHeaderBytes:
 | 
						|
			if !safeReadBits(br, 2, &bits) {
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			if bits == 0 {
 | 
						|
				s.substate_metablock_header = stateMetablockHeaderNone
 | 
						|
				return decoderSuccess
 | 
						|
			}
 | 
						|
 | 
						|
			s.size_nibbles = uint(byte(bits))
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderMetadata
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockHeaderMetadata:
 | 
						|
			i = s.loop_counter
 | 
						|
 | 
						|
			for ; i < int(s.size_nibbles); i++ {
 | 
						|
				if !safeReadBits(br, 8, &bits) {
 | 
						|
					s.loop_counter = i
 | 
						|
					return decoderNeedsMoreInput
 | 
						|
				}
 | 
						|
 | 
						|
				if uint(i+1) == s.size_nibbles && s.size_nibbles > 1 && bits == 0 {
 | 
						|
					return decoderErrorFormatExuberantMetaNibble
 | 
						|
				}
 | 
						|
 | 
						|
				s.meta_block_remaining_len |= int(bits << uint(i*8))
 | 
						|
			}
 | 
						|
 | 
						|
			s.meta_block_remaining_len++
 | 
						|
			s.substate_metablock_header = stateMetablockHeaderNone
 | 
						|
			return decoderSuccess
 | 
						|
 | 
						|
		default:
 | 
						|
			return decoderErrorUnreachable
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes the Huffman code.
 | 
						|
   This method doesn't read data from the bit reader, BUT drops the amount of
 | 
						|
   bits that correspond to the decoded symbol.
 | 
						|
   bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */
 | 
						|
func decodeSymbol(bits uint32, table []huffmanCode, br *bitReader) uint32 {
 | 
						|
	table = table[bits&huffmanTableMask:]
 | 
						|
	if table[0].bits > huffmanTableBits {
 | 
						|
		var nbits uint32 = uint32(table[0].bits) - huffmanTableBits
 | 
						|
		dropBits(br, huffmanTableBits)
 | 
						|
		table = table[uint32(table[0].value)+((bits>>huffmanTableBits)&bitMask(nbits)):]
 | 
						|
	}
 | 
						|
 | 
						|
	dropBits(br, uint32(table[0].bits))
 | 
						|
	return uint32(table[0].value)
 | 
						|
}
 | 
						|
 | 
						|
/* Reads and decodes the next Huffman code from bit-stream.
 | 
						|
   This method peeks 16 bits of input and drops 0 - 15 of them. */
 | 
						|
func readSymbol(table []huffmanCode, br *bitReader) uint32 {
 | 
						|
	return decodeSymbol(get16BitsUnmasked(br), table, br)
 | 
						|
}
 | 
						|
 | 
						|
/* Same as DecodeSymbol, but it is known that there is less than 15 bits of
 | 
						|
   input are currently available. */
 | 
						|
func safeDecodeSymbol(table []huffmanCode, br *bitReader, result *uint32) bool {
 | 
						|
	var val uint32
 | 
						|
	var available_bits uint32 = getAvailableBits(br)
 | 
						|
	if available_bits == 0 {
 | 
						|
		if table[0].bits == 0 {
 | 
						|
			*result = uint32(table[0].value)
 | 
						|
			return true
 | 
						|
		}
 | 
						|
 | 
						|
		return false /* No valid bits at all. */
 | 
						|
	}
 | 
						|
 | 
						|
	val = uint32(getBitsUnmasked(br))
 | 
						|
	table = table[val&huffmanTableMask:]
 | 
						|
	if table[0].bits <= huffmanTableBits {
 | 
						|
		if uint32(table[0].bits) <= available_bits {
 | 
						|
			dropBits(br, uint32(table[0].bits))
 | 
						|
			*result = uint32(table[0].value)
 | 
						|
			return true
 | 
						|
		} else {
 | 
						|
			return false /* Not enough bits for the first level. */
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if available_bits <= huffmanTableBits {
 | 
						|
		return false /* Not enough bits to move to the second level. */
 | 
						|
	}
 | 
						|
 | 
						|
	/* Speculatively drop HUFFMAN_TABLE_BITS. */
 | 
						|
	val = (val & bitMask(uint32(table[0].bits))) >> huffmanTableBits
 | 
						|
 | 
						|
	available_bits -= huffmanTableBits
 | 
						|
	table = table[uint32(table[0].value)+val:]
 | 
						|
	if available_bits < uint32(table[0].bits) {
 | 
						|
		return false /* Not enough bits for the second level. */
 | 
						|
	}
 | 
						|
 | 
						|
	dropBits(br, huffmanTableBits+uint32(table[0].bits))
 | 
						|
	*result = uint32(table[0].value)
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func safeReadSymbol(table []huffmanCode, br *bitReader, result *uint32) bool {
 | 
						|
	var val uint32
 | 
						|
	if safeGetBits(br, 15, &val) {
 | 
						|
		*result = decodeSymbol(val, table, br)
 | 
						|
		return true
 | 
						|
	}
 | 
						|
 | 
						|
	return safeDecodeSymbol(table, br, result)
 | 
						|
}
 | 
						|
 | 
						|
/* Makes a look-up in first level Huffman table. Peeks 8 bits. */
 | 
						|
func preloadSymbol(safe int, table []huffmanCode, br *bitReader, bits *uint32, value *uint32) {
 | 
						|
	if safe != 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	table = table[getBits(br, huffmanTableBits):]
 | 
						|
	*bits = uint32(table[0].bits)
 | 
						|
	*value = uint32(table[0].value)
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes the next Huffman code using data prepared by PreloadSymbol.
 | 
						|
   Reads 0 - 15 bits. Also peeks 8 following bits. */
 | 
						|
func readPreloadedSymbol(table []huffmanCode, br *bitReader, bits *uint32, value *uint32) uint32 {
 | 
						|
	var result uint32 = *value
 | 
						|
	var ext []huffmanCode
 | 
						|
	if *bits > huffmanTableBits {
 | 
						|
		var val uint32 = get16BitsUnmasked(br)
 | 
						|
		ext = table[val&huffmanTableMask:][*value:]
 | 
						|
		var mask uint32 = bitMask((*bits - huffmanTableBits))
 | 
						|
		dropBits(br, huffmanTableBits)
 | 
						|
		ext = ext[(val>>huffmanTableBits)&mask:]
 | 
						|
		dropBits(br, uint32(ext[0].bits))
 | 
						|
		result = uint32(ext[0].value)
 | 
						|
	} else {
 | 
						|
		dropBits(br, *bits)
 | 
						|
	}
 | 
						|
 | 
						|
	preloadSymbol(0, table, br, bits, value)
 | 
						|
	return result
 | 
						|
}
 | 
						|
 | 
						|
func log2Floor(x uint32) uint32 {
 | 
						|
	var result uint32 = 0
 | 
						|
	for x != 0 {
 | 
						|
		x >>= 1
 | 
						|
		result++
 | 
						|
	}
 | 
						|
 | 
						|
	return result
 | 
						|
}
 | 
						|
 | 
						|
/* Reads (s->symbol + 1) symbols.
 | 
						|
   Totally 1..4 symbols are read, 1..11 bits each.
 | 
						|
   The list of symbols MUST NOT contain duplicates. */
 | 
						|
func readSimpleHuffmanSymbols(alphabet_size uint32, max_symbol uint32, s *Reader) int {
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var max_bits uint32 = log2Floor(alphabet_size - 1)
 | 
						|
	var i uint32 = s.sub_loop_counter
 | 
						|
	/* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */
 | 
						|
 | 
						|
	var num_symbols uint32 = s.symbol
 | 
						|
	for i <= num_symbols {
 | 
						|
		var v uint32
 | 
						|
		if !safeReadBits(br, max_bits, &v) {
 | 
						|
			s.sub_loop_counter = i
 | 
						|
			s.substate_huffman = stateHuffmanSimpleRead
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
 | 
						|
		if v >= max_symbol {
 | 
						|
			return decoderErrorFormatSimpleHuffmanAlphabet
 | 
						|
		}
 | 
						|
 | 
						|
		s.symbols_lists_array[i] = uint16(v)
 | 
						|
		i++
 | 
						|
	}
 | 
						|
 | 
						|
	for i = 0; i < num_symbols; i++ {
 | 
						|
		var k uint32 = i + 1
 | 
						|
		for ; k <= num_symbols; k++ {
 | 
						|
			if s.symbols_lists_array[i] == s.symbols_lists_array[k] {
 | 
						|
				return decoderErrorFormatSimpleHuffmanSame
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
/* Process single decoded symbol code length:
 | 
						|
   A) reset the repeat variable
 | 
						|
   B) remember code length (if it is not 0)
 | 
						|
   C) extend corresponding index-chain
 | 
						|
   D) reduce the Huffman space
 | 
						|
   E) update the histogram */
 | 
						|
func processSingleCodeLength(code_len uint32, symbol *uint32, repeat *uint32, space *uint32, prev_code_len *uint32, symbol_lists symbolList, code_length_histo []uint16, next_symbol []int) {
 | 
						|
	*repeat = 0
 | 
						|
	if code_len != 0 { /* code_len == 1..15 */
 | 
						|
		symbolListPut(symbol_lists, next_symbol[code_len], uint16(*symbol))
 | 
						|
		next_symbol[code_len] = int(*symbol)
 | 
						|
		*prev_code_len = code_len
 | 
						|
		*space -= 32768 >> code_len
 | 
						|
		code_length_histo[code_len]++
 | 
						|
	}
 | 
						|
 | 
						|
	(*symbol)++
 | 
						|
}
 | 
						|
 | 
						|
/* Process repeated symbol code length.
 | 
						|
    A) Check if it is the extension of previous repeat sequence; if the decoded
 | 
						|
       value is not BROTLI_REPEAT_PREVIOUS_CODE_LENGTH, then it is a new
 | 
						|
       symbol-skip
 | 
						|
    B) Update repeat variable
 | 
						|
    C) Check if operation is feasible (fits alphabet)
 | 
						|
    D) For each symbol do the same operations as in ProcessSingleCodeLength
 | 
						|
 | 
						|
   PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or
 | 
						|
                 code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */
 | 
						|
func processRepeatedCodeLength(code_len uint32, repeat_delta uint32, alphabet_size uint32, symbol *uint32, repeat *uint32, space *uint32, prev_code_len *uint32, repeat_code_len *uint32, symbol_lists symbolList, code_length_histo []uint16, next_symbol []int) {
 | 
						|
	var old_repeat uint32 /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */ /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */
 | 
						|
	var extra_bits uint32 = 3
 | 
						|
	var new_len uint32 = 0
 | 
						|
	if code_len == repeatPreviousCodeLength {
 | 
						|
		new_len = *prev_code_len
 | 
						|
		extra_bits = 2
 | 
						|
	}
 | 
						|
 | 
						|
	if *repeat_code_len != new_len {
 | 
						|
		*repeat = 0
 | 
						|
		*repeat_code_len = new_len
 | 
						|
	}
 | 
						|
 | 
						|
	old_repeat = *repeat
 | 
						|
	if *repeat > 0 {
 | 
						|
		*repeat -= 2
 | 
						|
		*repeat <<= extra_bits
 | 
						|
	}
 | 
						|
 | 
						|
	*repeat += repeat_delta + 3
 | 
						|
	repeat_delta = *repeat - old_repeat
 | 
						|
	if *symbol+repeat_delta > alphabet_size {
 | 
						|
		*symbol = alphabet_size
 | 
						|
		*space = 0xFFFFF
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if *repeat_code_len != 0 {
 | 
						|
		var last uint = uint(*symbol + repeat_delta)
 | 
						|
		var next int = next_symbol[*repeat_code_len]
 | 
						|
		for {
 | 
						|
			symbolListPut(symbol_lists, next, uint16(*symbol))
 | 
						|
			next = int(*symbol)
 | 
						|
			(*symbol)++
 | 
						|
			if (*symbol) == uint32(last) {
 | 
						|
				break
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		next_symbol[*repeat_code_len] = next
 | 
						|
		*space -= repeat_delta << (15 - *repeat_code_len)
 | 
						|
		code_length_histo[*repeat_code_len] = uint16(uint32(code_length_histo[*repeat_code_len]) + repeat_delta)
 | 
						|
	} else {
 | 
						|
		*symbol += repeat_delta
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Reads and decodes symbol codelengths. */
 | 
						|
func readSymbolCodeLengths(alphabet_size uint32, s *Reader) int {
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var symbol uint32 = s.symbol
 | 
						|
	var repeat uint32 = s.repeat
 | 
						|
	var space uint32 = s.space
 | 
						|
	var prev_code_len uint32 = s.prev_code_len
 | 
						|
	var repeat_code_len uint32 = s.repeat_code_len
 | 
						|
	var symbol_lists symbolList = s.symbol_lists
 | 
						|
	var code_length_histo []uint16 = s.code_length_histo[:]
 | 
						|
	var next_symbol []int = s.next_symbol[:]
 | 
						|
	if !warmupBitReader(br) {
 | 
						|
		return decoderNeedsMoreInput
 | 
						|
	}
 | 
						|
	var p []huffmanCode
 | 
						|
	for symbol < alphabet_size && space > 0 {
 | 
						|
		p = s.table[:]
 | 
						|
		var code_len uint32
 | 
						|
		if !checkInputAmount(br, shortFillBitWindowRead) {
 | 
						|
			s.symbol = symbol
 | 
						|
			s.repeat = repeat
 | 
						|
			s.prev_code_len = prev_code_len
 | 
						|
			s.repeat_code_len = repeat_code_len
 | 
						|
			s.space = space
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
 | 
						|
		fillBitWindow16(br)
 | 
						|
		p = p[getBitsUnmasked(br)&uint64(bitMask(huffmanMaxCodeLengthCodeLength)):]
 | 
						|
		dropBits(br, uint32(p[0].bits)) /* Use 1..5 bits. */
 | 
						|
		code_len = uint32(p[0].value)   /* code_len == 0..17 */
 | 
						|
		if code_len < repeatPreviousCodeLength {
 | 
						|
			processSingleCodeLength(code_len, &symbol, &repeat, &space, &prev_code_len, symbol_lists, code_length_histo, next_symbol) /* code_len == 16..17, extra_bits == 2..3 */
 | 
						|
		} else {
 | 
						|
			var extra_bits uint32
 | 
						|
			if code_len == repeatPreviousCodeLength {
 | 
						|
				extra_bits = 2
 | 
						|
			} else {
 | 
						|
				extra_bits = 3
 | 
						|
			}
 | 
						|
			var repeat_delta uint32 = uint32(getBitsUnmasked(br)) & bitMask(extra_bits)
 | 
						|
			dropBits(br, extra_bits)
 | 
						|
			processRepeatedCodeLength(code_len, repeat_delta, alphabet_size, &symbol, &repeat, &space, &prev_code_len, &repeat_code_len, symbol_lists, code_length_histo, next_symbol)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	s.space = space
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
func safeReadSymbolCodeLengths(alphabet_size uint32, s *Reader) int {
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var get_byte bool = false
 | 
						|
	var p []huffmanCode
 | 
						|
	for s.symbol < alphabet_size && s.space > 0 {
 | 
						|
		p = s.table[:]
 | 
						|
		var code_len uint32
 | 
						|
		var available_bits uint32
 | 
						|
		var bits uint32 = 0
 | 
						|
		if get_byte && !pullByte(br) {
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
		get_byte = false
 | 
						|
		available_bits = getAvailableBits(br)
 | 
						|
		if available_bits != 0 {
 | 
						|
			bits = uint32(getBitsUnmasked(br))
 | 
						|
		}
 | 
						|
 | 
						|
		p = p[bits&bitMask(huffmanMaxCodeLengthCodeLength):]
 | 
						|
		if uint32(p[0].bits) > available_bits {
 | 
						|
			get_byte = true
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		code_len = uint32(p[0].value) /* code_len == 0..17 */
 | 
						|
		if code_len < repeatPreviousCodeLength {
 | 
						|
			dropBits(br, uint32(p[0].bits))
 | 
						|
			processSingleCodeLength(code_len, &s.symbol, &s.repeat, &s.space, &s.prev_code_len, s.symbol_lists, s.code_length_histo[:], s.next_symbol[:]) /* code_len == 16..17, extra_bits == 2..3 */
 | 
						|
		} else {
 | 
						|
			var extra_bits uint32 = code_len - 14
 | 
						|
			var repeat_delta uint32 = (bits >> p[0].bits) & bitMask(extra_bits)
 | 
						|
			if available_bits < uint32(p[0].bits)+extra_bits {
 | 
						|
				get_byte = true
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			dropBits(br, uint32(p[0].bits)+extra_bits)
 | 
						|
			processRepeatedCodeLength(code_len, repeat_delta, alphabet_size, &s.symbol, &s.repeat, &s.space, &s.prev_code_len, &s.repeat_code_len, s.symbol_lists, s.code_length_histo[:], s.next_symbol[:])
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
/* Reads and decodes 15..18 codes using static prefix code.
 | 
						|
   Each code is 2..4 bits long. In total 30..72 bits are used. */
 | 
						|
func readCodeLengthCodeLengths(s *Reader) int {
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var num_codes uint32 = s.repeat
 | 
						|
	var space uint32 = s.space
 | 
						|
	var i uint32 = s.sub_loop_counter
 | 
						|
	for ; i < codeLengthCodes; i++ {
 | 
						|
		var code_len_idx byte = kCodeLengthCodeOrder[i]
 | 
						|
		var ix uint32
 | 
						|
		var v uint32
 | 
						|
		if !safeGetBits(br, 4, &ix) {
 | 
						|
			var available_bits uint32 = getAvailableBits(br)
 | 
						|
			if available_bits != 0 {
 | 
						|
				ix = uint32(getBitsUnmasked(br) & 0xF)
 | 
						|
			} else {
 | 
						|
				ix = 0
 | 
						|
			}
 | 
						|
 | 
						|
			if uint32(kCodeLengthPrefixLength[ix]) > available_bits {
 | 
						|
				s.sub_loop_counter = i
 | 
						|
				s.repeat = num_codes
 | 
						|
				s.space = space
 | 
						|
				s.substate_huffman = stateHuffmanComplex
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		v = uint32(kCodeLengthPrefixValue[ix])
 | 
						|
		dropBits(br, uint32(kCodeLengthPrefixLength[ix]))
 | 
						|
		s.code_length_code_lengths[code_len_idx] = byte(v)
 | 
						|
		if v != 0 {
 | 
						|
			space = space - (32 >> v)
 | 
						|
			num_codes++
 | 
						|
			s.code_length_histo[v]++
 | 
						|
			if space-1 >= 32 {
 | 
						|
				/* space is 0 or wrapped around. */
 | 
						|
				break
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if num_codes != 1 && space != 0 {
 | 
						|
		return decoderErrorFormatClSpace
 | 
						|
	}
 | 
						|
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes the Huffman tables.
 | 
						|
   There are 2 scenarios:
 | 
						|
    A) Huffman code contains only few symbols (1..4). Those symbols are read
 | 
						|
       directly; their code lengths are defined by the number of symbols.
 | 
						|
       For this scenario 4 - 49 bits will be read.
 | 
						|
 | 
						|
    B) 2-phase decoding:
 | 
						|
    B.1) Small Huffman table is decoded; it is specified with code lengths
 | 
						|
         encoded with predefined entropy code. 32 - 74 bits are used.
 | 
						|
    B.2) Decoded table is used to decode code lengths of symbols in resulting
 | 
						|
         Huffman table. In worst case 3520 bits are read. */
 | 
						|
func readHuffmanCode(alphabet_size uint32, max_symbol uint32, table []huffmanCode, opt_table_size *uint32, s *Reader) int {
 | 
						|
	var br *bitReader = &s.br
 | 
						|
 | 
						|
	/* Unnecessary masking, but might be good for safety. */
 | 
						|
	alphabet_size &= 0x7FF
 | 
						|
 | 
						|
	/* State machine. */
 | 
						|
	for {
 | 
						|
		switch s.substate_huffman {
 | 
						|
		case stateHuffmanNone:
 | 
						|
			if !safeReadBits(br, 2, &s.sub_loop_counter) {
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			/* The value is used as follows:
 | 
						|
			   1 for simple code;
 | 
						|
			   0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
 | 
						|
			if s.sub_loop_counter != 1 {
 | 
						|
				s.space = 32
 | 
						|
				s.repeat = 0 /* num_codes */
 | 
						|
				var i int
 | 
						|
				for i = 0; i <= huffmanMaxCodeLengthCodeLength; i++ {
 | 
						|
					s.code_length_histo[i] = 0
 | 
						|
				}
 | 
						|
 | 
						|
				for i = 0; i < codeLengthCodes; i++ {
 | 
						|
					s.code_length_code_lengths[i] = 0
 | 
						|
				}
 | 
						|
 | 
						|
				s.substate_huffman = stateHuffmanComplex
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Read symbols, codes & code lengths directly. */
 | 
						|
		case stateHuffmanSimpleSize:
 | 
						|
			if !safeReadBits(br, 2, &s.symbol) { /* num_symbols */
 | 
						|
				s.substate_huffman = stateHuffmanSimpleSize
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			s.sub_loop_counter = 0
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateHuffmanSimpleRead:
 | 
						|
			{
 | 
						|
				var result int = readSimpleHuffmanSymbols(alphabet_size, max_symbol, s)
 | 
						|
				if result != decoderSuccess {
 | 
						|
					return result
 | 
						|
				}
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateHuffmanSimpleBuild:
 | 
						|
			var table_size uint32
 | 
						|
			if s.symbol == 3 {
 | 
						|
				var bits uint32
 | 
						|
				if !safeReadBits(br, 1, &bits) {
 | 
						|
					s.substate_huffman = stateHuffmanSimpleBuild
 | 
						|
					return decoderNeedsMoreInput
 | 
						|
				}
 | 
						|
 | 
						|
				s.symbol += bits
 | 
						|
			}
 | 
						|
 | 
						|
			table_size = buildSimpleHuffmanTable(table, huffmanTableBits, s.symbols_lists_array[:], s.symbol)
 | 
						|
			if opt_table_size != nil {
 | 
						|
				*opt_table_size = table_size
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_huffman = stateHuffmanNone
 | 
						|
			return decoderSuccess
 | 
						|
 | 
						|
			/* Decode Huffman-coded code lengths. */
 | 
						|
		case stateHuffmanComplex:
 | 
						|
			{
 | 
						|
				var i uint32
 | 
						|
				var result int = readCodeLengthCodeLengths(s)
 | 
						|
				if result != decoderSuccess {
 | 
						|
					return result
 | 
						|
				}
 | 
						|
 | 
						|
				buildCodeLengthsHuffmanTable(s.table[:], s.code_length_code_lengths[:], s.code_length_histo[:])
 | 
						|
				for i = 0; i < 16; i++ {
 | 
						|
					s.code_length_histo[i] = 0
 | 
						|
				}
 | 
						|
 | 
						|
				for i = 0; i <= huffmanMaxCodeLength; i++ {
 | 
						|
					s.next_symbol[i] = int(i) - (huffmanMaxCodeLength + 1)
 | 
						|
					symbolListPut(s.symbol_lists, s.next_symbol[i], 0xFFFF)
 | 
						|
				}
 | 
						|
 | 
						|
				s.symbol = 0
 | 
						|
				s.prev_code_len = initialRepeatedCodeLength
 | 
						|
				s.repeat = 0
 | 
						|
				s.repeat_code_len = 0
 | 
						|
				s.space = 32768
 | 
						|
				s.substate_huffman = stateHuffmanLengthSymbols
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateHuffmanLengthSymbols:
 | 
						|
			var table_size uint32
 | 
						|
			var result int = readSymbolCodeLengths(max_symbol, s)
 | 
						|
			if result == decoderNeedsMoreInput {
 | 
						|
				result = safeReadSymbolCodeLengths(max_symbol, s)
 | 
						|
			}
 | 
						|
 | 
						|
			if result != decoderSuccess {
 | 
						|
				return result
 | 
						|
			}
 | 
						|
 | 
						|
			if s.space != 0 {
 | 
						|
				return decoderErrorFormatHuffmanSpace
 | 
						|
			}
 | 
						|
 | 
						|
			table_size = buildHuffmanTable(table, huffmanTableBits, s.symbol_lists, s.code_length_histo[:])
 | 
						|
			if opt_table_size != nil {
 | 
						|
				*opt_table_size = table_size
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_huffman = stateHuffmanNone
 | 
						|
			return decoderSuccess
 | 
						|
 | 
						|
		default:
 | 
						|
			return decoderErrorUnreachable
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes a block length by reading 3..39 bits. */
 | 
						|
func readBlockLength(table []huffmanCode, br *bitReader) uint32 {
 | 
						|
	var code uint32
 | 
						|
	var nbits uint32
 | 
						|
	code = readSymbol(table, br)
 | 
						|
	nbits = kBlockLengthPrefixCode[code].nbits /* nbits == 2..24 */
 | 
						|
	return kBlockLengthPrefixCode[code].offset + readBits(br, nbits)
 | 
						|
}
 | 
						|
 | 
						|
/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then
 | 
						|
   reading can't be continued with ReadBlockLength. */
 | 
						|
func safeReadBlockLength(s *Reader, result *uint32, table []huffmanCode, br *bitReader) bool {
 | 
						|
	var index uint32
 | 
						|
	if s.substate_read_block_length == stateReadBlockLengthNone {
 | 
						|
		if !safeReadSymbol(table, br, &index) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		index = s.block_length_index
 | 
						|
	}
 | 
						|
	{
 | 
						|
		var bits uint32 /* nbits == 2..24 */
 | 
						|
		var nbits uint32 = kBlockLengthPrefixCode[index].nbits
 | 
						|
		if !safeReadBits(br, nbits, &bits) {
 | 
						|
			s.block_length_index = index
 | 
						|
			s.substate_read_block_length = stateReadBlockLengthSuffix
 | 
						|
			return false
 | 
						|
		}
 | 
						|
 | 
						|
		*result = kBlockLengthPrefixCode[index].offset + bits
 | 
						|
		s.substate_read_block_length = stateReadBlockLengthNone
 | 
						|
		return true
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Transform:
 | 
						|
    1) initialize list L with values 0, 1,... 255
 | 
						|
    2) For each input element X:
 | 
						|
    2.1) let Y = L[X]
 | 
						|
    2.2) remove X-th element from L
 | 
						|
    2.3) prepend Y to L
 | 
						|
    2.4) append Y to output
 | 
						|
 | 
						|
   In most cases max(Y) <= 7, so most of L remains intact.
 | 
						|
   To reduce the cost of initialization, we reuse L, remember the upper bound
 | 
						|
   of Y values, and reinitialize only first elements in L.
 | 
						|
 | 
						|
   Most of input values are 0 and 1. To reduce number of branches, we replace
 | 
						|
   inner for loop with do-while. */
 | 
						|
func inverseMoveToFrontTransform(v []byte, v_len uint32, state *Reader) {
 | 
						|
	var mtf [256]byte
 | 
						|
	var i int
 | 
						|
	for i = 1; i < 256; i++ {
 | 
						|
		mtf[i] = byte(i)
 | 
						|
	}
 | 
						|
	var mtf_1 byte
 | 
						|
 | 
						|
	/* Transform the input. */
 | 
						|
	for i = 0; uint32(i) < v_len; i++ {
 | 
						|
		var index int = int(v[i])
 | 
						|
		var value byte = mtf[index]
 | 
						|
		v[i] = value
 | 
						|
		mtf_1 = value
 | 
						|
		for index >= 1 {
 | 
						|
			index--
 | 
						|
			mtf[index+1] = mtf[index]
 | 
						|
		}
 | 
						|
 | 
						|
		mtf[0] = mtf_1
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes a series of Huffman table using ReadHuffmanCode function. */
 | 
						|
func huffmanTreeGroupDecode(group *huffmanTreeGroup, s *Reader) int {
 | 
						|
	if s.substate_tree_group != stateTreeGroupLoop {
 | 
						|
		s.next = group.codes
 | 
						|
		s.htree_index = 0
 | 
						|
		s.substate_tree_group = stateTreeGroupLoop
 | 
						|
	}
 | 
						|
 | 
						|
	for s.htree_index < int(group.num_htrees) {
 | 
						|
		var table_size uint32
 | 
						|
		var result int = readHuffmanCode(uint32(group.alphabet_size), uint32(group.max_symbol), s.next, &table_size, s)
 | 
						|
		if result != decoderSuccess {
 | 
						|
			return result
 | 
						|
		}
 | 
						|
		group.htrees[s.htree_index] = s.next
 | 
						|
		s.next = s.next[table_size:]
 | 
						|
		s.htree_index++
 | 
						|
	}
 | 
						|
 | 
						|
	s.substate_tree_group = stateTreeGroupNone
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes a context map.
 | 
						|
   Decoding is done in 4 phases:
 | 
						|
    1) Read auxiliary information (6..16 bits) and allocate memory.
 | 
						|
       In case of trivial context map, decoding is finished at this phase.
 | 
						|
    2) Decode Huffman table using ReadHuffmanCode function.
 | 
						|
       This table will be used for reading context map items.
 | 
						|
    3) Read context map items; "0" values could be run-length encoded.
 | 
						|
    4) Optionally, apply InverseMoveToFront transform to the resulting map. */
 | 
						|
func decodeContextMap(context_map_size uint32, num_htrees *uint32, context_map_arg *[]byte, s *Reader) int {
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var result int = decoderSuccess
 | 
						|
 | 
						|
	switch int(s.substate_context_map) {
 | 
						|
	case stateContextMapNone:
 | 
						|
		result = decodeVarLenUint8(s, br, num_htrees)
 | 
						|
		if result != decoderSuccess {
 | 
						|
			return result
 | 
						|
		}
 | 
						|
 | 
						|
		(*num_htrees)++
 | 
						|
		s.context_index = 0
 | 
						|
		*context_map_arg = make([]byte, uint(context_map_size))
 | 
						|
		if *context_map_arg == nil {
 | 
						|
			return decoderErrorAllocContextMap
 | 
						|
		}
 | 
						|
 | 
						|
		if *num_htrees <= 1 {
 | 
						|
			for i := 0; i < int(context_map_size); i++ {
 | 
						|
				(*context_map_arg)[i] = 0
 | 
						|
			}
 | 
						|
			return decoderSuccess
 | 
						|
		}
 | 
						|
 | 
						|
		s.substate_context_map = stateContextMapReadPrefix
 | 
						|
		fallthrough
 | 
						|
	/* Fall through. */
 | 
						|
	case stateContextMapReadPrefix:
 | 
						|
		{
 | 
						|
			var bits uint32
 | 
						|
 | 
						|
			/* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe
 | 
						|
			   to peek 4 bits ahead. */
 | 
						|
			if !safeGetBits(br, 5, &bits) {
 | 
						|
				return decoderNeedsMoreInput
 | 
						|
			}
 | 
						|
 | 
						|
			if bits&1 != 0 { /* Use RLE for zeros. */
 | 
						|
				s.max_run_length_prefix = (bits >> 1) + 1
 | 
						|
				dropBits(br, 5)
 | 
						|
			} else {
 | 
						|
				s.max_run_length_prefix = 0
 | 
						|
				dropBits(br, 1)
 | 
						|
			}
 | 
						|
 | 
						|
			s.substate_context_map = stateContextMapHuffman
 | 
						|
		}
 | 
						|
		fallthrough
 | 
						|
 | 
						|
		/* Fall through. */
 | 
						|
	case stateContextMapHuffman:
 | 
						|
		{
 | 
						|
			var alphabet_size uint32 = *num_htrees + s.max_run_length_prefix
 | 
						|
			result = readHuffmanCode(alphabet_size, alphabet_size, s.context_map_table[:], nil, s)
 | 
						|
			if result != decoderSuccess {
 | 
						|
				return result
 | 
						|
			}
 | 
						|
			s.code = 0xFFFF
 | 
						|
			s.substate_context_map = stateContextMapDecode
 | 
						|
		}
 | 
						|
		fallthrough
 | 
						|
 | 
						|
		/* Fall through. */
 | 
						|
	case stateContextMapDecode:
 | 
						|
		{
 | 
						|
			var context_index uint32 = s.context_index
 | 
						|
			var max_run_length_prefix uint32 = s.max_run_length_prefix
 | 
						|
			var context_map []byte = *context_map_arg
 | 
						|
			var code uint32 = s.code
 | 
						|
			var skip_preamble bool = (code != 0xFFFF)
 | 
						|
			for context_index < context_map_size || skip_preamble {
 | 
						|
				if !skip_preamble {
 | 
						|
					if !safeReadSymbol(s.context_map_table[:], br, &code) {
 | 
						|
						s.code = 0xFFFF
 | 
						|
						s.context_index = context_index
 | 
						|
						return decoderNeedsMoreInput
 | 
						|
					}
 | 
						|
 | 
						|
					if code == 0 {
 | 
						|
						context_map[context_index] = 0
 | 
						|
						context_index++
 | 
						|
						continue
 | 
						|
					}
 | 
						|
 | 
						|
					if code > max_run_length_prefix {
 | 
						|
						context_map[context_index] = byte(code - max_run_length_prefix)
 | 
						|
						context_index++
 | 
						|
						continue
 | 
						|
					}
 | 
						|
				} else {
 | 
						|
					skip_preamble = false
 | 
						|
				}
 | 
						|
 | 
						|
				/* RLE sub-stage. */
 | 
						|
				{
 | 
						|
					var reps uint32
 | 
						|
					if !safeReadBits(br, code, &reps) {
 | 
						|
						s.code = code
 | 
						|
						s.context_index = context_index
 | 
						|
						return decoderNeedsMoreInput
 | 
						|
					}
 | 
						|
 | 
						|
					reps += 1 << code
 | 
						|
					if context_index+reps > context_map_size {
 | 
						|
						return decoderErrorFormatContextMapRepeat
 | 
						|
					}
 | 
						|
 | 
						|
					for {
 | 
						|
						context_map[context_index] = 0
 | 
						|
						context_index++
 | 
						|
						reps--
 | 
						|
						if reps == 0 {
 | 
						|
							break
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		fallthrough
 | 
						|
 | 
						|
	case stateContextMapTransform:
 | 
						|
		var bits uint32
 | 
						|
		if !safeReadBits(br, 1, &bits) {
 | 
						|
			s.substate_context_map = stateContextMapTransform
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
 | 
						|
		if bits != 0 {
 | 
						|
			inverseMoveToFrontTransform(*context_map_arg, context_map_size, s)
 | 
						|
		}
 | 
						|
 | 
						|
		s.substate_context_map = stateContextMapNone
 | 
						|
		return decoderSuccess
 | 
						|
 | 
						|
	default:
 | 
						|
		return decoderErrorUnreachable
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes a command or literal and updates block type ring-buffer.
 | 
						|
   Reads 3..54 bits. */
 | 
						|
func decodeBlockTypeAndLength(safe int, s *Reader, tree_type int) bool {
 | 
						|
	var max_block_type uint32 = s.num_block_types[tree_type]
 | 
						|
	var type_tree []huffmanCode
 | 
						|
	type_tree = s.block_type_trees[tree_type*huffmanMaxSize258:]
 | 
						|
	var len_tree []huffmanCode
 | 
						|
	len_tree = s.block_len_trees[tree_type*huffmanMaxSize26:]
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var ringbuffer []uint32 = s.block_type_rb[tree_type*2:]
 | 
						|
	var block_type uint32
 | 
						|
	if max_block_type <= 1 {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	/* Read 0..15 + 3..39 bits. */
 | 
						|
	if safe == 0 {
 | 
						|
		block_type = readSymbol(type_tree, br)
 | 
						|
		s.block_length[tree_type] = readBlockLength(len_tree, br)
 | 
						|
	} else {
 | 
						|
		var memento bitReaderState
 | 
						|
		bitReaderSaveState(br, &memento)
 | 
						|
		if !safeReadSymbol(type_tree, br, &block_type) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
		if !safeReadBlockLength(s, &s.block_length[tree_type], len_tree, br) {
 | 
						|
			s.substate_read_block_length = stateReadBlockLengthNone
 | 
						|
			bitReaderRestoreState(br, &memento)
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if block_type == 1 {
 | 
						|
		block_type = ringbuffer[1] + 1
 | 
						|
	} else if block_type == 0 {
 | 
						|
		block_type = ringbuffer[0]
 | 
						|
	} else {
 | 
						|
		block_type -= 2
 | 
						|
	}
 | 
						|
 | 
						|
	if block_type >= max_block_type {
 | 
						|
		block_type -= max_block_type
 | 
						|
	}
 | 
						|
 | 
						|
	ringbuffer[0] = ringbuffer[1]
 | 
						|
	ringbuffer[1] = block_type
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func detectTrivialLiteralBlockTypes(s *Reader) {
 | 
						|
	var i uint
 | 
						|
	for i = 0; i < 8; i++ {
 | 
						|
		s.trivial_literal_contexts[i] = 0
 | 
						|
	}
 | 
						|
	for i = 0; uint32(i) < s.num_block_types[0]; i++ {
 | 
						|
		var offset uint = i << literalContextBits
 | 
						|
		var error uint = 0
 | 
						|
		var sample uint = uint(s.context_map[offset])
 | 
						|
		var j uint
 | 
						|
		for j = 0; j < 1<<literalContextBits; {
 | 
						|
			var k int
 | 
						|
			for k = 0; k < 4; k++ {
 | 
						|
				error |= uint(s.context_map[offset+j]) ^ sample
 | 
						|
				j++
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if error == 0 {
 | 
						|
			s.trivial_literal_contexts[i>>5] |= 1 << (i & 31)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func prepareLiteralDecoding(s *Reader) {
 | 
						|
	var context_mode byte
 | 
						|
	var trivial uint
 | 
						|
	var block_type uint32 = s.block_type_rb[1]
 | 
						|
	var context_offset uint32 = block_type << literalContextBits
 | 
						|
	s.context_map_slice = s.context_map[context_offset:]
 | 
						|
	trivial = uint(s.trivial_literal_contexts[block_type>>5])
 | 
						|
	s.trivial_literal_context = int((trivial >> (block_type & 31)) & 1)
 | 
						|
	s.literal_htree = []huffmanCode(s.literal_hgroup.htrees[s.context_map_slice[0]])
 | 
						|
	context_mode = s.context_modes[block_type] & 3
 | 
						|
	s.context_lookup = getContextLUT(int(context_mode))
 | 
						|
}
 | 
						|
 | 
						|
/* Decodes the block type and updates the state for literal context.
 | 
						|
   Reads 3..54 bits. */
 | 
						|
func decodeLiteralBlockSwitchInternal(safe int, s *Reader) bool {
 | 
						|
	if !decodeBlockTypeAndLength(safe, s, 0) {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	prepareLiteralDecoding(s)
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func decodeLiteralBlockSwitch(s *Reader) {
 | 
						|
	decodeLiteralBlockSwitchInternal(0, s)
 | 
						|
}
 | 
						|
 | 
						|
func safeDecodeLiteralBlockSwitch(s *Reader) bool {
 | 
						|
	return decodeLiteralBlockSwitchInternal(1, s)
 | 
						|
}
 | 
						|
 | 
						|
/* Block switch for insert/copy length.
 | 
						|
   Reads 3..54 bits. */
 | 
						|
func decodeCommandBlockSwitchInternal(safe int, s *Reader) bool {
 | 
						|
	if !decodeBlockTypeAndLength(safe, s, 1) {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	s.htree_command = []huffmanCode(s.insert_copy_hgroup.htrees[s.block_type_rb[3]])
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func decodeCommandBlockSwitch(s *Reader) {
 | 
						|
	decodeCommandBlockSwitchInternal(0, s)
 | 
						|
}
 | 
						|
 | 
						|
func safeDecodeCommandBlockSwitch(s *Reader) bool {
 | 
						|
	return decodeCommandBlockSwitchInternal(1, s)
 | 
						|
}
 | 
						|
 | 
						|
/* Block switch for distance codes.
 | 
						|
   Reads 3..54 bits. */
 | 
						|
func decodeDistanceBlockSwitchInternal(safe int, s *Reader) bool {
 | 
						|
	if !decodeBlockTypeAndLength(safe, s, 2) {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	s.dist_context_map_slice = s.dist_context_map[s.block_type_rb[5]<<distanceContextBits:]
 | 
						|
	s.dist_htree_index = s.dist_context_map_slice[s.distance_context]
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func decodeDistanceBlockSwitch(s *Reader) {
 | 
						|
	decodeDistanceBlockSwitchInternal(0, s)
 | 
						|
}
 | 
						|
 | 
						|
func safeDecodeDistanceBlockSwitch(s *Reader) bool {
 | 
						|
	return decodeDistanceBlockSwitchInternal(1, s)
 | 
						|
}
 | 
						|
 | 
						|
func unwrittenBytes(s *Reader, wrap bool) uint {
 | 
						|
	var pos uint
 | 
						|
	if wrap && s.pos > s.ringbuffer_size {
 | 
						|
		pos = uint(s.ringbuffer_size)
 | 
						|
	} else {
 | 
						|
		pos = uint(s.pos)
 | 
						|
	}
 | 
						|
	var partial_pos_rb uint = (s.rb_roundtrips * uint(s.ringbuffer_size)) + pos
 | 
						|
	return partial_pos_rb - s.partial_pos_out
 | 
						|
}
 | 
						|
 | 
						|
/* Dumps output.
 | 
						|
   Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push
 | 
						|
   and either ring-buffer is as big as window size, or |force| is true. */
 | 
						|
func writeRingBuffer(s *Reader, available_out *uint, next_out *[]byte, total_out *uint, force bool) int {
 | 
						|
	var start []byte
 | 
						|
	start = s.ringbuffer[s.partial_pos_out&uint(s.ringbuffer_mask):]
 | 
						|
	var to_write uint = unwrittenBytes(s, true)
 | 
						|
	var num_written uint = *available_out
 | 
						|
	if num_written > to_write {
 | 
						|
		num_written = to_write
 | 
						|
	}
 | 
						|
 | 
						|
	if s.meta_block_remaining_len < 0 {
 | 
						|
		return decoderErrorFormatBlockLength1
 | 
						|
	}
 | 
						|
 | 
						|
	if next_out != nil && *next_out == nil {
 | 
						|
		*next_out = start
 | 
						|
	} else {
 | 
						|
		if next_out != nil {
 | 
						|
			copy(*next_out, start[:num_written])
 | 
						|
			*next_out = (*next_out)[num_written:]
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	*available_out -= num_written
 | 
						|
	s.partial_pos_out += num_written
 | 
						|
	if total_out != nil {
 | 
						|
		*total_out = s.partial_pos_out
 | 
						|
	}
 | 
						|
 | 
						|
	if num_written < to_write {
 | 
						|
		if s.ringbuffer_size == 1<<s.window_bits || force {
 | 
						|
			return decoderNeedsMoreOutput
 | 
						|
		} else {
 | 
						|
			return decoderSuccess
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* Wrap ring buffer only if it has reached its maximal size. */
 | 
						|
	if s.ringbuffer_size == 1<<s.window_bits && s.pos >= s.ringbuffer_size {
 | 
						|
		s.pos -= s.ringbuffer_size
 | 
						|
		s.rb_roundtrips++
 | 
						|
		if uint(s.pos) != 0 {
 | 
						|
			s.should_wrap_ringbuffer = 1
 | 
						|
		} else {
 | 
						|
			s.should_wrap_ringbuffer = 0
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
func wrapRingBuffer(s *Reader) {
 | 
						|
	if s.should_wrap_ringbuffer != 0 {
 | 
						|
		copy(s.ringbuffer, s.ringbuffer_end[:uint(s.pos)])
 | 
						|
		s.should_wrap_ringbuffer = 0
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Allocates ring-buffer.
 | 
						|
 | 
						|
   s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before
 | 
						|
   this function is called.
 | 
						|
 | 
						|
   Last two bytes of ring-buffer are initialized to 0, so context calculation
 | 
						|
   could be done uniformly for the first two and all other positions. */
 | 
						|
func ensureRingBuffer(s *Reader) bool {
 | 
						|
	var old_ringbuffer []byte = s.ringbuffer
 | 
						|
	if s.ringbuffer_size == s.new_ringbuffer_size {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
 | 
						|
	s.ringbuffer = make([]byte, uint(s.new_ringbuffer_size)+uint(kRingBufferWriteAheadSlack))
 | 
						|
	if s.ringbuffer == nil {
 | 
						|
		/* Restore previous value. */
 | 
						|
		s.ringbuffer = old_ringbuffer
 | 
						|
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	s.ringbuffer[s.new_ringbuffer_size-2] = 0
 | 
						|
	s.ringbuffer[s.new_ringbuffer_size-1] = 0
 | 
						|
 | 
						|
	if !(old_ringbuffer == nil) {
 | 
						|
		copy(s.ringbuffer, old_ringbuffer[:uint(s.pos)])
 | 
						|
 | 
						|
		old_ringbuffer = nil
 | 
						|
	}
 | 
						|
 | 
						|
	s.ringbuffer_size = s.new_ringbuffer_size
 | 
						|
	s.ringbuffer_mask = s.new_ringbuffer_size - 1
 | 
						|
	s.ringbuffer_end = s.ringbuffer[s.ringbuffer_size:]
 | 
						|
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func copyUncompressedBlockToOutput(available_out *uint, next_out *[]byte, total_out *uint, s *Reader) int {
 | 
						|
	/* TODO: avoid allocation for single uncompressed block. */
 | 
						|
	if !ensureRingBuffer(s) {
 | 
						|
		return decoderErrorAllocRingBuffer1
 | 
						|
	}
 | 
						|
 | 
						|
	/* State machine */
 | 
						|
	for {
 | 
						|
		switch s.substate_uncompressed {
 | 
						|
		case stateUncompressedNone:
 | 
						|
			{
 | 
						|
				var nbytes int = int(getRemainingBytes(&s.br))
 | 
						|
				if nbytes > s.meta_block_remaining_len {
 | 
						|
					nbytes = s.meta_block_remaining_len
 | 
						|
				}
 | 
						|
 | 
						|
				if s.pos+nbytes > s.ringbuffer_size {
 | 
						|
					nbytes = s.ringbuffer_size - s.pos
 | 
						|
				}
 | 
						|
 | 
						|
				/* Copy remaining bytes from s->br.buf_ to ring-buffer. */
 | 
						|
				copyBytes(s.ringbuffer[s.pos:], &s.br, uint(nbytes))
 | 
						|
 | 
						|
				s.pos += nbytes
 | 
						|
				s.meta_block_remaining_len -= nbytes
 | 
						|
				if s.pos < 1<<s.window_bits {
 | 
						|
					if s.meta_block_remaining_len == 0 {
 | 
						|
						return decoderSuccess
 | 
						|
					}
 | 
						|
 | 
						|
					return decoderNeedsMoreInput
 | 
						|
				}
 | 
						|
 | 
						|
				s.substate_uncompressed = stateUncompressedWrite
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateUncompressedWrite:
 | 
						|
			{
 | 
						|
				var result int
 | 
						|
				result = writeRingBuffer(s, available_out, next_out, total_out, false)
 | 
						|
				if result != decoderSuccess {
 | 
						|
					return result
 | 
						|
				}
 | 
						|
 | 
						|
				if s.ringbuffer_size == 1<<s.window_bits {
 | 
						|
					s.max_distance = s.max_backward_distance
 | 
						|
				}
 | 
						|
 | 
						|
				s.substate_uncompressed = stateUncompressedNone
 | 
						|
				break
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Calculates the smallest feasible ring buffer.
 | 
						|
 | 
						|
   If we know the data size is small, do not allocate more ring buffer
 | 
						|
   size than needed to reduce memory usage.
 | 
						|
 | 
						|
   When this method is called, metablock size and flags MUST be decoded. */
 | 
						|
func calculateRingBufferSize(s *Reader) {
 | 
						|
	var window_size int = 1 << s.window_bits
 | 
						|
	var new_ringbuffer_size int = window_size
 | 
						|
	var min_size int
 | 
						|
	/* We need at least 2 bytes of ring buffer size to get the last two
 | 
						|
	   bytes for context from there */
 | 
						|
	if s.ringbuffer_size != 0 {
 | 
						|
		min_size = s.ringbuffer_size
 | 
						|
	} else {
 | 
						|
		min_size = 1024
 | 
						|
	}
 | 
						|
	var output_size int
 | 
						|
 | 
						|
	/* If maximum is already reached, no further extension is retired. */
 | 
						|
	if s.ringbuffer_size == window_size {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	/* Metadata blocks does not touch ring buffer. */
 | 
						|
	if s.is_metadata != 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if s.ringbuffer == nil {
 | 
						|
		output_size = 0
 | 
						|
	} else {
 | 
						|
		output_size = s.pos
 | 
						|
	}
 | 
						|
 | 
						|
	output_size += s.meta_block_remaining_len
 | 
						|
	if min_size < output_size {
 | 
						|
		min_size = output_size
 | 
						|
	}
 | 
						|
 | 
						|
	if !(s.canny_ringbuffer_allocation == 0) {
 | 
						|
		/* Reduce ring buffer size to save memory when server is unscrupulous.
 | 
						|
		   In worst case memory usage might be 1.5x bigger for a short period of
 | 
						|
		   ring buffer reallocation. */
 | 
						|
		for new_ringbuffer_size>>1 >= min_size {
 | 
						|
			new_ringbuffer_size >>= 1
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	s.new_ringbuffer_size = new_ringbuffer_size
 | 
						|
}
 | 
						|
 | 
						|
/* Reads 1..256 2-bit context modes. */
 | 
						|
func readContextModes(s *Reader) int {
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var i int = s.loop_counter
 | 
						|
 | 
						|
	for i < int(s.num_block_types[0]) {
 | 
						|
		var bits uint32
 | 
						|
		if !safeReadBits(br, 2, &bits) {
 | 
						|
			s.loop_counter = i
 | 
						|
			return decoderNeedsMoreInput
 | 
						|
		}
 | 
						|
 | 
						|
		s.context_modes[i] = byte(bits)
 | 
						|
		i++
 | 
						|
	}
 | 
						|
 | 
						|
	return decoderSuccess
 | 
						|
}
 | 
						|
 | 
						|
func takeDistanceFromRingBuffer(s *Reader) {
 | 
						|
	if s.distance_code == 0 {
 | 
						|
		s.dist_rb_idx--
 | 
						|
		s.distance_code = s.dist_rb[s.dist_rb_idx&3]
 | 
						|
 | 
						|
		/* Compensate double distance-ring-buffer roll for dictionary items. */
 | 
						|
		s.distance_context = 1
 | 
						|
	} else {
 | 
						|
		var distance_code int = s.distance_code << 1
 | 
						|
		const kDistanceShortCodeIndexOffset uint32 = 0xAAAFFF1B
 | 
						|
		const kDistanceShortCodeValueOffset uint32 = 0xFA5FA500
 | 
						|
		var v int = (s.dist_rb_idx + int(kDistanceShortCodeIndexOffset>>uint(distance_code))) & 0x3
 | 
						|
		/* kDistanceShortCodeIndexOffset has 2-bit values from LSB:
 | 
						|
		   3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */
 | 
						|
 | 
						|
		/* kDistanceShortCodeValueOffset has 2-bit values from LSB:
 | 
						|
		   -0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */
 | 
						|
		s.distance_code = s.dist_rb[v]
 | 
						|
 | 
						|
		v = int(kDistanceShortCodeValueOffset>>uint(distance_code)) & 0x3
 | 
						|
		if distance_code&0x3 != 0 {
 | 
						|
			s.distance_code += v
 | 
						|
		} else {
 | 
						|
			s.distance_code -= v
 | 
						|
			if s.distance_code <= 0 {
 | 
						|
				/* A huge distance will cause a () soon.
 | 
						|
				   This is a little faster than failing here. */
 | 
						|
				s.distance_code = 0x7FFFFFFF
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func safeReadBitsMaybeZero(br *bitReader, n_bits uint32, val *uint32) bool {
 | 
						|
	if n_bits != 0 {
 | 
						|
		return safeReadBits(br, n_bits, val)
 | 
						|
	} else {
 | 
						|
		*val = 0
 | 
						|
		return true
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Precondition: s->distance_code < 0. */
 | 
						|
func readDistanceInternal(safe int, s *Reader, br *bitReader) bool {
 | 
						|
	var distval int
 | 
						|
	var memento bitReaderState
 | 
						|
	var distance_tree []huffmanCode = []huffmanCode(s.distance_hgroup.htrees[s.dist_htree_index])
 | 
						|
	if safe == 0 {
 | 
						|
		s.distance_code = int(readSymbol(distance_tree, br))
 | 
						|
	} else {
 | 
						|
		var code uint32
 | 
						|
		bitReaderSaveState(br, &memento)
 | 
						|
		if !safeReadSymbol(distance_tree, br, &code) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
 | 
						|
		s.distance_code = int(code)
 | 
						|
	}
 | 
						|
 | 
						|
	/* Convert the distance code to the actual distance by possibly
 | 
						|
	   looking up past distances from the s->ringbuffer. */
 | 
						|
	s.distance_context = 0
 | 
						|
 | 
						|
	if s.distance_code&^0xF == 0 {
 | 
						|
		takeDistanceFromRingBuffer(s)
 | 
						|
		s.block_length[2]--
 | 
						|
		return true
 | 
						|
	}
 | 
						|
 | 
						|
	distval = s.distance_code - int(s.num_direct_distance_codes)
 | 
						|
	if distval >= 0 {
 | 
						|
		var nbits uint32
 | 
						|
		var postfix int
 | 
						|
		var offset int
 | 
						|
		if safe == 0 && (s.distance_postfix_bits == 0) {
 | 
						|
			nbits = (uint32(distval) >> 1) + 1
 | 
						|
			offset = ((2 + (distval & 1)) << nbits) - 4
 | 
						|
			s.distance_code = int(s.num_direct_distance_codes) + offset + int(readBits(br, nbits))
 | 
						|
		} else {
 | 
						|
			/* This branch also works well when s->distance_postfix_bits == 0. */
 | 
						|
			var bits uint32
 | 
						|
			postfix = distval & s.distance_postfix_mask
 | 
						|
			distval >>= s.distance_postfix_bits
 | 
						|
			nbits = (uint32(distval) >> 1) + 1
 | 
						|
			if safe != 0 {
 | 
						|
				if !safeReadBitsMaybeZero(br, nbits, &bits) {
 | 
						|
					s.distance_code = -1 /* Restore precondition. */
 | 
						|
					bitReaderRestoreState(br, &memento)
 | 
						|
					return false
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				bits = readBits(br, nbits)
 | 
						|
			}
 | 
						|
 | 
						|
			offset = ((2 + (distval & 1)) << nbits) - 4
 | 
						|
			s.distance_code = int(s.num_direct_distance_codes) + ((offset + int(bits)) << s.distance_postfix_bits) + postfix
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	s.distance_code = s.distance_code - numDistanceShortCodes + 1
 | 
						|
	s.block_length[2]--
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func readDistance(s *Reader, br *bitReader) {
 | 
						|
	readDistanceInternal(0, s, br)
 | 
						|
}
 | 
						|
 | 
						|
func safeReadDistance(s *Reader, br *bitReader) bool {
 | 
						|
	return readDistanceInternal(1, s, br)
 | 
						|
}
 | 
						|
 | 
						|
func readCommandInternal(safe int, s *Reader, br *bitReader, insert_length *int) bool {
 | 
						|
	var cmd_code uint32
 | 
						|
	var insert_len_extra uint32 = 0
 | 
						|
	var copy_length uint32
 | 
						|
	var v cmdLutElement
 | 
						|
	var memento bitReaderState
 | 
						|
	if safe == 0 {
 | 
						|
		cmd_code = readSymbol(s.htree_command, br)
 | 
						|
	} else {
 | 
						|
		bitReaderSaveState(br, &memento)
 | 
						|
		if !safeReadSymbol(s.htree_command, br, &cmd_code) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	v = kCmdLut[cmd_code]
 | 
						|
	s.distance_code = int(v.distance_code)
 | 
						|
	s.distance_context = int(v.context)
 | 
						|
	s.dist_htree_index = s.dist_context_map_slice[s.distance_context]
 | 
						|
	*insert_length = int(v.insert_len_offset)
 | 
						|
	if safe == 0 {
 | 
						|
		if v.insert_len_extra_bits != 0 {
 | 
						|
			insert_len_extra = readBits(br, uint32(v.insert_len_extra_bits))
 | 
						|
		}
 | 
						|
 | 
						|
		copy_length = readBits(br, uint32(v.copy_len_extra_bits))
 | 
						|
	} else {
 | 
						|
		if !safeReadBitsMaybeZero(br, uint32(v.insert_len_extra_bits), &insert_len_extra) || !safeReadBitsMaybeZero(br, uint32(v.copy_len_extra_bits), ©_length) {
 | 
						|
			bitReaderRestoreState(br, &memento)
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	s.copy_length = int(copy_length) + int(v.copy_len_offset)
 | 
						|
	s.block_length[1]--
 | 
						|
	*insert_length += int(insert_len_extra)
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func readCommand(s *Reader, br *bitReader, insert_length *int) {
 | 
						|
	readCommandInternal(0, s, br, insert_length)
 | 
						|
}
 | 
						|
 | 
						|
func safeReadCommand(s *Reader, br *bitReader, insert_length *int) bool {
 | 
						|
	return readCommandInternal(1, s, br, insert_length)
 | 
						|
}
 | 
						|
 | 
						|
func checkInputAmountMaybeSafe(safe int, br *bitReader, num uint) bool {
 | 
						|
	if safe != 0 {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
 | 
						|
	return checkInputAmount(br, num)
 | 
						|
}
 | 
						|
 | 
						|
func processCommandsInternal(safe int, s *Reader) int {
 | 
						|
	var pos int = s.pos
 | 
						|
	var i int = s.loop_counter
 | 
						|
	var result int = decoderSuccess
 | 
						|
	var br *bitReader = &s.br
 | 
						|
	var hc []huffmanCode
 | 
						|
 | 
						|
	if !checkInputAmountMaybeSafe(safe, br, 28) {
 | 
						|
		result = decoderNeedsMoreInput
 | 
						|
		goto saveStateAndReturn
 | 
						|
	}
 | 
						|
 | 
						|
	if safe == 0 {
 | 
						|
		warmupBitReader(br)
 | 
						|
	}
 | 
						|
 | 
						|
	/* Jump into state machine. */
 | 
						|
	if s.state == stateCommandBegin {
 | 
						|
		goto CommandBegin
 | 
						|
	} else if s.state == stateCommandInner {
 | 
						|
		goto CommandInner
 | 
						|
	} else if s.state == stateCommandPostDecodeLiterals {
 | 
						|
		goto CommandPostDecodeLiterals
 | 
						|
	} else if s.state == stateCommandPostWrapCopy {
 | 
						|
		goto CommandPostWrapCopy
 | 
						|
	} else {
 | 
						|
		return decoderErrorUnreachable
 | 
						|
	}
 | 
						|
 | 
						|
CommandBegin:
 | 
						|
	if safe != 0 {
 | 
						|
		s.state = stateCommandBegin
 | 
						|
	}
 | 
						|
 | 
						|
	if !checkInputAmountMaybeSafe(safe, br, 28) { /* 156 bits + 7 bytes */
 | 
						|
		s.state = stateCommandBegin
 | 
						|
		result = decoderNeedsMoreInput
 | 
						|
		goto saveStateAndReturn
 | 
						|
	}
 | 
						|
 | 
						|
	if s.block_length[1] == 0 {
 | 
						|
		if safe != 0 {
 | 
						|
			if !safeDecodeCommandBlockSwitch(s) {
 | 
						|
				result = decoderNeedsMoreInput
 | 
						|
				goto saveStateAndReturn
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			decodeCommandBlockSwitch(s)
 | 
						|
		}
 | 
						|
 | 
						|
		goto CommandBegin
 | 
						|
	}
 | 
						|
 | 
						|
	/* Read the insert/copy length in the command. */
 | 
						|
	if safe != 0 {
 | 
						|
		if !safeReadCommand(s, br, &i) {
 | 
						|
			result = decoderNeedsMoreInput
 | 
						|
			goto saveStateAndReturn
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		readCommand(s, br, &i)
 | 
						|
	}
 | 
						|
 | 
						|
	if i == 0 {
 | 
						|
		goto CommandPostDecodeLiterals
 | 
						|
	}
 | 
						|
 | 
						|
	s.meta_block_remaining_len -= i
 | 
						|
 | 
						|
CommandInner:
 | 
						|
	if safe != 0 {
 | 
						|
		s.state = stateCommandInner
 | 
						|
	}
 | 
						|
 | 
						|
	/* Read the literals in the command. */
 | 
						|
	if s.trivial_literal_context != 0 {
 | 
						|
		var bits uint32
 | 
						|
		var value uint32
 | 
						|
		preloadSymbol(safe, s.literal_htree, br, &bits, &value)
 | 
						|
		for {
 | 
						|
			if !checkInputAmountMaybeSafe(safe, br, 28) { /* 162 bits + 7 bytes */
 | 
						|
				s.state = stateCommandInner
 | 
						|
				result = decoderNeedsMoreInput
 | 
						|
				goto saveStateAndReturn
 | 
						|
			}
 | 
						|
 | 
						|
			if s.block_length[0] == 0 {
 | 
						|
				if safe != 0 {
 | 
						|
					if !safeDecodeLiteralBlockSwitch(s) {
 | 
						|
						result = decoderNeedsMoreInput
 | 
						|
						goto saveStateAndReturn
 | 
						|
					}
 | 
						|
				} else {
 | 
						|
					decodeLiteralBlockSwitch(s)
 | 
						|
				}
 | 
						|
 | 
						|
				preloadSymbol(safe, s.literal_htree, br, &bits, &value)
 | 
						|
				if s.trivial_literal_context == 0 {
 | 
						|
					goto CommandInner
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if safe == 0 {
 | 
						|
				s.ringbuffer[pos] = byte(readPreloadedSymbol(s.literal_htree, br, &bits, &value))
 | 
						|
			} else {
 | 
						|
				var literal uint32
 | 
						|
				if !safeReadSymbol(s.literal_htree, br, &literal) {
 | 
						|
					result = decoderNeedsMoreInput
 | 
						|
					goto saveStateAndReturn
 | 
						|
				}
 | 
						|
 | 
						|
				s.ringbuffer[pos] = byte(literal)
 | 
						|
			}
 | 
						|
 | 
						|
			s.block_length[0]--
 | 
						|
			pos++
 | 
						|
			if pos == s.ringbuffer_size {
 | 
						|
				s.state = stateCommandInnerWrite
 | 
						|
				i--
 | 
						|
				goto saveStateAndReturn
 | 
						|
			}
 | 
						|
			i--
 | 
						|
			if i == 0 {
 | 
						|
				break
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		var p1 byte = s.ringbuffer[(pos-1)&s.ringbuffer_mask]
 | 
						|
		var p2 byte = s.ringbuffer[(pos-2)&s.ringbuffer_mask]
 | 
						|
		for {
 | 
						|
			var context byte
 | 
						|
			if !checkInputAmountMaybeSafe(safe, br, 28) { /* 162 bits + 7 bytes */
 | 
						|
				s.state = stateCommandInner
 | 
						|
				result = decoderNeedsMoreInput
 | 
						|
				goto saveStateAndReturn
 | 
						|
			}
 | 
						|
 | 
						|
			if s.block_length[0] == 0 {
 | 
						|
				if safe != 0 {
 | 
						|
					if !safeDecodeLiteralBlockSwitch(s) {
 | 
						|
						result = decoderNeedsMoreInput
 | 
						|
						goto saveStateAndReturn
 | 
						|
					}
 | 
						|
				} else {
 | 
						|
					decodeLiteralBlockSwitch(s)
 | 
						|
				}
 | 
						|
 | 
						|
				if s.trivial_literal_context != 0 {
 | 
						|
					goto CommandInner
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			context = getContext(p1, p2, s.context_lookup)
 | 
						|
			hc = []huffmanCode(s.literal_hgroup.htrees[s.context_map_slice[context]])
 | 
						|
			p2 = p1
 | 
						|
			if safe == 0 {
 | 
						|
				p1 = byte(readSymbol(hc, br))
 | 
						|
			} else {
 | 
						|
				var literal uint32
 | 
						|
				if !safeReadSymbol(hc, br, &literal) {
 | 
						|
					result = decoderNeedsMoreInput
 | 
						|
					goto saveStateAndReturn
 | 
						|
				}
 | 
						|
 | 
						|
				p1 = byte(literal)
 | 
						|
			}
 | 
						|
 | 
						|
			s.ringbuffer[pos] = p1
 | 
						|
			s.block_length[0]--
 | 
						|
			pos++
 | 
						|
			if pos == s.ringbuffer_size {
 | 
						|
				s.state = stateCommandInnerWrite
 | 
						|
				i--
 | 
						|
				goto saveStateAndReturn
 | 
						|
			}
 | 
						|
			i--
 | 
						|
			if i == 0 {
 | 
						|
				break
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if s.meta_block_remaining_len <= 0 {
 | 
						|
		s.state = stateMetablockDone
 | 
						|
		goto saveStateAndReturn
 | 
						|
	}
 | 
						|
 | 
						|
CommandPostDecodeLiterals:
 | 
						|
	if safe != 0 {
 | 
						|
		s.state = stateCommandPostDecodeLiterals
 | 
						|
	}
 | 
						|
 | 
						|
	if s.distance_code >= 0 {
 | 
						|
		/* Implicit distance case. */
 | 
						|
		if s.distance_code != 0 {
 | 
						|
			s.distance_context = 0
 | 
						|
		} else {
 | 
						|
			s.distance_context = 1
 | 
						|
		}
 | 
						|
 | 
						|
		s.dist_rb_idx--
 | 
						|
		s.distance_code = s.dist_rb[s.dist_rb_idx&3]
 | 
						|
	} else {
 | 
						|
		/* Read distance code in the command, unless it was implicitly zero. */
 | 
						|
		if s.block_length[2] == 0 {
 | 
						|
			if safe != 0 {
 | 
						|
				if !safeDecodeDistanceBlockSwitch(s) {
 | 
						|
					result = decoderNeedsMoreInput
 | 
						|
					goto saveStateAndReturn
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				decodeDistanceBlockSwitch(s)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if safe != 0 {
 | 
						|
			if !safeReadDistance(s, br) {
 | 
						|
				result = decoderNeedsMoreInput
 | 
						|
				goto saveStateAndReturn
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			readDistance(s, br)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if s.max_distance != s.max_backward_distance {
 | 
						|
		if pos < s.max_backward_distance {
 | 
						|
			s.max_distance = pos
 | 
						|
		} else {
 | 
						|
			s.max_distance = s.max_backward_distance
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	i = s.copy_length
 | 
						|
 | 
						|
	/* Apply copy of LZ77 back-reference, or static dictionary reference if
 | 
						|
	   the distance is larger than the max LZ77 distance */
 | 
						|
	if s.distance_code > s.max_distance {
 | 
						|
		/* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC.
 | 
						|
		   With this choice, no signed overflow can occur after decoding
 | 
						|
		   a special distance code (e.g., after adding 3 to the last distance). */
 | 
						|
		if s.distance_code > maxAllowedDistance {
 | 
						|
			return decoderErrorFormatDistance
 | 
						|
		}
 | 
						|
 | 
						|
		if i >= minDictionaryWordLength && i <= maxDictionaryWordLength {
 | 
						|
			var address int = s.distance_code - s.max_distance - 1
 | 
						|
			var words *dictionary = s.dictionary
 | 
						|
			var trans *transforms = s.transforms
 | 
						|
			var offset int = int(s.dictionary.offsets_by_length[i])
 | 
						|
			var shift uint32 = uint32(s.dictionary.size_bits_by_length[i])
 | 
						|
			var mask int = int(bitMask(shift))
 | 
						|
			var word_idx int = address & mask
 | 
						|
			var transform_idx int = address >> shift
 | 
						|
 | 
						|
			/* Compensate double distance-ring-buffer roll. */
 | 
						|
			s.dist_rb_idx += s.distance_context
 | 
						|
 | 
						|
			offset += word_idx * i
 | 
						|
			if words.data == nil {
 | 
						|
				return decoderErrorDictionaryNotSet
 | 
						|
			}
 | 
						|
 | 
						|
			if transform_idx < int(trans.num_transforms) {
 | 
						|
				var word []byte
 | 
						|
				word = words.data[offset:]
 | 
						|
				var len int = i
 | 
						|
				if transform_idx == int(trans.cutOffTransforms[0]) {
 | 
						|
					copy(s.ringbuffer[pos:], word[:uint(len)])
 | 
						|
				} else {
 | 
						|
					len = transformDictionaryWord(s.ringbuffer[pos:], word, int(len), trans, transform_idx)
 | 
						|
				}
 | 
						|
 | 
						|
				pos += int(len)
 | 
						|
				s.meta_block_remaining_len -= int(len)
 | 
						|
				if pos >= s.ringbuffer_size {
 | 
						|
					s.state = stateCommandPostWrite1
 | 
						|
					goto saveStateAndReturn
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				return decoderErrorFormatTransform
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			return decoderErrorFormatDictionary
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		var src_start int = (pos - s.distance_code) & s.ringbuffer_mask
 | 
						|
		var copy_dst []byte
 | 
						|
		copy_dst = s.ringbuffer[pos:]
 | 
						|
		var copy_src []byte
 | 
						|
		copy_src = s.ringbuffer[src_start:]
 | 
						|
		var dst_end int = pos + i
 | 
						|
		var src_end int = src_start + i
 | 
						|
 | 
						|
		/* Update the recent distances cache. */
 | 
						|
		s.dist_rb[s.dist_rb_idx&3] = s.distance_code
 | 
						|
 | 
						|
		s.dist_rb_idx++
 | 
						|
		s.meta_block_remaining_len -= i
 | 
						|
 | 
						|
		/* There are 32+ bytes of slack in the ring-buffer allocation.
 | 
						|
		   Also, we have 16 short codes, that make these 16 bytes irrelevant
 | 
						|
		   in the ring-buffer. Let's copy over them as a first guess. */
 | 
						|
		copy(copy_dst, copy_src[:16])
 | 
						|
 | 
						|
		if src_end > pos && dst_end > src_start {
 | 
						|
			/* Regions intersect. */
 | 
						|
			goto CommandPostWrapCopy
 | 
						|
		}
 | 
						|
 | 
						|
		if dst_end >= s.ringbuffer_size || src_end >= s.ringbuffer_size {
 | 
						|
			/* At least one region wraps. */
 | 
						|
			goto CommandPostWrapCopy
 | 
						|
		}
 | 
						|
 | 
						|
		pos += i
 | 
						|
		if i > 16 {
 | 
						|
			if i > 32 {
 | 
						|
				copy(copy_dst[16:], copy_src[16:][:uint(i-16)])
 | 
						|
			} else {
 | 
						|
				/* This branch covers about 45% cases.
 | 
						|
				   Fixed size short copy allows more compiler optimizations. */
 | 
						|
				copy(copy_dst[16:], copy_src[16:][:16])
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if s.meta_block_remaining_len <= 0 {
 | 
						|
		/* Next metablock, if any. */
 | 
						|
		s.state = stateMetablockDone
 | 
						|
 | 
						|
		goto saveStateAndReturn
 | 
						|
	} else {
 | 
						|
		goto CommandBegin
 | 
						|
	}
 | 
						|
CommandPostWrapCopy:
 | 
						|
	{
 | 
						|
		var wrap_guard int = s.ringbuffer_size - pos
 | 
						|
		for {
 | 
						|
			i--
 | 
						|
			if i < 0 {
 | 
						|
				break
 | 
						|
			}
 | 
						|
			s.ringbuffer[pos] = s.ringbuffer[(pos-s.distance_code)&s.ringbuffer_mask]
 | 
						|
			pos++
 | 
						|
			wrap_guard--
 | 
						|
			if wrap_guard == 0 {
 | 
						|
				s.state = stateCommandPostWrite2
 | 
						|
				goto saveStateAndReturn
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if s.meta_block_remaining_len <= 0 {
 | 
						|
		/* Next metablock, if any. */
 | 
						|
		s.state = stateMetablockDone
 | 
						|
 | 
						|
		goto saveStateAndReturn
 | 
						|
	} else {
 | 
						|
		goto CommandBegin
 | 
						|
	}
 | 
						|
 | 
						|
saveStateAndReturn:
 | 
						|
	s.pos = pos
 | 
						|
	s.loop_counter = i
 | 
						|
	return result
 | 
						|
}
 | 
						|
 | 
						|
func processCommands(s *Reader) int {
 | 
						|
	return processCommandsInternal(0, s)
 | 
						|
}
 | 
						|
 | 
						|
func safeProcessCommands(s *Reader) int {
 | 
						|
	return processCommandsInternal(1, s)
 | 
						|
}
 | 
						|
 | 
						|
/* Returns the maximum number of distance symbols which can only represent
 | 
						|
   distances not exceeding BROTLI_MAX_ALLOWED_DISTANCE. */
 | 
						|
 | 
						|
var maxDistanceSymbol_bound = [maxNpostfix + 1]uint32{0, 4, 12, 28}
 | 
						|
var maxDistanceSymbol_diff = [maxNpostfix + 1]uint32{73, 126, 228, 424}
 | 
						|
 | 
						|
func maxDistanceSymbol(ndirect uint32, npostfix uint32) uint32 {
 | 
						|
	var postfix uint32 = 1 << npostfix
 | 
						|
	if ndirect < maxDistanceSymbol_bound[npostfix] {
 | 
						|
		return ndirect + maxDistanceSymbol_diff[npostfix] + postfix
 | 
						|
	} else if ndirect > maxDistanceSymbol_bound[npostfix]+postfix {
 | 
						|
		return ndirect + maxDistanceSymbol_diff[npostfix]
 | 
						|
	} else {
 | 
						|
		return maxDistanceSymbol_bound[npostfix] + maxDistanceSymbol_diff[npostfix] + postfix
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* Invariant: input stream is never overconsumed:
 | 
						|
   - invalid input implies that the whole stream is invalid -> any amount of
 | 
						|
     input could be read and discarded
 | 
						|
   - when result is "needs more input", then at least one more byte is REQUIRED
 | 
						|
     to complete decoding; all input data MUST be consumed by decoder, so
 | 
						|
     client could swap the input buffer
 | 
						|
   - when result is "needs more output" decoder MUST ensure that it doesn't
 | 
						|
     hold more than 7 bits in bit reader; this saves client from swapping input
 | 
						|
     buffer ahead of time
 | 
						|
   - when result is "success" decoder MUST return all unused data back to input
 | 
						|
     buffer; this is possible because the invariant is held on enter */
 | 
						|
func decoderDecompressStream(s *Reader, available_in *uint, next_in *[]byte, available_out *uint, next_out *[]byte) int {
 | 
						|
	var result int = decoderSuccess
 | 
						|
	var br *bitReader = &s.br
 | 
						|
 | 
						|
	/* Do not try to process further in a case of unrecoverable error. */
 | 
						|
	if int(s.error_code) < 0 {
 | 
						|
		return decoderResultError
 | 
						|
	}
 | 
						|
 | 
						|
	if *available_out != 0 && (next_out == nil || *next_out == nil) {
 | 
						|
		return saveErrorCode(s, decoderErrorInvalidArguments)
 | 
						|
	}
 | 
						|
 | 
						|
	if *available_out == 0 {
 | 
						|
		next_out = nil
 | 
						|
	}
 | 
						|
	if s.buffer_length == 0 { /* Just connect bit reader to input stream. */
 | 
						|
		br.input_len = *available_in
 | 
						|
		br.input = *next_in
 | 
						|
		br.byte_pos = 0
 | 
						|
	} else {
 | 
						|
		/* At least one byte of input is required. More than one byte of input may
 | 
						|
		   be required to complete the transaction -> reading more data must be
 | 
						|
		   done in a loop -> do it in a main loop. */
 | 
						|
		result = decoderNeedsMoreInput
 | 
						|
 | 
						|
		br.input = s.buffer.u8[:]
 | 
						|
		br.byte_pos = 0
 | 
						|
	}
 | 
						|
 | 
						|
	/* State machine */
 | 
						|
	for {
 | 
						|
		if result != decoderSuccess {
 | 
						|
			/* Error, needs more input/output. */
 | 
						|
			if result == decoderNeedsMoreInput {
 | 
						|
				if s.ringbuffer != nil { /* Pro-actively push output. */
 | 
						|
					var intermediate_result int = writeRingBuffer(s, available_out, next_out, nil, true)
 | 
						|
 | 
						|
					/* WriteRingBuffer checks s->meta_block_remaining_len validity. */
 | 
						|
					if int(intermediate_result) < 0 {
 | 
						|
						result = intermediate_result
 | 
						|
						break
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				if s.buffer_length != 0 { /* Used with internal buffer. */
 | 
						|
					if br.byte_pos == br.input_len {
 | 
						|
						/* Successfully finished read transaction.
 | 
						|
						   Accumulator contains less than 8 bits, because internal buffer
 | 
						|
						   is expanded byte-by-byte until it is enough to complete read. */
 | 
						|
						s.buffer_length = 0
 | 
						|
 | 
						|
						/* Switch to input stream and restart. */
 | 
						|
						result = decoderSuccess
 | 
						|
 | 
						|
						br.input_len = *available_in
 | 
						|
						br.input = *next_in
 | 
						|
						br.byte_pos = 0
 | 
						|
						continue
 | 
						|
					} else if *available_in != 0 {
 | 
						|
						/* Not enough data in buffer, but can take one more byte from
 | 
						|
						   input stream. */
 | 
						|
						result = decoderSuccess
 | 
						|
 | 
						|
						s.buffer.u8[s.buffer_length] = (*next_in)[0]
 | 
						|
						s.buffer_length++
 | 
						|
						br.input_len = uint(s.buffer_length)
 | 
						|
						*next_in = (*next_in)[1:]
 | 
						|
						(*available_in)--
 | 
						|
 | 
						|
						/* Retry with more data in buffer. */
 | 
						|
						continue
 | 
						|
					}
 | 
						|
 | 
						|
					/* Can't finish reading and no more input. */
 | 
						|
					break
 | 
						|
					/* Input stream doesn't contain enough input. */
 | 
						|
				} else {
 | 
						|
					/* Copy tail to internal buffer and return. */
 | 
						|
					*next_in = br.input[br.byte_pos:]
 | 
						|
 | 
						|
					*available_in = br.input_len - br.byte_pos
 | 
						|
					for *available_in != 0 {
 | 
						|
						s.buffer.u8[s.buffer_length] = (*next_in)[0]
 | 
						|
						s.buffer_length++
 | 
						|
						*next_in = (*next_in)[1:]
 | 
						|
						(*available_in)--
 | 
						|
					}
 | 
						|
 | 
						|
					break
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			/* Unreachable. */
 | 
						|
 | 
						|
			/* Fail or needs more output. */
 | 
						|
			if s.buffer_length != 0 {
 | 
						|
				/* Just consumed the buffered input and produced some output. Otherwise
 | 
						|
				   it would result in "needs more input". Reset internal buffer. */
 | 
						|
				s.buffer_length = 0
 | 
						|
			} else {
 | 
						|
				/* Using input stream in last iteration. When decoder switches to input
 | 
						|
				   stream it has less than 8 bits in accumulator, so it is safe to
 | 
						|
				   return unused accumulator bits there. */
 | 
						|
				bitReaderUnload(br)
 | 
						|
 | 
						|
				*available_in = br.input_len - br.byte_pos
 | 
						|
				*next_in = br.input[br.byte_pos:]
 | 
						|
			}
 | 
						|
 | 
						|
			break
 | 
						|
		}
 | 
						|
 | 
						|
		switch s.state {
 | 
						|
		/* Prepare to the first read. */
 | 
						|
		case stateUninited:
 | 
						|
			if !warmupBitReader(br) {
 | 
						|
				result = decoderNeedsMoreInput
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			/* Decode window size. */
 | 
						|
			result = decodeWindowBits(s, br) /* Reads 1..8 bits. */
 | 
						|
			if result != decoderSuccess {
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			if s.large_window {
 | 
						|
				s.state = stateLargeWindowBits
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.state = stateInitialize
 | 
						|
 | 
						|
		case stateLargeWindowBits:
 | 
						|
			if !safeReadBits(br, 6, &s.window_bits) {
 | 
						|
				result = decoderNeedsMoreInput
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			if s.window_bits < largeMinWbits || s.window_bits > largeMaxWbits {
 | 
						|
				result = decoderErrorFormatWindowBits
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.state = stateInitialize
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Maximum distance, see section 9.1. of the spec. */
 | 
						|
		/* Fall through. */
 | 
						|
		case stateInitialize:
 | 
						|
			s.max_backward_distance = (1 << s.window_bits) - windowGap
 | 
						|
 | 
						|
			/* Allocate memory for both block_type_trees and block_len_trees. */
 | 
						|
			s.block_type_trees = make([]huffmanCode, (3 * (huffmanMaxSize258 + huffmanMaxSize26)))
 | 
						|
 | 
						|
			if s.block_type_trees == nil {
 | 
						|
				result = decoderErrorAllocBlockTypeTrees
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.block_len_trees = s.block_type_trees[3*huffmanMaxSize258:]
 | 
						|
 | 
						|
			s.state = stateMetablockBegin
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockBegin:
 | 
						|
			decoderStateMetablockBegin(s)
 | 
						|
 | 
						|
			s.state = stateMetablockHeader
 | 
						|
			fallthrough
 | 
						|
 | 
						|
			/* Fall through. */
 | 
						|
		case stateMetablockHeader:
 | 
						|
			result = decodeMetaBlockLength(s, br)
 | 
						|
			/* Reads 2 - 31 bits. */
 | 
						|
			if result != decoderSuccess {
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			if s.is_metadata != 0 || s.is_uncompressed != 0 {
 | 
						|
				if !bitReaderJumpToByteBoundary(br) {
 | 
						|
					result = decoderErrorFormatPadding1
 | 
						|
					break
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if s.is_metadata != 0 {
 | 
						|
				s.state = stateMetadata
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			if s.meta_block_remaining_len == 0 {
 | 
						|
				s.state = stateMetablockDone
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			calculateRingBufferSize(s)
 | 
						|
			if s.is_uncompressed != 0 {
 | 
						|
				s.state = stateUncompressed
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.loop_counter = 0
 | 
						|
			s.state = stateHuffmanCode0
 | 
						|
 | 
						|
		case stateUncompressed:
 | 
						|
			result = copyUncompressedBlockToOutput(available_out, next_out, nil, s)
 | 
						|
			if result == decoderSuccess {
 | 
						|
				s.state = stateMetablockDone
 | 
						|
			}
 | 
						|
 | 
						|
		case stateMetadata:
 | 
						|
			for ; s.meta_block_remaining_len > 0; s.meta_block_remaining_len-- {
 | 
						|
				var bits uint32
 | 
						|
 | 
						|
				/* Read one byte and ignore it. */
 | 
						|
				if !safeReadBits(br, 8, &bits) {
 | 
						|
					result = decoderNeedsMoreInput
 | 
						|
					break
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if result == decoderSuccess {
 | 
						|
				s.state = stateMetablockDone
 | 
						|
			}
 | 
						|
 | 
						|
		case stateHuffmanCode0:
 | 
						|
			if s.loop_counter >= 3 {
 | 
						|
				s.state = stateMetablockHeader2
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			/* Reads 1..11 bits. */
 | 
						|
			result = decodeVarLenUint8(s, br, &s.num_block_types[s.loop_counter])
 | 
						|
 | 
						|
			if result != decoderSuccess {
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.num_block_types[s.loop_counter]++
 | 
						|
			if s.num_block_types[s.loop_counter] < 2 {
 | 
						|
				s.loop_counter++
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.state = stateHuffmanCode1
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateHuffmanCode1:
 | 
						|
			{
 | 
						|
				var alphabet_size uint32 = s.num_block_types[s.loop_counter] + 2
 | 
						|
				var tree_offset int = s.loop_counter * huffmanMaxSize258
 | 
						|
				result = readHuffmanCode(alphabet_size, alphabet_size, s.block_type_trees[tree_offset:], nil, s)
 | 
						|
				if result != decoderSuccess {
 | 
						|
					break
 | 
						|
				}
 | 
						|
				s.state = stateHuffmanCode2
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateHuffmanCode2:
 | 
						|
			{
 | 
						|
				var alphabet_size uint32 = numBlockLenSymbols
 | 
						|
				var tree_offset int = s.loop_counter * huffmanMaxSize26
 | 
						|
				result = readHuffmanCode(alphabet_size, alphabet_size, s.block_len_trees[tree_offset:], nil, s)
 | 
						|
				if result != decoderSuccess {
 | 
						|
					break
 | 
						|
				}
 | 
						|
				s.state = stateHuffmanCode3
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateHuffmanCode3:
 | 
						|
			var tree_offset int = s.loop_counter * huffmanMaxSize26
 | 
						|
			if !safeReadBlockLength(s, &s.block_length[s.loop_counter], s.block_len_trees[tree_offset:], br) {
 | 
						|
				result = decoderNeedsMoreInput
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.loop_counter++
 | 
						|
			s.state = stateHuffmanCode0
 | 
						|
 | 
						|
		case stateMetablockHeader2:
 | 
						|
			{
 | 
						|
				var bits uint32
 | 
						|
				if !safeReadBits(br, 6, &bits) {
 | 
						|
					result = decoderNeedsMoreInput
 | 
						|
					break
 | 
						|
				}
 | 
						|
 | 
						|
				s.distance_postfix_bits = bits & bitMask(2)
 | 
						|
				bits >>= 2
 | 
						|
				s.num_direct_distance_codes = numDistanceShortCodes + (bits << s.distance_postfix_bits)
 | 
						|
				s.distance_postfix_mask = int(bitMask(s.distance_postfix_bits))
 | 
						|
				s.context_modes = make([]byte, uint(s.num_block_types[0]))
 | 
						|
				if s.context_modes == nil {
 | 
						|
					result = decoderErrorAllocContextModes
 | 
						|
					break
 | 
						|
				}
 | 
						|
 | 
						|
				s.loop_counter = 0
 | 
						|
				s.state = stateContextModes
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateContextModes:
 | 
						|
			result = readContextModes(s)
 | 
						|
 | 
						|
			if result != decoderSuccess {
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			s.state = stateContextMap1
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateContextMap1:
 | 
						|
			result = decodeContextMap(s.num_block_types[0]<<literalContextBits, &s.num_literal_htrees, &s.context_map, s)
 | 
						|
 | 
						|
			if result != decoderSuccess {
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			detectTrivialLiteralBlockTypes(s)
 | 
						|
			s.state = stateContextMap2
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateContextMap2:
 | 
						|
			{
 | 
						|
				var num_direct_codes uint32 = s.num_direct_distance_codes - numDistanceShortCodes
 | 
						|
				var num_distance_codes uint32
 | 
						|
				var max_distance_symbol uint32
 | 
						|
				if s.large_window {
 | 
						|
					num_distance_codes = uint32(distanceAlphabetSize(uint(s.distance_postfix_bits), uint(num_direct_codes), largeMaxDistanceBits))
 | 
						|
					max_distance_symbol = maxDistanceSymbol(num_direct_codes, s.distance_postfix_bits)
 | 
						|
				} else {
 | 
						|
					num_distance_codes = uint32(distanceAlphabetSize(uint(s.distance_postfix_bits), uint(num_direct_codes), maxDistanceBits))
 | 
						|
					max_distance_symbol = num_distance_codes
 | 
						|
				}
 | 
						|
				var allocation_success bool = true
 | 
						|
				result = decodeContextMap(s.num_block_types[2]<<distanceContextBits, &s.num_dist_htrees, &s.dist_context_map, s)
 | 
						|
				if result != decoderSuccess {
 | 
						|
					break
 | 
						|
				}
 | 
						|
 | 
						|
				if !decoderHuffmanTreeGroupInit(s, &s.literal_hgroup, numLiteralSymbols, numLiteralSymbols, s.num_literal_htrees) {
 | 
						|
					allocation_success = false
 | 
						|
				}
 | 
						|
 | 
						|
				if !decoderHuffmanTreeGroupInit(s, &s.insert_copy_hgroup, numCommandSymbols, numCommandSymbols, s.num_block_types[1]) {
 | 
						|
					allocation_success = false
 | 
						|
				}
 | 
						|
 | 
						|
				if !decoderHuffmanTreeGroupInit(s, &s.distance_hgroup, num_distance_codes, max_distance_symbol, s.num_dist_htrees) {
 | 
						|
					allocation_success = false
 | 
						|
				}
 | 
						|
 | 
						|
				if !allocation_success {
 | 
						|
					return saveErrorCode(s, decoderErrorAllocTreeGroups)
 | 
						|
				}
 | 
						|
 | 
						|
				s.loop_counter = 0
 | 
						|
				s.state = stateTreeGroup
 | 
						|
			}
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateTreeGroup:
 | 
						|
			var hgroup *huffmanTreeGroup = nil
 | 
						|
			switch s.loop_counter {
 | 
						|
			case 0:
 | 
						|
				hgroup = &s.literal_hgroup
 | 
						|
			case 1:
 | 
						|
				hgroup = &s.insert_copy_hgroup
 | 
						|
			case 2:
 | 
						|
				hgroup = &s.distance_hgroup
 | 
						|
			default:
 | 
						|
				return saveErrorCode(s, decoderErrorUnreachable)
 | 
						|
			}
 | 
						|
 | 
						|
			result = huffmanTreeGroupDecode(hgroup, s)
 | 
						|
			if result != decoderSuccess {
 | 
						|
				break
 | 
						|
			}
 | 
						|
			s.loop_counter++
 | 
						|
			if s.loop_counter >= 3 {
 | 
						|
				prepareLiteralDecoding(s)
 | 
						|
				s.dist_context_map_slice = s.dist_context_map
 | 
						|
				s.htree_command = []huffmanCode(s.insert_copy_hgroup.htrees[0])
 | 
						|
				if !ensureRingBuffer(s) {
 | 
						|
					result = decoderErrorAllocRingBuffer2
 | 
						|
					break
 | 
						|
				}
 | 
						|
 | 
						|
				s.state = stateCommandBegin
 | 
						|
			}
 | 
						|
 | 
						|
		case stateCommandBegin, stateCommandInner, stateCommandPostDecodeLiterals, stateCommandPostWrapCopy:
 | 
						|
			result = processCommands(s)
 | 
						|
 | 
						|
			if result == decoderNeedsMoreInput {
 | 
						|
				result = safeProcessCommands(s)
 | 
						|
			}
 | 
						|
 | 
						|
		case stateCommandInnerWrite, stateCommandPostWrite1, stateCommandPostWrite2:
 | 
						|
			result = writeRingBuffer(s, available_out, next_out, nil, false)
 | 
						|
 | 
						|
			if result != decoderSuccess {
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			wrapRingBuffer(s)
 | 
						|
			if s.ringbuffer_size == 1<<s.window_bits {
 | 
						|
				s.max_distance = s.max_backward_distance
 | 
						|
			}
 | 
						|
 | 
						|
			if s.state == stateCommandPostWrite1 {
 | 
						|
				if s.meta_block_remaining_len == 0 {
 | 
						|
					/* Next metablock, if any. */
 | 
						|
					s.state = stateMetablockDone
 | 
						|
				} else {
 | 
						|
					s.state = stateCommandBegin
 | 
						|
				}
 | 
						|
 | 
						|
				break
 | 
						|
			} else if s.state == stateCommandPostWrite2 {
 | 
						|
				s.state = stateCommandPostWrapCopy /* BROTLI_STATE_COMMAND_INNER_WRITE */
 | 
						|
			} else {
 | 
						|
				if s.loop_counter == 0 {
 | 
						|
					if s.meta_block_remaining_len == 0 {
 | 
						|
						s.state = stateMetablockDone
 | 
						|
					} else {
 | 
						|
						s.state = stateCommandPostDecodeLiterals
 | 
						|
					}
 | 
						|
 | 
						|
					break
 | 
						|
				}
 | 
						|
 | 
						|
				s.state = stateCommandInner
 | 
						|
			}
 | 
						|
 | 
						|
		case stateMetablockDone:
 | 
						|
			if s.meta_block_remaining_len < 0 {
 | 
						|
				result = decoderErrorFormatBlockLength2
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			decoderStateCleanupAfterMetablock(s)
 | 
						|
			if s.is_last_metablock == 0 {
 | 
						|
				s.state = stateMetablockBegin
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			if !bitReaderJumpToByteBoundary(br) {
 | 
						|
				result = decoderErrorFormatPadding2
 | 
						|
				break
 | 
						|
			}
 | 
						|
 | 
						|
			if s.buffer_length == 0 {
 | 
						|
				bitReaderUnload(br)
 | 
						|
				*available_in = br.input_len - br.byte_pos
 | 
						|
				*next_in = br.input[br.byte_pos:]
 | 
						|
			}
 | 
						|
 | 
						|
			s.state = stateDone
 | 
						|
			fallthrough
 | 
						|
 | 
						|
		case stateDone:
 | 
						|
			if s.ringbuffer != nil {
 | 
						|
				result = writeRingBuffer(s, available_out, next_out, nil, true)
 | 
						|
				if result != decoderSuccess {
 | 
						|
					break
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			return saveErrorCode(s, result)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return saveErrorCode(s, result)
 | 
						|
}
 | 
						|
 | 
						|
func decoderHasMoreOutput(s *Reader) bool {
 | 
						|
	/* After unrecoverable error remaining output is considered nonsensical. */
 | 
						|
	if int(s.error_code) < 0 {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	return s.ringbuffer != nil && unwrittenBytes(s, false) != 0
 | 
						|
}
 | 
						|
 | 
						|
func decoderGetErrorCode(s *Reader) int {
 | 
						|
	return int(s.error_code)
 | 
						|
}
 | 
						|
 | 
						|
func decoderErrorString(c int) string {
 | 
						|
	switch c {
 | 
						|
	case decoderNoError:
 | 
						|
		return "NO_ERROR"
 | 
						|
	case decoderSuccess:
 | 
						|
		return "SUCCESS"
 | 
						|
	case decoderNeedsMoreInput:
 | 
						|
		return "NEEDS_MORE_INPUT"
 | 
						|
	case decoderNeedsMoreOutput:
 | 
						|
		return "NEEDS_MORE_OUTPUT"
 | 
						|
	case decoderErrorFormatExuberantNibble:
 | 
						|
		return "EXUBERANT_NIBBLE"
 | 
						|
	case decoderErrorFormatReserved:
 | 
						|
		return "RESERVED"
 | 
						|
	case decoderErrorFormatExuberantMetaNibble:
 | 
						|
		return "EXUBERANT_META_NIBBLE"
 | 
						|
	case decoderErrorFormatSimpleHuffmanAlphabet:
 | 
						|
		return "SIMPLE_HUFFMAN_ALPHABET"
 | 
						|
	case decoderErrorFormatSimpleHuffmanSame:
 | 
						|
		return "SIMPLE_HUFFMAN_SAME"
 | 
						|
	case decoderErrorFormatClSpace:
 | 
						|
		return "CL_SPACE"
 | 
						|
	case decoderErrorFormatHuffmanSpace:
 | 
						|
		return "HUFFMAN_SPACE"
 | 
						|
	case decoderErrorFormatContextMapRepeat:
 | 
						|
		return "CONTEXT_MAP_REPEAT"
 | 
						|
	case decoderErrorFormatBlockLength1:
 | 
						|
		return "BLOCK_LENGTH_1"
 | 
						|
	case decoderErrorFormatBlockLength2:
 | 
						|
		return "BLOCK_LENGTH_2"
 | 
						|
	case decoderErrorFormatTransform:
 | 
						|
		return "TRANSFORM"
 | 
						|
	case decoderErrorFormatDictionary:
 | 
						|
		return "DICTIONARY"
 | 
						|
	case decoderErrorFormatWindowBits:
 | 
						|
		return "WINDOW_BITS"
 | 
						|
	case decoderErrorFormatPadding1:
 | 
						|
		return "PADDING_1"
 | 
						|
	case decoderErrorFormatPadding2:
 | 
						|
		return "PADDING_2"
 | 
						|
	case decoderErrorFormatDistance:
 | 
						|
		return "DISTANCE"
 | 
						|
	case decoderErrorDictionaryNotSet:
 | 
						|
		return "DICTIONARY_NOT_SET"
 | 
						|
	case decoderErrorInvalidArguments:
 | 
						|
		return "INVALID_ARGUMENTS"
 | 
						|
	case decoderErrorAllocContextModes:
 | 
						|
		return "CONTEXT_MODES"
 | 
						|
	case decoderErrorAllocTreeGroups:
 | 
						|
		return "TREE_GROUPS"
 | 
						|
	case decoderErrorAllocContextMap:
 | 
						|
		return "CONTEXT_MAP"
 | 
						|
	case decoderErrorAllocRingBuffer1:
 | 
						|
		return "RING_BUFFER_1"
 | 
						|
	case decoderErrorAllocRingBuffer2:
 | 
						|
		return "RING_BUFFER_2"
 | 
						|
	case decoderErrorAllocBlockTypeTrees:
 | 
						|
		return "BLOCK_TYPE_TREES"
 | 
						|
	case decoderErrorUnreachable:
 | 
						|
		return "UNREACHABLE"
 | 
						|
	default:
 | 
						|
		return "INVALID"
 | 
						|
	}
 | 
						|
}
 | 
						|
 |