< Summary

Line coverage
92%
Covered lines: 344
Uncovered lines: 27
Coverable lines: 371
Total lines: 695
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)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/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 =>
 8427620        [
 8427621            0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
 8427622            3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16
 8427623        ];
 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 =>
 8396028        [
 8396029            3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
 8396030            59, 67, 83, 99, 115, 131, 163, 195, 227, 3
 8396031        ];
 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 =>
 5153036        [
 5153037            1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
 5153038            769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153
 5153039        ];
 40
 41        // code lengths for code length alphabet is stored in following order
 8951042        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 =>
 2086845        [
 2086846            0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, 0x02, 0x12, 0x0a, 0x1a,
 2086847            0x06, 0x16, 0x0e, 0x1e, 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
 2086848            0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f
 2086849        ];
 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
 471861        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
 471883        internal InflaterManaged(bool deflate64, long uncompressedSize)
 471884        {
 471885            _output = new OutputWindow();
 471886            _input = new InputBuffer();
 87
 471888            _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements];
 471889            _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements];
 471890            _deflate64 = deflate64;
 471891            _uncompressedSize = uncompressedSize;
 471892            _state = InflaterState.ReadingBFinal; // start by reading BFinal bit
 471893        }
 94
 95        public void SetInput(Memory<byte> inputBytes) => _input.SetInput(inputBytes);
 96
 97        public void SetInput(byte[] inputBytes, int offset, int length) =>
 471898            _input.SetInput(inputBytes, offset, length); // append the bytes
 99
 47300100        public bool Finished() => _state == InflaterState.Done || _state == InflaterState.VerifyingFooter;
 101
 564102        public int AvailableOutput => _output.AvailableBytes;
 103
 104        public int Inflate(Span<byte> bytes)
 13838105        {
 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.
 13838109            int count = 0;
 110            do
 22866111            {
 22866112                int copied = 0;
 22866113                if (_uncompressedSize == -1)
 22866114                {
 22866115                    copied = _output.CopyTo(bytes);
 22866116                }
 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                }
 22866131                if (copied > 0)
 8668132                {
 8668133                    bytes = bytes.Slice(copied);
 8668134                    count += copied;
 8668135                }
 136
 22866137                if (bytes.IsEmpty)
 2842138                {
 139                    // filled in the bytes buffer
 2842140                    break;
 141                }
 142                // Decode will return false when more input is needed
 40048143            } while (!Finished() && Decode());
 144
 12002145            return count;
 12002146        }
 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()
 18896172        {
 18896173            bool eob = false;
 174            bool result;
 175
 18896176            if (Finished())
 0177            {
 0178                return true;
 179            }
 180
 18896181            if (_state == InflaterState.ReadingBFinal)
 14648182            {
 183                // reading bfinal bit
 184                // Need 1 bit
 14648185                if (!_input.EnsureBitsAvailable(1))
 4778186                    return false;
 187
 9870188                _bfinal = _input.GetBits(1);
 9870189                _state = InflaterState.ReadingBType;
 9870190            }
 191
 14118192            if (_state == InflaterState.ReadingBType)
 9874193            {
 194                // Need 2 bits
 9874195                if (!_input.EnsureBitsAvailable(2))
 8196                {
 8197                    _state = InflaterState.ReadingBType;
 8198                    return false;
 199                }
 200
 9866201                _blockType = (BlockType)_input.GetBits(2);
 9866202                if (_blockType == BlockType.Dynamic)
 3552203                {
 3552204                    _state = InflaterState.ReadingNumLitCodes;
 3552205                }
 6314206                else if (_blockType == BlockType.Static)
 4006207                {
 4006208                    _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
 4006209                    _distanceTree = HuffmanTree.StaticDistanceTree;
 4006210                    _state = InflaterState.DecodeTop;
 4006211                }
 2308212                else if (_blockType == BlockType.Uncompressed)
 2182213                {
 2182214                    _state = InflaterState.UncompressedAligning;
 2182215                }
 216                else
 126217                {
 126218                    throw new InvalidDataException(SR.UnknownBlockType);
 219                }
 9740220            }
 221
 13984222            if (_blockType == BlockType.Dynamic)
 5534223            {
 5534224                if (_state < InflaterState.DecodeTop)
 3794225                {
 226                    // we are reading the header
 3794227                    result = DecodeDynamicBlockHeader();
 2570228                }
 229                else
 1740230                {
 1740231                    result = DecodeBlock(out eob); // this can returns true when output is full
 1554232                }
 4124233            }
 8450234            else if (_blockType == BlockType.Static)
 6044235            {
 6044236                result = DecodeBlock(out eob);
 5912237            }
 2406238            else if (_blockType == BlockType.Uncompressed)
 2406239            {
 2406240                result = DecodeUncompressedBlock(out eob);
 2238241            }
 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            //
 12274251            if (eob && (_bfinal != 0))
 578252            {
 578253                _state = InflaterState.Done;
 578254            }
 12274255            return result;
 17060256        }
 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)
 2406272        {
 2406273            end_of_block = false;
 10812274            while (true)
 10812275            {
 10812276                switch (_state)
 277                {
 278                    case InflaterState.UncompressedAligning: // initial state when calling this function
 279                                                             // we must skip to a byte boundary
 2182280                        _input.SkipToByteBoundary();
 2182281                        _state = InflaterState.UncompressedByte1;
 2182282                        goto case InflaterState.UncompressedByte1;
 283
 284                    case InflaterState.UncompressedByte1:   // decoding block length
 285                    case InflaterState.UncompressedByte2:
 286                    case InflaterState.UncompressedByte3:
 287                    case InflaterState.UncompressedByte4:
 8712288                        int bits = _input.GetBits(8);
 8712289                        if (bits < 0)
 138290                        {
 138291                            return false;
 292                        }
 293
 8574294                        _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits;
 8574295                        if (_state == InflaterState.UncompressedByte4)
 2106296                        {
 2106297                            _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256;
 2106298                            int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256;
 299
 300                            // make sure complement matches
 2106301                            if ((ushort)_blockLength != (ushort)(~blockLengthComplement))
 168302                            {
 168303                                throw new InvalidDataException(SR.InvalidBlockLength);
 304                            }
 1938305                        }
 306
 8406307                        _state += 1;
 8406308                        break;
 309
 310                    case InflaterState.DecodingUncompressed: // copying block data
 311
 312                        // Directly copy bytes from input to output.
 2100313                        int bytesCopied = _output.CopyFrom(_input, _blockLength);
 2100314                        _blockLength -= bytesCopied;
 315
 2100316                        if (_blockLength == 0)
 1850317                        {
 318                            // Done with this block, need to re-init bit buffer for next block
 1850319                            _state = InflaterState.ReadingBFinal;
 1850320                            end_of_block = true;
 1850321                            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
 250327                        if (_output.FreeBytes == 0)
 0328                        {
 0329                            return true;
 330                        }
 331
 250332                        return false;
 333
 334                    default:
 0335                        Debug.Fail("check why we are here!");
 336                        throw new InvalidDataException(SR.UnknownState);
 337                }
 8406338            }
 2238339        }
 340
 341        private bool DecodeBlock(out bool end_of_block_code_seen)
 7784342        {
 7784343            end_of_block_code_seen = false;
 344
 7784345            int freeBytes = _output.FreeBytes;   // it is a little bit faster than frequently accessing the property
 322762346            while (freeBytes >= MaxMatchLength)
 321100347            {
 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;
 321100353                switch (_state)
 354                {
 355                    case InflaterState.DecodeTop:
 356                        // decode an element from the literal tree
 357
 320868358                        Debug.Assert(_literalLengthTree != null);
 359                        // TODO: optimize this!!!
 320868360                        symbol = _literalLengthTree.GetNextSymbol(_input);
 320762361                        if (symbol < 0)
 1122362                        {
 363                            // running out of input
 1122364                            return false;
 365                        }
 366
 319640367                        if (symbol < 256)
 236564368                        {
 369                            // literal
 236564370                            _output.Write((byte)symbol);
 236564371                            --freeBytes;
 236564372                        }
 83076373                        else if (symbol == 256)
 3912374                        {
 375                            // end of block
 3912376                            end_of_block_code_seen = true;
 377                            // Reset state
 3912378                            _state = InflaterState.ReadingBFinal;
 3912379                            return true;
 380                        }
 381                        else
 79164382                        {
 383                            // length/distance pair
 79164384                            symbol -= 257;     // length code started at 257
 79164385                            if (symbol < 8)
 36960386                            {
 36960387                                symbol += 3;   // match length = 3,4,5,6,7,8,9,10
 36960388                                _extraBits = 0;
 36960389                            }
 42204390                            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
 42204397                            {
 42204398                                if ((uint)symbol >= ExtraLengthBits.Length)
 132399                                {
 132400                                    throw new InvalidDataException(SR.GenericInvalidData);
 401                                }
 42072402                                _extraBits = ExtraLengthBits[symbol];
 42072403                                Debug.Assert(_extraBits != 0, "We handle other cases separately!");
 42072404                            }
 79032405                            _length = symbol;
 79032406                            goto case InflaterState.HaveInitialLength;
 407                        }
 236564408                        break;
 409
 410                    case InflaterState.HaveInitialLength:
 79094411                        if (_extraBits > 0)
 42134412                        {
 42134413                            _state = InflaterState.HaveInitialLength;
 42134414                            int bits = _input.GetBits(_extraBits);
 42134415                            if (bits < 0)
 154416                            {
 154417                                return false;
 418                            }
 419
 41980420                            if (_length < 0 || _length >= LengthBase.Length)
 0421                            {
 0422                                throw new InvalidDataException(SR.GenericInvalidData);
 423                            }
 41980424                            _length = LengthBase[_length] + bits;
 41980425                        }
 78940426                        _state = InflaterState.HaveFullLength;
 78940427                        goto case InflaterState.HaveFullLength;
 428
 429                    case InflaterState.HaveFullLength:
 78996430                        if (_blockType == BlockType.Dynamic)
 57996431                        {
 57996432                            Debug.Assert(_distanceTree != null);
 57996433                            _distanceCode = _distanceTree.GetNextSymbol(_input);
 57916434                        }
 435                        else
 21000436                        {
 437                            // get distance code directly for static block
 21000438                            _distanceCode = _input.GetBits(5);
 21000439                            if (_distanceCode >= 0)
 20868440                            {
 20868441                                _distanceCode = StaticDistanceTreeTable[_distanceCode];
 20868442                            }
 21000443                        }
 444
 78916445                        if (_distanceCode < 0)
 322446                        {
 447                            // running out input
 322448                            return false;
 449                        }
 450
 78594451                        _state = InflaterState.HaveDistCode;
 78594452                        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;
 78708458                        if (_distanceCode > 3)
 51824459                        {
 51824460                            _extraBits = (_distanceCode - 2) >> 1;
 51824461                            int bits = _input.GetBits(_extraBits);
 51824462                            if (bits < 0)
 294463                            {
 294464                                return false;
 465                            }
 51530466                            offset = DistanceBasePosition[_distanceCode] + bits;
 51530467                        }
 468                        else
 26884469                        {
 26884470                            offset = _distanceCode + 1;
 26884471                        }
 472
 78414473                        _output.WriteLengthDistance(_length, offset);
 78414474                        freeBytes -= _length;
 78414475                        _state = InflaterState.DecodeTop;
 78414476                        break;
 477
 478                    default:
 0479                        Debug.Fail("check why we are here!");
 480                        throw new InvalidDataException(SR.UnknownState);
 481                }
 314978482            }
 483
 1662484            return true;
 7466485        }
 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()
 3794512        {
 3794513            switch (_state)
 514            {
 515                case InflaterState.ReadingNumLitCodes:
 3584516                    _literalLengthCodeCount = _input.GetBits(5);
 3584517                    if (_literalLengthCodeCount < 0)
 66518                    {
 66519                        return false;
 520                    }
 3518521                    _literalLengthCodeCount += 257;
 3518522                    _state = InflaterState.ReadingNumDistCodes;
 3518523                    goto case InflaterState.ReadingNumDistCodes;
 524
 525                case InflaterState.ReadingNumDistCodes:
 3588526                    _distanceCodeCount = _input.GetBits(5);
 3588527                    if (_distanceCodeCount < 0)
 142528                    {
 142529                        return false;
 530                    }
 3446531                    _distanceCodeCount += 1;
 3446532                    _state = InflaterState.ReadingNumCodeLengthCodes;
 3446533                    goto case InflaterState.ReadingNumCodeLengthCodes;
 534
 535                case InflaterState.ReadingNumCodeLengthCodes:
 3452536                    _codeLengthCodeCount = _input.GetBits(4);
 3452537                    if (_codeLengthCodeCount < 0)
 16538                    {
 16539                        return false;
 540                    }
 3436541                    _codeLengthCodeCount += 4;
 3436542                    _loopCounter = 0;
 3436543                    _state = InflaterState.ReadingCodeLengthCodes;
 3436544                    goto case InflaterState.ReadingCodeLengthCodes;
 545
 546                case InflaterState.ReadingCodeLengthCodes:
 45814547                    while (_loopCounter < _codeLengthCodeCount)
 42442548                    {
 42442549                        int bits = _input.GetBits(3);
 42442550                        if (bits < 0)
 120551                        {
 120552                            return false;
 553                        }
 42322554                        _codeLengthTreeCodeLength[CodeOrder[_loopCounter]] = (byte)bits;
 42322555                        ++_loopCounter;
 42322556                    }
 557
 50560558                    for (int i = _codeLengthCodeCount; i < CodeOrder.Length; i++)
 21908559                    {
 21908560                        _codeLengthTreeCodeLength[CodeOrder[i]] = 0;
 21908561                    }
 562
 563                    // create huffman tree for code length
 3372564                    _codeLengthTree = new HuffmanTree(_codeLengthTreeCodeLength);
 3372565                    _codeArraySize = _literalLengthCodeCount + _distanceCodeCount;
 3372566                    _loopCounter = 0; // reset loop count
 567
 3372568                    _state = InflaterState.ReadingTreeCodesBefore;
 3372569                    goto case InflaterState.ReadingTreeCodesBefore;
 570
 571                case InflaterState.ReadingTreeCodesBefore:
 572                case InflaterState.ReadingTreeCodesAfter:
 376244573                    while (_loopCounter < _codeArraySize)
 374152574                    {
 374152575                        if (_state == InflaterState.ReadingTreeCodesBefore)
 374110576                        {
 374110577                            Debug.Assert(_codeLengthTree != null);
 374110578                            if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0)
 386579                            {
 386580                                return false;
 581                            }
 373598582                        }
 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)
 373640596                        if (_lengthCode <= 15)
 329672597                        {
 329672598                            _codeList[_loopCounter++] = (byte)_lengthCode;
 329672599                        }
 600                        else
 43968601                        {
 602                            int repeatCount;
 43968603                            if (_lengthCode == 16)
 13318604                            {
 13318605                                if (!_input.EnsureBitsAvailable(2))
 80606                                {
 80607                                    _state = InflaterState.ReadingTreeCodesAfter;
 80608                                    return false;
 609                                }
 610
 13238611                                if (_loopCounter == 0)
 122612                                {
 613                                    // can't have "prev code" on first code
 122614                                    throw new InvalidDataException();
 615                                }
 616
 13116617                                byte previousCode = _codeList[_loopCounter - 1];
 13116618                                repeatCount = _input.GetBits(2) + 3;
 619
 13116620                                if (_loopCounter + repeatCount > _codeArraySize)
 88621                                {
 88622                                    throw new InvalidDataException();
 623                                }
 624
 13028625                                _codeList.AsSpan(_loopCounter, repeatCount).Fill(previousCode);
 13028626                                _loopCounter += repeatCount;
 13028627                            }
 30650628                            else if (_lengthCode == 17)
 24226629                            {
 24226630                                if (!_input.EnsureBitsAvailable(3))
 92631                                {
 92632                                    _state = InflaterState.ReadingTreeCodesAfter;
 92633                                    return false;
 634                                }
 635
 24134636                                repeatCount = _input.GetBits(3) + 3;
 637
 24134638                                if (_loopCounter + repeatCount > _codeArraySize)
 62639                                {
 62640                                    throw new InvalidDataException();
 641                                }
 642
 24072643                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 24072644                                _loopCounter += repeatCount;
 24072645                            }
 646                            else
 6424647                            {
 648                                // code == 18
 6424649                                if (!_input.EnsureBitsAvailable(7))
 64650                                {
 64651                                    _state = InflaterState.ReadingTreeCodesAfter;
 64652                                    return false;
 653                                }
 654
 6360655                                repeatCount = _input.GetBits(7) + 11;
 656
 6360657                                if (_loopCounter + repeatCount > _codeArraySize)
 338658                                {
 338659                                    throw new InvalidDataException();
 660                                }
 661
 6022662                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 6022663                                _loopCounter += repeatCount;
 6022664                            }
 43122665                        }
 372794666                        _state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code.
 372794667                    }
 2092668                    break;
 669
 670                default:
 0671                    Debug.Fail("check why we are here!");
 672                    throw new InvalidDataException(SR.UnknownState);
 673            }
 674
 2092675            byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements];
 2092676            byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements];
 677
 678            // Create literal and distance tables
 2092679            Array.Copy(_codeList, literalTreeCodeLength, _literalLengthCodeCount);
 2092680            Array.Copy(_codeList, _literalLengthCodeCount, distanceTreeCodeLength, 0, _distanceCodeCount);
 681
 682            // Make sure there is an end-of-block code, otherwise how could we ever end?
 2092683            if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0)
 138684            {
 138685                throw new InvalidDataException();
 686            }
 687
 1954688            _literalLengthTree = new HuffmanTree(literalTreeCodeLength);
 1662689            _distanceTree = new HuffmanTree(distanceTreeCodeLength);
 1604690            _state = InflaterState.DecodeTop;
 1604691            return true;
 2570692        }
 693    }
 694}
 695