/
EntityHandle.cs
134 lines (113 loc) · 4.02 KB
/
EntityHandle.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// 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 a metadata entity (type reference/definition/specification, method definition, custom attribute, etc.).
/// </summary>
/// <remarks>
/// Use <see cref="EntityHandle"/> to store multiple kinds of entity handles.
/// It has smaller memory footprint than <see cref="Handle"/>.
/// </remarks>
public readonly struct EntityHandle : IEquatable<EntityHandle>
{
// bits:
// 31: IsVirtual
// 24..30: type
// 0..23: row id
private readonly uint _vToken;
internal EntityHandle(uint vToken)
{
_vToken = vToken;
}
public static implicit operator Handle(EntityHandle handle)
{
return Handle.FromVToken(handle._vToken);
}
public static explicit operator EntityHandle(Handle handle)
{
if (handle.IsHeapHandle)
{
Throw.InvalidCast();
}
return new EntityHandle(handle.EntityHandleValue);
}
internal uint Type
{
get { return _vToken & TokenTypeIds.TypeMask; }
}
internal uint VType
{
get { return _vToken & (TokenTypeIds.VirtualBit | TokenTypeIds.TypeMask); }
}
internal bool IsVirtual
{
get { return (_vToken & TokenTypeIds.VirtualBit) != 0; }
}
public bool IsNil
{
// virtual handle is never nil
get { return (_vToken & (TokenTypeIds.VirtualBit | TokenTypeIds.RIDMask)) == 0; }
}
internal int RowId
{
get { return (int)(_vToken & TokenTypeIds.RIDMask); }
}
/// <summary>
/// Value stored in a specific entity handle (see <see cref="TypeDefinitionHandle"/>, <see cref="MethodDefinitionHandle"/>, etc.).
/// </summary>
internal uint SpecificHandleValue
{
get { return _vToken & (TokenTypeIds.VirtualBit | TokenTypeIds.RIDMask); }
}
public HandleKind Kind
{
get
{
// EntityHandles cannot be StringHandles and therefore we do not need
// to handle stripping the extra non-virtual string type bits here.
return (HandleKind)(Type >> TokenTypeIds.RowIdBitCount);
}
}
internal int Token
{
get
{
Debug.Assert(!IsVirtual);
return (int)_vToken;
}
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
return obj is EntityHandle entityHandle && Equals(entityHandle);
}
public bool Equals(EntityHandle other)
{
return _vToken == other._vToken;
}
public override int GetHashCode()
{
return unchecked((int)_vToken);
}
public static bool operator ==(EntityHandle left, EntityHandle right)
{
return left.Equals(right);
}
public static bool operator !=(EntityHandle left, EntityHandle right)
{
return !left.Equals(right);
}
internal static int Compare(EntityHandle left, EntityHandle 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 left._vToken.CompareTo(right._vToken);
}
public static readonly ModuleDefinitionHandle ModuleDefinition = new ModuleDefinitionHandle(1);
public static readonly AssemblyDefinitionHandle AssemblyDefinition = new AssemblyDefinitionHandle(1);
}
}