| File: System\Reflection\Metadata\Ecma335\MetadataTokens.cs | Web Access |
| Project: src\runtime\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. namespace System.Reflection.Metadata.Ecma335 { public static class MetadataTokens { /// <summary> /// Maximum number of tables that can be present in Ecma335 metadata. /// </summary> public static readonly int TableCount = 64; // headers use 64bit table masks /// <summary> /// Maximum number of tables that can be present in Ecma335 metadata. /// </summary> public static readonly int HeapCount = HeapIndexExtensions.Count; /// <summary> /// Returns the row number of a metadata table entry that corresponds /// to the specified <paramref name="handle"/> in the context of <paramref name="reader"/>. /// </summary> /// <returns>One based row number.</returns> /// <exception cref="ArgumentException">The <paramref name="handle"/> is not a valid metadata table handle.</exception> public static int GetRowNumber(this MetadataReader reader, EntityHandle handle) { if (handle.IsVirtual) { return MapVirtualHandleRowId(reader, handle); } return handle.RowId; } /// <summary> /// Returns the offset of metadata heap data that corresponds /// to the specified <paramref name="handle"/> in the context of <paramref name="reader"/>. /// </summary> /// <returns>Zero based offset, or -1 if <paramref name="handle"/> isn't a metadata heap handle.</returns> /// <exception cref="NotSupportedException">The operation is not supported for the specified <paramref name="handle"/>.</exception> /// <exception cref="ArgumentException">The <paramref name="handle"/> is invalid.</exception> public static int GetHeapOffset(this MetadataReader reader, Handle handle) { if (!handle.IsHeapHandle) { Throw.HeapHandleRequired(); } if (handle.IsVirtual) { return MapVirtualHandleRowId(reader, handle); } return handle.Offset; } /// <summary> /// Returns the metadata token of the specified <paramref name="handle"/> in the context of <paramref name="reader"/>. /// </summary> /// <returns>Metadata token.</returns> /// <exception cref="NotSupportedException">The operation is not supported for the specified <paramref name="handle"/>.</exception> public static int GetToken(this MetadataReader reader, EntityHandle handle) { if (handle.IsVirtual) { return (int)handle.Type | MapVirtualHandleRowId(reader, handle); } return handle.Token; } /// <summary> /// Returns the metadata token of the specified <paramref name="handle"/> in the context of <paramref name="reader"/>. /// </summary> /// <returns>Metadata token.</returns> /// <exception cref="ArgumentException"> /// Handle represents a metadata entity that doesn't have a token. /// A token can only be retrieved for a metadata table handle or a heap handle of type <see cref="HandleKind.UserString"/>. /// </exception> /// <exception cref="NotSupportedException">The operation is not supported for the specified <paramref name="handle"/>.</exception> public static int GetToken(this MetadataReader reader, Handle handle) { if (!handle.IsEntityOrUserStringHandle) { Throw.EntityOrUserStringHandleRequired(); } if (handle.IsVirtual) { return (int)handle.EntityHandleType | MapVirtualHandleRowId(reader, handle); } return handle.Token; } private static int MapVirtualHandleRowId(MetadataReader reader, Handle handle) { switch (handle.Kind) { case HandleKind.AssemblyReference: // pretend that virtual rows immediately follow real rows: return reader.AssemblyRefTable.NumberOfNonVirtualRows + 1 + handle.RowId; case HandleKind.String: case HandleKind.Blob: // We could precalculate offsets for virtual strings and blobs as we are creating them // if we wanted to implement this. throw new NotSupportedException(SR.CantGetOffsetForVirtualHeapHandle); default: Throw.InvalidArgument_UnexpectedHandleKind(handle.Kind); return 0; } } /// <summary> /// Returns the row number of a metadata table entry that corresponds /// to the specified <paramref name="handle"/>. /// </summary> /// <returns> /// One based row number, or -1 if <paramref name="handle"/> can only be interpreted in a context of a specific <see cref="MetadataReader"/>. /// See <see cref="GetRowNumber(MetadataReader, EntityHandle)"/>. /// </returns> public static int GetRowNumber(EntityHandle handle) { return handle.IsVirtual ? -1 : handle.RowId; } /// <summary> /// Returns the offset of metadata heap data that corresponds /// to the specified <paramref name="handle"/>. /// </summary> /// <returns> /// An offset in the corresponding heap, or -1 if <paramref name="handle"/> can only be interpreted in a context of a specific <see cref="MetadataReader"/> or <see cref="MetadataBuilder"/>. /// See <see cref="GetHeapOffset(MetadataReader, Handle)"/>. /// </returns> public static int GetHeapOffset(Handle handle) { if (!handle.IsHeapHandle) { Throw.HeapHandleRequired(); } if (handle.IsVirtual) { return -1; } return handle.Offset; } /// <summary> /// Returns the offset of metadata heap data that corresponds /// to the specified <paramref name="handle"/>. /// </summary> /// <returns> /// Zero based offset, or -1 if <paramref name="handle"/> can only be interpreted in a context of a specific <see cref="MetadataReader"/> or <see cref="MetadataBuilder"/>. /// See <see cref="GetHeapOffset(MetadataReader, Handle)"/>. /// </returns> public static int GetHeapOffset(BlobHandle handle) => handle.IsVirtual ? -1 : handle.GetHeapOffset(); /// <summary> /// Returns the offset of metadata heap data that corresponds /// to the specified <paramref name="handle"/>. /// </summary> /// <returns> /// 1-based index into the #Guid heap. Unlike other heaps, which are essentially byte arrays, the #Guid heap is an array of 16-byte GUIDs. /// </returns> public static int GetHeapOffset(GuidHandle handle) => handle.Index; /// <summary> /// Returns the offset of metadata heap data that corresponds /// to the specified <paramref name="handle"/>. /// </summary> /// <returns> /// Zero based offset. /// </returns> public static int GetHeapOffset(UserStringHandle handle) => handle.GetHeapOffset(); /// <summary> /// Returns the offset of metadata heap data that corresponds /// to the specified <paramref name="handle"/>. /// </summary> /// <returns> /// Zero based offset, or -1 if <paramref name="handle"/> can only be interpreted in a context of a specific <see cref="MetadataReader"/> or <see cref="MetadataBuilder"/>. /// See <see cref="GetHeapOffset(MetadataReader, Handle)"/>. /// </returns> public static int GetHeapOffset(StringHandle handle) => handle.IsVirtual ? -1 : handle.GetHeapOffset(); /// <summary> /// Returns the metadata token of the specified <paramref name="handle"/>. /// </summary> /// <returns> /// Metadata token, or 0 if <paramref name="handle"/> can only be interpreted in a context of a specific <see cref="MetadataReader"/>. /// See <see cref="GetToken(MetadataReader, Handle)"/>. /// </returns> /// <exception cref="ArgumentException"> /// Handle represents a metadata entity that doesn't have a token. /// A token can only be retrieved for a metadata table handle or a heap handle of type <see cref="HandleKind.UserString"/>. /// </exception> public static int GetToken(Handle handle) { if (!handle.IsEntityOrUserStringHandle) { Throw.EntityOrUserStringHandleRequired(); } if (handle.IsVirtual) { return 0; } return handle.Token; } /// <summary> /// Returns the metadata token of the specified <paramref name="handle"/>. /// </summary> /// <returns> /// Metadata token, or 0 if <paramref name="handle"/> can only be interpreted in a context of a specific <see cref="MetadataReader"/>. /// See <see cref="GetToken(MetadataReader, EntityHandle)"/>. /// </returns> public static int GetToken(EntityHandle handle) { return handle.IsVirtual ? 0 : handle.Token; } /// <summary> /// Gets the <see cref="TableIndex"/> of the table corresponding to the specified <see cref="HandleKind"/>. /// </summary> /// <param name="type">Handle type.</param> /// <param name="index">Table index.</param> /// <returns>True if the handle type corresponds to an Ecma335 or Portable PDB table, false otherwise.</returns> public static bool TryGetTableIndex(HandleKind type, out TableIndex index) { // We don't have a HandleKind for PropertyMap, EventMap, MethodSemantics, *Ptr, AssemblyOS, etc. tables, // but one can get ahold of one by creating a handle from a token and getting its Kind. if ((int)type < TableCount && ((1UL << (int)type) & (ulong)TableMask.AllTables) != 0) { index = (TableIndex)type; return true; } index = 0; return false; } /// <summary> /// Gets the <see cref="HeapIndex"/> of the heap corresponding to the specified <see cref="HandleKind"/>. /// </summary> /// <param name="type">Handle type.</param> /// <param name="index">Heap index.</param> /// <returns>True if the handle type corresponds to an Ecma335 heap, false otherwise.</returns> public static bool TryGetHeapIndex(HandleKind type, out HeapIndex index) { switch (type) { case HandleKind.UserString: index = HeapIndex.UserString; return true; case HandleKind.String: case HandleKind.NamespaceDefinition: index = HeapIndex.String; return true; case HandleKind.Blob: index = HeapIndex.Blob; return true; case HandleKind.Guid: index = HeapIndex.Guid; return true; default: index = 0; return false; } } #region Handle Factories /// <summary> /// Creates a handle from a token value. /// </summary> /// <exception cref="ArgumentException"> /// <paramref name="token"/> is not a valid metadata token. /// It must encode a metadata table entity or an offset in <see cref="HandleKind.UserString"/> heap. /// </exception> public static Handle Handle(int token) { if (!TokenTypeIds.IsEntityOrUserStringToken(unchecked((uint)token))) { Throw.InvalidToken(); } return Metadata.Handle.FromVToken((uint)token); } /// <summary> /// Creates an entity handle from a token value. /// </summary> /// <exception cref="ArgumentException"><paramref name="token"/> is not a valid metadata entity token.</exception> public static EntityHandle EntityHandle(int token) { if (!TokenTypeIds.IsEntityToken(unchecked((uint)token))) { Throw.InvalidToken(); } return new EntityHandle((uint)token); } /// <summary> /// Creates an <see cref="Metadata.EntityHandle"/> from a token value. /// </summary> /// <exception cref="ArgumentException"> /// <paramref name="tableIndex"/> is not a valid table index.</exception> public static EntityHandle EntityHandle(TableIndex tableIndex, int rowNumber) { return Handle(tableIndex, rowNumber); } /// <summary> /// Creates an <see cref="Metadata.EntityHandle"/> from a token value. /// </summary> /// <exception cref="ArgumentException"> /// <paramref name="tableIndex"/> is not a valid table index.</exception> public static EntityHandle Handle(TableIndex tableIndex, int rowNumber) { int token = ((int)tableIndex << TokenTypeIds.RowIdBitCount) | rowNumber; if (!TokenTypeIds.IsEntityOrUserStringToken(unchecked((uint)token))) { Throw.TableIndexOutOfRange(); } return new EntityHandle((uint)token); } private static int ToRowId(int rowNumber) { return rowNumber & (int)TokenTypeIds.RIDMask; } public static MethodDefinitionHandle MethodDefinitionHandle(int rowNumber) { return Metadata.MethodDefinitionHandle.FromRowId(ToRowId(rowNumber)); } public static MethodImplementationHandle MethodImplementationHandle(int rowNumber) { return Metadata.MethodImplementationHandle.FromRowId(ToRowId(rowNumber)); } public static MethodSpecificationHandle MethodSpecificationHandle(int rowNumber) { return Metadata.MethodSpecificationHandle.FromRowId(ToRowId(rowNumber)); } public static TypeDefinitionHandle TypeDefinitionHandle(int rowNumber) { return Metadata.TypeDefinitionHandle.FromRowId(ToRowId(rowNumber)); } public static ExportedTypeHandle ExportedTypeHandle(int rowNumber) { return Metadata.ExportedTypeHandle.FromRowId(ToRowId(rowNumber)); } public static TypeReferenceHandle TypeReferenceHandle(int rowNumber) { return Metadata.TypeReferenceHandle.FromRowId(ToRowId(rowNumber)); } public static TypeSpecificationHandle TypeSpecificationHandle(int rowNumber) { return Metadata.TypeSpecificationHandle.FromRowId(ToRowId(rowNumber)); } public static InterfaceImplementationHandle InterfaceImplementationHandle(int rowNumber) { return Metadata.InterfaceImplementationHandle.FromRowId(ToRowId(rowNumber)); } public static MemberReferenceHandle MemberReferenceHandle(int rowNumber) { return Metadata.MemberReferenceHandle.FromRowId(ToRowId(rowNumber)); } public static FieldDefinitionHandle FieldDefinitionHandle(int rowNumber) { return Metadata.FieldDefinitionHandle.FromRowId(ToRowId(rowNumber)); } public static EventDefinitionHandle EventDefinitionHandle(int rowNumber) { return Metadata.EventDefinitionHandle.FromRowId(ToRowId(rowNumber)); } public static PropertyDefinitionHandle PropertyDefinitionHandle(int rowNumber) { return Metadata.PropertyDefinitionHandle.FromRowId(ToRowId(rowNumber)); } public static StandaloneSignatureHandle StandaloneSignatureHandle(int rowNumber) { return Metadata.StandaloneSignatureHandle.FromRowId(ToRowId(rowNumber)); } public static ParameterHandle ParameterHandle(int rowNumber) { return Metadata.ParameterHandle.FromRowId(ToRowId(rowNumber)); } public static GenericParameterHandle GenericParameterHandle(int rowNumber) { return Metadata.GenericParameterHandle.FromRowId(ToRowId(rowNumber)); } public static GenericParameterConstraintHandle GenericParameterConstraintHandle(int rowNumber) { return Metadata.GenericParameterConstraintHandle.FromRowId(ToRowId(rowNumber)); } public static ModuleReferenceHandle ModuleReferenceHandle(int rowNumber) { return Metadata.ModuleReferenceHandle.FromRowId(ToRowId(rowNumber)); } public static AssemblyReferenceHandle AssemblyReferenceHandle(int rowNumber) { return Metadata.AssemblyReferenceHandle.FromRowId(ToRowId(rowNumber)); } public static CustomAttributeHandle CustomAttributeHandle(int rowNumber) { return Metadata.CustomAttributeHandle.FromRowId(ToRowId(rowNumber)); } public static DeclarativeSecurityAttributeHandle DeclarativeSecurityAttributeHandle(int rowNumber) { return Metadata.DeclarativeSecurityAttributeHandle.FromRowId(ToRowId(rowNumber)); } public static ConstantHandle ConstantHandle(int rowNumber) { return Metadata.ConstantHandle.FromRowId(ToRowId(rowNumber)); } public static ManifestResourceHandle ManifestResourceHandle(int rowNumber) { return Metadata.ManifestResourceHandle.FromRowId(ToRowId(rowNumber)); } public static AssemblyFileHandle AssemblyFileHandle(int rowNumber) { return Metadata.AssemblyFileHandle.FromRowId(ToRowId(rowNumber)); } // debug public static DocumentHandle DocumentHandle(int rowNumber) { return Metadata.DocumentHandle.FromRowId(ToRowId(rowNumber)); } public static MethodDebugInformationHandle MethodDebugInformationHandle(int rowNumber) { return Metadata.MethodDebugInformationHandle.FromRowId(ToRowId(rowNumber)); } public static LocalScopeHandle LocalScopeHandle(int rowNumber) { return Metadata.LocalScopeHandle.FromRowId(ToRowId(rowNumber)); } public static LocalVariableHandle LocalVariableHandle(int rowNumber) { return Metadata.LocalVariableHandle.FromRowId(ToRowId(rowNumber)); } public static LocalConstantHandle LocalConstantHandle(int rowNumber) { return Metadata.LocalConstantHandle.FromRowId(ToRowId(rowNumber)); } public static ImportScopeHandle ImportScopeHandle(int rowNumber) { return Metadata.ImportScopeHandle.FromRowId(ToRowId(rowNumber)); } public static CustomDebugInformationHandle CustomDebugInformationHandle(int rowNumber) { return Metadata.CustomDebugInformationHandle.FromRowId(ToRowId(rowNumber)); } // heaps public static UserStringHandle UserStringHandle(int offset) { return Metadata.UserStringHandle.FromOffset(offset & (int)TokenTypeIds.RIDMask); } public static StringHandle StringHandle(int offset) { return Metadata.StringHandle.FromOffset(offset); } public static BlobHandle BlobHandle(int offset) { return Metadata.BlobHandle.FromOffset(offset); } public static GuidHandle GuidHandle(int offset) { return Metadata.GuidHandle.FromIndex(offset); } public static DocumentNameBlobHandle DocumentNameBlobHandle(int offset) { return Metadata.DocumentNameBlobHandle.FromOffset(offset); } #endregion } }