private void decodeHuffmanData (final BZip2HuffmanStageDecoder huffmanDecoder) throws IOException {

		final byte[] bwtBlock = this.bwtBlock;
		final byte[] huffmanSymbolMap = this.huffmanSymbolMap;
		final int streamBlockSize = this.bwtBlock.length;
		final int huffmanEndOfBlockSymbol = this.huffmanEndOfBlockSymbol;
		final int[] bwtByteCounts = this.bwtByteCounts;
		final MoveToFront symbolMTF = new MoveToFront();
		int bwtBlockLength = 0;
		int repeatCount = 0;
		int repeatIncrement = 1;
		int mtfValue = 0;

		for (;;) {
			final int nextSymbol = huffmanDecoder.nextSymbol();

			if (nextSymbol == BZip2Constants.HUFFMAN_SYMBOL_RUNA) {
				repeatCount += repeatIncrement;
				repeatIncrement <<= 1;
			} else if (nextSymbol == BZip2Constants.HUFFMAN_SYMBOL_RUNB) {
				repeatCount += repeatIncrement << 1;
				repeatIncrement <<= 1;
			} else {
				if (repeatCount > 0) {
					if (bwtBlockLength + repeatCount > streamBlockSize) {
						throw new BZip2Exception ("BZip2 block exceeds declared block size");
					}
					final byte nextByte = huffmanSymbolMap[mtfValue];
					bwtByteCounts[nextByte & 0xff] += repeatCount;
					while (--repeatCount >= 0) {
						bwtBlock[bwtBlockLength++] = nextByte;
					}

					repeatCount = 0;
					repeatIncrement = 1;
				}

				if (nextSymbol == huffmanEndOfBlockSymbol)
					break;

				if (bwtBlockLength >= streamBlockSize) {
					throw new BZip2Exception ("BZip2 block exceeds declared block size");
				}

				mtfValue = symbolMTF.indexToFront (nextSymbol - 1) & 0xff;

				final byte nextByte = huffmanSymbolMap[mtfValue];
				bwtByteCounts[nextByte & 0xff]++;
				bwtBlock[bwtBlockLength++] = nextByte;

			}
		}

		this.bwtBlockLength = bwtBlockLength;

	}