< Summary

Information
Class: System.IO.Compression.InflaterManaged
Assembly: System.IO.Compression
File(s): D:\runner\runtime\src\libraries\System.IO.Compression\src\System\IO\Compression\DeflateManaged\InflaterManaged.cs
Line coverage
92%
Covered lines: 344
Uncovered lines: 27
Coverable lines: 371
Total lines: 694
Line coverage: 92.7%
Branch coverage
91%
Covered branches: 132
Total branches: 145
Branch coverage: 91%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
SetInput(...)100%11100%
Finished()100%22100%
Inflate(...)75%121261.29%
Decode()92.85%282893.54%
DecodeUncompressedBlock(...)88.23%171791.89%
DecodeBlock(...)87.17%393992.55%
DecodeDynamicBlockHeader()97.87%474799.13%

File(s)

D:\runner\runtime\src\libraries\System.IO.Compression\src\System\IO\Compression\DeflateManaged\InflaterManaged.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5
 6namespace System.IO.Compression
 7{
 8    internal sealed class InflaterManaged
 9    {
 10        // The maximum match length emitted by a Deflate64 length code. Length code 285 carries
 11        // 16 extra bits and a base length of 3, so the maximum length is 3 + 65535 = 65538.
 12        // Deflate (non-64) special-cases code 285 to length 258, so this bound is conservative
 13        // there as well.
 14        private const int MaxMatchLength = 65538;
 15
 16        // const tables used in decoding:
 17
 18        // Extra bits for length code 257 - 285.
 19        private static ReadOnlySpan<byte> ExtraLengthBits =>
 14546820        [
 14546821            0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
 14546822            3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16
 14546823        ];
 24
 25        // The base length for length code 257 - 285.
 26        // The formula to get the real length for a length code is lengthBase[code - 257] + (value stored in extraBits)
 27        private static ReadOnlySpan<byte> LengthBase =>
 14512028        [
 14512029            3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
 14512030            59, 67, 83, 99, 115, 131, 163, 195, 227, 3
 14512031        ];
 32
 33        // The base distance for distance code 0 - 31
 34        // The real distance for a distance code is  distanceBasePosition[code] + (value stored in extraBits)
 35        private static ReadOnlySpan<ushort> DistanceBasePosition =>
 8058836        [
 8058837            1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
 8058838            769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153
 8058839        ];
 40
 41        // code lengths for code length alphabet is stored in following order
 11658442        private static ReadOnlySpan<byte> CodeOrder => [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
 43
 44        private static ReadOnlySpan<byte> StaticDistanceTreeTable =>
 4473045        [
 4473046            0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, 0x02, 0x12, 0x0a, 0x1a,
 4473047            0x06, 0x16, 0x0e, 0x1e, 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
 4473048            0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f
 4473049        ];
 50
 51        private readonly OutputWindow _output;
 52        private readonly InputBuffer _input;
 53        private HuffmanTree? _literalLengthTree;
 54        private HuffmanTree? _distanceTree;
 55
 56        private InflaterState _state;
 57        private int _bfinal;
 58        private BlockType _blockType;
 59
 60        // uncompressed block
 629261        private readonly byte[] _blockLengthBuffer = new byte[4];
 62        private int _blockLength;
 63
 64        // compressed block
 65        private int _length;
 66        private int _distanceCode;
 67        private int _extraBits;
 68
 69        private int _loopCounter;
 70        private int _literalLengthCodeCount;
 71        private int _distanceCodeCount;
 72        private int _codeLengthCodeCount;
 73        private int _codeArraySize;
 74        private int _lengthCode;
 75
 76        private readonly byte[] _codeList; // temporary array to store the code length for literal/Length and distance
 77        private readonly byte[] _codeLengthTreeCodeLength;
 78        private readonly bool _deflate64;
 79        private HuffmanTree? _codeLengthTree;
 80        private readonly long _uncompressedSize;
 81        private long _currentInflatedCount;
 82
 629283        internal InflaterManaged(bool deflate64, long uncompressedSize)
 629284        {
 629285            _output = new OutputWindow();
 629286            _input = new InputBuffer();
 87
 629288            _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements];
 629289            _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements];
 629290            _deflate64 = deflate64;
 629291            _uncompressedSize = uncompressedSize;
 629292            _state = InflaterState.ReadingBFinal; // start by reading BFinal bit
 629293        }
 94
 95        public void SetInput(Memory<byte> inputBytes) => _input.SetInput(inputBytes);
 96
 97        public void SetInput(byte[] inputBytes, int offset, int length) =>
 629298            _input.SetInput(inputBytes, offset, length); // append the bytes
 99
 64542100        public bool Finished() => _state == InflaterState.Done || _state == InflaterState.VerifyingFooter;
 101
 698102        public int AvailableOutput => _output.AvailableBytes;
 103
 104        public int Inflate(Span<byte> bytes)
 21700105        {
 106            // copy bytes from output to outputbytes if we have available bytes
 107            // if buffer is not filled up. keep decoding until no input are available
 108            // if decodeBlock returns false. Throw an exception.
 21700109            int count = 0;
 110            do
 33304111            {
 33304112                int copied = 0;
 33304113                if (_uncompressedSize == -1)
 33304114                {
 33304115                    copied = _output.CopyTo(bytes);
 33304116                }
 117                else
 0118                {
 0119                    if (_uncompressedSize > _currentInflatedCount)
 0120                    {
 0121                        bytes = bytes.Slice(0, (int)Math.Min(bytes.Length, _uncompressedSize - _currentInflatedCount));
 0122                        copied = _output.CopyTo(bytes);
 0123                        _currentInflatedCount += copied;
 0124                    }
 125                    else
 0126                    {
 0127                        _state = InflaterState.Done;
 0128                        _output.ClearBytesUsed();
 0129                    }
 0130                }
 33304131                if (copied > 0)
 15586132                {
 15586133                    bytes = bytes.Slice(copied);
 15586134                    count += copied;
 15586135                }
 136
 33304137                if (bytes.IsEmpty)
 6208138                {
 139                    // filled in the bytes buffer
 6208140                    break;
 141                }
 142                // Decode will return false when more input is needed
 54192143            } while (!Finished() && Decode());
 144
 19408145            return count;
 19408146        }
 147
 148        public int Inflate(byte[] bytes, int offset, int length) => Inflate(bytes.AsSpan(offset, length));
 149
 150        //Each block of compressed data begins with 3 header bits
 151        // containing the following data:
 152        //    first bit       BFINAL
 153        //    next 2 bits     BTYPE
 154        // Note that the header bits do not necessarily begin on a byte
 155        // boundary, since a block does not necessarily occupy an integral
 156        // number of bytes.
 157        // BFINAL is set if and only if this is the last block of the data
 158        // set.
 159        // BTYPE specifies how the data are compressed, as follows:
 160        //    00 - no compression
 161        //    01 - compressed with fixed Huffman codes
 162        //    10 - compressed with dynamic Huffman codes
 163        //    11 - reserved (error)
 164        // The only difference between the two compressed cases is how the
 165        // Huffman codes for the literal/length and distance alphabets are
 166        // defined.
 167        //
 168        // This function returns true for success (end of block or output window is full,)
 169        // false if we are short of input
 170        //
 171        private bool Decode()
 25700172        {
 25700173            bool eob = false;
 174            bool result;
 175
 25700176            if (Finished())
 0177            {
 0178                return true;
 179            }
 180
 25700181            if (_state == InflaterState.ReadingBFinal)
 17758182            {
 183                // reading bfinal bit
 184                // Need 1 bit
 17758185                if (!_input.EnsureBitsAvailable(1))
 6304186                    return false;
 187
 11454188                _bfinal = _input.GetBits(1);
 11454189                _state = InflaterState.ReadingBType;
 11454190            }
 191
 19396192            if (_state == InflaterState.ReadingBType)
 11456193            {
 194                // Need 2 bits
 11456195                if (!_input.EnsureBitsAvailable(2))
 4196                {
 4197                    _state = InflaterState.ReadingBType;
 4198                    return false;
 199                }
 200
 11452201                _blockType = (BlockType)_input.GetBits(2);
 11452202                if (_blockType == BlockType.Dynamic)
 4544203                {
 4544204                    _state = InflaterState.ReadingNumLitCodes;
 4544205                }
 6908206                else if (_blockType == BlockType.Static)
 5130207                {
 5130208                    _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
 5130209                    _distanceTree = HuffmanTree.StaticDistanceTree;
 5130210                    _state = InflaterState.DecodeTop;
 5130211                }
 1778212                else if (_blockType == BlockType.Uncompressed)
 1680213                {
 1680214                    _state = InflaterState.UncompressedAligning;
 1680215                }
 216                else
 98217                {
 98218                    throw new InvalidDataException(SR.UnknownBlockType);
 219                }
 11354220            }
 221
 19294222            if (_blockType == BlockType.Dynamic)
 6830223            {
 6830224                if (_state < InflaterState.DecodeTop)
 4896225                {
 226                    // we are reading the header
 4896227                    result = DecodeDynamicBlockHeader();
 3212228                }
 229                else
 1934230                {
 1934231                    result = DecodeBlock(out eob); // this can returns true when output is full
 1806232                }
 5018233            }
 12464234            else if (_blockType == BlockType.Static)
 10486235            {
 10486236                result = DecodeBlock(out eob);
 10386237            }
 1978238            else if (_blockType == BlockType.Uncompressed)
 1978239            {
 1978240                result = DecodeUncompressedBlock(out eob);
 1696241            }
 242            else
 0243            {
 0244                throw new InvalidDataException(SR.UnknownBlockType);
 245            }
 246
 247            //
 248            // If we reached the end of the block and the block we were decoding had
 249            // bfinal=1 (final block)
 250            //
 17100251            if (eob && (_bfinal != 0))
 726252            {
 726253                _state = InflaterState.Done;
 726254            }
 17100255            return result;
 23408256        }
 257
 258
 259        // Format of Non-compressed blocks (BTYPE=00):
 260        //
 261        // Any bits of input up to the next byte boundary are ignored.
 262        // The rest of the block consists of the following information:
 263        //
 264        //     0   1   2   3   4...
 265        //   +---+---+---+---+================================+
 266        //   |  LEN  | NLEN  |... LEN bytes of literal data...|
 267        //   +---+---+---+---+================================+
 268        //
 269        // LEN is the number of data bytes in the block.  NLEN is the
 270        // one's complement of LEN.
 271        private bool DecodeUncompressedBlock(out bool end_of_block)
 1978272        {
 1978273            end_of_block = false;
 8260274            while (true)
 8260275            {
 8260276                switch (_state)
 277                {
 278                    case InflaterState.UncompressedAligning: // initial state when calling this function
 279                                                             // we must skip to a byte boundary
 1680280                        _input.SkipToByteBoundary();
 1680281                        _state = InflaterState.UncompressedByte1;
 1680282                        goto case InflaterState.UncompressedByte1;
 283
 284                    case InflaterState.UncompressedByte1:   // decoding block length
 285                    case InflaterState.UncompressedByte2:
 286                    case InflaterState.UncompressedByte3:
 287                    case InflaterState.UncompressedByte4:
 6740288                        int bits = _input.GetBits(8);
 6740289                        if (bits < 0)
 176290                        {
 176291                            return false;
 292                        }
 293
 6564294                        _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits;
 6564295                        if (_state == InflaterState.UncompressedByte4)
 1582296                        {
 1582297                            _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256;
 1582298                            int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256;
 299
 300                            // make sure complement matches
 1582301                            if ((ushort)_blockLength != (ushort)(~blockLengthComplement))
 282302                            {
 282303                                throw new InvalidDataException(SR.InvalidBlockLength);
 304                            }
 1300305                        }
 306
 6282307                        _state += 1;
 6282308                        break;
 309
 310                    case InflaterState.DecodingUncompressed: // copying block data
 311
 312                        // Directly copy bytes from input to output.
 1520313                        int bytesCopied = _output.CopyFrom(_input, _blockLength);
 1520314                        _blockLength -= bytesCopied;
 315
 1520316                        if (_blockLength == 0)
 1160317                        {
 318                            // Done with this block, need to re-init bit buffer for next block
 1160319                            _state = InflaterState.ReadingBFinal;
 1160320                            end_of_block = true;
 1160321                            return true;
 322                        }
 323
 324                        // We can fail to copy all bytes for two reasons:
 325                        //    Running out of Input
 326                        //    running out of free space in output window
 360327                        if (_output.FreeBytes == 0)
 0328                        {
 0329                            return true;
 330                        }
 331
 360332                        return false;
 333
 334                    default:
 0335                        Debug.Fail("check why we are here!");
 336                        throw new InvalidDataException(SR.UnknownState);
 337                }
 6282338            }
 1696339        }
 340
 341        private bool DecodeBlock(out bool end_of_block_code_seen)
 12420342        {
 12420343            end_of_block_code_seen = false;
 344
 12420345            int freeBytes = _output.FreeBytes;   // it is a little bit faster than frequently accessing the property
 631070346            while (freeBytes >= MaxMatchLength)
 627172347            {
 348                // With Deflate64 a length/distance pair can produce up to 65538 bytes, so we ensure
 349                // at least that much space is available in the OutputWindow before decoding the next
 350                // symbol to avoid overwriting previous unflushed output data.
 351
 352                int symbol;
 627172353                switch (_state)
 354                {
 355                    case InflaterState.DecodeTop:
 356                        // decode an element from the literal tree
 357
 626656358                        Debug.Assert(_literalLengthTree != null);
 359                        // TODO: optimize this!!!
 626656360                        symbol = _literalLengthTree.GetNextSymbol(_input);
 626636361                        if (symbol < 0)
 2334362                        {
 363                            // running out of input
 2334364                            return false;
 365                        }
 366
 624302367                        if (symbol < 256)
 507460368                        {
 369                            // literal
 507460370                            _output.Write((byte)symbol);
 507460371                            --freeBytes;
 507460372                        }
 116842373                        else if (symbol == 256)
 4734374                        {
 375                            // end of block
 4734376                            end_of_block_code_seen = true;
 377                            // Reset state
 4734378                            _state = InflaterState.ReadingBFinal;
 4734379                            return true;
 380                        }
 381                        else
 112108382                        {
 383                            // length/distance pair
 112108384                            symbol -= 257;     // length code started at 257
 112108385                            if (symbol < 8)
 39324386                            {
 39324387                                symbol += 3;   // match length = 3,4,5,6,7,8,9,10
 39324388                                _extraBits = 0;
 39324389                            }
 72784390                            else if (!_deflate64 && symbol == 28)
 0391                            {
 392                                // extra bits for code 285 is 0
 0393                                symbol = 258;             // code 285 means length 258
 0394                                _extraBits = 0;
 0395                            }
 396                            else
 72784397                            {
 72784398                                if ((uint)symbol >= ExtraLengthBits.Length)
 100399                                {
 100400                                    throw new InvalidDataException(SR.GenericInvalidData);
 401                                }
 72684402                                _extraBits = ExtraLengthBits[symbol];
 72684403                                Debug.Assert(_extraBits != 0, "We handle other cases separately!");
 72684404                            }
 112008405                            _length = symbol;
 112008406                            goto case InflaterState.HaveInitialLength;
 407                        }
 507460408                        break;
 409
 410                    case InflaterState.HaveInitialLength:
 112124411                        if (_extraBits > 0)
 72800412                        {
 72800413                            _state = InflaterState.HaveInitialLength;
 72800414                            int bits = _input.GetBits(_extraBits);
 72800415                            if (bits < 0)
 240416                            {
 240417                                return false;
 418                            }
 419
 72560420                            if (_length < 0 || _length >= LengthBase.Length)
 0421                            {
 0422                                throw new InvalidDataException(SR.GenericInvalidData);
 423                            }
 72560424                            _length = LengthBase[_length] + bits;
 72560425                        }
 111884426                        _state = InflaterState.HaveFullLength;
 111884427                        goto case InflaterState.HaveFullLength;
 428
 429                    case InflaterState.HaveFullLength:
 112118430                        if (_blockType == BlockType.Dynamic)
 66948431                        {
 66948432                            Debug.Assert(_distanceTree != null);
 66948433                            _distanceCode = _distanceTree.GetNextSymbol(_input);
 66840434                        }
 435                        else
 45170436                        {
 437                            // get distance code directly for static block
 45170438                            _distanceCode = _input.GetBits(5);
 45170439                            if (_distanceCode >= 0)
 44730440                            {
 44730441                                _distanceCode = StaticDistanceTreeTable[_distanceCode];
 44730442                            }
 45170443                        }
 444
 112010445                        if (_distanceCode < 0)
 616446                        {
 447                            // running out input
 616448                            return false;
 449                        }
 450
 111394451                        _state = InflaterState.HaveDistCode;
 111394452                        goto case InflaterState.HaveDistCode;
 453
 454                    case InflaterState.HaveDistCode:
 455                        // To avoid a table lookup we note that for distanceCode > 3,
 456                        // extra_bits = (distanceCode-2) >> 1
 457                        int offset;
 111560458                        if (_distanceCode > 3)
 80958459                        {
 80958460                            _extraBits = (_distanceCode - 2) >> 1;
 80958461                            int bits = _input.GetBits(_extraBits);
 80958462                            if (bits < 0)
 370463                            {
 370464                                return false;
 465                            }
 80588466                            offset = DistanceBasePosition[_distanceCode] + bits;
 80588467                        }
 468                        else
 30602469                        {
 30602470                            offset = _distanceCode + 1;
 30602471                        }
 472
 111190473                        _output.WriteLengthDistance(_length, offset);
 111190474                        freeBytes -= _length;
 111190475                        _state = InflaterState.DecodeTop;
 111190476                        break;
 477
 478                    default:
 0479                        Debug.Fail("check why we are here!");
 480                        throw new InvalidDataException(SR.UnknownState);
 481                }
 618650482            }
 483
 3898484            return true;
 12192485        }
 486
 487
 488        // Format of the dynamic block header:
 489        //      5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
 490        //      5 Bits: HDIST, # of Distance codes - 1        (1 - 32)
 491        //      4 Bits: HCLEN, # of Code Length codes - 4     (4 - 19)
 492        //
 493        //      (HCLEN + 4) x 3 bits: code lengths for the code length
 494        //          alphabet given just above, in the order: 16, 17, 18,
 495        //          0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
 496        //
 497        //          These code lengths are interpreted as 3-bit integers
 498        //          (0-7); as above, a code length of 0 means the
 499        //          corresponding symbol (literal/length or distance code
 500        //          length) is not used.
 501        //
 502        //      HLIT + 257 code lengths for the literal/length alphabet,
 503        //          encoded using the code length Huffman code
 504        //
 505        //       HDIST + 1 code lengths for the distance alphabet,
 506        //          encoded using the code length Huffman code
 507        //
 508        // The code length repeat codes can cross from HLIT + 257 to the
 509        // HDIST + 1 code lengths.  In other words, all code lengths form
 510        // a single sequence of HLIT + HDIST + 258 values.
 511        private bool DecodeDynamicBlockHeader()
 4896512        {
 4896513            switch (_state)
 514            {
 515                case InflaterState.ReadingNumLitCodes:
 4546516                    _literalLengthCodeCount = _input.GetBits(5);
 4546517                    if (_literalLengthCodeCount < 0)
 4518                    {
 4519                        return false;
 520                    }
 4542521                    _literalLengthCodeCount += 257;
 4542522                    _state = InflaterState.ReadingNumDistCodes;
 4542523                    goto case InflaterState.ReadingNumDistCodes;
 524
 525                case InflaterState.ReadingNumDistCodes:
 4552526                    _distanceCodeCount = _input.GetBits(5);
 4552527                    if (_distanceCodeCount < 0)
 22528                    {
 22529                        return false;
 530                    }
 4530531                    _distanceCodeCount += 1;
 4530532                    _state = InflaterState.ReadingNumCodeLengthCodes;
 4530533                    goto case InflaterState.ReadingNumCodeLengthCodes;
 534
 535                case InflaterState.ReadingNumCodeLengthCodes:
 4556536                    _codeLengthCodeCount = _input.GetBits(4);
 4556537                    if (_codeLengthCodeCount < 0)
 54538                    {
 54539                        return false;
 540                    }
 4502541                    _codeLengthCodeCount += 4;
 4502542                    _loopCounter = 0;
 4502543                    _state = InflaterState.ReadingCodeLengthCodes;
 4502544                    goto case InflaterState.ReadingCodeLengthCodes;
 545
 546                case InflaterState.ReadingCodeLengthCodes:
 59436547                    while (_loopCounter < _codeLengthCodeCount)
 55066548                    {
 55066549                        int bits = _input.GetBits(3);
 55066550                        if (bits < 0)
 236551                        {
 236552                            return false;
 553                        }
 54830554                        _codeLengthTreeCodeLength[CodeOrder[_loopCounter]] = (byte)bits;
 54830555                        ++_loopCounter;
 54830556                    }
 557
 66124558                    for (int i = _codeLengthCodeCount; i < CodeOrder.Length; i++)
 28692559                    {
 28692560                        _codeLengthTreeCodeLength[CodeOrder[i]] = 0;
 28692561                    }
 562
 563                    // create huffman tree for code length
 4370564                    _codeLengthTree = new HuffmanTree(_codeLengthTreeCodeLength);
 4370565                    _codeArraySize = _literalLengthCodeCount + _distanceCodeCount;
 4370566                    _loopCounter = 0; // reset loop count
 567
 4370568                    _state = InflaterState.ReadingTreeCodesBefore;
 4370569                    goto case InflaterState.ReadingTreeCodesBefore;
 570
 571                case InflaterState.ReadingTreeCodesBefore:
 572                case InflaterState.ReadingTreeCodesAfter:
 466054573                    while (_loopCounter < _codeArraySize)
 463704574                    {
 463704575                        if (_state == InflaterState.ReadingTreeCodesBefore)
 463598576                        {
 463598577                            Debug.Assert(_codeLengthTree != null);
 463598578                            if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0)
 702579                            {
 702580                                return false;
 581                            }
 462706582                        }
 583
 584                        // The alphabet for code lengths is as follows:
 585                        //  0 - 15: Represent code lengths of 0 - 15
 586                        //  16: Copy the previous code length 3 - 6 times.
 587                        //  The next 2 bits indicate repeat length
 588                        //         (0 = 3, ... , 3 = 6)
 589                        //      Example:  Codes 8, 16 (+2 bits 11),
 590                        //                16 (+2 bits 10) will expand to
 591                        //                12 code lengths of 8 (1 + 6 + 5)
 592                        //  17: Repeat a code length of 0 for 3 - 10 times.
 593                        //    (3 bits of length)
 594                        //  18: Repeat a code length of 0 for 11 - 138 times
 595                        //    (7 bits of length)
 462812596                        if (_lengthCode <= 15)
 423848597                        {
 423848598                            _codeList[_loopCounter++] = (byte)_lengthCode;
 423848599                        }
 600                        else
 38964601                        {
 602                            int repeatCount;
 38964603                            if (_lengthCode == 16)
 12684604                            {
 12684605                                if (!_input.EnsureBitsAvailable(2))
 78606                                {
 78607                                    _state = InflaterState.ReadingTreeCodesAfter;
 78608                                    return false;
 609                                }
 610
 12606611                                if (_loopCounter == 0)
 180612                                {
 613                                    // can't have "prev code" on first code
 180614                                    throw new InvalidDataException();
 615                                }
 616
 12426617                                byte previousCode = _codeList[_loopCounter - 1];
 12426618                                repeatCount = _input.GetBits(2) + 3;
 619
 12426620                                if (_loopCounter + repeatCount > _codeArraySize)
 100621                                {
 100622                                    throw new InvalidDataException();
 623                                }
 624
 12326625                                _codeList.AsSpan(_loopCounter, repeatCount).Fill(previousCode);
 12326626                                _loopCounter += repeatCount;
 12326627                            }
 26280628                            else if (_lengthCode == 17)
 17534629                            {
 17534630                                if (!_input.EnsureBitsAvailable(3))
 134631                                {
 134632                                    _state = InflaterState.ReadingTreeCodesAfter;
 134633                                    return false;
 634                                }
 635
 17400636                                repeatCount = _input.GetBits(3) + 3;
 637
 17400638                                if (_loopCounter + repeatCount > _codeArraySize)
 156639                                {
 156640                                    throw new InvalidDataException();
 641                                }
 642
 17244643                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 17244644                                _loopCounter += repeatCount;
 17244645                            }
 646                            else
 8746647                            {
 648                                // code == 18
 8746649                                if (!_input.EnsureBitsAvailable(7))
 170650                                {
 170651                                    _state = InflaterState.ReadingTreeCodesAfter;
 170652                                    return false;
 653                                }
 654
 8576655                                repeatCount = _input.GetBits(7) + 11;
 656
 8576657                                if (_loopCounter + repeatCount > _codeArraySize)
 520658                                {
 520659                                    throw new InvalidDataException();
 660                                }
 661
 8056662                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 8056663                                _loopCounter += repeatCount;
 8056664                            }
 37626665                        }
 461474666                        _state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code.
 461474667                    }
 2350668                    break;
 669
 670                default:
 0671                    Debug.Fail("check why we are here!");
 672                    throw new InvalidDataException(SR.UnknownState);
 673            }
 674
 2350675            byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements];
 2350676            byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements];
 677
 678            // Create literal and distance tables
 2350679            Array.Copy(_codeList, literalTreeCodeLength, _literalLengthCodeCount);
 2350680            Array.Copy(_codeList, _literalLengthCodeCount, distanceTreeCodeLength, 0, _distanceCodeCount);
 681
 682            // Make sure there is an end-of-block code, otherwise how could we ever end?
 2350683            if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0)
 150684            {
 150685                throw new InvalidDataException();
 686            }
 687
 2200688            _literalLengthTree = new HuffmanTree(literalTreeCodeLength);
 1886689            _distanceTree = new HuffmanTree(distanceTreeCodeLength);
 1812690            _state = InflaterState.DecodeTop;
 1812691            return true;
 3212692        }
 693    }
 694}