// dnlib: See LICENSE.txt for more info
using System;
namespace dnlib.DotNet.MD {
///
/// Contains all possible coded token classes
///
public sealed class CodedToken {
/// TypeDefOrRef coded token
public static readonly CodedToken TypeDefOrRef = new CodedToken(2, new Table[3] {
Table.TypeDef, Table.TypeRef, Table.TypeSpec,
});
/// HasConstant coded token
public static readonly CodedToken HasConstant = new CodedToken(2, new Table[3] {
Table.Field, Table.Param, Table.Property,
});
/// HasCustomAttribute coded token
public static readonly CodedToken HasCustomAttribute = new CodedToken(5, new Table[24] {
Table.Method, Table.Field, Table.TypeRef, Table.TypeDef,
Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module,
Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig,
Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef,
Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam,
Table.GenericParamConstraint, Table.MethodSpec, 0, 0,
});
/// HasFieldMarshal coded token
public static readonly CodedToken HasFieldMarshal = new CodedToken(1, new Table[2] {
Table.Field, Table.Param,
});
/// HasDeclSecurity coded token
public static readonly CodedToken HasDeclSecurity = new CodedToken(2, new Table[3] {
Table.TypeDef, Table.Method, Table.Assembly,
});
/// MemberRefParent coded token
public static readonly CodedToken MemberRefParent = new CodedToken(3, new Table[5] {
Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method,
Table.TypeSpec,
});
/// HasSemantic coded token
public static readonly CodedToken HasSemantic = new CodedToken(1, new Table[2] {
Table.Event, Table.Property,
});
/// MethodDefOrRef coded token
public static readonly CodedToken MethodDefOrRef = new CodedToken(1, new Table[2] {
Table.Method, Table.MemberRef,
});
/// MemberForwarded coded token
public static readonly CodedToken MemberForwarded = new CodedToken(1, new Table[2] {
Table.Field, Table.Method,
});
/// Implementation coded token
public static readonly CodedToken Implementation = new CodedToken(2, new Table[3] {
Table.File, Table.AssemblyRef, Table.ExportedType,
});
/// CustomAttributeType coded token
public static readonly CodedToken CustomAttributeType = new CodedToken(3, new Table[5] {
0, 0, Table.Method, Table.MemberRef, 0,
});
/// ResolutionScope coded token
public static readonly CodedToken ResolutionScope = new CodedToken(2, new Table[4] {
Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef,
});
/// TypeOrMethodDef coded token
public static readonly CodedToken TypeOrMethodDef = new CodedToken(1, new Table[2] {
Table.TypeDef, Table.Method,
});
/// HasCustomDebugInformation coded token
public static readonly CodedToken HasCustomDebugInformation = new CodedToken(5, new Table[27] {
Table.Method, Table.Field, Table.TypeRef, Table.TypeDef,
Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module,
Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig,
Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef,
Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam,
Table.GenericParamConstraint, Table.MethodSpec, Table.Document, Table.LocalScope,
Table.LocalVariable, Table.LocalConstant, Table.ImportScope,
});
readonly Table[] tableTypes;
readonly int bits;
readonly int mask;
///
/// Returns all types of tables
///
public Table[] TableTypes => tableTypes;
///
/// Returns the number of bits that is used to encode table type
///
public int Bits => bits;
///
/// Constructor
///
/// Number of bits used to encode token type
/// All table types
internal CodedToken(int bits, Table[] tableTypes) {
this.bits = bits;
mask = (1 << bits) - 1;
this.tableTypes = tableTypes;
}
///
/// Encodes a token
///
/// The token
/// Coded token
///
public uint Encode(MDToken token) => Encode(token.Raw);
///
/// Encodes a token
///
/// The token
/// Coded token
///
public uint Encode(uint token) {
Encode(token, out uint codedToken);
return codedToken;
}
///
/// Encodes a token
///
/// The token
/// Coded token
/// true if successful
public bool Encode(MDToken token, out uint codedToken) => Encode(token.Raw, out codedToken);
///
/// Encodes a token
///
/// The token
/// Coded token
/// true if successful
public bool Encode(uint token, out uint codedToken) {
int index = Array.IndexOf(tableTypes, MDToken.ToTable(token));
if (index < 0) {
codedToken = uint.MaxValue;
return false;
}
// This shift can never overflow a uint since bits < 8 (it's at most 5), and
// ToRid() returns an integer <= 0x00FFFFFF.
codedToken = (MDToken.ToRID(token) << bits) | (uint)index;
return true;
}
///
/// Decodes a coded token
///
/// The coded token
/// Decoded token or 0 on failure
///
public MDToken Decode2(uint codedToken) {
Decode(codedToken, out uint token);
return new MDToken(token);
}
///
/// Decodes a coded token
///
/// The coded token
/// Decoded token or 0 on failure
///
public uint Decode(uint codedToken) {
Decode(codedToken, out uint token);
return token;
}
///
/// Decodes a coded token
///
/// The coded token
/// Decoded token
/// true if successful
public bool Decode(uint codedToken, out MDToken token) {
bool result = Decode(codedToken, out uint decodedToken);
token = new MDToken(decodedToken);
return result;
}
///
/// Decodes a coded token
///
/// The coded token
/// Decoded token
/// true if successful
public bool Decode(uint codedToken, out uint token) {
uint rid = codedToken >> bits;
int index = (int)(codedToken & mask);
if (rid > MDToken.RID_MAX || index >= tableTypes.Length) {
token = 0;
return false;
}
token = ((uint)tableTypes[index] << MDToken.TABLE_SHIFT) | rid;
return true;
}
}
}