| File: System\Reflection\Metadata\Handle.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. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata.Ecma335; namespace System.Reflection.Metadata { /// <summary> /// Represents any metadata entity (type reference/definition/specification, method definition, custom attribute, etc.) or value (string, blob, guid, user string). /// </summary> /// <remarks> /// Use <see cref="Handle"/> to store multiple kinds of handles. /// </remarks> public readonly struct Handle : IEquatable<Handle> { private readonly int _value; // bits: // 7: IsVirtual // 0..6: token type private readonly byte _vType; /// <summary> /// Creates <see cref="Handle"/> from a token or a token combined with a virtual flag. /// </summary> internal static Handle FromVToken(uint vToken) { return new Handle((byte)(vToken >> TokenTypeIds.RowIdBitCount), (int)(vToken & TokenTypeIds.RIDMask)); } internal Handle(byte vType, int value) { _vType = vType; _value = value; Debug.Assert(value >= 0); // No table can have more than 2^24 rows. // User String heap is also limited by 2^24 since user strings have tokens in IL. // We limit the size of #Blob, #String and #GUID heaps to 2^29 (max compressed integer) in order // to keep the sizes of corresponding handles to 32 bit. As a result we don't support reading metadata // files with heaps larger than 0.5GB. Debug.Assert(IsHeapHandle && value <= HeapHandleType.OffsetMask || !IsHeapHandle && value <= TokenTypeIds.RIDMask); } // for entity handles: internal int RowId { get { Debug.Assert(!IsHeapHandle); return _value; } } // for heap handles: internal int Offset { get { Debug.Assert(IsHeapHandle); return _value; } } /// <summary> /// Token type (0x##000000), does not include virtual flag. /// </summary> internal uint EntityHandleType { get { return Type << TokenTypeIds.RowIdBitCount; } } /// <summary> /// Small token type (0x##), does not include virtual flag. /// </summary> internal uint Type { get { return _vType & HandleType.TypeMask; } } /// <summary> /// Value stored in an <see cref="EntityHandle"/>. /// </summary> internal uint EntityHandleValue { get { Debug.Assert((_value & TokenTypeIds.RIDMask) == _value); return (uint)_vType << TokenTypeIds.RowIdBitCount | (uint)_value; } } /// <summary> /// Value stored in a concrete entity handle (see <see cref="TypeDefinitionHandle"/>, <see cref="MethodDefinitionHandle"/>, etc.). /// </summary> internal uint SpecificEntityHandleValue { get { Debug.Assert((_value & TokenTypeIds.RIDMask) == _value); return (_vType & HandleType.VirtualBit) << TokenTypeIds.RowIdBitCount | (uint)_value; } } internal byte VType { get { return _vType; } } internal bool IsVirtual { get { return (_vType & HandleType.VirtualBit) != 0; } } internal bool IsHeapHandle { get { return (_vType & HandleType.HeapMask) == HandleType.HeapMask; } } public HandleKind Kind { get { uint type = Type; // Do not surface extra non-virtual string type bits in public handle kind if ((type & ~HandleType.NonVirtualStringTypeMask) == HandleType.String) { return HandleKind.String; } return (HandleKind)type; } } public bool IsNil { // virtual handles are never nil get { return ((uint)_value | (_vType & HandleType.VirtualBit)) == 0; } } internal bool IsEntityOrUserStringHandle { get { return Type <= HandleType.UserString; } } internal int Token { get { Debug.Assert(IsEntityOrUserStringHandle); Debug.Assert(!IsVirtual); Debug.Assert((_value & TokenTypeIds.RIDMask) == _value); return _vType << TokenTypeIds.RowIdBitCount | _value; } } public override bool Equals([NotNullWhen(true)] object? obj) { return obj is Handle handle && Equals(handle); } public bool Equals(Handle other) { return _value == other._value && _vType == other._vType; } public override int GetHashCode() { return _value ^ (_vType << 24); } public static bool operator ==(Handle left, Handle right) { return left.Equals(right); } public static bool operator !=(Handle left, Handle right) { return !left.Equals(right); } internal static int Compare(Handle left, Handle right) { // All virtual tokens will be sorted after non-virtual tokens. // The order of handles that differ in kind is undefined, // but we include it so that we ensure consistency with == and != operators. return ((long)(uint)left._value | (long)left._vType << 32).CompareTo((long)(uint)right._value | (long)right._vType << 32); } public static readonly ModuleDefinitionHandle ModuleDefinition = new ModuleDefinitionHandle(1); public static readonly AssemblyDefinitionHandle AssemblyDefinition = new AssemblyDefinitionHandle(1); } }