< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 66
Coverable lines: 66
Total lines: 200
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 12
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
FromVToken(...)100%110%
.ctor(...)0%660%
Equals(...)0%220%
Equals(...)0%220%
GetHashCode()100%110%
op_Equality(...)100%110%
op_Inequality(...)100%110%
Compare(...)100%110%
.cctor()100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Handle.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.Diagnostics.CodeAnalysis;
 6using System.Reflection.Metadata.Ecma335;
 7
 8namespace System.Reflection.Metadata
 9{
 10    /// <summary>
 11    /// Represents any metadata entity (type reference/definition/specification, method definition, custom attribute, et
 12    /// </summary>
 13    /// <remarks>
 14    /// Use <see cref="Handle"/> to store multiple kinds of handles.
 15    /// </remarks>
 16    public readonly struct Handle : IEquatable<Handle>
 17    {
 18        private readonly int _value;
 19
 20        // bits:
 21        //    7: IsVirtual
 22        // 0..6: token type
 23        private readonly byte _vType;
 24
 25        /// <summary>
 26        /// Creates <see cref="Handle"/> from a token or a token combined with a virtual flag.
 27        /// </summary>
 28        internal static Handle FromVToken(uint vToken)
 029        {
 030            return new Handle((byte)(vToken >> TokenTypeIds.RowIdBitCount), (int)(vToken & TokenTypeIds.RIDMask));
 031        }
 32
 33        internal Handle(byte vType, int value)
 034        {
 035            _vType = vType;
 036            _value = value;
 37
 038            Debug.Assert(value >= 0);
 39
 40            // No table can have more than 2^24 rows.
 41            // User String heap is also limited by 2^24 since user strings have tokens in IL.
 42            // We limit the size of #Blob, #String and #GUID heaps to 2^29 (max compressed integer) in order
 43            // to keep the sizes of corresponding handles to 32 bit. As a result we don't support reading metadata
 44            // files with heaps larger than 0.5GB.
 045            Debug.Assert(IsHeapHandle && value <= HeapHandleType.OffsetMask ||
 046                         !IsHeapHandle && value <= TokenTypeIds.RIDMask);
 047        }
 48
 49        // for entity handles:
 50        internal int RowId
 51        {
 52            get
 053            {
 054                Debug.Assert(!IsHeapHandle);
 055                return _value;
 056            }
 57        }
 58
 59        // for heap handles:
 60        internal int Offset
 61        {
 62            get
 063            {
 064                Debug.Assert(IsHeapHandle);
 065                return _value;
 066            }
 67        }
 68
 69        /// <summary>
 70        /// Token type (0x##000000), does not include virtual flag.
 71        /// </summary>
 72        internal uint EntityHandleType
 73        {
 074            get { return Type << TokenTypeIds.RowIdBitCount; }
 75        }
 76
 77        /// <summary>
 78        /// Small token type (0x##), does not include virtual flag.
 79        /// </summary>
 80        internal uint Type
 81        {
 082            get { return _vType & HandleType.TypeMask; }
 83        }
 84
 85        /// <summary>
 86        /// Value stored in an <see cref="EntityHandle"/>.
 87        /// </summary>
 88        internal uint EntityHandleValue
 89        {
 90            get
 091            {
 092                Debug.Assert((_value & TokenTypeIds.RIDMask) == _value);
 093                return (uint)_vType << TokenTypeIds.RowIdBitCount | (uint)_value;
 094            }
 95        }
 96
 97        /// <summary>
 98        /// Value stored in a concrete entity handle (see <see cref="TypeDefinitionHandle"/>, <see cref="MethodDefinitio
 99        /// </summary>
 100        internal uint SpecificEntityHandleValue
 101        {
 102            get
 0103            {
 0104                Debug.Assert((_value & TokenTypeIds.RIDMask) == _value);
 0105                return (_vType & HandleType.VirtualBit) << TokenTypeIds.RowIdBitCount | (uint)_value;
 0106            }
 107        }
 108
 109        internal byte VType
 110        {
 0111            get { return _vType; }
 112        }
 113
 114        internal bool IsVirtual
 115        {
 0116            get { return (_vType & HandleType.VirtualBit) != 0; }
 117        }
 118
 119        internal bool IsHeapHandle
 120        {
 0121            get { return (_vType & HandleType.HeapMask) == HandleType.HeapMask; }
 122        }
 123
 124        public HandleKind Kind
 125        {
 126            get
 0127            {
 0128                uint type = Type;
 129
 130                // Do not surface extra non-virtual string type bits in public handle kind
 0131                if ((type & ~HandleType.NonVirtualStringTypeMask) == HandleType.String)
 0132                {
 0133                    return HandleKind.String;
 134                }
 135
 0136                return (HandleKind)type;
 0137            }
 138        }
 139
 140        public bool IsNil
 141        {
 142            // virtual handles are never nil
 0143            get { return ((uint)_value | (_vType & HandleType.VirtualBit)) == 0; }
 144        }
 145
 146        internal bool IsEntityOrUserStringHandle
 147        {
 0148            get { return Type <= HandleType.UserString; }
 149        }
 150
 151        internal int Token
 152        {
 153            get
 0154            {
 0155                Debug.Assert(IsEntityOrUserStringHandle);
 0156                Debug.Assert(!IsVirtual);
 0157                Debug.Assert((_value & TokenTypeIds.RIDMask) == _value);
 158
 0159                return _vType << TokenTypeIds.RowIdBitCount | _value;
 0160            }
 161        }
 162
 163        public override bool Equals([NotNullWhen(true)] object? obj)
 0164        {
 0165            return obj is Handle handle && Equals(handle);
 0166        }
 167
 168        public bool Equals(Handle other)
 0169        {
 0170            return _value == other._value && _vType == other._vType;
 0171        }
 172
 173        public override int GetHashCode()
 0174        {
 0175            return _value ^ (_vType << 24);
 0176        }
 177
 178        public static bool operator ==(Handle left, Handle right)
 0179        {
 0180            return left.Equals(right);
 0181        }
 182
 183        public static bool operator !=(Handle left, Handle right)
 0184        {
 0185            return !left.Equals(right);
 0186        }
 187
 188        internal static int Compare(Handle left, Handle right)
 0189        {
 190            // All virtual tokens will be sorted after non-virtual tokens.
 191            // The order of handles that differ in kind is undefined,
 192            // but we include it so that we ensure consistency with == and != operators.
 0193            return ((long)(uint)left._value | (long)left._vType << 32).CompareTo((long)(uint)right._value | (long)right.
 0194        }
 195
 0196        public static readonly ModuleDefinitionHandle ModuleDefinition = new ModuleDefinitionHandle(1);
 0197        public static readonly AssemblyDefinitionHandle AssemblyDefinition = new AssemblyDefinitionHandle(1);
 198    }
 199}
 200