< 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
0%
Covered lines: 0
Uncovered lines: 371
Coverable lines: 371
Total lines: 694
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 145
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
SetInput(...)100%110%
Finished()0%220%
Inflate(...)0%12120%
Decode()0%28280%
DecodeUncompressedBlock(...)0%17170%
DecodeBlock(...)0%39390%
DecodeDynamicBlockHeader()0%47470%

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 =>
 020        [
 021            0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
 022            3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16
 023        ];
 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 =>
 028        [
 029            3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
 030            59, 67, 83, 99, 115, 131, 163, 195, 227, 3
 031        ];
 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 =>
 036        [
 037            1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
 038            769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153
 039        ];
 40
 41        // code lengths for code length alphabet is stored in following order
 042        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 =>
 045        [
 046            0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, 0x02, 0x12, 0x0a, 0x1a,
 047            0x06, 0x16, 0x0e, 0x1e, 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
 048            0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f
 049        ];
 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
 061        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
 083        internal InflaterManaged(bool deflate64, long uncompressedSize)
 084        {
 085            _output = new OutputWindow();
 086            _input = new InputBuffer();
 87
 088            _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements];
 089            _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements];
 090            _deflate64 = deflate64;
 091            _uncompressedSize = uncompressedSize;
 092            _state = InflaterState.ReadingBFinal; // start by reading BFinal bit
 093        }
 94
 95        public void SetInput(Memory<byte> inputBytes) => _input.SetInput(inputBytes);
 96
 97        public void SetInput(byte[] inputBytes, int offset, int length) =>
 098            _input.SetInput(inputBytes, offset, length); // append the bytes
 99
 0100        public bool Finished() => _state == InflaterState.Done || _state == InflaterState.VerifyingFooter;
 101
 0102        public int AvailableOutput => _output.AvailableBytes;
 103
 104        public int Inflate(Span<byte> bytes)
 0105        {
 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.
 0109            int count = 0;
 110            do
 0111            {
 0112                int copied = 0;
 0113                if (_uncompressedSize == -1)
 0114                {
 0115                    copied = _output.CopyTo(bytes);
 0116                }
 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                }
 0131                if (copied > 0)
 0132                {
 0133                    bytes = bytes.Slice(copied);
 0134                    count += copied;
 0135                }
 136
 0137                if (bytes.IsEmpty)
 0138                {
 139                    // filled in the bytes buffer
 0140                    break;
 141                }
 142                // Decode will return false when more input is needed
 0143            } while (!Finished() && Decode());
 144
 0145            return count;
 0146        }
 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()
 0172        {
 0173            bool eob = false;
 174            bool result;
 175
 0176            if (Finished())
 0177            {
 0178                return true;
 179            }
 180
 0181            if (_state == InflaterState.ReadingBFinal)
 0182            {
 183                // reading bfinal bit
 184                // Need 1 bit
 0185                if (!_input.EnsureBitsAvailable(1))
 0186                    return false;
 187
 0188                _bfinal = _input.GetBits(1);
 0189                _state = InflaterState.ReadingBType;
 0190            }
 191
 0192            if (_state == InflaterState.ReadingBType)
 0193            {
 194                // Need 2 bits
 0195                if (!_input.EnsureBitsAvailable(2))
 0196                {
 0197                    _state = InflaterState.ReadingBType;
 0198                    return false;
 199                }
 200
 0201                _blockType = (BlockType)_input.GetBits(2);
 0202                if (_blockType == BlockType.Dynamic)
 0203                {
 0204                    _state = InflaterState.ReadingNumLitCodes;
 0205                }
 0206                else if (_blockType == BlockType.Static)
 0207                {
 0208                    _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
 0209                    _distanceTree = HuffmanTree.StaticDistanceTree;
 0210                    _state = InflaterState.DecodeTop;
 0211                }
 0212                else if (_blockType == BlockType.Uncompressed)
 0213                {
 0214                    _state = InflaterState.UncompressedAligning;
 0215                }
 216                else
 0217                {
 0218                    throw new InvalidDataException(SR.UnknownBlockType);
 219                }
 0220            }
 221
 0222            if (_blockType == BlockType.Dynamic)
 0223            {
 0224                if (_state < InflaterState.DecodeTop)
 0225                {
 226                    // we are reading the header
 0227                    result = DecodeDynamicBlockHeader();
 0228                }
 229                else
 0230                {
 0231                    result = DecodeBlock(out eob); // this can returns true when output is full
 0232                }
 0233            }
 0234            else if (_blockType == BlockType.Static)
 0235            {
 0236                result = DecodeBlock(out eob);
 0237            }
 0238            else if (_blockType == BlockType.Uncompressed)
 0239            {
 0240                result = DecodeUncompressedBlock(out eob);
 0241            }
 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            //
 0251            if (eob && (_bfinal != 0))
 0252            {
 0253                _state = InflaterState.Done;
 0254            }
 0255            return result;
 0256        }
 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)
 0272        {
 0273            end_of_block = false;
 0274            while (true)
 0275            {
 0276                switch (_state)
 277                {
 278                    case InflaterState.UncompressedAligning: // initial state when calling this function
 279                                                             // we must skip to a byte boundary
 0280                        _input.SkipToByteBoundary();
 0281                        _state = InflaterState.UncompressedByte1;
 0282                        goto case InflaterState.UncompressedByte1;
 283
 284                    case InflaterState.UncompressedByte1:   // decoding block length
 285                    case InflaterState.UncompressedByte2:
 286                    case InflaterState.UncompressedByte3:
 287                    case InflaterState.UncompressedByte4:
 0288                        int bits = _input.GetBits(8);
 0289                        if (bits < 0)
 0290                        {
 0291                            return false;
 292                        }
 293
 0294                        _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits;
 0295                        if (_state == InflaterState.UncompressedByte4)
 0296                        {
 0297                            _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256;
 0298                            int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256;
 299
 300                            // make sure complement matches
 0301                            if ((ushort)_blockLength != (ushort)(~blockLengthComplement))
 0302                            {
 0303                                throw new InvalidDataException(SR.InvalidBlockLength);
 304                            }
 0305                        }
 306
 0307                        _state += 1;
 0308                        break;
 309
 310                    case InflaterState.DecodingUncompressed: // copying block data
 311
 312                        // Directly copy bytes from input to output.
 0313                        int bytesCopied = _output.CopyFrom(_input, _blockLength);
 0314                        _blockLength -= bytesCopied;
 315
 0316                        if (_blockLength == 0)
 0317                        {
 318                            // Done with this block, need to re-init bit buffer for next block
 0319                            _state = InflaterState.ReadingBFinal;
 0320                            end_of_block = true;
 0321                            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
 0327                        if (_output.FreeBytes == 0)
 0328                        {
 0329                            return true;
 330                        }
 331
 0332                        return false;
 333
 334                    default:
 0335                        Debug.Fail("check why we are here!");
 336                        throw new InvalidDataException(SR.UnknownState);
 337                }
 0338            }
 0339        }
 340
 341        private bool DecodeBlock(out bool end_of_block_code_seen)
 0342        {
 0343            end_of_block_code_seen = false;
 344
 0345            int freeBytes = _output.FreeBytes;   // it is a little bit faster than frequently accessing the property
 0346            while (freeBytes >= MaxMatchLength)
 0347            {
 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;
 0353                switch (_state)
 354                {
 355                    case InflaterState.DecodeTop:
 356                        // decode an element from the literal tree
 357
 0358                        Debug.Assert(_literalLengthTree != null);
 359                        // TODO: optimize this!!!
 0360                        symbol = _literalLengthTree.GetNextSymbol(_input);
 0361                        if (symbol < 0)
 0362                        {
 363                            // running out of input
 0364                            return false;
 365                        }
 366
 0367                        if (symbol < 256)
 0368                        {
 369                            // literal
 0370                            _output.Write((byte)symbol);
 0371                            --freeBytes;
 0372                        }
 0373                        else if (symbol == 256)
 0374                        {
 375                            // end of block
 0376                            end_of_block_code_seen = true;
 377                            // Reset state
 0378                            _state = InflaterState.ReadingBFinal;
 0379                            return true;
 380                        }
 381                        else
 0382                        {
 383                            // length/distance pair
 0384                            symbol -= 257;     // length code started at 257
 0385                            if (symbol < 8)
 0386                            {
 0387                                symbol += 3;   // match length = 3,4,5,6,7,8,9,10
 0388                                _extraBits = 0;
 0389                            }
 0390                            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
 0397                            {
 0398                                if ((uint)symbol >= ExtraLengthBits.Length)
 0399                                {
 0400                                    throw new InvalidDataException(SR.GenericInvalidData);
 401                                }
 0402                                _extraBits = ExtraLengthBits[symbol];
 0403                                Debug.Assert(_extraBits != 0, "We handle other cases separately!");
 0404                            }
 0405                            _length = symbol;
 0406                            goto case InflaterState.HaveInitialLength;
 407                        }
 0408                        break;
 409
 410                    case InflaterState.HaveInitialLength:
 0411                        if (_extraBits > 0)
 0412                        {
 0413                            _state = InflaterState.HaveInitialLength;
 0414                            int bits = _input.GetBits(_extraBits);
 0415                            if (bits < 0)
 0416                            {
 0417                                return false;
 418                            }
 419
 0420                            if (_length < 0 || _length >= LengthBase.Length)
 0421                            {
 0422                                throw new InvalidDataException(SR.GenericInvalidData);
 423                            }
 0424                            _length = LengthBase[_length] + bits;
 0425                        }
 0426                        _state = InflaterState.HaveFullLength;
 0427                        goto case InflaterState.HaveFullLength;
 428
 429                    case InflaterState.HaveFullLength:
 0430                        if (_blockType == BlockType.Dynamic)
 0431                        {
 0432                            Debug.Assert(_distanceTree != null);
 0433                            _distanceCode = _distanceTree.GetNextSymbol(_input);
 0434                        }
 435                        else
 0436                        {
 437                            // get distance code directly for static block
 0438                            _distanceCode = _input.GetBits(5);
 0439                            if (_distanceCode >= 0)
 0440                            {
 0441                                _distanceCode = StaticDistanceTreeTable[_distanceCode];
 0442                            }
 0443                        }
 444
 0445                        if (_distanceCode < 0)
 0446                        {
 447                            // running out input
 0448                            return false;
 449                        }
 450
 0451                        _state = InflaterState.HaveDistCode;
 0452                        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;
 0458                        if (_distanceCode > 3)
 0459                        {
 0460                            _extraBits = (_distanceCode - 2) >> 1;
 0461                            int bits = _input.GetBits(_extraBits);
 0462                            if (bits < 0)
 0463                            {
 0464                                return false;
 465                            }
 0466                            offset = DistanceBasePosition[_distanceCode] + bits;
 0467                        }
 468                        else
 0469                        {
 0470                            offset = _distanceCode + 1;
 0471                        }
 472
 0473                        _output.WriteLengthDistance(_length, offset);
 0474                        freeBytes -= _length;
 0475                        _state = InflaterState.DecodeTop;
 0476                        break;
 477
 478                    default:
 0479                        Debug.Fail("check why we are here!");
 480                        throw new InvalidDataException(SR.UnknownState);
 481                }
 0482            }
 483
 0484            return true;
 0485        }
 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()
 0512        {
 0513            switch (_state)
 514            {
 515                case InflaterState.ReadingNumLitCodes:
 0516                    _literalLengthCodeCount = _input.GetBits(5);
 0517                    if (_literalLengthCodeCount < 0)
 0518                    {
 0519                        return false;
 520                    }
 0521                    _literalLengthCodeCount += 257;
 0522                    _state = InflaterState.ReadingNumDistCodes;
 0523                    goto case InflaterState.ReadingNumDistCodes;
 524
 525                case InflaterState.ReadingNumDistCodes:
 0526                    _distanceCodeCount = _input.GetBits(5);
 0527                    if (_distanceCodeCount < 0)
 0528                    {
 0529                        return false;
 530                    }
 0531                    _distanceCodeCount += 1;
 0532                    _state = InflaterState.ReadingNumCodeLengthCodes;
 0533                    goto case InflaterState.ReadingNumCodeLengthCodes;
 534
 535                case InflaterState.ReadingNumCodeLengthCodes:
 0536                    _codeLengthCodeCount = _input.GetBits(4);
 0537                    if (_codeLengthCodeCount < 0)
 0538                    {
 0539                        return false;
 540                    }
 0541                    _codeLengthCodeCount += 4;
 0542                    _loopCounter = 0;
 0543                    _state = InflaterState.ReadingCodeLengthCodes;
 0544                    goto case InflaterState.ReadingCodeLengthCodes;
 545
 546                case InflaterState.ReadingCodeLengthCodes:
 0547                    while (_loopCounter < _codeLengthCodeCount)
 0548                    {
 0549                        int bits = _input.GetBits(3);
 0550                        if (bits < 0)
 0551                        {
 0552                            return false;
 553                        }
 0554                        _codeLengthTreeCodeLength[CodeOrder[_loopCounter]] = (byte)bits;
 0555                        ++_loopCounter;
 0556                    }
 557
 0558                    for (int i = _codeLengthCodeCount; i < CodeOrder.Length; i++)
 0559                    {
 0560                        _codeLengthTreeCodeLength[CodeOrder[i]] = 0;
 0561                    }
 562
 563                    // create huffman tree for code length
 0564                    _codeLengthTree = new HuffmanTree(_codeLengthTreeCodeLength);
 0565                    _codeArraySize = _literalLengthCodeCount + _distanceCodeCount;
 0566                    _loopCounter = 0; // reset loop count
 567
 0568                    _state = InflaterState.ReadingTreeCodesBefore;
 0569                    goto case InflaterState.ReadingTreeCodesBefore;
 570
 571                case InflaterState.ReadingTreeCodesBefore:
 572                case InflaterState.ReadingTreeCodesAfter:
 0573                    while (_loopCounter < _codeArraySize)
 0574                    {
 0575                        if (_state == InflaterState.ReadingTreeCodesBefore)
 0576                        {
 0577                            Debug.Assert(_codeLengthTree != null);
 0578                            if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0)
 0579                            {
 0580                                return false;
 581                            }
 0582                        }
 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)
 0596                        if (_lengthCode <= 15)
 0597                        {
 0598                            _codeList[_loopCounter++] = (byte)_lengthCode;
 0599                        }
 600                        else
 0601                        {
 602                            int repeatCount;
 0603                            if (_lengthCode == 16)
 0604                            {
 0605                                if (!_input.EnsureBitsAvailable(2))
 0606                                {
 0607                                    _state = InflaterState.ReadingTreeCodesAfter;
 0608                                    return false;
 609                                }
 610
 0611                                if (_loopCounter == 0)
 0612                                {
 613                                    // can't have "prev code" on first code
 0614                                    throw new InvalidDataException();
 615                                }
 616
 0617                                byte previousCode = _codeList[_loopCounter - 1];
 0618                                repeatCount = _input.GetBits(2) + 3;
 619
 0620                                if (_loopCounter + repeatCount > _codeArraySize)
 0621                                {
 0622                                    throw new InvalidDataException();
 623                                }
 624
 0625                                _codeList.AsSpan(_loopCounter, repeatCount).Fill(previousCode);
 0626                                _loopCounter += repeatCount;
 0627                            }
 0628                            else if (_lengthCode == 17)
 0629                            {
 0630                                if (!_input.EnsureBitsAvailable(3))
 0631                                {
 0632                                    _state = InflaterState.ReadingTreeCodesAfter;
 0633                                    return false;
 634                                }
 635
 0636                                repeatCount = _input.GetBits(3) + 3;
 637
 0638                                if (_loopCounter + repeatCount > _codeArraySize)
 0639                                {
 0640                                    throw new InvalidDataException();
 641                                }
 642
 0643                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 0644                                _loopCounter += repeatCount;
 0645                            }
 646                            else
 0647                            {
 648                                // code == 18
 0649                                if (!_input.EnsureBitsAvailable(7))
 0650                                {
 0651                                    _state = InflaterState.ReadingTreeCodesAfter;
 0652                                    return false;
 653                                }
 654
 0655                                repeatCount = _input.GetBits(7) + 11;
 656
 0657                                if (_loopCounter + repeatCount > _codeArraySize)
 0658                                {
 0659                                    throw new InvalidDataException();
 660                                }
 661
 0662                                _codeList.AsSpan(_loopCounter, repeatCount).Clear();
 0663                                _loopCounter += repeatCount;
 0664                            }
 0665                        }
 0666                        _state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code.
 0667                    }
 0668                    break;
 669
 670                default:
 0671                    Debug.Fail("check why we are here!");
 672                    throw new InvalidDataException(SR.UnknownState);
 673            }
 674
 0675            byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements];
 0676            byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements];
 677
 678            // Create literal and distance tables
 0679            Array.Copy(_codeList, literalTreeCodeLength, _literalLengthCodeCount);
 0680            Array.Copy(_codeList, _literalLengthCodeCount, distanceTreeCodeLength, 0, _distanceCodeCount);
 681
 682            // Make sure there is an end-of-block code, otherwise how could we ever end?
 0683            if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0)
 0684            {
 0685                throw new InvalidDataException();
 686            }
 687
 0688            _literalLengthTree = new HuffmanTree(literalTreeCodeLength);
 0689            _distanceTree = new HuffmanTree(distanceTreeCodeLength);
 0690            _state = InflaterState.DecodeTop;
 0691            return true;
 0692        }
 693    }
 694}