< 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 =>
 15057420        [
 15057421            0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
 15057422            3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16
 15057423        ];
 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 =>
 15020028        [
 15020029            3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
 15020030            59, 67, 83, 99, 115, 131, 163, 195, 227, 3
 15020031        ];
 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 =>
 8311036        [
 8311037            1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
 8311038            769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153
 8311039        ];
 40
 41        // code lengths for code length alphabet is stored in following order
 11863642        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 =>
 4686645        [
 4686646            0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, 0x02, 0x12, 0x0a, 0x1a,
 4686647            0x06, 0x16, 0x0e, 0x1e, 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
 4686648            0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f
 4686649        ];
 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
 650261        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
 650283        internal InflaterManaged(bool deflate64, long uncompressedSize)
 650284        {
 650285            _output = new OutputWindow();
 650286            _input = new InputBuffer();
 87
 650288            _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements];
 650289            _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements];
 650290            _deflate64 = deflate64;
 650291            _uncompressedSize = uncompressedSize;
 650292            _state = InflaterState.ReadingBFinal; // start by reading BFinal bit
 650293        }
 94
 95        public void SetInput(Memory<byte> inputBytes) => _input.SetInput(inputBytes);
 96
 97        public void SetInput(byte[] inputBytes, int offset, int length) =>
 650298            _input.SetInput(inputBytes, offset, length); // append the bytes
 99
 67559100        public bool Finished() => _state == InflaterState.Done || _state == InflaterState.VerifyingFooter;
 101
 702102        public int AvailableOutput => _output.AvailableBytes;
 103
 104        public int Inflate(Span<byte> bytes)
 22670105        {
 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.
 22670109            int count = 0;
 110            do
 34946111            {
 34946112                int copied = 0;
 34946113                if (_uncompressedSize == -1)
 34946114                {
 34946115                    copied = _output.CopyTo(bytes);
 34946116                }
 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                }
 34946131                if (copied > 0)
 16532132                {
 16532133                    bytes = bytes.Slice(copied);
 16532134                    count += copied;
 16532135                }
 136
 34946137                if (bytes.IsEmpty)
 6576138                {
 139                    // filled in the bytes buffer
 6576140                    break;
 141                }
 142                // Decode will return false when more input is needed
 56740143            } while (!Finished() && Decode());
 144
 20344145            return count;
 20344146        }
 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()
 26966172        {
 26966173            bool eob = false;
 174            bool result;
 175
 26966176            if (Finished())
 0177            {
 0178                return true;
 179            }
 180
 26966181            if (_state == InflaterState.ReadingBFinal)
 18572182            {
 183                // reading bfinal bit
 184                // Need 1 bit
 18572185                if (!_input.EnsureBitsAvailable(1))
 6514186                    return false;
 187
 12058188                _bfinal = _input.GetBits(1);
 12058189                _state = InflaterState.ReadingBType;
 12058190            }
 191
 20452192            if (_state == InflaterState.ReadingBType)
 12060193            {
 194                // Need 2 bits
 12060195                if (!_input.EnsureBitsAvailable(2))
 4196                {
 4197                    _state = InflaterState.ReadingBType;
 4198                    return false;
 199                }
 200
 12056201                _blockType = (BlockType)_input.GetBits(2);
 12056202                if (_blockType == BlockType.Dynamic)
 4626203                {
 4626204                    _state = InflaterState.ReadingNumLitCodes;
 4626205                }
 7430206                else if (_blockType == BlockType.Static)
 5486207                {
 5486208                    _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
 5486209                    _distanceTree = HuffmanTree.StaticDistanceTree;
 5486210                    _state = InflaterState.DecodeTop;
 5486211                }
 1944212                else if (_blockType == BlockType.Uncompressed)
 1846213                {
 1846214                    _state = InflaterState.UncompressedAligning;
 1846215                }
 216                else
 98217                {
 98218                    throw new InvalidDataException(SR.UnknownBlockType);
 219                }
 11958220            }
 221
 20350222            if (_blockType == BlockType.Dynamic)
 6968223            {
 6968224                if (_state < InflaterState.DecodeTop)
 4988225                {
 226                    // we are reading the header
 4988227                    result = DecodeDynamicBlockHeader();
 3286228                }
 229                else
 1980230                {
 1980231                    result = DecodeBlock(out eob); // this can returns true when output is full
 1852232                }
 5138233            }
 13382234            else if (_blockType == BlockType.Static)
 11198235            {
 11198236                result = DecodeBlock(out eob);
 11096237            }
 2184238            else if (_blockType == BlockType.Uncompressed)
 2184239            {
 2184240                result = DecodeUncompressedBlock(out eob);
 1888241            }
 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            //
 18122251            if (eob && (_bfinal != 0))
 730252            {
 730253                _state = InflaterState.Done;
 730254            }
 18122255            return result;
 24640256        }
 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)
 2184272        {
 2184273            end_of_block = false;
 9092274            while (true)
 9092275            {
 9092276                switch (_state)
 277                {
 278                    case InflaterState.UncompressedAligning: // initial state when calling this function
 279                                                             // we must skip to a byte boundary
 1846280                        _input.SkipToByteBoundary();
 1846281                        _state = InflaterState.UncompressedByte1;
 1846282                        goto case InflaterState.UncompressedByte1;
 283
 284                    case InflaterState.UncompressedByte1:   // decoding block length
 285                    case InflaterState.UncompressedByte2:
 286                    case InflaterState.UncompressedByte3:
 287                    case InflaterState.UncompressedByte4:
 7404288                        int bits = _input.GetBits(8);
 7404289                        if (bits < 0)
 200290                        {
 200291                            return false;
 292                        }
 293
 7204294                        _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits;
 7204295                        if (_state == InflaterState.UncompressedByte4)
 1736296                        {
 1736297                            _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256;
 1736298                            int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256;
 299
 300                            // make sure complement matches
 1736301                            if ((ushort)_blockLength != (ushort)(~blockLengthComplement))
 296302                            {
 296303                                throw new InvalidDataException(SR.InvalidBlockLength);
 304                            }
 1440305                        }
 306
 6908307                        _state += 1;
 6908308                        break;
 309
 310                    case InflaterState.DecodingUncompressed: // copying block data
 311
 312                        // Directly copy bytes from input to output.
 1688313                        int bytesCopied = _output.CopyFrom(_input, _blockLength);
 1688314                        _blockLength -= bytesCopied;
 315
 1688316                        if (_blockLength == 0)
 1284317                        {
 318                            // Done with this block, need to re-init bit buffer for next block
 1284319                            _state = InflaterState.ReadingBFinal;
 1284320                            end_of_block = true;
 1284321                            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
 404327                        if (_output.FreeBytes == 0)
 0328                        {
 0329                            return true;
 330                        }
 331
 404332                        return false;
 333
 334                    default:
 0335                        Debug.Fail("check why we are here!");
 336                        throw new InvalidDataException(SR.UnknownState);
 337                }
 6908338            }
 1888339        }
 340
 341        private bool DecodeBlock(out bool end_of_block_code_seen)
 13178342        {
 13178343            end_of_block_code_seen = false;
 344
 13178345            int freeBytes = _output.FreeBytes;   // it is a little bit faster than frequently accessing the property
 645492346            while (freeBytes >= MaxMatchLength)
 641358347            {
 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;
 641358353                switch (_state)
 354                {
 355                    case InflaterState.DecodeTop:
 356                        // decode an element from the literal tree
 357
 640794358                        Debug.Assert(_literalLengthTree != null);
 359                        // TODO: optimize this!!!
 640794360                        symbol = _literalLengthTree.GetNextSymbol(_input);
 640774361                        if (symbol < 0)
 2488362                        {
 363                            // running out of input
 2488364                            return false;
 365                        }
 366
 638286367                        if (symbol < 256)
 517578368                        {
 369                            // literal
 517578370                            _output.Write((byte)symbol);
 517578371                            --freeBytes;
 517578372                        }
 120708373                        else if (symbol == 256)
 5008374                        {
 375                            // end of block
 5008376                            end_of_block_code_seen = true;
 377                            // Reset state
 5008378                            _state = InflaterState.ReadingBFinal;
 5008379                            return true;
 380                        }
 381                        else
 115700382                        {
 383                            // length/distance pair
 115700384                            symbol -= 257;     // length code started at 257
 115700385                            if (symbol < 8)
 40362386                            {
 40362387                                symbol += 3;   // match length = 3,4,5,6,7,8,9,10
 40362388                                _extraBits = 0;
 40362389                            }
 75338390                            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
 75338397                            {
 75338398                                if ((uint)symbol >= ExtraLengthBits.Length)
 102399                                {
 102400                                    throw new InvalidDataException(SR.GenericInvalidData);
 401                                }
 75236402                                _extraBits = ExtraLengthBits[symbol];
 75236403                                Debug.Assert(_extraBits != 0, "We handle other cases separately!");
 75236404                            }
 115598405                            _length = symbol;
 115598406                            goto case InflaterState.HaveInitialLength;
 407                        }
 517578408                        break;
 409
 410                    case InflaterState.HaveInitialLength:
 115730411                        if (_extraBits > 0)
 75368412                        {
 75368413                            _state = InflaterState.HaveInitialLength;
 75368414                            int bits = _input.GetBits(_extraBits);
 75368415                            if (bits < 0)
 268416                            {
 268417                                return false;
 418                            }
 419
 75100420                            if (_length < 0 || _length >= LengthBase.Length)
 0421                            {
 0422                                throw new InvalidDataException(SR.GenericInvalidData);
 423                            }
 75100424                            _length = LengthBase[_length] + bits;
 75100425                        }
 115462426                        _state = InflaterState.HaveFullLength;
 115462427                        goto case InflaterState.HaveFullLength;
 428
 429                    case InflaterState.HaveFullLength:
 115712430                        if (_blockType == BlockType.Dynamic)
 68382431                        {
 68382432                            Debug.Assert(_distanceTree != null);
 68382433                            _distanceCode = _distanceTree.GetNextSymbol(_input);
 68274434                        }
 435                        else
 47330436                        {
 437                            // get distance code directly for static block
 47330438                            _distanceCode = _input.GetBits(5);
 47330439                            if (_distanceCode >= 0)
 46866440                            {
 46866441                                _distanceCode = StaticDistanceTreeTable[_distanceCode];
 46866442                            }
 47330443                        }
 444
 115604445                        if (_distanceCode < 0)
 650446                        {
 447                            // running out input
 650448                            return false;
 449                        }
 450
 114954451                        _state = InflaterState.HaveDistCode;
 114954452                        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;
 115136458                        if (_distanceCode > 3)
 83510459                        {
 83510460                            _extraBits = (_distanceCode - 2) >> 1;
 83510461                            int bits = _input.GetBits(_extraBits);
 83510462                            if (bits < 0)
 400463                            {
 400464                                return false;
 465                            }
 83110466                            offset = DistanceBasePosition[_distanceCode] + bits;
 83110467                        }
 468                        else
 31626469                        {
 31626470                            offset = _distanceCode + 1;
 31626471                        }
 472
 114736473                        _output.WriteLengthDistance(_length, offset);
 114736474                        freeBytes -= _length;
 114736475                        _state = InflaterState.DecodeTop;
 114736476                        break;
 477
 478                    default:
 0479                        Debug.Fail("check why we are here!");
 480                        throw new InvalidDataException(SR.UnknownState);
 481                }
 632314482            }
 483
 4134484            return true;
 12948485        }
 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()
 4988512        {
 4988513            switch (_state)
 514            {
 515                case InflaterState.ReadingNumLitCodes:
 4628516                    _literalLengthCodeCount = _input.GetBits(5);
 4628517                    if (_literalLengthCodeCount < 0)
 4518                    {
 4519                        return false;
 520                    }
 4624521                    _literalLengthCodeCount += 257;
 4624522                    _state = InflaterState.ReadingNumDistCodes;
 4624523                    goto case InflaterState.ReadingNumDistCodes;
 524
 525                case InflaterState.ReadingNumDistCodes:
 4634526                    _distanceCodeCount = _input.GetBits(5);
 4634527                    if (_distanceCodeCount < 0)
 22528                    {
 22529                        return false;
 530                    }
 4612531                    _distanceCodeCount += 1;
 4612532                    _state = InflaterState.ReadingNumCodeLengthCodes;
 4612533                    goto case InflaterState.ReadingNumCodeLengthCodes;
 534
 535                case InflaterState.ReadingNumCodeLengthCodes:
 4642536                    _codeLengthCodeCount = _input.GetBits(4);
 4642537                    if (_codeLengthCodeCount < 0)
 62538                    {
 62539                        return false;
 540                    }
 4580541                    _codeLengthCodeCount += 4;
 4580542                    _loopCounter = 0;
 4580543                    _state = InflaterState.ReadingCodeLengthCodes;
 4580544                    goto case InflaterState.ReadingCodeLengthCodes;
 545
 546                case InflaterState.ReadingCodeLengthCodes:
 60436547                    while (_loopCounter < _codeLengthCodeCount)
 55990548                    {
 55990549                        int bits = _input.GetBits(3);
 55990550                        if (bits < 0)
 240551                        {
 240552                            return false;
 553                        }
 55750554                        _codeLengthTreeCodeLength[CodeOrder[_loopCounter]] = (byte)bits;
 55750555                        ++_loopCounter;
 55750556                    }
 557
 67332558                    for (int i = _codeLengthCodeCount; i < CodeOrder.Length; i++)
 29220559                    {
 29220560                        _codeLengthTreeCodeLength[CodeOrder[i]] = 0;
 29220561                    }
 562
 563                    // create huffman tree for code length
 4446564                    _codeLengthTree = new HuffmanTree(_codeLengthTreeCodeLength);
 4446565                    _codeArraySize = _literalLengthCodeCount + _distanceCodeCount;
 4446566                    _loopCounter = 0; // reset loop count
 567
 4446568                    _state = InflaterState.ReadingTreeCodesBefore;
 4446569                    goto case InflaterState.ReadingTreeCodesBefore;
 570
 571                case InflaterState.ReadingTreeCodesBefore:
 572                case InflaterState.ReadingTreeCodesAfter:
 471714573                    while (_loopCounter < _codeArraySize)
 469326574                    {
 469326575                        if (_state == InflaterState.ReadingTreeCodesBefore)
 469220576                        {
 469220577                            Debug.Assert(_codeLengthTree != null);
 469220578                            if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0)
 722579                            {
 722580                                return false;
 581                            }
 468302582                        }
 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)
 468408596                        if (_lengthCode <= 15)
 428884597                        {
 428884598                            _codeList[_loopCounter++] = (byte)_lengthCode;
 428884599                        }
 600                        else
 39524601                        {
 602                            int repeatCount;
 39524603                            if (_lengthCode == 16)
 12908604                            {
 12908605                                if (!_input.EnsureBitsAvailable(2))
 80606                                {
 80607                                    _state = InflaterState.ReadingTreeCodesAfter;
 80608                                    return false;
 609                                }
 610
 12828611                                if (_loopCounter == 0)
 180612                                {
 613                                    // can't have "prev code" on first code
 180614                                    throw new InvalidDataException();
 615                                }
 616
 12648617                                byte previousCode = _codeList[_loopCounter - 1];
 12648618                                repeatCount = _input.GetBits(2) + 3;
 619
 12648620                                if (_loopCounter + repeatCount > _codeArraySize)
 106621                                {
 106622                                    throw new InvalidDataException();
 623                                }
 624
 12542625                                _codeList.AsSpan(_loopCounter, repeatCount).Fill(previousCode);
 12542626                                _loopCounter += repeatCount;
 12542627                            }
 26616628                            else if (_lengthCode == 17)
 17684629                            {
 17684630                                if (!_input.EnsureBitsAvailable(3))
 134631                                {
 134632                                    _state = InflaterState.ReadingTreeCodesAfter;
 134633                                    return false;
 634                                }
 635
 17550636                                repeatCount = _input.GetBits(3) + 3;
 637
 17550638                                if (_loopCounter + repeatCount > _codeArraySize)
 158639                                {
 158640                                    throw new InvalidDataException();
 641                                }
 642
 17392643                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 17392644                                _loopCounter += repeatCount;
 17392645                            }
 646                            else
 8932647                            {
 648                                // code == 18
 8932649                                if (!_input.EnsureBitsAvailable(7))
 172650                                {
 172651                                    _state = InflaterState.ReadingTreeCodesAfter;
 172652                                    return false;
 653                                }
 654
 8760655                                repeatCount = _input.GetBits(7) + 11;
 656
 8760657                                if (_loopCounter + repeatCount > _codeArraySize)
 524658                                {
 524659                                    throw new InvalidDataException();
 660                                }
 661
 8236662                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 8236663                                _loopCounter += repeatCount;
 8236664                            }
 38170665                        }
 467054666                        _state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code.
 467054667                    }
 2388668                    break;
 669
 670                default:
 0671                    Debug.Fail("check why we are here!");
 672                    throw new InvalidDataException(SR.UnknownState);
 673            }
 674
 2388675            byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements];
 2388676            byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements];
 677
 678            // Create literal and distance tables
 2388679            Array.Copy(_codeList, literalTreeCodeLength, _literalLengthCodeCount);
 2388680            Array.Copy(_codeList, _literalLengthCodeCount, distanceTreeCodeLength, 0, _distanceCodeCount);
 681
 682            // Make sure there is an end-of-block code, otherwise how could we ever end?
 2388683            if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0)
 150684            {
 150685                throw new InvalidDataException();
 686            }
 687
 2238688            _literalLengthTree = new HuffmanTree(literalTreeCodeLength);
 1924689            _distanceTree = new HuffmanTree(distanceTreeCodeLength);
 1850690            _state = InflaterState.DecodeTop;
 1850691            return true;
 3286692        }
 693    }
 694}