using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Hamunii")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.7.14.0")] [assembly: AssemblyInformationalVersion("0.7.14+0d55abe3fd0d330206803b376c57bc7135c48257")] [assembly: AssemblyProduct("MonoDetour.Reflection")] [assembly: AssemblyTitle("MonoDetour.Reflection")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/MonoDetour/MonoDetour")] [assembly: AssemblyVersion("0.7.14.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MonoDetour.Reflection.Unspeakable { public delegate ref T EnumeratorFieldReferenceGetter(IEnumerator instance); internal static class F195F66C6DA9E115B6F6704672598F4179F4F7206901F87F23A1D221B9EE964B6__EnumeratorExtensionsCache { internal static readonly ConcurrentDictionary<(Type, int), EnumeratorFieldReferenceGetter> s_FieldToRef = new ConcurrentDictionary<(Type, int), EnumeratorFieldReferenceGetter>(); internal static readonly ConcurrentDictionary<(Type, string), EnumeratorFieldReferenceGetter> s_3ToRef = new ConcurrentDictionary<(Type, string), EnumeratorFieldReferenceGetter>(); } public static class EnumeratorReflection { private const string DeclaringTypeNull = "Declaring type of method is null!"; public static void EnumeratorFastFieldReferenceThis(this MethodInfo methodInfo, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = methodInfo.EnumeratorFastFieldReferenceThis(); } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReferenceThis(this MethodInfo methodInfo) { return methodInfo.DeclaringType?.EnumeratorFastFieldReferenceThis() ?? throw new NullReferenceException("Declaring type of method is null!"); } public static void EnumeratorFastFieldReferenceThis(this Type enumeratorType, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = enumeratorType.EnumeratorFastFieldReferenceThis(); } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReferenceThis(this Type enumeratorType) { return enumeratorType.EnumeratorFastFieldReference(4); } public static void EnumeratorFastFieldReferenceCurrent(this MethodInfo methodInfo, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = methodInfo.EnumeratorFastFieldReferenceCurrent(); } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReferenceCurrent(this MethodInfo methodInfo) { return methodInfo.DeclaringType?.EnumeratorFastFieldReferenceCurrent() ?? throw new NullReferenceException("Declaring type of method is null!"); } public static void EnumeratorFastFieldReferenceCurrent(this Type enumeratorType, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = enumeratorType.EnumeratorFastFieldReferenceCurrent(); } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReferenceCurrent(this Type enumeratorType) { return enumeratorType.EnumeratorFastFieldReference(2); } public static void EnumeratorFastFieldReferenceState(this MethodInfo methodInfo, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = methodInfo.EnumeratorFastFieldReferenceState(); } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReferenceState(this MethodInfo methodInfo) { return methodInfo.DeclaringType?.EnumeratorFastFieldReferenceState() ?? throw new NullReferenceException("Declaring type of method is null!"); } public static void EnumeratorFastFieldReferenceState(this Type enumeratorType, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = enumeratorType.EnumeratorFastFieldReferenceState(); } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReferenceState(this Type enumeratorType) { return enumeratorType.EnumeratorFastFieldReference(1); } public static void EnumeratorFastFieldReference(this MethodInfo methodInfo, string fieldName, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = methodInfo.EnumeratorFastFieldReference(fieldName); } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReference(this MethodInfo methodInfo, string fieldName) { return methodInfo.DeclaringType?.EnumeratorFastFieldReference(fieldName) ?? throw new NullReferenceException("Declaring type of method is null!"); } public static void EnumeratorFastFieldReference(this Type enumeratorType, string fieldName, ref EnumeratorFieldReferenceGetter enumeratorFieldReference) { enumeratorFieldReference = enumeratorType.EnumeratorFastFieldReference(fieldName); } private static EnumeratorFieldReferenceGetter EnumeratorFastFieldReference(this Type enumeratorType, int fieldId) { if (F195F66C6DA9E115B6F6704672598F4179F4F7206901F87F23A1D221B9EE964B6__EnumeratorExtensionsCache.s_FieldToRef.TryGetValue((enumeratorType, fieldId), out EnumeratorFieldReferenceGetter value)) { return value; } string text = fieldId switch { 1 => "<>1__state", 2 => "<>2__current", 3 => throw new ArgumentException("field id 3 is not constant."), 4 => "<>4__this", _ => throw new ArgumentOutOfRangeException("fieldId", $"Valid values are 1, 2, and 4. The value provided was: {fieldId}"), }; FieldInfo fieldInfo = enumeratorType.GetField(text, (BindingFlags)(-1)) ?? throw new NullReferenceException($"'{text}' field not found on type {enumeratorType}."); if (!typeof(T).IsAssignableFrom(fieldInfo.FieldType)) { throw new InvalidCastException($"{typeof(T)} is not assignable from '{text}' field type {fieldInfo.FieldType}"); } value = CreateFastFieldReference(fieldInfo); F195F66C6DA9E115B6F6704672598F4179F4F7206901F87F23A1D221B9EE964B6__EnumeratorExtensionsCache.s_FieldToRef.TryAdd((enumeratorType, fieldId), value); return value; } public static EnumeratorFieldReferenceGetter EnumeratorFastFieldReference(this Type enumeratorType, string fieldName) { if (F195F66C6DA9E115B6F6704672598F4179F4F7206901F87F23A1D221B9EE964B6__EnumeratorExtensionsCache.s_3ToRef.TryGetValue((enumeratorType, fieldName), out EnumeratorFieldReferenceGetter value)) { return value; } FieldInfo fieldInfo = enumeratorType.GetField(fieldName, (BindingFlags)(-1)) ?? throw new NullReferenceException($"'{fieldName}' field not found on type {enumeratorType}."); if (!typeof(T).IsAssignableFrom(fieldInfo.FieldType)) { throw new InvalidCastException($"{typeof(T)} is not assignable from '{fieldName}' field type {fieldInfo.FieldType}"); } value = CreateFastFieldReference(fieldInfo); F195F66C6DA9E115B6F6704672598F4179F4F7206901F87F23A1D221B9EE964B6__EnumeratorExtensionsCache.s_3ToRef.TryAdd((enumeratorType, fieldName), value); return value; } private static EnumeratorFieldReferenceGetter CreateFastFieldReference(FieldInfo fieldInfo) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) DynamicMethodDefinition val = new DynamicMethodDefinition("FastFieldReference", typeof(T).MakeByRefType(), new Type[1] { typeof(object) }); ILProcessor iLProcessor = val.GetILProcessor(); iLProcessor.Emit(OpCodes.Ldarg_0); Extensions.Emit(iLProcessor, OpCodes.Ldflda, fieldInfo); iLProcessor.Emit(OpCodes.Ret); return Extensions.CreateDelegate>((MethodBase)val.Generate()); } } public interface ISpeakableEnumerator { } public sealed class SpeakableEnumerator : ISpeakableEnumerator { private readonly EnumeratorFieldReferenceGetter getThisRef; private readonly EnumeratorFieldReferenceGetter getCurrentRef; private readonly EnumeratorFieldReferenceGetter getStateRef; private readonly IEnumerator instance; private static readonly ConditionalWeakTable, SpeakableEnumerator> s_EnumeratorToSpeakable = new ConditionalWeakTable, SpeakableEnumerator>(); public TThis This => getThisRef(instance); public IEnumerator Enumerator => instance; public TCurrent Current { get { return getCurrentRef(instance); } set { getCurrentRef(instance) = value; } } public int State { get { return getStateRef(instance); } set { getStateRef(instance) = value; } } public SpeakableEnumerator(IEnumerator instance) { Type type = instance.GetType(); this.instance = instance; getCurrentRef = type.EnumeratorFastFieldReferenceCurrent(); getStateRef = type.EnumeratorFastFieldReferenceState(); getThisRef = type.EnumeratorFastFieldReferenceThis(); } public static void PreBuildFieldReferenceGetters(Type type) { SpeakableEnumerator.PreBuildFieldReferenceGetters(type); type.EnumeratorFastFieldReferenceThis(); } public static SpeakableEnumerator GetOrCreate(IEnumerator instance) { if (s_EnumeratorToSpeakable.TryGetValue(instance, out SpeakableEnumerator value)) { return value; } value = new SpeakableEnumerator(instance); s_EnumeratorToSpeakable.Add(instance, value); return value; } } public sealed class SpeakableEnumerator : ISpeakableEnumerator { private readonly EnumeratorFieldReferenceGetter getCurrentRef; private readonly EnumeratorFieldReferenceGetter getStateRef; private readonly IEnumerator instance; private static readonly ConditionalWeakTable, SpeakableEnumerator> s_EnumeratorToSpeakable = new ConditionalWeakTable, SpeakableEnumerator>(); public IEnumerator Enumerator => instance; public TCurrent Current { get { return getCurrentRef(instance); } set { getCurrentRef(instance) = value; } } public int State { get { return getStateRef(instance); } set { getStateRef(instance) = value; } } public SpeakableEnumerator(IEnumerator instance) { Type type = instance.GetType(); this.instance = instance; getCurrentRef = type.EnumeratorFastFieldReferenceCurrent(); getStateRef = type.EnumeratorFastFieldReferenceState(); } public static void PreBuildFieldReferenceGetters(Type type) { type.EnumeratorFastFieldReferenceCurrent(); type.EnumeratorFastFieldReferenceState(); } public static SpeakableEnumerator GetOrCreate(IEnumerator instance) { if (s_EnumeratorToSpeakable.TryGetValue(instance, out SpeakableEnumerator value)) { return value; } value = new SpeakableEnumerator(instance); s_EnumeratorToSpeakable.Add(instance, value); return value; } } }