File: System\Reflection\Metadata\PortablePdb\Tables.Debug.cs
Web Access
Project: src\src\libraries\System.Reflection.Metadata\src\System.Reflection.Metadata.csproj (System.Reflection.Metadata)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Reflection.Internal;
 
namespace System.Reflection.Metadata.Ecma335
{
    internal readonly struct DocumentTableReader
    {
        internal readonly int NumberOfRows;
 
        private readonly bool _isGuidHeapRefSizeSmall;
        private readonly bool _isBlobHeapRefSizeSmall;
 
        private const int NameOffset = 0;
        private readonly int _hashAlgorithmOffset;
        private readonly int _hashOffset;
        private readonly int _languageOffset;
 
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal DocumentTableReader(
            int numberOfRows,
            int guidHeapRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isGuidHeapRefSizeSmall = guidHeapRefSize == 2;
            _isBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 
            _hashAlgorithmOffset = NameOffset + blobHeapRefSize;
            _hashOffset = _hashAlgorithmOffset + guidHeapRefSize;
            _languageOffset = _hashOffset + blobHeapRefSize;
            RowSize = _languageOffset + guidHeapRefSize;
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
        }
 
        internal DocumentNameBlobHandle GetName(DocumentHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return DocumentNameBlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + NameOffset, _isBlobHeapRefSizeSmall));
        }
 
        internal GuidHandle GetHashAlgorithm(DocumentHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return GuidHandle.FromIndex(Block.PeekHeapReference(rowOffset + _hashAlgorithmOffset, _isGuidHeapRefSizeSmall));
        }
 
        internal BlobHandle GetHash(DocumentHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _hashOffset, _isBlobHeapRefSizeSmall));
        }
 
        internal GuidHandle GetLanguage(DocumentHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return GuidHandle.FromIndex(Block.PeekHeapReference(rowOffset + _languageOffset, _isGuidHeapRefSizeSmall));
        }
    }
 
    internal readonly struct MethodDebugInformationTableReader
    {
        internal readonly int NumberOfRows;
 
        private readonly bool _isDocumentRefSmall;
        private readonly bool _isBlobHeapRefSizeSmall;
 
        private const int DocumentOffset = 0;
        private readonly int _sequencePointsOffset;
 
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal MethodDebugInformationTableReader(
            int numberOfRows,
            int documentRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isDocumentRefSmall = documentRefSize == 2;
            _isBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 
            _sequencePointsOffset = DocumentOffset + documentRefSize;
            RowSize = _sequencePointsOffset + blobHeapRefSize;
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
        }
 
        internal DocumentHandle GetDocument(MethodDebugInformationHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return DocumentHandle.FromRowId(Block.PeekReference(rowOffset + DocumentOffset, _isDocumentRefSmall));
        }
 
        internal BlobHandle GetSequencePoints(MethodDebugInformationHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _sequencePointsOffset, _isBlobHeapRefSizeSmall));
        }
    }
 
    internal readonly struct LocalScopeTableReader
    {
        internal readonly int NumberOfRows;
 
        private readonly bool _isMethodRefSmall;
        private readonly bool _isImportScopeRefSmall;
        private readonly bool _isLocalConstantRefSmall;
        private readonly bool _isLocalVariableRefSmall;
 
        private const int MethodOffset = 0;
        private readonly int _importScopeOffset;
        private readonly int _variableListOffset;
        private readonly int _constantListOffset;
        private readonly int _startOffsetOffset;
        private readonly int _lengthOffset;
 
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal LocalScopeTableReader(
            int numberOfRows,
            bool declaredSorted,
            int methodRefSize,
            int importScopeRefSize,
            int localVariableRefSize,
            int localConstantRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isMethodRefSmall = methodRefSize == 2;
            _isImportScopeRefSmall = importScopeRefSize == 2;
            _isLocalVariableRefSmall = localVariableRefSize == 2;
            _isLocalConstantRefSmall = localConstantRefSize == 2;
 
            _importScopeOffset = MethodOffset + methodRefSize;
            _variableListOffset = _importScopeOffset + importScopeRefSize;
            _constantListOffset = _variableListOffset + localVariableRefSize;
            _startOffsetOffset = _constantListOffset + localConstantRefSize;
            _lengthOffset = _startOffsetOffset + sizeof(uint);
            RowSize = _lengthOffset + sizeof(uint);
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
 
            if (numberOfRows > 0 && !declaredSorted)
            {
                Throw.TableNotSorted(TableIndex.LocalScope);
            }
        }
 
        internal MethodDefinitionHandle GetMethod(int rowId)
        {
            int rowOffset = (rowId - 1) * RowSize;
            return MethodDefinitionHandle.FromRowId(Block.PeekReference(rowOffset + MethodOffset, _isMethodRefSmall));
        }
 
        internal ImportScopeHandle GetImportScope(LocalScopeHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return ImportScopeHandle.FromRowId(Block.PeekReference(rowOffset + _importScopeOffset, _isImportScopeRefSmall));
        }
 
        internal int GetVariableStart(int rowId)
        {
            int rowOffset = (rowId - 1) * RowSize;
            return Block.PeekReference(rowOffset + _variableListOffset, _isLocalVariableRefSmall);
        }
 
        internal int GetConstantStart(int rowId)
        {
            int rowOffset = (rowId - 1) * RowSize;
            return Block.PeekReference(rowOffset + _constantListOffset, _isLocalConstantRefSmall);
        }
 
        internal int GetStartOffset(int rowId)
        {
            int rowOffset = (rowId - 1) * RowSize;
            return Block.PeekInt32(rowOffset + _startOffsetOffset);
        }
 
        internal int GetLength(int rowId)
        {
            int rowOffset = (rowId - 1) * RowSize;
            return Block.PeekInt32(rowOffset + _lengthOffset);
        }
 
        internal int GetEndOffset(int rowId)
        {
            int rowOffset = (rowId - 1) * RowSize;
 
            long result =
                Block.PeekUInt32(rowOffset + _startOffsetOffset) +
                Block.PeekUInt32(rowOffset + _lengthOffset);
 
            if (unchecked((int)result) != result)
            {
                Throw.ValueOverflow();
            }
 
            return (int)result;
        }
 
        internal void GetLocalScopeRange(int methodDefRid, out int firstScopeRowId, out int lastScopeRowId)
        {
            int startRowNumber, endRowNumber;
            Block.BinarySearchReferenceRange(
                NumberOfRows,
                RowSize,
                MethodOffset,
                (uint)methodDefRid,
                _isMethodRefSmall,
                out startRowNumber,
                out endRowNumber
            );
 
            if (startRowNumber == -1)
            {
                firstScopeRowId = 1;
                lastScopeRowId = 0;
            }
            else
            {
                firstScopeRowId = startRowNumber + 1;
                lastScopeRowId = endRowNumber + 1;
            }
        }
    }
 
    internal readonly struct LocalVariableTableReader
    {
        internal readonly int NumberOfRows;
        private readonly bool _isStringHeapRefSizeSmall;
        private readonly int _attributesOffset;
        private readonly int _indexOffset;
        private readonly int _nameOffset;
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal LocalVariableTableReader(
            int numberOfRows,
            int stringHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset
        )
        {
            NumberOfRows = numberOfRows;
            _isStringHeapRefSizeSmall = stringHeapRefSize == 2;
 
            _attributesOffset = 0;
            _indexOffset = _attributesOffset + sizeof(ushort);
            _nameOffset = _indexOffset + sizeof(ushort);
            RowSize = _nameOffset + stringHeapRefSize;
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
        }
 
        internal LocalVariableAttributes GetAttributes(LocalVariableHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return (LocalVariableAttributes)Block.PeekUInt16(rowOffset + _attributesOffset);
        }
 
        internal ushort GetIndex(LocalVariableHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return Block.PeekUInt16(rowOffset + _indexOffset);
        }
 
        internal StringHandle GetName(LocalVariableHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return StringHandle.FromOffset(Block.PeekHeapReference(rowOffset + _nameOffset, _isStringHeapRefSizeSmall));
        }
    }
 
    internal readonly struct LocalConstantTableReader
    {
        internal readonly int NumberOfRows;
        private readonly bool _isStringHeapRefSizeSmall;
        private readonly bool _isBlobHeapRefSizeSmall;
 
        private const int NameOffset = 0;
        private readonly int _signatureOffset;
 
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal LocalConstantTableReader(
            int numberOfRows,
            int stringHeapRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isStringHeapRefSizeSmall = stringHeapRefSize == 2;
            _isBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 
            _signatureOffset = NameOffset + stringHeapRefSize;
            RowSize = _signatureOffset + blobHeapRefSize;
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
        }
 
        internal StringHandle GetName(LocalConstantHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return StringHandle.FromOffset(Block.PeekHeapReference(rowOffset + NameOffset, _isStringHeapRefSizeSmall));
        }
 
        internal BlobHandle GetSignature(LocalConstantHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _signatureOffset, _isBlobHeapRefSizeSmall));
        }
    }
 
    internal readonly struct StateMachineMethodTableReader
    {
        internal readonly int NumberOfRows;
 
        private readonly bool _isMethodRefSizeSmall;
 
        private const int MoveNextMethodOffset = 0;
        private readonly int _kickoffMethodOffset;
 
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal StateMachineMethodTableReader(
            int numberOfRows,
            bool declaredSorted,
            int methodRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isMethodRefSizeSmall = methodRefSize == 2;
 
            _kickoffMethodOffset = methodRefSize;
            RowSize = _kickoffMethodOffset + methodRefSize;
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
 
            if (numberOfRows > 0 && !declaredSorted)
            {
                Throw.TableNotSorted(TableIndex.StateMachineMethod);
            }
        }
 
        internal MethodDefinitionHandle FindKickoffMethod(int moveNextMethodRowId)
        {
            int foundRowNumber =
              this.Block.BinarySearchReference(
                this.NumberOfRows,
                this.RowSize,
                MoveNextMethodOffset,
                (uint)moveNextMethodRowId,
                _isMethodRefSizeSmall);
 
            if (foundRowNumber < 0)
            {
                return default(MethodDefinitionHandle);
            }
 
            return GetKickoffMethod(foundRowNumber + 1);
        }
 
        private MethodDefinitionHandle GetKickoffMethod(int rowId)
        {
            int rowOffset = (rowId - 1) * RowSize;
            return MethodDefinitionHandle.FromRowId(Block.PeekReference(rowOffset + _kickoffMethodOffset, _isMethodRefSizeSmall));
        }
    }
 
    internal readonly struct ImportScopeTableReader
    {
        internal readonly int NumberOfRows;
 
        private readonly bool _isImportScopeRefSizeSmall;
        private readonly bool _isBlobHeapRefSizeSmall;
 
        private const int ParentOffset = 0;
        private readonly int _importsOffset;
 
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal ImportScopeTableReader(
            int numberOfRows,
            int importScopeRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isImportScopeRefSizeSmall = importScopeRefSize == 2;
            _isBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 
            _importsOffset = ParentOffset + importScopeRefSize;
            RowSize = _importsOffset + blobHeapRefSize;
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
        }
 
        internal ImportScopeHandle GetParent(ImportScopeHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return ImportScopeHandle.FromRowId(Block.PeekReference(rowOffset + ParentOffset, _isImportScopeRefSizeSmall));
        }
 
        internal BlobHandle GetImports(ImportScopeHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _importsOffset, _isBlobHeapRefSizeSmall));
        }
    }
 
    internal readonly struct CustomDebugInformationTableReader
    {
        internal readonly int NumberOfRows;
 
        private readonly bool _isHasCustomDebugInformationRefSizeSmall;
        private readonly bool _isGuidHeapRefSizeSmall;
        private readonly bool _isBlobHeapRefSizeSmall;
 
        private const int ParentOffset = 0;
        private readonly int _kindOffset;
        private readonly int _valueOffset;
 
        internal readonly int RowSize;
        internal readonly MemoryBlock Block;
 
        internal CustomDebugInformationTableReader(
            int numberOfRows,
            bool declaredSorted,
            int hasCustomDebugInformationRefSize,
            int guidHeapRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isHasCustomDebugInformationRefSizeSmall = hasCustomDebugInformationRefSize == 2;
            _isGuidHeapRefSizeSmall = guidHeapRefSize == 2;
            _isBlobHeapRefSizeSmall = blobHeapRefSize == 2;
 
            _kindOffset = ParentOffset + hasCustomDebugInformationRefSize;
            _valueOffset = _kindOffset + guidHeapRefSize;
            RowSize = _valueOffset + blobHeapRefSize;
 
            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
 
            if (numberOfRows > 0 && !declaredSorted)
            {
                Throw.TableNotSorted(TableIndex.CustomDebugInformation);
            }
        }
 
        internal EntityHandle GetParent(CustomDebugInformationHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return HasCustomDebugInformationTag.ConvertToHandle(Block.PeekTaggedReference(rowOffset + ParentOffset, _isHasCustomDebugInformationRefSizeSmall));
        }
 
        internal GuidHandle GetKind(CustomDebugInformationHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return GuidHandle.FromIndex(Block.PeekHeapReference(rowOffset + _kindOffset, _isGuidHeapRefSizeSmall));
        }
 
        internal BlobHandle GetValue(CustomDebugInformationHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;
            return BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _valueOffset, _isBlobHeapRefSizeSmall));
        }
 
        internal void GetRange(EntityHandle parentHandle, out int firstImplRowId, out int lastImplRowId)
        {
            int startRowNumber, endRowNumber;
 
            Block.BinarySearchReferenceRange(
                NumberOfRows,
                RowSize,
                ParentOffset,
                HasCustomDebugInformationTag.ConvertToTag(parentHandle),
                _isHasCustomDebugInformationRefSizeSmall,
                out startRowNumber,
                out endRowNumber
            );
 
            if (startRowNumber == -1)
            {
                firstImplRowId = 1;
                lastImplRowId = 0;
            }
            else
            {
                firstImplRowId = startRowNumber + 1;
                lastImplRowId = endRowNumber + 1;
            }
        }
    }
}