< Summary

Information
Line coverage
0%
Covered lines: 0
Uncovered lines: 47
Coverable lines: 47
Total lines: 2643
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 6
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(...)0%440%
GetClass(...)100%110%
GetMethodBody(...)100%110%
GetMethodDeclaration(...)100%110%
GetMethodImplRange(...)0%220%
CheckSorted()100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/Tables.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;
 5using System.Reflection.Internal;
 6
 7namespace System.Reflection.Metadata.Ecma335
 8{
 9    internal readonly struct ModuleTableReader
 10    {
 11        internal readonly int NumberOfRows;
 12        private readonly bool _IsStringHeapRefSizeSmall;
 13        private readonly bool _IsGUIDHeapRefSizeSmall;
 14        private readonly int _GenerationOffset;
 15        private readonly int _NameOffset;
 16        private readonly int _MVIdOffset;
 17        private readonly int _EnCIdOffset;
 18        private readonly int _EnCBaseIdOffset;
 19        internal readonly int RowSize;
 20        internal readonly MemoryBlock Block;
 21
 22        internal ModuleTableReader(
 23            int numberOfRows,
 24            int stringHeapRefSize,
 25            int guidHeapRefSize,
 26            MemoryBlock containingBlock,
 27            int containingBlockOffset
 28        )
 29        {
 30            this.NumberOfRows = numberOfRows;
 31            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 32            _IsGUIDHeapRefSizeSmall = guidHeapRefSize == 2;
 33            _GenerationOffset = 0;
 34            _NameOffset = _GenerationOffset + sizeof(ushort);
 35            _MVIdOffset = _NameOffset + stringHeapRefSize;
 36            _EnCIdOffset = _MVIdOffset + guidHeapRefSize;
 37            _EnCBaseIdOffset = _EnCIdOffset + guidHeapRefSize;
 38            this.RowSize = _EnCBaseIdOffset + guidHeapRefSize;
 39            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 40        }
 41
 42        internal ushort GetGeneration()
 43        {
 44            Debug.Assert(NumberOfRows > 0);
 45            return this.Block.PeekUInt16(_GenerationOffset);
 46        }
 47
 48        internal StringHandle GetName()
 49        {
 50            Debug.Assert(NumberOfRows > 0);
 51            return StringHandle.FromOffset(this.Block.PeekHeapReference(_NameOffset, _IsStringHeapRefSizeSmall));
 52        }
 53
 54        internal GuidHandle GetMvid()
 55        {
 56            Debug.Assert(NumberOfRows > 0);
 57            return GuidHandle.FromIndex(this.Block.PeekHeapReference(_MVIdOffset, _IsGUIDHeapRefSizeSmall));
 58        }
 59
 60        internal GuidHandle GetEncId()
 61        {
 62            Debug.Assert(NumberOfRows > 0);
 63            return GuidHandle.FromIndex(this.Block.PeekHeapReference(_EnCIdOffset, _IsGUIDHeapRefSizeSmall));
 64        }
 65
 66        internal GuidHandle GetEncBaseId()
 67        {
 68            Debug.Assert(NumberOfRows > 0);
 69            return GuidHandle.FromIndex(this.Block.PeekHeapReference(_EnCBaseIdOffset, _IsGUIDHeapRefSizeSmall));
 70        }
 71    }
 72
 73    internal readonly struct TypeRefTableReader
 74    {
 75        internal readonly int NumberOfRows;
 76        private readonly bool _IsResolutionScopeRefSizeSmall;
 77        private readonly bool _IsStringHeapRefSizeSmall;
 78        private readonly int _ResolutionScopeOffset;
 79        private readonly int _NameOffset;
 80        private readonly int _NamespaceOffset;
 81        internal readonly int RowSize;
 82        internal readonly MemoryBlock Block;
 83
 84        internal TypeRefTableReader(
 85            int numberOfRows,
 86            int resolutionScopeRefSize,
 87            int stringHeapRefSize,
 88            MemoryBlock containingBlock,
 89            int containingBlockOffset
 90        )
 91        {
 92            this.NumberOfRows = numberOfRows;
 93            _IsResolutionScopeRefSizeSmall = resolutionScopeRefSize == 2;
 94            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 95            _ResolutionScopeOffset = 0;
 96            _NameOffset = _ResolutionScopeOffset + resolutionScopeRefSize;
 97            _NamespaceOffset = _NameOffset + stringHeapRefSize;
 98            this.RowSize = _NamespaceOffset + stringHeapRefSize;
 99            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 100        }
 101
 102        internal EntityHandle GetResolutionScope(TypeReferenceHandle handle)
 103        {
 104            int rowOffset = (handle.RowId - 1) * this.RowSize;
 105            return ResolutionScopeTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ResolutionScopeOffset,
 106        }
 107
 108        internal StringHandle GetName(TypeReferenceHandle handle)
 109        {
 110            int rowOffset = (handle.RowId - 1) * this.RowSize;
 111            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 112        }
 113
 114        internal StringHandle GetNamespace(TypeReferenceHandle handle)
 115        {
 116            int rowOffset = (handle.RowId - 1) * this.RowSize;
 117            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NamespaceOffset, _IsStringHeapRefSi
 118        }
 119    }
 120
 121    internal struct TypeDefTableReader
 122    {
 123        internal readonly int NumberOfRows;
 124        private readonly bool _IsFieldRefSizeSmall;
 125        private readonly bool _IsMethodRefSizeSmall;
 126        private readonly bool _IsTypeDefOrRefRefSizeSmall;
 127        private readonly bool _IsStringHeapRefSizeSmall;
 128        private readonly int _FlagsOffset;
 129        private readonly int _NameOffset;
 130        private readonly int _NamespaceOffset;
 131        private readonly int _ExtendsOffset;
 132        private readonly int _FieldListOffset;
 133        private readonly int _MethodListOffset;
 134        internal readonly int RowSize;
 135        internal MemoryBlock Block;
 136
 137        internal TypeDefTableReader(
 138            int numberOfRows,
 139            int fieldRefSize,
 140            int methodRefSize,
 141            int typeDefOrRefRefSize,
 142            int stringHeapRefSize,
 143            MemoryBlock containingBlock,
 144            int containingBlockOffset)
 145        {
 146            this.NumberOfRows = numberOfRows;
 147            _IsFieldRefSizeSmall = fieldRefSize == 2;
 148            _IsMethodRefSizeSmall = methodRefSize == 2;
 149            _IsTypeDefOrRefRefSizeSmall = typeDefOrRefRefSize == 2;
 150            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 151            _FlagsOffset = 0;
 152            _NameOffset = _FlagsOffset + sizeof(uint);
 153            _NamespaceOffset = _NameOffset + stringHeapRefSize;
 154            _ExtendsOffset = _NamespaceOffset + stringHeapRefSize;
 155            _FieldListOffset = _ExtendsOffset + typeDefOrRefRefSize;
 156            _MethodListOffset = _FieldListOffset + fieldRefSize;
 157            this.RowSize = _MethodListOffset + methodRefSize;
 158            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 159        }
 160
 161        internal TypeAttributes GetFlags(TypeDefinitionHandle handle)
 162        {
 163            int rowOffset = (handle.RowId - 1) * this.RowSize;
 164            return (TypeAttributes)this.Block.PeekUInt32(rowOffset + _FlagsOffset);
 165        }
 166
 167        internal NamespaceDefinitionHandle GetNamespaceDefinition(TypeDefinitionHandle handle)
 168        {
 169            int rowOffset = (handle.RowId - 1) * this.RowSize;
 170            return NamespaceDefinitionHandle.FromFullNameOffset(this.Block.PeekHeapReference(rowOffset + _NamespaceOffse
 171        }
 172
 173        internal StringHandle GetNamespace(TypeDefinitionHandle handle)
 174        {
 175            int rowOffset = (handle.RowId - 1) * this.RowSize;
 176            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NamespaceOffset, _IsStringHeapRefSi
 177        }
 178
 179        internal StringHandle GetName(TypeDefinitionHandle handle)
 180        {
 181            int rowOffset = (handle.RowId - 1) * this.RowSize;
 182            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 183        }
 184
 185        internal EntityHandle GetExtends(TypeDefinitionHandle handle)
 186        {
 187            int rowOffset = (handle.RowId - 1) * this.RowSize;
 188            return TypeDefOrRefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ExtendsOffset, _IsTypeDef
 189        }
 190
 191        internal int GetFieldStart(int rowId)
 192        {
 193            int rowOffset = (rowId - 1) * this.RowSize;
 194            return this.Block.PeekReference(rowOffset + _FieldListOffset, _IsFieldRefSizeSmall);
 195        }
 196
 197        internal int GetMethodStart(int rowId)
 198        {
 199            int rowOffset = (rowId - 1) * this.RowSize;
 200            return this.Block.PeekReference(rowOffset + _MethodListOffset, _IsMethodRefSizeSmall);
 201        }
 202
 203        internal TypeDefinitionHandle FindTypeContainingMethod(int methodDefOrPtrRowId, int numberOfMethods)
 204        {
 205            int numOfRows = this.NumberOfRows;
 206            int slot = this.Block.BinarySearchForSlot(numOfRows, this.RowSize, _MethodListOffset, (uint)methodDefOrPtrRo
 207            int row = slot + 1;
 208            if (row == 0)
 209            {
 210                return default(TypeDefinitionHandle);
 211            }
 212
 213            if (row > numOfRows)
 214            {
 215                if (methodDefOrPtrRowId <= numberOfMethods)
 216                {
 217                    return TypeDefinitionHandle.FromRowId(numOfRows);
 218                }
 219
 220                return default(TypeDefinitionHandle);
 221            }
 222
 223            int value = this.GetMethodStart(row);
 224            if (value == methodDefOrPtrRowId)
 225            {
 226                while (row < numOfRows)
 227                {
 228                    int newRow = row + 1;
 229                    value = this.GetMethodStart(newRow);
 230                    if (value == methodDefOrPtrRowId)
 231                    {
 232                        row = newRow;
 233                    }
 234                    else
 235                    {
 236                        break;
 237                    }
 238                }
 239            }
 240
 241            return TypeDefinitionHandle.FromRowId(row);
 242        }
 243
 244        internal TypeDefinitionHandle FindTypeContainingField(int fieldDefOrPtrRowId, int numberOfFields)
 245        {
 246            int numOfRows = this.NumberOfRows;
 247            int slot = this.Block.BinarySearchForSlot(numOfRows, this.RowSize, _FieldListOffset, (uint)fieldDefOrPtrRowI
 248            int row = slot + 1;
 249            if (row == 0)
 250            {
 251                return default(TypeDefinitionHandle);
 252            }
 253
 254            if (row > numOfRows)
 255            {
 256                if (fieldDefOrPtrRowId <= numberOfFields)
 257                {
 258                    return TypeDefinitionHandle.FromRowId(numOfRows);
 259                }
 260
 261                return default(TypeDefinitionHandle);
 262            }
 263
 264            int value = this.GetFieldStart(row);
 265            if (value == fieldDefOrPtrRowId)
 266            {
 267                while (row < numOfRows)
 268                {
 269                    int newRow = row + 1;
 270                    value = this.GetFieldStart(newRow);
 271                    if (value == fieldDefOrPtrRowId)
 272                    {
 273                        row = newRow;
 274                    }
 275                    else
 276                    {
 277                        break;
 278                    }
 279                }
 280            }
 281
 282            return TypeDefinitionHandle.FromRowId(row);
 283        }
 284    }
 285
 286    internal readonly struct FieldPtrTableReader
 287    {
 288        internal readonly int NumberOfRows;
 289        private readonly bool _IsFieldTableRowRefSizeSmall;
 290        private readonly int _FieldOffset;
 291        internal readonly int RowSize;
 292        internal readonly MemoryBlock Block;
 293
 294        internal FieldPtrTableReader(
 295            int numberOfRows,
 296            int fieldTableRowRefSize,
 297            MemoryBlock containingBlock,
 298            int containingBlockOffset
 299        )
 300        {
 301            this.NumberOfRows = numberOfRows;
 302            _IsFieldTableRowRefSizeSmall = fieldTableRowRefSize == 2;
 303            _FieldOffset = 0;
 304            this.RowSize = _FieldOffset + fieldTableRowRefSize;
 305            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 306        }
 307
 308        internal FieldDefinitionHandle GetFieldFor(int rowId)
 309        {
 310            int rowOffset = (rowId - 1) * this.RowSize;
 311            return FieldDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _FieldOffset, _IsFieldTableRowRe
 312        }
 313
 314        internal int GetRowIdForFieldDefRow(int fieldDefRowId)
 315        {
 316            return this.Block.LinearSearchReference(this.RowSize, _FieldOffset, (uint)fieldDefRowId, _IsFieldTableRowRef
 317        }
 318    }
 319
 320    internal readonly struct FieldTableReader
 321    {
 322        internal readonly int NumberOfRows;
 323        private readonly bool _IsStringHeapRefSizeSmall;
 324        private readonly bool _IsBlobHeapRefSizeSmall;
 325        private readonly int _FlagsOffset;
 326        private readonly int _NameOffset;
 327        private readonly int _SignatureOffset;
 328        internal readonly int RowSize;
 329        internal readonly MemoryBlock Block;
 330
 331        internal FieldTableReader(
 332            int numberOfRows,
 333            int stringHeapRefSize,
 334            int blobHeapRefSize,
 335            MemoryBlock containingBlock,
 336            int containingBlockOffset
 337        )
 338        {
 339            this.NumberOfRows = numberOfRows;
 340            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 341            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 342            _FlagsOffset = 0;
 343            _NameOffset = _FlagsOffset + sizeof(ushort);
 344            _SignatureOffset = _NameOffset + stringHeapRefSize;
 345            this.RowSize = _SignatureOffset + blobHeapRefSize;
 346            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 347        }
 348
 349        internal StringHandle GetName(FieldDefinitionHandle handle)
 350        {
 351            int rowOffset = (handle.RowId - 1) * this.RowSize;
 352            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 353        }
 354
 355        internal FieldAttributes GetFlags(FieldDefinitionHandle handle)
 356        {
 357            int rowOffset = (handle.RowId - 1) * this.RowSize;
 358            return (FieldAttributes)this.Block.PeekUInt16(rowOffset + _FlagsOffset);
 359        }
 360
 361        internal BlobHandle GetSignature(FieldDefinitionHandle handle)
 362        {
 363            int rowOffset = (handle.RowId - 1) * this.RowSize;
 364            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _SignatureOffset, _IsBlobHeapRefSizeSm
 365        }
 366    }
 367
 368    internal readonly struct MethodPtrTableReader
 369    {
 370        internal readonly int NumberOfRows;
 371        private readonly bool _IsMethodTableRowRefSizeSmall;
 372        private readonly int _MethodOffset;
 373        internal readonly int RowSize;
 374        internal readonly MemoryBlock Block;
 375
 376        internal MethodPtrTableReader(
 377            int numberOfRows,
 378            int methodTableRowRefSize,
 379            MemoryBlock containingBlock,
 380            int containingBlockOffset
 381        )
 382        {
 383            this.NumberOfRows = numberOfRows;
 384            _IsMethodTableRowRefSizeSmall = methodTableRowRefSize == 2;
 385            _MethodOffset = 0;
 386            this.RowSize = _MethodOffset + methodTableRowRefSize;
 387            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 388        }
 389
 390        // returns a rid
 391        internal MethodDefinitionHandle GetMethodFor(int rowId)
 392        {
 393            int rowOffset = (rowId - 1) * this.RowSize;
 394            return MethodDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _MethodOffset, _IsMethodTableRo
 395        }
 396
 397        internal int GetRowIdForMethodDefRow(int methodDefRowId)
 398        {
 399            return this.Block.LinearSearchReference(this.RowSize, _MethodOffset, (uint)methodDefRowId, _IsMethodTableRow
 400        }
 401    }
 402
 403    internal readonly struct MethodTableReader
 404    {
 405        internal readonly int NumberOfRows;
 406        private readonly bool _IsParamRefSizeSmall;
 407        private readonly bool _IsStringHeapRefSizeSmall;
 408        private readonly bool _IsBlobHeapRefSizeSmall;
 409        private readonly int _RvaOffset;
 410        private readonly int _ImplFlagsOffset;
 411        private readonly int _FlagsOffset;
 412        private readonly int _NameOffset;
 413        private readonly int _SignatureOffset;
 414        private readonly int _ParamListOffset;
 415        internal readonly int RowSize;
 416        internal readonly MemoryBlock Block;
 417
 418        internal MethodTableReader(
 419            int numberOfRows,
 420            int paramRefSize,
 421            int stringHeapRefSize,
 422            int blobHeapRefSize,
 423            MemoryBlock containingBlock,
 424            int containingBlockOffset
 425        )
 426        {
 427            this.NumberOfRows = numberOfRows;
 428            _IsParamRefSizeSmall = paramRefSize == 2;
 429            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 430            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 431            _RvaOffset = 0;
 432            _ImplFlagsOffset = _RvaOffset + sizeof(uint);
 433            _FlagsOffset = _ImplFlagsOffset + sizeof(ushort);
 434            _NameOffset = _FlagsOffset + sizeof(ushort);
 435            _SignatureOffset = _NameOffset + stringHeapRefSize;
 436            _ParamListOffset = _SignatureOffset + blobHeapRefSize;
 437            this.RowSize = _ParamListOffset + paramRefSize;
 438            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 439        }
 440
 441        internal int GetParamStart(int rowId)
 442        {
 443            int rowOffset = (rowId - 1) * this.RowSize;
 444            return this.Block.PeekReference(rowOffset + _ParamListOffset, _IsParamRefSizeSmall);
 445        }
 446
 447        internal BlobHandle GetSignature(MethodDefinitionHandle handle)
 448        {
 449            int rowOffset = (handle.RowId - 1) * this.RowSize;
 450            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _SignatureOffset, _IsBlobHeapRefSizeSm
 451        }
 452
 453        internal int GetRva(MethodDefinitionHandle handle)
 454        {
 455            int rowOffset = (handle.RowId - 1) * this.RowSize;
 456            return this.Block.PeekInt32(rowOffset + _RvaOffset);
 457        }
 458
 459        internal StringHandle GetName(MethodDefinitionHandle handle)
 460        {
 461            int rowOffset = (handle.RowId - 1) * this.RowSize;
 462            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 463        }
 464
 465        internal MethodAttributes GetFlags(MethodDefinitionHandle handle)
 466        {
 467            int rowOffset = (handle.RowId - 1) * this.RowSize;
 468            return (MethodAttributes)this.Block.PeekUInt16(rowOffset + _FlagsOffset);
 469        }
 470
 471        internal MethodImplAttributes GetImplFlags(MethodDefinitionHandle handle)
 472        {
 473            int rowOffset = (handle.RowId - 1) * this.RowSize;
 474            return (MethodImplAttributes)this.Block.PeekUInt16(rowOffset + _ImplFlagsOffset);
 475        }
 476    }
 477
 478    internal readonly struct ParamPtrTableReader
 479    {
 480        internal readonly int NumberOfRows;
 481        private readonly bool _IsParamTableRowRefSizeSmall;
 482        private readonly int _ParamOffset;
 483        internal readonly int RowSize;
 484        internal readonly MemoryBlock Block;
 485
 486        internal ParamPtrTableReader(
 487            int numberOfRows,
 488            int paramTableRowRefSize,
 489            MemoryBlock containingBlock,
 490            int containingBlockOffset
 491        )
 492        {
 493            this.NumberOfRows = numberOfRows;
 494            _IsParamTableRowRefSizeSmall = paramTableRowRefSize == 2;
 495            _ParamOffset = 0;
 496            this.RowSize = _ParamOffset + paramTableRowRefSize;
 497            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 498        }
 499
 500        internal ParameterHandle GetParamFor(int rowId)
 501        {
 502            int rowOffset = (rowId - 1) * this.RowSize;
 503            return ParameterHandle.FromRowId(this.Block.PeekReference(rowOffset + _ParamOffset, _IsParamTableRowRefSizeS
 504        }
 505    }
 506
 507    internal readonly struct ParamTableReader
 508    {
 509        internal readonly int NumberOfRows;
 510        private readonly bool _IsStringHeapRefSizeSmall;
 511        private readonly int _FlagsOffset;
 512        private readonly int _SequenceOffset;
 513        private readonly int _NameOffset;
 514        internal readonly int RowSize;
 515        internal readonly MemoryBlock Block;
 516
 517        internal ParamTableReader(
 518            int numberOfRows,
 519            int stringHeapRefSize,
 520            MemoryBlock containingBlock,
 521            int containingBlockOffset
 522        )
 523        {
 524            this.NumberOfRows = numberOfRows;
 525            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 526            _FlagsOffset = 0;
 527            _SequenceOffset = _FlagsOffset + sizeof(ushort);
 528            _NameOffset = _SequenceOffset + sizeof(ushort);
 529            this.RowSize = _NameOffset + stringHeapRefSize;
 530            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 531        }
 532
 533        internal ParameterAttributes GetFlags(ParameterHandle handle)
 534        {
 535            int rowOffset = (handle.RowId - 1) * this.RowSize;
 536            return (ParameterAttributes)this.Block.PeekUInt16(rowOffset + _FlagsOffset);
 537        }
 538
 539        internal ushort GetSequence(ParameterHandle handle)
 540        {
 541            int rowOffset = (handle.RowId - 1) * this.RowSize;
 542            return this.Block.PeekUInt16(rowOffset + _SequenceOffset);
 543        }
 544
 545        internal StringHandle GetName(ParameterHandle handle)
 546        {
 547            int rowOffset = (handle.RowId - 1) * this.RowSize;
 548            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 549        }
 550    }
 551
 552    internal readonly struct InterfaceImplTableReader
 553    {
 554        internal readonly int NumberOfRows;
 555        private readonly bool _IsTypeDefTableRowRefSizeSmall;
 556        private readonly bool _IsTypeDefOrRefRefSizeSmall;
 557        private readonly int _ClassOffset;
 558        private readonly int _InterfaceOffset;
 559        internal readonly int RowSize;
 560        internal readonly MemoryBlock Block;
 561
 562        internal InterfaceImplTableReader(
 563            int numberOfRows,
 564            bool declaredSorted,
 565            int typeDefTableRowRefSize,
 566            int typeDefOrRefRefSize,
 567            MemoryBlock containingBlock,
 568            int containingBlockOffset
 569        )
 570        {
 571            this.NumberOfRows = numberOfRows;
 572            _IsTypeDefTableRowRefSizeSmall = typeDefTableRowRefSize == 2;
 573            _IsTypeDefOrRefRefSizeSmall = typeDefOrRefRefSize == 2;
 574            _ClassOffset = 0;
 575            _InterfaceOffset = _ClassOffset + typeDefTableRowRefSize;
 576            this.RowSize = _InterfaceOffset + typeDefOrRefRefSize;
 577            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 578
 579            if (!declaredSorted && !CheckSorted())
 580            {
 581                Throw.TableNotSorted(TableIndex.InterfaceImpl);
 582            }
 583        }
 584
 585        private bool CheckSorted()
 586        {
 587            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _ClassOffset, _IsTypeDefTableRowRefSizeSmall);
 588        }
 589
 590        internal void GetInterfaceImplRange(
 591            TypeDefinitionHandle typeDef,
 592            out int firstImplRowId,
 593            out int lastImplRowId)
 594        {
 595            int typeDefRid = typeDef.RowId;
 596
 597            int startRowNumber, endRowNumber;
 598            this.Block.BinarySearchReferenceRange(
 599                this.NumberOfRows,
 600                this.RowSize,
 601                _ClassOffset,
 602                (uint)typeDefRid,
 603                _IsTypeDefTableRowRefSizeSmall,
 604                out startRowNumber,
 605                out endRowNumber);
 606
 607            if (startRowNumber == -1)
 608            {
 609                firstImplRowId = 1;
 610                lastImplRowId = 0;
 611            }
 612            else
 613            {
 614                firstImplRowId = startRowNumber + 1;
 615                lastImplRowId = endRowNumber + 1;
 616            }
 617        }
 618
 619        internal EntityHandle GetInterface(int rowId)
 620        {
 621            int rowOffset = (rowId - 1) * this.RowSize;
 622            return TypeDefOrRefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _InterfaceOffset, _IsTypeD
 623        }
 624    }
 625
 626    internal struct MemberRefTableReader
 627    {
 628        internal int NumberOfRows;
 629        private readonly bool _IsMemberRefParentRefSizeSmall;
 630        private readonly bool _IsStringHeapRefSizeSmall;
 631        private readonly bool _IsBlobHeapRefSizeSmall;
 632        private readonly int _ClassOffset;
 633        private readonly int _NameOffset;
 634        private readonly int _SignatureOffset;
 635        internal readonly int RowSize;
 636        internal MemoryBlock Block;
 637
 638        internal MemberRefTableReader(
 639            int numberOfRows,
 640            int memberRefParentRefSize,
 641            int stringHeapRefSize,
 642            int blobHeapRefSize,
 643            MemoryBlock containingBlock,
 644            int containingBlockOffset
 645        )
 646        {
 647            this.NumberOfRows = numberOfRows;
 648            _IsMemberRefParentRefSizeSmall = memberRefParentRefSize == 2;
 649            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 650            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 651            _ClassOffset = 0;
 652            _NameOffset = _ClassOffset + memberRefParentRefSize;
 653            _SignatureOffset = _NameOffset + stringHeapRefSize;
 654            this.RowSize = _SignatureOffset + blobHeapRefSize;
 655            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 656        }
 657
 658        internal BlobHandle GetSignature(MemberReferenceHandle handle)
 659        {
 660            int rowOffset = (handle.RowId - 1) * this.RowSize;
 661            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _SignatureOffset, _IsBlobHeapRefSizeSm
 662        }
 663
 664        internal StringHandle GetName(MemberReferenceHandle handle)
 665        {
 666            int rowOffset = (handle.RowId - 1) * this.RowSize;
 667            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 668        }
 669
 670        internal EntityHandle GetClass(MemberReferenceHandle handle)
 671        {
 672            int rowOffset = (handle.RowId - 1) * this.RowSize;
 673            return MemberRefParentTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ClassOffset, _IsMember
 674        }
 675    }
 676
 677    internal readonly struct ConstantTableReader
 678    {
 679        internal readonly int NumberOfRows;
 680        private readonly bool _IsHasConstantRefSizeSmall;
 681        private readonly bool _IsBlobHeapRefSizeSmall;
 682        private readonly int _TypeOffset;
 683        private readonly int _ParentOffset;
 684        private readonly int _ValueOffset;
 685        internal readonly int RowSize;
 686        internal readonly MemoryBlock Block;
 687
 688        internal ConstantTableReader(
 689            int numberOfRows,
 690            bool declaredSorted,
 691            int hasConstantRefSize,
 692            int blobHeapRefSize,
 693            MemoryBlock containingBlock,
 694            int containingBlockOffset
 695        )
 696        {
 697            this.NumberOfRows = numberOfRows;
 698            _IsHasConstantRefSizeSmall = hasConstantRefSize == 2;
 699            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 700            _TypeOffset = 0;
 701            _ParentOffset = _TypeOffset + sizeof(byte) + 1; // Alignment here (+1)...
 702            _ValueOffset = _ParentOffset + hasConstantRefSize;
 703            this.RowSize = _ValueOffset + blobHeapRefSize;
 704            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 705
 706            if (!declaredSorted && !CheckSorted())
 707            {
 708                Throw.TableNotSorted(TableIndex.Constant);
 709            }
 710        }
 711
 712        internal ConstantTypeCode GetType(ConstantHandle handle)
 713        {
 714            int rowOffset = (handle.RowId - 1) * this.RowSize;
 715            return (ConstantTypeCode)this.Block.PeekByte(rowOffset + _TypeOffset);
 716        }
 717
 718        internal BlobHandle GetValue(ConstantHandle handle)
 719        {
 720            int rowOffset = (handle.RowId - 1) * this.RowSize;
 721            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _ValueOffset, _IsBlobHeapRefSizeSmall)
 722        }
 723
 724        internal EntityHandle GetParent(ConstantHandle handle)
 725        {
 726            int rowOffset = (handle.RowId - 1) * this.RowSize;
 727            return HasConstantTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ParentOffset, _IsHasConsta
 728        }
 729
 730        internal ConstantHandle FindConstant(EntityHandle parentHandle)
 731        {
 732            int foundRowNumber =
 733              this.Block.BinarySearchReference(
 734                this.NumberOfRows,
 735                this.RowSize,
 736                _ParentOffset,
 737                HasConstantTag.ConvertToTag(parentHandle),
 738                _IsHasConstantRefSizeSmall);
 739
 740            return ConstantHandle.FromRowId(foundRowNumber + 1);
 741        }
 742
 743        private bool CheckSorted()
 744        {
 745            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _ParentOffset, _IsHasConstantRefSizeSmall);
 746        }
 747    }
 748
 749    internal readonly struct CustomAttributeTableReader
 750    {
 751        internal readonly int NumberOfRows;
 752        private readonly bool _IsHasCustomAttributeRefSizeSmall;
 753        private readonly bool _IsCustomAttributeTypeRefSizeSmall;
 754        private readonly bool _IsBlobHeapRefSizeSmall;
 755        private readonly int _ParentOffset;
 756        private readonly int _TypeOffset;
 757        private readonly int _ValueOffset;
 758        internal readonly int RowSize;
 759        internal readonly MemoryBlock Block;
 760
 761        // row ids in the CustomAttribute table sorted by parents
 762        internal readonly int[]? PtrTable;
 763
 764        internal CustomAttributeTableReader(
 765            int numberOfRows,
 766            bool declaredSorted,
 767            int hasCustomAttributeRefSize,
 768            int customAttributeTypeRefSize,
 769            int blobHeapRefSize,
 770            MemoryBlock containingBlock,
 771            int containingBlockOffset
 772        )
 773        {
 774            this.NumberOfRows = numberOfRows;
 775            _IsHasCustomAttributeRefSizeSmall = hasCustomAttributeRefSize == 2;
 776            _IsCustomAttributeTypeRefSizeSmall = customAttributeTypeRefSize == 2;
 777            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 778            _ParentOffset = 0;
 779            _TypeOffset = _ParentOffset + hasCustomAttributeRefSize;
 780            _ValueOffset = _TypeOffset + customAttributeTypeRefSize;
 781            this.RowSize = _ValueOffset + blobHeapRefSize;
 782            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 783            this.PtrTable = null;
 784
 785            if (!declaredSorted && !CheckSorted())
 786            {
 787                this.PtrTable = this.Block.BuildPtrTable(
 788                    numberOfRows,
 789                    this.RowSize,
 790                    _ParentOffset,
 791                    _IsHasCustomAttributeRefSizeSmall);
 792            }
 793        }
 794
 795        internal EntityHandle GetParent(CustomAttributeHandle handle)
 796        {
 797            int rowOffset = (handle.RowId - 1) * this.RowSize;
 798            return HasCustomAttributeTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ParentOffset, _IsHa
 799        }
 800
 801        internal EntityHandle GetConstructor(CustomAttributeHandle handle)
 802        {
 803            int rowOffset = (handle.RowId - 1) * this.RowSize;
 804            return CustomAttributeTypeTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _TypeOffset, _IsCus
 805        }
 806
 807        internal BlobHandle GetValue(CustomAttributeHandle handle)
 808        {
 809            int rowOffset = (handle.RowId - 1) * this.RowSize;
 810            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _ValueOffset, _IsBlobHeapRefSizeSmall)
 811        }
 812
 813        internal void GetAttributeRange(EntityHandle parentHandle, out int firstImplRowId, out int lastImplRowId)
 814        {
 815            int startRowNumber, endRowNumber;
 816
 817            if (this.PtrTable != null)
 818            {
 819                this.Block.BinarySearchReferenceRange(
 820                    this.PtrTable,
 821                    this.RowSize,
 822                    _ParentOffset,
 823                    HasCustomAttributeTag.ConvertToTag(parentHandle),
 824                    _IsHasCustomAttributeRefSizeSmall,
 825                    out startRowNumber,
 826                    out endRowNumber
 827                );
 828            }
 829            else
 830            {
 831                this.Block.BinarySearchReferenceRange(
 832                    this.NumberOfRows,
 833                    this.RowSize,
 834                    _ParentOffset,
 835                    HasCustomAttributeTag.ConvertToTag(parentHandle),
 836                    _IsHasCustomAttributeRefSizeSmall,
 837                    out startRowNumber,
 838                    out endRowNumber
 839                );
 840            }
 841
 842            if (startRowNumber == -1)
 843            {
 844                firstImplRowId = 1;
 845                lastImplRowId = 0;
 846            }
 847            else
 848            {
 849                firstImplRowId = startRowNumber + 1;
 850                lastImplRowId = endRowNumber + 1;
 851            }
 852        }
 853
 854        private bool CheckSorted()
 855        {
 856            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _ParentOffset, _IsHasCustomAttributeRefSizeSma
 857        }
 858    }
 859
 860    internal readonly struct FieldMarshalTableReader
 861    {
 862        internal readonly int NumberOfRows;
 863        private readonly bool _IsHasFieldMarshalRefSizeSmall;
 864        private readonly bool _IsBlobHeapRefSizeSmall;
 865        private readonly int _ParentOffset;
 866        private readonly int _NativeTypeOffset;
 867        internal readonly int RowSize;
 868        internal readonly MemoryBlock Block;
 869
 870        internal FieldMarshalTableReader(
 871            int numberOfRows,
 872            bool declaredSorted,
 873            int hasFieldMarshalRefSize,
 874            int blobHeapRefSize,
 875            MemoryBlock containingBlock,
 876            int containingBlockOffset
 877        )
 878        {
 879            this.NumberOfRows = numberOfRows;
 880            _IsHasFieldMarshalRefSizeSmall = hasFieldMarshalRefSize == 2;
 881            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 882            _ParentOffset = 0;
 883            _NativeTypeOffset = _ParentOffset + hasFieldMarshalRefSize;
 884            this.RowSize = _NativeTypeOffset + blobHeapRefSize;
 885            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 886
 887            if (!declaredSorted && !CheckSorted())
 888            {
 889                Throw.TableNotSorted(TableIndex.FieldMarshal);
 890            }
 891        }
 892
 893        internal EntityHandle GetParent(int rowId)
 894        {
 895            int rowOffset = (rowId - 1) * this.RowSize;
 896            return HasFieldMarshalTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ParentOffset, _IsHasFi
 897        }
 898
 899        internal BlobHandle GetNativeType(int rowId)
 900        {
 901            int rowOffset = (rowId - 1) * this.RowSize;
 902            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NativeTypeOffset, _IsBlobHeapRefSizeS
 903        }
 904
 905        internal int FindFieldMarshalRowId(EntityHandle handle)
 906        {
 907            int foundRowNumber =
 908              this.Block.BinarySearchReference(
 909                this.NumberOfRows,
 910                this.RowSize,
 911                _ParentOffset,
 912                HasFieldMarshalTag.ConvertToTag(handle),
 913                _IsHasFieldMarshalRefSizeSmall);
 914
 915            return foundRowNumber + 1;
 916        }
 917
 918        private bool CheckSorted()
 919        {
 920            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _ParentOffset, _IsHasFieldMarshalRefSizeSmall)
 921        }
 922    }
 923
 924    internal readonly struct DeclSecurityTableReader
 925    {
 926        internal readonly int NumberOfRows;
 927        private readonly bool _IsHasDeclSecurityRefSizeSmall;
 928        private readonly bool _IsBlobHeapRefSizeSmall;
 929        private readonly int _ActionOffset;
 930        private readonly int _ParentOffset;
 931        private readonly int _PermissionSetOffset;
 932        internal readonly int RowSize;
 933        internal readonly MemoryBlock Block;
 934
 935        internal DeclSecurityTableReader(
 936            int numberOfRows,
 937            bool declaredSorted,
 938            int hasDeclSecurityRefSize,
 939            int blobHeapRefSize,
 940            MemoryBlock containingBlock,
 941            int containingBlockOffset
 942        )
 943        {
 944            this.NumberOfRows = numberOfRows;
 945            _IsHasDeclSecurityRefSizeSmall = hasDeclSecurityRefSize == 2;
 946            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 947            _ActionOffset = 0;
 948            _ParentOffset = _ActionOffset + sizeof(ushort);
 949            _PermissionSetOffset = _ParentOffset + hasDeclSecurityRefSize;
 950            this.RowSize = _PermissionSetOffset + blobHeapRefSize;
 951            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 952
 953            if (!declaredSorted && !CheckSorted())
 954            {
 955                Throw.TableNotSorted(TableIndex.DeclSecurity);
 956            }
 957        }
 958
 959        internal DeclarativeSecurityAction GetAction(int rowId)
 960        {
 961            int rowOffset = (rowId - 1) * this.RowSize;
 962            return (DeclarativeSecurityAction)this.Block.PeekUInt16(rowOffset + _ActionOffset);
 963        }
 964
 965        internal EntityHandle GetParent(int rowId)
 966        {
 967            int rowOffset = (rowId - 1) * this.RowSize;
 968            return HasDeclSecurityTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ParentOffset, _IsHasDe
 969        }
 970
 971        internal BlobHandle GetPermissionSet(int rowId)
 972        {
 973            int rowOffset = (rowId - 1) * this.RowSize;
 974            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _PermissionSetOffset, _IsBlobHeapRefSi
 975        }
 976
 977        internal void GetAttributeRange(EntityHandle parentToken, out int firstImplRowId, out int lastImplRowId)
 978        {
 979            int startRowNumber, endRowNumber;
 980
 981            this.Block.BinarySearchReferenceRange(
 982                this.NumberOfRows,
 983                this.RowSize,
 984                _ParentOffset,
 985                HasDeclSecurityTag.ConvertToTag(parentToken),
 986                _IsHasDeclSecurityRefSizeSmall,
 987                out startRowNumber,
 988                out endRowNumber);
 989
 990            if (startRowNumber == -1)
 991            {
 992                firstImplRowId = 1;
 993                lastImplRowId = 0;
 994            }
 995            else
 996            {
 997                firstImplRowId = startRowNumber + 1;
 998                lastImplRowId = endRowNumber + 1;
 999            }
 1000        }
 1001
 1002        private bool CheckSorted()
 1003        {
 1004            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _ParentOffset, _IsHasDeclSecurityRefSizeSmall)
 1005        }
 1006    }
 1007
 1008    internal struct ClassLayoutTableReader
 1009    {
 1010        internal int NumberOfRows;
 1011        private readonly bool _IsTypeDefTableRowRefSizeSmall;
 1012        private readonly int _PackagingSizeOffset;
 1013        private readonly int _ClassSizeOffset;
 1014        private readonly int _ParentOffset;
 1015        internal readonly int RowSize;
 1016        internal MemoryBlock Block;
 1017
 1018        internal ClassLayoutTableReader(
 1019            int numberOfRows,
 1020            bool declaredSorted,
 1021            int typeDefTableRowRefSize,
 1022            MemoryBlock containingBlock,
 1023            int containingBlockOffset)
 1024        {
 1025            this.NumberOfRows = numberOfRows;
 1026            _IsTypeDefTableRowRefSizeSmall = typeDefTableRowRefSize == 2;
 1027            _PackagingSizeOffset = 0;
 1028            _ClassSizeOffset = _PackagingSizeOffset + sizeof(ushort);
 1029            _ParentOffset = _ClassSizeOffset + sizeof(uint);
 1030            this.RowSize = _ParentOffset + typeDefTableRowRefSize;
 1031            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1032
 1033            if (!declaredSorted && !CheckSorted())
 1034            {
 1035                Throw.TableNotSorted(TableIndex.ClassLayout);
 1036            }
 1037        }
 1038
 1039        internal TypeDefinitionHandle GetParent(int rowId)
 1040        {
 1041            int rowOffset = (rowId - 1) * this.RowSize;
 1042            return TypeDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _ParentOffset, _IsTypeDefTableRow
 1043        }
 1044
 1045        internal ushort GetPackingSize(int rowId)
 1046        {
 1047            int rowOffset = (rowId - 1) * this.RowSize;
 1048            return this.Block.PeekUInt16(rowOffset + _PackagingSizeOffset);
 1049        }
 1050
 1051        internal uint GetClassSize(int rowId)
 1052        {
 1053            int rowOffset = (rowId - 1) * this.RowSize;
 1054            return this.Block.PeekUInt32(rowOffset + _ClassSizeOffset);
 1055        }
 1056
 1057        // Returns RowId (0 means we there is no record in this table corresponding to the specified type).
 1058        internal int FindRow(TypeDefinitionHandle typeDef)
 1059        {
 1060            return 1 + this.Block.BinarySearchReference(
 1061                this.NumberOfRows,
 1062                this.RowSize,
 1063                _ParentOffset,
 1064                (uint)typeDef.RowId,
 1065                _IsTypeDefTableRowRefSizeSmall);
 1066        }
 1067
 1068        private bool CheckSorted()
 1069        {
 1070            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _ParentOffset, _IsTypeDefTableRowRefSizeSmall)
 1071        }
 1072    }
 1073
 1074    internal readonly struct FieldLayoutTableReader
 1075    {
 1076        internal readonly int NumberOfRows;
 1077        private readonly bool _IsFieldTableRowRefSizeSmall;
 1078        private readonly int _OffsetOffset;
 1079        private readonly int _FieldOffset;
 1080        internal readonly int RowSize;
 1081        internal readonly MemoryBlock Block;
 1082
 1083        internal FieldLayoutTableReader(
 1084            int numberOfRows,
 1085            bool declaredSorted,
 1086            int fieldTableRowRefSize,
 1087            MemoryBlock containingBlock,
 1088            int containingBlockOffset)
 1089        {
 1090            this.NumberOfRows = numberOfRows;
 1091            _IsFieldTableRowRefSizeSmall = fieldTableRowRefSize == 2;
 1092            _OffsetOffset = 0;
 1093            _FieldOffset = _OffsetOffset + sizeof(uint);
 1094            this.RowSize = _FieldOffset + fieldTableRowRefSize;
 1095            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1096
 1097            if (!declaredSorted && !CheckSorted())
 1098            {
 1099                Throw.TableNotSorted(TableIndex.FieldLayout);
 1100            }
 1101        }
 1102
 1103        /// <summary>
 1104        /// Returns field offset for given field RowId, or -1 if not available.
 1105        /// </summary>
 1106        internal int FindFieldLayoutRowId(FieldDefinitionHandle handle)
 1107        {
 1108            int rowNumber =
 1109              this.Block.BinarySearchReference(
 1110                this.NumberOfRows,
 1111                this.RowSize,
 1112                _FieldOffset,
 1113                (uint)handle.RowId,
 1114                _IsFieldTableRowRefSizeSmall);
 1115
 1116            return rowNumber + 1;
 1117        }
 1118
 1119        internal uint GetOffset(int rowId)
 1120        {
 1121            int rowOffset = (rowId - 1) * this.RowSize;
 1122            return this.Block.PeekUInt32(rowOffset + _OffsetOffset);
 1123        }
 1124
 1125        internal FieldDefinitionHandle GetField(int rowId)
 1126        {
 1127            int rowOffset = (rowId - 1) * this.RowSize;
 1128            return FieldDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _FieldOffset, _IsFieldTableRowRe
 1129        }
 1130
 1131        private bool CheckSorted()
 1132        {
 1133            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _FieldOffset, _IsFieldTableRowRefSizeSmall);
 1134        }
 1135    }
 1136
 1137    internal readonly struct StandAloneSigTableReader
 1138    {
 1139        internal readonly int NumberOfRows;
 1140        private readonly bool _IsBlobHeapRefSizeSmall;
 1141        private readonly int _SignatureOffset;
 1142        internal readonly int RowSize;
 1143        internal readonly MemoryBlock Block;
 1144
 1145        internal StandAloneSigTableReader(
 1146            int numberOfRows,
 1147            int blobHeapRefSize,
 1148            MemoryBlock containingBlock,
 1149            int containingBlockOffset)
 1150        {
 1151            this.NumberOfRows = numberOfRows;
 1152            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 1153            _SignatureOffset = 0;
 1154            this.RowSize = _SignatureOffset + blobHeapRefSize;
 1155            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1156        }
 1157
 1158        internal BlobHandle GetSignature(int rowId)
 1159        {
 1160            int rowOffset = (rowId - 1) * this.RowSize;
 1161            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _SignatureOffset, _IsBlobHeapRefSizeSm
 1162        }
 1163    }
 1164
 1165    internal readonly struct EventMapTableReader
 1166    {
 1167        internal readonly int NumberOfRows;
 1168        private readonly bool _IsTypeDefTableRowRefSizeSmall;
 1169        private readonly bool _IsEventRefSizeSmall;
 1170        private readonly int _ParentOffset;
 1171        private readonly int _EventListOffset;
 1172        internal readonly int RowSize;
 1173        internal readonly MemoryBlock Block;
 1174
 1175        internal EventMapTableReader(
 1176            int numberOfRows,
 1177            int typeDefTableRowRefSize,
 1178            int eventRefSize,
 1179            MemoryBlock containingBlock,
 1180            int containingBlockOffset)
 1181        {
 1182            this.NumberOfRows = numberOfRows;
 1183            _IsTypeDefTableRowRefSizeSmall = typeDefTableRowRefSize == 2;
 1184            _IsEventRefSizeSmall = eventRefSize == 2;
 1185            _ParentOffset = 0;
 1186            _EventListOffset = _ParentOffset + typeDefTableRowRefSize;
 1187            this.RowSize = _EventListOffset + eventRefSize;
 1188            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1189        }
 1190
 1191        internal int FindEventMapRowIdFor(TypeDefinitionHandle typeDef)
 1192        {
 1193            // We do a linear scan here because we don't have these tables sorted
 1194            // TODO: We can scan the table to see if it is sorted and use binary search if so.
 1195            // Also, the compilers should make sure it's sorted.
 1196            int rowNumber = this.Block.LinearSearchReference(
 1197                this.RowSize,
 1198                _ParentOffset,
 1199                (uint)typeDef.RowId,
 1200                _IsTypeDefTableRowRefSizeSmall);
 1201
 1202            return rowNumber + 1;
 1203        }
 1204
 1205        internal TypeDefinitionHandle GetParentType(int rowId)
 1206        {
 1207            int rowOffset = (rowId - 1) * this.RowSize;
 1208            return TypeDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _ParentOffset, _IsTypeDefTableRow
 1209        }
 1210
 1211        internal int GetEventListStartFor(int rowId)
 1212        {
 1213            int rowOffset = (rowId - 1) * this.RowSize;
 1214            return this.Block.PeekReference(rowOffset + _EventListOffset, _IsEventRefSizeSmall);
 1215        }
 1216
 1217        internal TypeDefinitionHandle FindTypeContainingEvent(int eventRowId, int numberOfEvents)
 1218        {
 1219            int numOfRows = this.NumberOfRows;
 1220            int slot = this.Block.BinarySearchForSlot(numOfRows, this.RowSize, _EventListOffset, (uint)eventRowId, _IsEv
 1221            int row = slot + 1;
 1222            if (row == 0)
 1223            {
 1224                return default(TypeDefinitionHandle);
 1225            }
 1226
 1227            if (row > numOfRows)
 1228            {
 1229                if (eventRowId <= numberOfEvents)
 1230                {
 1231                    return GetParentType(numOfRows);
 1232                }
 1233
 1234                return default(TypeDefinitionHandle);
 1235            }
 1236
 1237            return GetParentType(row);
 1238        }
 1239    }
 1240
 1241    internal readonly struct EventPtrTableReader
 1242    {
 1243        internal readonly int NumberOfRows;
 1244        private readonly bool _IsEventTableRowRefSizeSmall;
 1245        private readonly int _EventOffset;
 1246        internal readonly int RowSize;
 1247        internal readonly MemoryBlock Block;
 1248
 1249        internal EventPtrTableReader(
 1250            int numberOfRows,
 1251            int eventTableRowRefSize,
 1252            MemoryBlock containingBlock,
 1253            int containingBlockOffset)
 1254        {
 1255            this.NumberOfRows = numberOfRows;
 1256            _IsEventTableRowRefSizeSmall = eventTableRowRefSize == 2;
 1257            _EventOffset = 0;
 1258            this.RowSize = _EventOffset + eventTableRowRefSize;
 1259            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1260        }
 1261
 1262        internal EventDefinitionHandle GetEventFor(int rowId)
 1263        {
 1264            int rowOffset = (rowId - 1) * this.RowSize;
 1265            return EventDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _EventOffset, _IsEventTableRowRe
 1266        }
 1267    }
 1268
 1269    internal struct EventTableReader
 1270    {
 1271        internal int NumberOfRows;
 1272        private readonly bool _IsTypeDefOrRefRefSizeSmall;
 1273        private readonly bool _IsStringHeapRefSizeSmall;
 1274        private readonly int _FlagsOffset;
 1275        private readonly int _NameOffset;
 1276        private readonly int _EventTypeOffset;
 1277        internal readonly int RowSize;
 1278        internal MemoryBlock Block;
 1279
 1280        internal EventTableReader(
 1281            int numberOfRows,
 1282            int typeDefOrRefRefSize,
 1283            int stringHeapRefSize,
 1284            MemoryBlock containingBlock,
 1285            int containingBlockOffset)
 1286        {
 1287            this.NumberOfRows = numberOfRows;
 1288            _IsTypeDefOrRefRefSizeSmall = typeDefOrRefRefSize == 2;
 1289            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 1290            _FlagsOffset = 0;
 1291            _NameOffset = _FlagsOffset + sizeof(ushort);
 1292            _EventTypeOffset = _NameOffset + stringHeapRefSize;
 1293            this.RowSize = _EventTypeOffset + typeDefOrRefRefSize;
 1294            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1295        }
 1296
 1297        internal EventAttributes GetFlags(EventDefinitionHandle handle)
 1298        {
 1299            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1300            return (EventAttributes)this.Block.PeekUInt16(rowOffset + _FlagsOffset);
 1301        }
 1302
 1303        internal StringHandle GetName(EventDefinitionHandle handle)
 1304        {
 1305            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1306            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 1307        }
 1308
 1309        internal EntityHandle GetEventType(EventDefinitionHandle handle)
 1310        {
 1311            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1312            return TypeDefOrRefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _EventTypeOffset, _IsTypeD
 1313        }
 1314    }
 1315
 1316    internal readonly struct PropertyMapTableReader
 1317    {
 1318        internal readonly int NumberOfRows;
 1319        private readonly bool _IsTypeDefTableRowRefSizeSmall;
 1320        private readonly bool _IsPropertyRefSizeSmall;
 1321        private readonly int _ParentOffset;
 1322        private readonly int _PropertyListOffset;
 1323        internal readonly int RowSize;
 1324        internal readonly MemoryBlock Block;
 1325
 1326        internal PropertyMapTableReader(
 1327            int numberOfRows,
 1328            int typeDefTableRowRefSize,
 1329            int propertyRefSize,
 1330            MemoryBlock containingBlock,
 1331            int containingBlockOffset
 1332        )
 1333        {
 1334            this.NumberOfRows = numberOfRows;
 1335            _IsTypeDefTableRowRefSizeSmall = typeDefTableRowRefSize == 2;
 1336            _IsPropertyRefSizeSmall = propertyRefSize == 2;
 1337            _ParentOffset = 0;
 1338            _PropertyListOffset = _ParentOffset + typeDefTableRowRefSize;
 1339            this.RowSize = _PropertyListOffset + propertyRefSize;
 1340            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1341        }
 1342
 1343        internal int FindPropertyMapRowIdFor(TypeDefinitionHandle typeDef)
 1344        {
 1345            // We do a linear scan here because we don't have these tables sorted.
 1346            // TODO: We can scan the table to see if it is sorted and use binary search if so.
 1347            // Also, the compilers should make sure it's sorted.
 1348            int rowNumber =
 1349              this.Block.LinearSearchReference(
 1350                this.RowSize,
 1351                _ParentOffset,
 1352                (uint)typeDef.RowId,
 1353                _IsTypeDefTableRowRefSizeSmall);
 1354
 1355            return rowNumber + 1;
 1356        }
 1357
 1358        internal TypeDefinitionHandle GetParentType(int rowId)
 1359        {
 1360            int rowOffset = (rowId - 1) * this.RowSize;
 1361            return TypeDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _ParentOffset, _IsTypeDefTableRow
 1362        }
 1363
 1364        internal int GetPropertyListStartFor(int rowId)
 1365        {
 1366            int rowOffset = (rowId - 1) * this.RowSize;
 1367            return this.Block.PeekReference(rowOffset + _PropertyListOffset, _IsPropertyRefSizeSmall);
 1368        }
 1369
 1370        internal TypeDefinitionHandle FindTypeContainingProperty(int propertyRowId, int numberOfProperties)
 1371        {
 1372            int numOfRows = this.NumberOfRows;
 1373            int slot = this.Block.BinarySearchForSlot(numOfRows, this.RowSize, _PropertyListOffset, (uint)propertyRowId,
 1374            int row = slot + 1;
 1375            if (row == 0)
 1376            {
 1377                return default(TypeDefinitionHandle);
 1378            }
 1379
 1380            if (row > numOfRows)
 1381            {
 1382                if (propertyRowId <= numberOfProperties)
 1383                {
 1384                    return GetParentType(numOfRows);
 1385                }
 1386
 1387                return default(TypeDefinitionHandle);
 1388            }
 1389
 1390            return GetParentType(row);
 1391        }
 1392    }
 1393
 1394    internal readonly struct PropertyPtrTableReader
 1395    {
 1396        internal readonly int NumberOfRows;
 1397        private readonly bool _IsPropertyTableRowRefSizeSmall;
 1398        private readonly int _PropertyOffset;
 1399        internal readonly int RowSize;
 1400        internal readonly MemoryBlock Block;
 1401
 1402        internal PropertyPtrTableReader(
 1403            int numberOfRows,
 1404            int propertyTableRowRefSize,
 1405            MemoryBlock containingBlock,
 1406            int containingBlockOffset
 1407        )
 1408        {
 1409            this.NumberOfRows = numberOfRows;
 1410            _IsPropertyTableRowRefSizeSmall = propertyTableRowRefSize == 2;
 1411            _PropertyOffset = 0;
 1412            this.RowSize = _PropertyOffset + propertyTableRowRefSize;
 1413            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1414        }
 1415
 1416        internal PropertyDefinitionHandle GetPropertyFor(
 1417          int rowId
 1418        )
 1419        // ^ requires rowId <= this.NumberOfRows;
 1420        {
 1421            int rowOffset = (rowId - 1) * this.RowSize;
 1422            return PropertyDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _PropertyOffset, _IsPropertyT
 1423        }
 1424    }
 1425
 1426    internal readonly struct PropertyTableReader
 1427    {
 1428        internal readonly int NumberOfRows;
 1429        private readonly bool _IsStringHeapRefSizeSmall;
 1430        private readonly bool _IsBlobHeapRefSizeSmall;
 1431        private readonly int _FlagsOffset;
 1432        private readonly int _NameOffset;
 1433        private readonly int _SignatureOffset;
 1434        internal readonly int RowSize;
 1435        internal readonly MemoryBlock Block;
 1436
 1437        internal PropertyTableReader(
 1438            int numberOfRows,
 1439            int stringHeapRefSize,
 1440            int blobHeapRefSize,
 1441            MemoryBlock containingBlock,
 1442            int containingBlockOffset)
 1443        {
 1444            this.NumberOfRows = numberOfRows;
 1445            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 1446            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 1447            _FlagsOffset = 0;
 1448            _NameOffset = _FlagsOffset + sizeof(ushort);
 1449            _SignatureOffset = _NameOffset + stringHeapRefSize;
 1450            this.RowSize = _SignatureOffset + blobHeapRefSize;
 1451            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1452        }
 1453
 1454        internal PropertyAttributes GetFlags(PropertyDefinitionHandle handle)
 1455        {
 1456            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1457            return (PropertyAttributes)this.Block.PeekUInt16(rowOffset + _FlagsOffset);
 1458        }
 1459
 1460        internal StringHandle GetName(PropertyDefinitionHandle handle)
 1461        {
 1462            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1463            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 1464        }
 1465
 1466        internal BlobHandle GetSignature(PropertyDefinitionHandle handle)
 1467        {
 1468            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1469            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _SignatureOffset, _IsBlobHeapRefSizeSm
 1470        }
 1471    }
 1472
 1473    internal readonly struct MethodSemanticsTableReader
 1474    {
 1475        internal readonly int NumberOfRows;
 1476        private readonly bool _IsMethodTableRowRefSizeSmall;
 1477        private readonly bool _IsHasSemanticRefSizeSmall;
 1478        private readonly int _SemanticsFlagOffset;
 1479        private readonly int _MethodOffset;
 1480        private readonly int _AssociationOffset;
 1481        internal readonly int RowSize;
 1482        internal readonly MemoryBlock Block;
 1483
 1484        internal MethodSemanticsTableReader(
 1485            int numberOfRows,
 1486            bool declaredSorted,
 1487            int methodTableRowRefSize,
 1488            int hasSemanticRefSize,
 1489            MemoryBlock containingBlock,
 1490            int containingBlockOffset)
 1491        {
 1492            this.NumberOfRows = numberOfRows;
 1493            _IsMethodTableRowRefSizeSmall = methodTableRowRefSize == 2;
 1494            _IsHasSemanticRefSizeSmall = hasSemanticRefSize == 2;
 1495            _SemanticsFlagOffset = 0;
 1496            _MethodOffset = _SemanticsFlagOffset + sizeof(ushort);
 1497            _AssociationOffset = _MethodOffset + methodTableRowRefSize;
 1498            this.RowSize = _AssociationOffset + hasSemanticRefSize;
 1499            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1500
 1501            if (!declaredSorted && !CheckSorted())
 1502            {
 1503                Throw.TableNotSorted(TableIndex.MethodSemantics);
 1504            }
 1505        }
 1506
 1507        internal MethodDefinitionHandle GetMethod(int rowId)
 1508        {
 1509            int rowOffset = (rowId - 1) * this.RowSize;
 1510            return MethodDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _MethodOffset, _IsMethodTableRo
 1511        }
 1512
 1513        internal MethodSemanticsAttributes GetSemantics(int rowId)
 1514        {
 1515            int rowOffset = (rowId - 1) * this.RowSize;
 1516            return (MethodSemanticsAttributes)this.Block.PeekUInt16(rowOffset + _SemanticsFlagOffset);
 1517        }
 1518
 1519        internal EntityHandle GetAssociation(int rowId)
 1520        {
 1521            int rowOffset = (rowId - 1) * this.RowSize;
 1522            return HasSemanticsTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _AssociationOffset, _IsHas
 1523        }
 1524
 1525        // returns rowID
 1526        internal int FindSemanticMethodsForEvent(EventDefinitionHandle eventDef, out ushort methodCount)
 1527        {
 1528            methodCount = 0;
 1529            uint searchCodedTag = HasSemanticsTag.ConvertEventHandleToTag(eventDef);
 1530            return this.BinarySearchTag(searchCodedTag, ref methodCount);
 1531        }
 1532
 1533        internal int FindSemanticMethodsForProperty(PropertyDefinitionHandle propertyDef, out ushort methodCount)
 1534        {
 1535            methodCount = 0;
 1536            uint searchCodedTag = HasSemanticsTag.ConvertPropertyHandleToTag(propertyDef);
 1537            return this.BinarySearchTag(searchCodedTag, ref methodCount);
 1538        }
 1539
 1540        private int BinarySearchTag(uint searchCodedTag, ref ushort methodCount)
 1541        {
 1542            int startRowNumber, endRowNumber;
 1543            this.Block.BinarySearchReferenceRange(
 1544                this.NumberOfRows,
 1545                this.RowSize,
 1546                _AssociationOffset,
 1547                searchCodedTag,
 1548                _IsHasSemanticRefSizeSmall,
 1549                out startRowNumber,
 1550                out endRowNumber
 1551            );
 1552
 1553            if (startRowNumber == -1)
 1554            {
 1555                methodCount = 0;
 1556                return 0;
 1557            }
 1558
 1559            methodCount = (ushort)(endRowNumber - startRowNumber + 1);
 1560            return startRowNumber + 1;
 1561        }
 1562
 1563        private bool CheckSorted()
 1564        {
 1565            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _AssociationOffset, _IsHasSemanticRefSizeSmall
 1566        }
 1567    }
 1568
 1569    internal readonly struct MethodImplTableReader
 1570    {
 1571        internal readonly int NumberOfRows;
 1572        private readonly bool _IsTypeDefTableRowRefSizeSmall;
 1573        private readonly bool _IsMethodDefOrRefRefSizeSmall;
 1574        private readonly int _ClassOffset;
 1575        private readonly int _MethodBodyOffset;
 1576        private readonly int _MethodDeclarationOffset;
 1577        internal readonly int RowSize;
 1578        internal readonly MemoryBlock Block;
 1579
 1580        internal MethodImplTableReader(
 1581            int numberOfRows,
 1582            bool declaredSorted,
 1583            int typeDefTableRowRefSize,
 1584            int methodDefOrRefRefSize,
 1585            MemoryBlock containingBlock,
 1586            int containingBlockOffset
 1587        )
 01588        {
 01589            this.NumberOfRows = numberOfRows;
 01590            _IsTypeDefTableRowRefSizeSmall = typeDefTableRowRefSize == 2;
 01591            _IsMethodDefOrRefRefSizeSmall = methodDefOrRefRefSize == 2;
 01592            _ClassOffset = 0;
 01593            _MethodBodyOffset = _ClassOffset + typeDefTableRowRefSize;
 01594            _MethodDeclarationOffset = _MethodBodyOffset + methodDefOrRefRefSize;
 01595            this.RowSize = _MethodDeclarationOffset + methodDefOrRefRefSize;
 01596            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1597
 01598            if (!declaredSorted && !CheckSorted())
 01599            {
 01600                Throw.TableNotSorted(TableIndex.MethodImpl);
 1601            }
 01602        }
 1603
 1604        internal TypeDefinitionHandle GetClass(MethodImplementationHandle handle)
 01605        {
 01606            int rowOffset = (handle.RowId - 1) * this.RowSize;
 01607            return TypeDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _ClassOffset, _IsTypeDefTableRowR
 01608        }
 1609
 1610        internal EntityHandle GetMethodBody(MethodImplementationHandle handle)
 01611        {
 01612            int rowOffset = (handle.RowId - 1) * this.RowSize;
 01613            return MethodDefOrRefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _MethodBodyOffset, _IsMe
 01614        }
 1615
 1616        internal EntityHandle GetMethodDeclaration(MethodImplementationHandle handle)
 01617        {
 01618            int rowOffset = (handle.RowId - 1) * this.RowSize;
 01619            return MethodDefOrRefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _MethodDeclarationOffset
 01620        }
 1621
 1622        internal void GetMethodImplRange(
 1623            TypeDefinitionHandle typeDef,
 1624            out int firstImplRowId,
 1625            out int lastImplRowId)
 01626        {
 1627            int startRowNumber, endRowNumber;
 01628            this.Block.BinarySearchReferenceRange(
 01629                this.NumberOfRows,
 01630                this.RowSize,
 01631                _ClassOffset,
 01632                (uint)typeDef.RowId,
 01633                _IsTypeDefTableRowRefSizeSmall,
 01634                out startRowNumber,
 01635                out endRowNumber);
 1636
 01637            if (startRowNumber == -1)
 01638            {
 01639                firstImplRowId = 1;
 01640                lastImplRowId = 0;
 01641            }
 1642            else
 01643            {
 01644                firstImplRowId = startRowNumber + 1;
 01645                lastImplRowId = endRowNumber + 1;
 01646            }
 01647        }
 1648
 1649        private bool CheckSorted()
 01650        {
 01651            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _ClassOffset, _IsTypeDefTableRowRefSizeSmall);
 01652        }
 1653    }
 1654
 1655    internal readonly struct ModuleRefTableReader
 1656    {
 1657        internal readonly int NumberOfRows;
 1658        private readonly bool _IsStringHeapRefSizeSmall;
 1659        private readonly int _NameOffset;
 1660        internal readonly int RowSize;
 1661        internal readonly MemoryBlock Block;
 1662
 1663        internal ModuleRefTableReader(
 1664            int numberOfRows,
 1665            int stringHeapRefSize,
 1666            MemoryBlock containingBlock,
 1667            int containingBlockOffset
 1668        )
 1669        {
 1670            this.NumberOfRows = numberOfRows;
 1671            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 1672            _NameOffset = 0;
 1673            this.RowSize = _NameOffset + stringHeapRefSize;
 1674            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1675        }
 1676
 1677        internal StringHandle GetName(ModuleReferenceHandle handle)
 1678        {
 1679            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1680            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 1681        }
 1682    }
 1683
 1684    internal readonly struct TypeSpecTableReader
 1685    {
 1686        internal readonly int NumberOfRows;
 1687        private readonly bool _IsBlobHeapRefSizeSmall;
 1688        private readonly int _SignatureOffset;
 1689        internal readonly int RowSize;
 1690        internal readonly MemoryBlock Block;
 1691
 1692        internal TypeSpecTableReader(
 1693            int numberOfRows,
 1694            int blobHeapRefSize,
 1695            MemoryBlock containingBlock,
 1696            int containingBlockOffset
 1697        )
 1698        {
 1699            this.NumberOfRows = numberOfRows;
 1700            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 1701            _SignatureOffset = 0;
 1702            this.RowSize = _SignatureOffset + blobHeapRefSize;
 1703            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1704        }
 1705
 1706        internal BlobHandle GetSignature(TypeSpecificationHandle handle)
 1707        {
 1708            int rowOffset = (handle.RowId - 1) * this.RowSize;
 1709            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _SignatureOffset, _IsBlobHeapRefSizeSm
 1710        }
 1711    }
 1712
 1713    internal readonly struct ImplMapTableReader
 1714    {
 1715        internal readonly int NumberOfRows;
 1716        private readonly bool _IsModuleRefTableRowRefSizeSmall;
 1717        private readonly bool _IsMemberForwardRowRefSizeSmall;
 1718        private readonly bool _IsStringHeapRefSizeSmall;
 1719        private readonly int _FlagsOffset;
 1720        private readonly int _MemberForwardedOffset;
 1721        private readonly int _ImportNameOffset;
 1722        private readonly int _ImportScopeOffset;
 1723        internal readonly int RowSize;
 1724        internal readonly MemoryBlock Block;
 1725
 1726        internal ImplMapTableReader(
 1727            int numberOfRows,
 1728            bool declaredSorted,
 1729            int moduleRefTableRowRefSize,
 1730            int memberForwardedRefSize,
 1731            int stringHeapRefSize,
 1732            MemoryBlock containingBlock,
 1733            int containingBlockOffset
 1734        )
 1735        {
 1736            this.NumberOfRows = numberOfRows;
 1737            _IsModuleRefTableRowRefSizeSmall = moduleRefTableRowRefSize == 2;
 1738            _IsMemberForwardRowRefSizeSmall = memberForwardedRefSize == 2;
 1739            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 1740            _FlagsOffset = 0;
 1741            _MemberForwardedOffset = _FlagsOffset + sizeof(ushort);
 1742            _ImportNameOffset = _MemberForwardedOffset + memberForwardedRefSize;
 1743            _ImportScopeOffset = _ImportNameOffset + stringHeapRefSize;
 1744            this.RowSize = _ImportScopeOffset + moduleRefTableRowRefSize;
 1745            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1746
 1747            if (!declaredSorted && !CheckSorted())
 1748            {
 1749                Throw.TableNotSorted(TableIndex.ImplMap);
 1750            }
 1751        }
 1752
 1753        internal MethodImport GetImport(int rowId)
 1754        {
 1755            int rowOffset = (rowId - 1) * this.RowSize;
 1756            var pInvokeMapFlags = (MethodImportAttributes)Block.PeekUInt16(rowOffset + _FlagsOffset);
 1757            var importName = StringHandle.FromOffset(Block.PeekHeapReference(rowOffset + _ImportNameOffset, _IsStringHea
 1758            var importScope = ModuleReferenceHandle.FromRowId(Block.PeekReference(rowOffset + _ImportScopeOffset, _IsMod
 1759            return new MethodImport(pInvokeMapFlags, importName, importScope);
 1760        }
 1761
 1762        internal EntityHandle GetMemberForwarded(int rowId)
 1763        {
 1764            int rowOffset = (rowId - 1) * this.RowSize;
 1765            return MemberForwardedTag.ConvertToHandle(Block.PeekTaggedReference(rowOffset + _MemberForwardedOffset, _IsM
 1766        }
 1767
 1768        internal int FindImplForMethod(MethodDefinitionHandle methodDef)
 1769        {
 1770            uint searchCodedTag = MemberForwardedTag.ConvertMethodDefToTag(methodDef);
 1771            return this.BinarySearchTag(searchCodedTag);
 1772        }
 1773
 1774        private int BinarySearchTag(uint searchCodedTag)
 1775        {
 1776            int foundRowNumber =
 1777              this.Block.BinarySearchReference(
 1778                this.NumberOfRows,
 1779                this.RowSize,
 1780                _MemberForwardedOffset,
 1781                searchCodedTag,
 1782                _IsMemberForwardRowRefSizeSmall);
 1783
 1784            return foundRowNumber + 1;
 1785        }
 1786
 1787        private bool CheckSorted()
 1788        {
 1789            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _MemberForwardedOffset, _IsMemberForwardRowRef
 1790        }
 1791    }
 1792
 1793    internal readonly struct FieldRVATableReader
 1794    {
 1795        internal readonly int NumberOfRows;
 1796        private readonly bool _IsFieldTableRowRefSizeSmall;
 1797        private readonly int _RvaOffset;
 1798        private readonly int _FieldOffset;
 1799        internal readonly int RowSize;
 1800        internal readonly MemoryBlock Block;
 1801
 1802        internal FieldRVATableReader(
 1803            int numberOfRows,
 1804            bool declaredSorted,
 1805            int fieldTableRowRefSize,
 1806            MemoryBlock containingBlock,
 1807            int containingBlockOffset)
 1808        {
 1809            this.NumberOfRows = numberOfRows;
 1810            _IsFieldTableRowRefSizeSmall = fieldTableRowRefSize == 2;
 1811            _RvaOffset = 0;
 1812            _FieldOffset = _RvaOffset + sizeof(uint);
 1813            this.RowSize = _FieldOffset + fieldTableRowRefSize;
 1814            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1815
 1816            if (!declaredSorted && !CheckSorted())
 1817            {
 1818                Throw.TableNotSorted(TableIndex.FieldRva);
 1819            }
 1820        }
 1821
 1822        internal int GetRva(int rowId)
 1823        {
 1824            int rowOffset = (rowId - 1) * this.RowSize;
 1825            return Block.PeekInt32(rowOffset + _RvaOffset);
 1826        }
 1827
 1828        internal int FindFieldRvaRowId(int fieldDefRowId)
 1829        {
 1830            int foundRowNumber = Block.BinarySearchReference(
 1831                this.NumberOfRows,
 1832                this.RowSize,
 1833                _FieldOffset,
 1834                (uint)fieldDefRowId,
 1835                _IsFieldTableRowRefSizeSmall);
 1836
 1837            return foundRowNumber + 1;
 1838        }
 1839
 1840        private bool CheckSorted()
 1841        {
 1842            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _FieldOffset, _IsFieldTableRowRefSizeSmall);
 1843        }
 1844    }
 1845
 1846    internal readonly struct EnCLogTableReader
 1847    {
 1848        internal readonly int NumberOfRows;
 1849        private readonly int _TokenOffset;
 1850        private readonly int _FuncCodeOffset;
 1851        internal readonly int RowSize;
 1852        internal readonly MemoryBlock Block;
 1853
 1854        internal EnCLogTableReader(
 1855            int numberOfRows,
 1856            MemoryBlock containingBlock,
 1857            int containingBlockOffset,
 1858            MetadataStreamKind metadataStreamKind)
 1859        {
 1860            // EnC tables are not allowed in a compressed stream.
 1861            // However when asked for a snapshot of the current metadata after an EnC change has been applied
 1862            // the CLR includes the EnCLog table into the snapshot (but not EnCMap). We pretend EnCLog is empty.
 1863            this.NumberOfRows = (metadataStreamKind == MetadataStreamKind.Compressed) ? 0 : numberOfRows;
 1864
 1865            _TokenOffset = 0;
 1866            _FuncCodeOffset = _TokenOffset + sizeof(uint);
 1867            this.RowSize = _FuncCodeOffset + sizeof(uint);
 1868            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1869        }
 1870
 1871        internal uint GetToken(int rowId)
 1872        {
 1873            int rowOffset = (rowId - 1) * this.RowSize;
 1874            return this.Block.PeekUInt32(rowOffset + _TokenOffset);
 1875        }
 1876
 1877        internal EditAndContinueOperation GetFuncCode(int rowId)
 1878        {
 1879            int rowOffset = (rowId - 1) * this.RowSize;
 1880            return (EditAndContinueOperation)this.Block.PeekUInt32(rowOffset + _FuncCodeOffset);
 1881        }
 1882    }
 1883
 1884    internal readonly struct EnCMapTableReader
 1885    {
 1886        internal readonly int NumberOfRows;
 1887        private readonly int _TokenOffset;
 1888        internal readonly int RowSize;
 1889        internal readonly MemoryBlock Block;
 1890
 1891        internal EnCMapTableReader(
 1892            int numberOfRows,
 1893            MemoryBlock containingBlock,
 1894            int containingBlockOffset)
 1895        {
 1896            this.NumberOfRows = numberOfRows;
 1897            _TokenOffset = 0;
 1898            this.RowSize = _TokenOffset + sizeof(uint);
 1899            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1900        }
 1901
 1902        internal uint GetToken(int rowId)
 1903        {
 1904            int rowOffset = (rowId - 1) * this.RowSize;
 1905            return this.Block.PeekUInt32(rowOffset + _TokenOffset);
 1906        }
 1907    }
 1908
 1909    internal readonly struct AssemblyTableReader
 1910    {
 1911        internal readonly int NumberOfRows;
 1912        private readonly bool _IsStringHeapRefSizeSmall;
 1913        private readonly bool _IsBlobHeapRefSizeSmall;
 1914        private readonly int _HashAlgIdOffset;
 1915        private readonly int _MajorVersionOffset;
 1916        private readonly int _MinorVersionOffset;
 1917        private readonly int _BuildNumberOffset;
 1918        private readonly int _RevisionNumberOffset;
 1919        private readonly int _FlagsOffset;
 1920        private readonly int _PublicKeyOffset;
 1921        private readonly int _NameOffset;
 1922        private readonly int _CultureOffset;
 1923        internal readonly int RowSize;
 1924        internal readonly MemoryBlock Block;
 1925
 1926        internal AssemblyTableReader(
 1927            int numberOfRows,
 1928            int stringHeapRefSize,
 1929            int blobHeapRefSize,
 1930            MemoryBlock containingBlock,
 1931            int containingBlockOffset
 1932        )
 1933        {
 1934            // NOTE: obfuscated assemblies may have more than one row in Assembly table,
 1935            //       we ignore all rows but the first one
 1936            this.NumberOfRows = numberOfRows > 1 ? 1 : numberOfRows;
 1937
 1938            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 1939            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 1940            _HashAlgIdOffset = 0;
 1941            _MajorVersionOffset = _HashAlgIdOffset + sizeof(uint);
 1942            _MinorVersionOffset = _MajorVersionOffset + sizeof(ushort);
 1943            _BuildNumberOffset = _MinorVersionOffset + sizeof(ushort);
 1944            _RevisionNumberOffset = _BuildNumberOffset + sizeof(ushort);
 1945            _FlagsOffset = _RevisionNumberOffset + sizeof(ushort);
 1946            _PublicKeyOffset = _FlagsOffset + sizeof(uint);
 1947            _NameOffset = _PublicKeyOffset + blobHeapRefSize;
 1948            _CultureOffset = _NameOffset + stringHeapRefSize;
 1949            this.RowSize = _CultureOffset + stringHeapRefSize;
 1950            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 1951        }
 1952
 1953        internal AssemblyHashAlgorithm GetHashAlgorithm()
 1954        {
 1955            Debug.Assert(NumberOfRows == 1);
 1956            return (AssemblyHashAlgorithm)this.Block.PeekUInt32(_HashAlgIdOffset);
 1957        }
 1958
 1959        internal Version GetVersion()
 1960        {
 1961            Debug.Assert(NumberOfRows == 1);
 1962            return new Version(
 1963                this.Block.PeekUInt16(_MajorVersionOffset),
 1964                this.Block.PeekUInt16(_MinorVersionOffset),
 1965                this.Block.PeekUInt16(_BuildNumberOffset),
 1966                this.Block.PeekUInt16(_RevisionNumberOffset));
 1967        }
 1968
 1969        internal AssemblyFlags GetFlags()
 1970        {
 1971            Debug.Assert(NumberOfRows == 1);
 1972            return (AssemblyFlags)this.Block.PeekUInt32(_FlagsOffset);
 1973        }
 1974
 1975        internal BlobHandle GetPublicKey()
 1976        {
 1977            Debug.Assert(NumberOfRows == 1);
 1978            return BlobHandle.FromOffset(this.Block.PeekHeapReference(_PublicKeyOffset, _IsBlobHeapRefSizeSmall));
 1979        }
 1980
 1981        internal StringHandle GetName()
 1982        {
 1983            Debug.Assert(NumberOfRows == 1);
 1984            return StringHandle.FromOffset(this.Block.PeekHeapReference(_NameOffset, _IsStringHeapRefSizeSmall));
 1985        }
 1986
 1987        internal StringHandle GetCulture()
 1988        {
 1989            Debug.Assert(NumberOfRows == 1);
 1990            return StringHandle.FromOffset(this.Block.PeekHeapReference(_CultureOffset, _IsStringHeapRefSizeSmall));
 1991        }
 1992    }
 1993
 1994    internal readonly struct AssemblyProcessorTableReader
 1995    {
 1996        internal readonly int NumberOfRows;
 1997        private readonly int _ProcessorOffset;
 1998        internal readonly int RowSize;
 1999        internal readonly MemoryBlock Block;
 2000
 2001        internal AssemblyProcessorTableReader(
 2002            int numberOfRows,
 2003            MemoryBlock containingBlock,
 2004            int containingBlockOffset
 2005        )
 2006        {
 2007            this.NumberOfRows = numberOfRows;
 2008            _ProcessorOffset = 0;
 2009            this.RowSize = _ProcessorOffset + sizeof(uint);
 2010            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2011        }
 2012    }
 2013
 2014    internal readonly struct AssemblyOSTableReader
 2015    {
 2016        internal readonly int NumberOfRows;
 2017        private readonly int _OSPlatformIdOffset;
 2018        private readonly int _OSMajorVersionIdOffset;
 2019        private readonly int _OSMinorVersionIdOffset;
 2020        internal readonly int RowSize;
 2021        internal readonly MemoryBlock Block;
 2022
 2023        internal AssemblyOSTableReader(
 2024            int numberOfRows,
 2025            MemoryBlock containingBlock,
 2026            int containingBlockOffset
 2027        )
 2028        {
 2029            this.NumberOfRows = numberOfRows;
 2030            _OSPlatformIdOffset = 0;
 2031            _OSMajorVersionIdOffset = _OSPlatformIdOffset + sizeof(uint);
 2032            _OSMinorVersionIdOffset = _OSMajorVersionIdOffset + sizeof(uint);
 2033            this.RowSize = _OSMinorVersionIdOffset + sizeof(uint);
 2034            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2035        }
 2036    }
 2037
 2038    internal readonly struct AssemblyRefTableReader
 2039    {
 2040        /// <summary>
 2041        /// In CLI metadata equal to the actual number of entries in AssemblyRef table.
 2042        /// In WinMD metadata it includes synthesized AssemblyRefs in addition.
 2043        /// </summary>
 2044        internal readonly int NumberOfNonVirtualRows;
 2045        internal readonly int NumberOfVirtualRows;
 2046
 2047        private readonly bool _IsStringHeapRefSizeSmall;
 2048        private readonly bool _IsBlobHeapRefSizeSmall;
 2049        private readonly int _MajorVersionOffset;
 2050        private readonly int _MinorVersionOffset;
 2051        private readonly int _BuildNumberOffset;
 2052        private readonly int _RevisionNumberOffset;
 2053        private readonly int _FlagsOffset;
 2054        private readonly int _PublicKeyOrTokenOffset;
 2055        private readonly int _NameOffset;
 2056        private readonly int _CultureOffset;
 2057        private readonly int _HashValueOffset;
 2058        internal readonly int RowSize;
 2059        internal readonly MemoryBlock Block;
 2060
 2061        internal AssemblyRefTableReader(
 2062            int numberOfRows,
 2063            int stringHeapRefSize,
 2064            int blobHeapRefSize,
 2065            MemoryBlock containingBlock,
 2066            int containingBlockOffset,
 2067            MetadataKind metadataKind)
 2068        {
 2069            this.NumberOfNonVirtualRows = numberOfRows;
 2070            this.NumberOfVirtualRows = (metadataKind == MetadataKind.Ecma335) ? 0 : (int)AssemblyReferenceHandle.Virtual
 2071
 2072            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 2073            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 2074            _MajorVersionOffset = 0;
 2075            _MinorVersionOffset = _MajorVersionOffset + sizeof(ushort);
 2076            _BuildNumberOffset = _MinorVersionOffset + sizeof(ushort);
 2077            _RevisionNumberOffset = _BuildNumberOffset + sizeof(ushort);
 2078            _FlagsOffset = _RevisionNumberOffset + sizeof(ushort);
 2079            _PublicKeyOrTokenOffset = _FlagsOffset + sizeof(uint);
 2080            _NameOffset = _PublicKeyOrTokenOffset + blobHeapRefSize;
 2081            _CultureOffset = _NameOffset + stringHeapRefSize;
 2082            _HashValueOffset = _CultureOffset + stringHeapRefSize;
 2083            this.RowSize = _HashValueOffset + blobHeapRefSize;
 2084            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2085        }
 2086
 2087        internal Version GetVersion(int rowId)
 2088        {
 2089            int rowOffset = (rowId - 1) * this.RowSize;
 2090            return new Version(
 2091                this.Block.PeekUInt16(rowOffset + _MajorVersionOffset),
 2092                this.Block.PeekUInt16(rowOffset + _MinorVersionOffset),
 2093                this.Block.PeekUInt16(rowOffset + _BuildNumberOffset),
 2094                this.Block.PeekUInt16(rowOffset + _RevisionNumberOffset));
 2095        }
 2096
 2097        internal AssemblyFlags GetFlags(int rowId)
 2098        {
 2099            int rowOffset = (rowId - 1) * this.RowSize;
 2100            return (AssemblyFlags)this.Block.PeekUInt32(rowOffset + _FlagsOffset);
 2101        }
 2102
 2103        internal BlobHandle GetPublicKeyOrToken(int rowId)
 2104        {
 2105            int rowOffset = (rowId - 1) * this.RowSize;
 2106            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _PublicKeyOrTokenOffset, _IsBlobHeapRe
 2107        }
 2108
 2109        internal StringHandle GetName(int rowId)
 2110        {
 2111            int rowOffset = (rowId - 1) * this.RowSize;
 2112            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 2113        }
 2114
 2115        internal StringHandle GetCulture(int rowId)
 2116        {
 2117            int rowOffset = (rowId - 1) * this.RowSize;
 2118            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _CultureOffset, _IsStringHeapRefSize
 2119        }
 2120
 2121        internal BlobHandle GetHashValue(int rowId)
 2122        {
 2123            int rowOffset = (rowId - 1) * this.RowSize;
 2124            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _HashValueOffset, _IsBlobHeapRefSizeSm
 2125        }
 2126    }
 2127
 2128    internal readonly struct AssemblyRefProcessorTableReader
 2129    {
 2130        internal readonly int NumberOfRows;
 2131        private readonly bool _IsAssemblyRefTableRowSizeSmall;
 2132        private readonly int _ProcessorOffset;
 2133        private readonly int _AssemblyRefOffset;
 2134        internal readonly int RowSize;
 2135        internal readonly MemoryBlock Block;
 2136
 2137        internal AssemblyRefProcessorTableReader(
 2138            int numberOfRows,
 2139            int assemblyRefTableRowRefSize,
 2140            MemoryBlock containingBlock,
 2141            int containingBlockOffset
 2142        )
 2143        {
 2144            this.NumberOfRows = numberOfRows;
 2145            _IsAssemblyRefTableRowSizeSmall = assemblyRefTableRowRefSize == 2;
 2146            _ProcessorOffset = 0;
 2147            _AssemblyRefOffset = _ProcessorOffset + sizeof(uint);
 2148            this.RowSize = _AssemblyRefOffset + assemblyRefTableRowRefSize;
 2149            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2150        }
 2151    }
 2152
 2153    internal readonly struct AssemblyRefOSTableReader
 2154    {
 2155        internal readonly int NumberOfRows;
 2156        private readonly bool _IsAssemblyRefTableRowRefSizeSmall;
 2157        private readonly int _OSPlatformIdOffset;
 2158        private readonly int _OSMajorVersionIdOffset;
 2159        private readonly int _OSMinorVersionIdOffset;
 2160        private readonly int _AssemblyRefOffset;
 2161        internal readonly int RowSize;
 2162        internal readonly MemoryBlock Block;
 2163
 2164        internal AssemblyRefOSTableReader(
 2165            int numberOfRows,
 2166            int assemblyRefTableRowRefSize,
 2167            MemoryBlock containingBlock,
 2168            int containingBlockOffset)
 2169        {
 2170            this.NumberOfRows = numberOfRows;
 2171            _IsAssemblyRefTableRowRefSizeSmall = assemblyRefTableRowRefSize == 2;
 2172            _OSPlatformIdOffset = 0;
 2173            _OSMajorVersionIdOffset = _OSPlatformIdOffset + sizeof(uint);
 2174            _OSMinorVersionIdOffset = _OSMajorVersionIdOffset + sizeof(uint);
 2175            _AssemblyRefOffset = _OSMinorVersionIdOffset + sizeof(uint);
 2176            this.RowSize = _AssemblyRefOffset + assemblyRefTableRowRefSize;
 2177            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2178        }
 2179    }
 2180
 2181    internal readonly struct FileTableReader
 2182    {
 2183        internal readonly int NumberOfRows;
 2184        private readonly bool _IsStringHeapRefSizeSmall;
 2185        private readonly bool _IsBlobHeapRefSizeSmall;
 2186        private readonly int _FlagsOffset;
 2187        private readonly int _NameOffset;
 2188        private readonly int _HashValueOffset;
 2189        internal readonly int RowSize;
 2190        internal readonly MemoryBlock Block;
 2191
 2192        internal FileTableReader(
 2193            int numberOfRows,
 2194            int stringHeapRefSize,
 2195            int blobHeapRefSize,
 2196            MemoryBlock containingBlock,
 2197            int containingBlockOffset)
 2198        {
 2199            this.NumberOfRows = numberOfRows;
 2200            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 2201            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 2202            _FlagsOffset = 0;
 2203            _NameOffset = _FlagsOffset + sizeof(uint);
 2204            _HashValueOffset = _NameOffset + stringHeapRefSize;
 2205            this.RowSize = _HashValueOffset + blobHeapRefSize;
 2206            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2207        }
 2208
 2209        internal BlobHandle GetHashValue(AssemblyFileHandle handle)
 2210        {
 2211            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2212            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _HashValueOffset, _IsBlobHeapRefSizeSm
 2213        }
 2214
 2215        internal uint GetFlags(AssemblyFileHandle handle)
 2216        {
 2217            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2218            return this.Block.PeekUInt32(rowOffset + _FlagsOffset);
 2219        }
 2220
 2221        internal StringHandle GetName(AssemblyFileHandle handle)
 2222        {
 2223            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2224            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 2225        }
 2226    }
 2227
 2228    internal readonly struct ExportedTypeTableReader
 2229    {
 2230        internal readonly int NumberOfRows;
 2231        private readonly bool _IsImplementationRefSizeSmall;
 2232        private readonly bool _IsStringHeapRefSizeSmall;
 2233        private readonly int _FlagsOffset;
 2234        private readonly int _TypeDefIdOffset;
 2235        private readonly int _TypeNameOffset;
 2236        private readonly int _TypeNamespaceOffset;
 2237        private readonly int _ImplementationOffset;
 2238        internal readonly int RowSize;
 2239        internal readonly MemoryBlock Block;
 2240
 2241        internal ExportedTypeTableReader(
 2242            int numberOfRows,
 2243            int implementationRefSize,
 2244            int stringHeapRefSize,
 2245            MemoryBlock containingBlock,
 2246            int containingBlockOffset
 2247        )
 2248        {
 2249            this.NumberOfRows = numberOfRows;
 2250            _IsImplementationRefSizeSmall = implementationRefSize == 2;
 2251            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 2252            _FlagsOffset = 0;
 2253            _TypeDefIdOffset = _FlagsOffset + sizeof(uint);
 2254            _TypeNameOffset = _TypeDefIdOffset + sizeof(uint);
 2255            _TypeNamespaceOffset = _TypeNameOffset + stringHeapRefSize;
 2256            _ImplementationOffset = _TypeNamespaceOffset + stringHeapRefSize;
 2257            this.RowSize = _ImplementationOffset + implementationRefSize;
 2258            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2259        }
 2260
 2261        internal StringHandle GetTypeName(int rowId)
 2262        {
 2263            int rowOffset = (rowId - 1) * this.RowSize;
 2264            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _TypeNameOffset, _IsStringHeapRefSiz
 2265        }
 2266
 2267        internal StringHandle GetTypeNamespaceString(int rowId)
 2268        {
 2269            int rowOffset = (rowId - 1) * this.RowSize;
 2270            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _TypeNamespaceOffset, _IsStringHeapR
 2271        }
 2272
 2273        internal NamespaceDefinitionHandle GetTypeNamespace(int rowId)
 2274        {
 2275            int rowOffset = (rowId - 1) * this.RowSize;
 2276            return NamespaceDefinitionHandle.FromFullNameOffset(this.Block.PeekHeapReference(rowOffset + _TypeNamespaceO
 2277        }
 2278
 2279        internal EntityHandle GetImplementation(int rowId)
 2280        {
 2281            int rowOffset = (rowId - 1) * this.RowSize;
 2282            return ImplementationTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ImplementationOffset, _
 2283        }
 2284
 2285        internal TypeAttributes GetFlags(int rowId)
 2286        {
 2287            int rowOffset = (rowId - 1) * this.RowSize;
 2288            return (TypeAttributes)this.Block.PeekUInt32(rowOffset + _FlagsOffset);
 2289        }
 2290
 2291        internal int GetTypeDefId(int rowId)
 2292        {
 2293            int rowOffset = (rowId - 1) * this.RowSize;
 2294            return this.Block.PeekInt32(rowOffset + _TypeDefIdOffset);
 2295        }
 2296
 2297        internal int GetNamespace(int rowId)
 2298        {
 2299            int rowOffset = (rowId - 1) * this.RowSize;
 2300            return this.Block.PeekReference(rowOffset + _TypeNamespaceOffset, _IsStringHeapRefSizeSmall);
 2301        }
 2302    }
 2303
 2304    internal readonly struct ManifestResourceTableReader
 2305    {
 2306        internal readonly int NumberOfRows;
 2307        private readonly bool _IsImplementationRefSizeSmall;
 2308        private readonly bool _IsStringHeapRefSizeSmall;
 2309        private readonly int _OffsetOffset;
 2310        private readonly int _FlagsOffset;
 2311        private readonly int _NameOffset;
 2312        private readonly int _ImplementationOffset;
 2313        internal readonly int RowSize;
 2314        internal readonly MemoryBlock Block;
 2315
 2316        internal ManifestResourceTableReader(
 2317            int numberOfRows,
 2318            int implementationRefSize,
 2319            int stringHeapRefSize,
 2320            MemoryBlock containingBlock,
 2321            int containingBlockOffset
 2322        )
 2323        {
 2324            this.NumberOfRows = numberOfRows;
 2325            _IsImplementationRefSizeSmall = implementationRefSize == 2;
 2326            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 2327            _OffsetOffset = 0;
 2328            _FlagsOffset = _OffsetOffset + sizeof(uint);
 2329            _NameOffset = _FlagsOffset + sizeof(uint);
 2330            _ImplementationOffset = _NameOffset + stringHeapRefSize;
 2331            this.RowSize = _ImplementationOffset + implementationRefSize;
 2332            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2333        }
 2334
 2335        internal StringHandle GetName(ManifestResourceHandle handle)
 2336        {
 2337            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2338            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 2339        }
 2340
 2341        internal EntityHandle GetImplementation(ManifestResourceHandle handle)
 2342        {
 2343            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2344            return ImplementationTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ImplementationOffset, _
 2345        }
 2346
 2347        internal uint GetOffset(ManifestResourceHandle handle)
 2348        {
 2349            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2350            return this.Block.PeekUInt32(rowOffset + _OffsetOffset);
 2351        }
 2352
 2353        internal ManifestResourceAttributes GetFlags(ManifestResourceHandle handle)
 2354        {
 2355            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2356            return (ManifestResourceAttributes)this.Block.PeekUInt32(rowOffset + _FlagsOffset);
 2357        }
 2358    }
 2359
 2360    internal readonly struct NestedClassTableReader
 2361    {
 2362        internal readonly int NumberOfRows;
 2363        private readonly bool _IsTypeDefTableRowRefSizeSmall;
 2364        private readonly int _NestedClassOffset;
 2365        private readonly int _EnclosingClassOffset;
 2366        internal readonly int RowSize;
 2367        internal readonly MemoryBlock Block;
 2368
 2369        internal NestedClassTableReader(
 2370            int numberOfRows,
 2371            bool declaredSorted,
 2372            int typeDefTableRowRefSize,
 2373            MemoryBlock containingBlock,
 2374            int containingBlockOffset
 2375        )
 2376        {
 2377            this.NumberOfRows = numberOfRows;
 2378            _IsTypeDefTableRowRefSizeSmall = typeDefTableRowRefSize == 2;
 2379            _NestedClassOffset = 0;
 2380            _EnclosingClassOffset = _NestedClassOffset + typeDefTableRowRefSize;
 2381            this.RowSize = _EnclosingClassOffset + typeDefTableRowRefSize;
 2382            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2383
 2384            if (!declaredSorted && !CheckSorted())
 2385            {
 2386                Throw.TableNotSorted(TableIndex.NestedClass);
 2387            }
 2388        }
 2389
 2390        internal TypeDefinitionHandle GetNestedClass(int rowId)
 2391        {
 2392            int rowOffset = (rowId - 1) * this.RowSize;
 2393            return TypeDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _NestedClassOffset, _IsTypeDefTab
 2394        }
 2395
 2396        internal TypeDefinitionHandle GetEnclosingClass(int rowId)
 2397        {
 2398            int rowOffset = (rowId - 1) * this.RowSize;
 2399            return TypeDefinitionHandle.FromRowId(this.Block.PeekReference(rowOffset + _EnclosingClassOffset, _IsTypeDef
 2400        }
 2401
 2402        internal TypeDefinitionHandle FindEnclosingType(TypeDefinitionHandle nestedTypeDef)
 2403        {
 2404            int rowNumber =
 2405              this.Block.BinarySearchReference(
 2406                this.NumberOfRows,
 2407                this.RowSize,
 2408                _NestedClassOffset,
 2409                (uint)nestedTypeDef.RowId,
 2410                _IsTypeDefTableRowRefSizeSmall);
 2411
 2412            if (rowNumber == -1)
 2413            {
 2414                return default(TypeDefinitionHandle);
 2415            }
 2416
 2417            return TypeDefinitionHandle.FromRowId(this.Block.PeekReference(rowNumber * this.RowSize + _EnclosingClassOff
 2418        }
 2419
 2420        private bool CheckSorted()
 2421        {
 2422            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _NestedClassOffset, _IsTypeDefTableRowRefSizeS
 2423        }
 2424    }
 2425
 2426    internal readonly struct GenericParamTableReader
 2427    {
 2428        internal readonly int NumberOfRows;
 2429        private readonly bool _IsTypeOrMethodDefRefSizeSmall;
 2430        private readonly bool _IsStringHeapRefSizeSmall;
 2431        private readonly int _NumberOffset;
 2432        private readonly int _FlagsOffset;
 2433        private readonly int _OwnerOffset;
 2434        private readonly int _NameOffset;
 2435        internal readonly int RowSize;
 2436        internal readonly MemoryBlock Block;
 2437
 2438        internal GenericParamTableReader(
 2439            int numberOfRows,
 2440            bool declaredSorted,
 2441            int typeOrMethodDefRefSize,
 2442            int stringHeapRefSize,
 2443            MemoryBlock containingBlock,
 2444            int containingBlockOffset)
 2445        {
 2446            this.NumberOfRows = numberOfRows;
 2447            _IsTypeOrMethodDefRefSizeSmall = typeOrMethodDefRefSize == 2;
 2448            _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
 2449            _NumberOffset = 0;
 2450            _FlagsOffset = _NumberOffset + sizeof(ushort);
 2451            _OwnerOffset = _FlagsOffset + sizeof(ushort);
 2452            _NameOffset = _OwnerOffset + typeOrMethodDefRefSize;
 2453            this.RowSize = _NameOffset + stringHeapRefSize;
 2454            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2455
 2456            if (!declaredSorted && !CheckSorted())
 2457            {
 2458                Throw.TableNotSorted(TableIndex.GenericParam);
 2459            }
 2460        }
 2461
 2462        internal ushort GetNumber(GenericParameterHandle handle)
 2463        {
 2464            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2465            return this.Block.PeekUInt16(rowOffset + _NumberOffset);
 2466        }
 2467
 2468        internal GenericParameterAttributes GetFlags(GenericParameterHandle handle)
 2469        {
 2470            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2471            return (GenericParameterAttributes)this.Block.PeekUInt16(rowOffset + _FlagsOffset);
 2472        }
 2473
 2474        internal StringHandle GetName(GenericParameterHandle handle)
 2475        {
 2476            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2477            return StringHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _NameOffset, _IsStringHeapRefSizeSma
 2478        }
 2479
 2480        internal EntityHandle GetOwner(GenericParameterHandle handle)
 2481        {
 2482            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2483            return TypeOrMethodDefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _OwnerOffset, _IsTypeOr
 2484        }
 2485
 2486        internal GenericParameterHandleCollection FindGenericParametersForType(TypeDefinitionHandle typeDef)
 2487        {
 2488            ushort count = 0;
 2489            uint searchCodedTag = TypeOrMethodDefTag.ConvertTypeDefRowIdToTag(typeDef);
 2490            int startRid = this.BinarySearchTag(searchCodedTag, ref count);
 2491
 2492            return new GenericParameterHandleCollection(startRid, count);
 2493        }
 2494
 2495        internal GenericParameterHandleCollection FindGenericParametersForMethod(MethodDefinitionHandle methodDef)
 2496        {
 2497            ushort count = 0;
 2498            uint searchCodedTag = TypeOrMethodDefTag.ConvertMethodDefToTag(methodDef);
 2499            int startRid = this.BinarySearchTag(searchCodedTag, ref count);
 2500
 2501            return new GenericParameterHandleCollection(startRid, count);
 2502        }
 2503
 2504        private int BinarySearchTag(uint searchCodedTag, ref ushort genericParamCount)
 2505        {
 2506            int startRowNumber, endRowNumber;
 2507            this.Block.BinarySearchReferenceRange(
 2508                this.NumberOfRows,
 2509                this.RowSize,
 2510                _OwnerOffset,
 2511                searchCodedTag,
 2512                _IsTypeOrMethodDefRefSizeSmall,
 2513                out startRowNumber,
 2514                out endRowNumber);
 2515
 2516            if (startRowNumber == -1)
 2517            {
 2518                genericParamCount = 0;
 2519                return 0;
 2520            }
 2521
 2522            genericParamCount = (ushort)(endRowNumber - startRowNumber + 1);
 2523            return startRowNumber + 1;
 2524        }
 2525
 2526        private bool CheckSorted()
 2527        {
 2528            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _OwnerOffset, _IsTypeOrMethodDefRefSizeSmall);
 2529        }
 2530    }
 2531
 2532    internal readonly struct MethodSpecTableReader
 2533    {
 2534        internal readonly int NumberOfRows;
 2535        private readonly bool _IsMethodDefOrRefRefSizeSmall;
 2536        private readonly bool _IsBlobHeapRefSizeSmall;
 2537        private readonly int _MethodOffset;
 2538        private readonly int _InstantiationOffset;
 2539        internal readonly int RowSize;
 2540        internal readonly MemoryBlock Block;
 2541
 2542        internal MethodSpecTableReader(
 2543            int numberOfRows,
 2544            int methodDefOrRefRefSize,
 2545            int blobHeapRefSize,
 2546            MemoryBlock containingBlock,
 2547            int containingBlockOffset)
 2548        {
 2549            this.NumberOfRows = numberOfRows;
 2550            _IsMethodDefOrRefRefSizeSmall = methodDefOrRefRefSize == 2;
 2551            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 2552            _MethodOffset = 0;
 2553            _InstantiationOffset = _MethodOffset + methodDefOrRefRefSize;
 2554            this.RowSize = _InstantiationOffset + blobHeapRefSize;
 2555            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2556        }
 2557
 2558        internal EntityHandle GetMethod(MethodSpecificationHandle handle)
 2559        {
 2560            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2561            return MethodDefOrRefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _MethodOffset, _IsMethod
 2562        }
 2563
 2564        internal BlobHandle GetInstantiation(MethodSpecificationHandle handle)
 2565        {
 2566            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2567            return BlobHandle.FromOffset(this.Block.PeekHeapReference(rowOffset + _InstantiationOffset, _IsBlobHeapRefSi
 2568        }
 2569    }
 2570
 2571    internal readonly struct GenericParamConstraintTableReader
 2572    {
 2573        internal readonly int NumberOfRows;
 2574        private readonly bool _IsGenericParamTableRowRefSizeSmall;
 2575        private readonly bool _IsTypeDefOrRefRefSizeSmall;
 2576        private readonly int _OwnerOffset;
 2577        private readonly int _ConstraintOffset;
 2578        internal readonly int RowSize;
 2579        internal readonly MemoryBlock Block;
 2580
 2581        internal GenericParamConstraintTableReader(
 2582            int numberOfRows,
 2583            bool declaredSorted,
 2584            int genericParamTableRowRefSize,
 2585            int typeDefOrRefRefSize,
 2586            MemoryBlock containingBlock,
 2587            int containingBlockOffset)
 2588        {
 2589            this.NumberOfRows = numberOfRows;
 2590            _IsGenericParamTableRowRefSizeSmall = genericParamTableRowRefSize == 2;
 2591            _IsTypeDefOrRefRefSizeSmall = typeDefOrRefRefSize == 2;
 2592            _OwnerOffset = 0;
 2593            _ConstraintOffset = _OwnerOffset + genericParamTableRowRefSize;
 2594            this.RowSize = _ConstraintOffset + typeDefOrRefRefSize;
 2595            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);
 2596
 2597            if (!declaredSorted && !CheckSorted())
 2598            {
 2599                Throw.TableNotSorted(TableIndex.GenericParamConstraint);
 2600            }
 2601        }
 2602
 2603        internal GenericParameterConstraintHandleCollection FindConstraintsForGenericParam(GenericParameterHandle generi
 2604        {
 2605            int startRowNumber, endRowNumber;
 2606            this.Block.BinarySearchReferenceRange(
 2607                this.NumberOfRows,
 2608                this.RowSize,
 2609                _OwnerOffset,
 2610                (uint)genericParameter.RowId,
 2611                _IsGenericParamTableRowRefSizeSmall,
 2612                out startRowNumber,
 2613                out endRowNumber);
 2614
 2615            if (startRowNumber == -1)
 2616            {
 2617                return default(GenericParameterConstraintHandleCollection);
 2618            }
 2619
 2620            return new GenericParameterConstraintHandleCollection(
 2621                firstRowId: startRowNumber + 1,
 2622                count: (ushort)(endRowNumber - startRowNumber + 1));
 2623        }
 2624
 2625        private bool CheckSorted()
 2626        {
 2627            return this.Block.IsOrderedByReferenceAscending(this.RowSize, _OwnerOffset, _IsGenericParamTableRowRefSizeSm
 2628        }
 2629
 2630        internal EntityHandle GetConstraint(GenericParameterConstraintHandle handle)
 2631        {
 2632            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2633            return TypeDefOrRefTag.ConvertToHandle(this.Block.PeekTaggedReference(rowOffset + _ConstraintOffset, _IsType
 2634        }
 2635
 2636        internal GenericParameterHandle GetOwner(GenericParameterConstraintHandle handle)
 2637        {
 2638            int rowOffset = (handle.RowId - 1) * this.RowSize;
 2639            return GenericParameterHandle.FromRowId(this.Block.PeekReference(rowOffset + _OwnerOffset, _IsGenericParamTa
 2640        }
 2641    }
 2642}
 2643