Decompiled source of HarmonyPatchExtensions v1.3.0

Harmony.PatchExtensions.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DolfeLive")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("An extension to Harmony aiming to create a Mixin like patching system via attributes")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0+ab8158bec05765c2649cfb5066ece72a8bd8b76b")]
[assembly: AssemblyProduct("Harmony.PatchExtensions")]
[assembly: AssemblyTitle("Harmony.PatchExtensions")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/UltraModding/Harmony.PatchExtensions/tree/master")]
[assembly: AssemblyVersion("1.3.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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;
		}
	}
}
namespace HarmonyLib.PatchExtensions
{
	internal static class ConflictResolver
	{
		public static void DetectPatchConflicts(Dictionary<MethodInfo, List<QueuedPatch>> patches, HashSet<MethodInfo> toRemove)
		{
			foreach (KeyValuePair<MethodInfo, List<QueuedPatch>> item in patches.Where<KeyValuePair<MethodInfo, List<QueuedPatch>>>((KeyValuePair<MethodInfo, List<QueuedPatch>> group) => group.Value.Count > 1))
			{
				LogConflict(item.Key, item.Value.Select((QueuedPatch p) => p.HarmonyMethod.method));
				switch (MixinLoader.ConflictResolutionMethod)
				{
				case MixinLoader.ConflictResolver.SkipConflicts:
					toRemove.Add(item.Key);
					break;
				case MixinLoader.ConflictResolver.Error:
					toRemove.Add(item.Key);
					throw new InvalidOperationException($"Conflict detected: {item.Value.Count} patches target {item.Key.Name}");
				}
			}
		}

		public static void DetectTranspilerConflicts(Dictionary<MethodBase, List<TranspilerConfig>> transpilers, HashSet<MethodBase> toRemove)
		{
			foreach (KeyValuePair<MethodBase, List<TranspilerConfig>> transpiler in transpilers)
			{
				MethodBase key = transpiler.Key;
				List<TranspilerConfig> value = transpiler.Value;
				IEnumerable<IGrouping<(string, uint, uint), TranspilerConfig>> source = from t in value
					group t by (TargetMember: t.TargetMember, StartIndex: t.StartIndex, Occurrence: t.Occurrence);
				foreach (IGrouping<(string, uint, uint), TranspilerConfig> item in source.Where((IGrouping<(string TargetMember, uint StartIndex, uint Occurrence), TranspilerConfig> grouping) => grouping.Count() > 1))
				{
					if (item.Count(delegate(TranspilerConfig transpilerConfig)
					{
						AT type = transpilerConfig.Type;
						return (type == AT.RETURN || type == AT.REDIRECT) ? true : false;
					}) > 1)
					{
						LogConflict(key, item.Select((TranspilerConfig transpilerConfig) => transpilerConfig.PatchMethod));
						switch (MixinLoader.ConflictResolutionMethod)
						{
						case MixinLoader.ConflictResolver.SkipConflicts:
							toRemove.Add(key);
							break;
						case MixinLoader.ConflictResolver.Error:
							toRemove.Add(key);
							throw new InvalidOperationException($"Conflict detected: {item.Count()} transpiler patches target {key.Name} at {item.Key}");
						}
					}
				}
			}
		}

		private static void LogConflict(MethodBase targetMethod, IEnumerable<MethodInfo> patchMethods)
		{
			Logger.LogWarning("Multiple Mixins queued for " + targetMethod.DeclaringType?.FullName + "." + targetMethod.Name);
			foreach (MethodInfo patchMethod in patchMethods)
			{
				string value = string.Join(", ", from p in patchMethod.GetParameters()
					select p.ParameterType.Name + " " + p.Name + (p.HasDefaultValue ? $" = {p.DefaultValue}" : ""));
				Logger.LogWarning($"  - {patchMethod.DeclaringType?.FullName}.{patchMethod.Name}({value})");
			}
		}
	}
	public static class Logger
	{
		private static StreamWriter _writer;

		public static string LogPath { get; private set; }

		static Logger()
		{
			LogPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "LogFile.txt");
			Log("Logging to file at: " + LogPath);
			_writer = new StreamWriter(LogPath);
		}

		public static void Log(string log)
		{
			Console.WriteLine("[HarmonyLib.PatchExtensions | Log] " + log);
		}

		public static void LogWarning(string log)
		{
			Console.WriteLine("[HarmonyLib.PatchExtensions | Warning] " + log);
		}

		public static void LogError(string log)
		{
			Console.WriteLine("[HarmonyLib.PatchExtensions | Error] " + log);
		}

		public static void LogFile(string toString)
		{
			_writer.WriteLine(toString);
			_writer.Flush();
		}
	}
	internal static class MixinApplier
	{
		public static void ApplyPatches(Dictionary<MethodInfo, List<QueuedPatch>> _queuedPatches, Harmony harmony, ModuleBuilder _moduleBuilder)
		{
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			foreach (KeyValuePair<MethodInfo, List<QueuedPatch>> _queuedPatch in _queuedPatches)
			{
				MethodInfo key = _queuedPatch.Key;
				foreach (QueuedPatch item in _queuedPatch.Value)
				{
					switch (item.Type)
					{
					case AT.HEAD:
						if (item.Overwriting && item.PatchMethod.ReturnType != typeof(bool) && item.PatchMethod.ReturnType != typeof(void))
						{
							if (item.PatchMethod.ReturnType != key.ReturnType)
							{
								Logger.LogError($"Patch {item.PatchMethod.Name} returns {item.PatchMethod.Name}, but target returns {key.ReturnType.Name}. They must match.");
								return;
							}
							Logger.Log($"Using wrapper as the method returns: {item.PatchMethod.ReturnType}");
							MethodInfo methodInfo = BoolLessPrefix(key, item.PatchMethod, _moduleBuilder);
							if (methodInfo == null)
							{
								Logger.LogError("Failed to create wrapper for " + item.PatchMethod.Name);
								break;
							}
							Logger.Log("Applied HEAD (prefix) with wrapper on " + key.Name + " using " + item.HarmonyMethod.methodName);
							harmony.Patch((MethodBase)key, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						}
						else
						{
							harmony.Patch((MethodBase)key, item.HarmonyMethod, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							Logger.Log("Applied HEAD (prefix) on " + key.Name + " using " + item.HarmonyMethod.methodName);
						}
						break;
					case AT.POSTFIX:
						harmony.Patch((MethodBase)key, (HarmonyMethod)null, item.HarmonyMethod, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.Log("Applied RETURN (postfix) on " + key.Name + " using " + item.HarmonyMethod.methodName);
						break;
					case AT.FINALLY:
					{
						Type returnType = item.PatchMethod.ReturnType;
						if (returnType != typeof(void) && returnType != typeof(Exception))
						{
							Logger.LogError($"Finalizer {item.PatchMethod.Name} must return void or Exception, got {returnType.Name}.");
						}
						else
						{
							harmony.Patch((MethodBase)key, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, item.HarmonyMethod, (HarmonyMethod)null);
							Logger.Log("Applied FINALLY on " + key.Name + " using " + item.HarmonyMethod.methodName);
						}
						break;
					}
					default:
						throw new NotImplementedException($"Have not implemented: {item.Type}");
					}
				}
			}
		}

		private static MethodInfo? BoolLessPrefix(MethodInfo targetMethod, MethodInfo userPatchMethod, ModuleBuilder _moduleBuilder)
		{
			string name = $"MixinWrapper_{userPatchMethod.Name}_{Guid.NewGuid():N}";
			TypeBuilder typeBuilder = _moduleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed);
			ParameterInfo[] parameters = userPatchMethod.GetParameters();
			Type returnType = targetMethod.ReturnType;
			List<Type> list = parameters.Select((ParameterInfo p) => p.ParameterType).ToList();
			list.Add(returnType.MakeByRefType());
			MethodBuilder methodBuilder = typeBuilder.DefineMethod("Wrapper_" + userPatchMethod.Name, MethodAttributes.Public | MethodAttributes.Static, typeof(bool), list.ToArray());
			for (int num = 0; num < parameters.Length; num++)
			{
				methodBuilder.DefineParameter(num + 1, ParameterAttributes.None, parameters[num].Name);
			}
			methodBuilder.DefineParameter(parameters.Length + 1, ParameterAttributes.Out, "__result");
			ILGenerator iLGenerator = methodBuilder.GetILGenerator();
			LoadArg(iLGenerator, parameters.Length);
			for (int num2 = 0; num2 < parameters.Length; num2++)
			{
				LoadArg(iLGenerator, num2);
			}
			iLGenerator.Emit(OpCodes.Call, userPatchMethod);
			iLGenerator.Emit(OpCodes.Stobj, returnType);
			iLGenerator.Emit(OpCodes.Ldc_I4_0);
			iLGenerator.Emit(OpCodes.Ret);
			Type type = CreateType(typeBuilder);
			return type.GetMethod("Wrapper_" + userPatchMethod.Name);
		}

		private static Type CreateType(TypeBuilder typeBuilder)
		{
			return typeBuilder.CreateTypeInfo().AsType();
		}

		private static void LoadArg(ILGenerator il, int index)
		{
			switch (index)
			{
			case 0:
				il.Emit(OpCodes.Ldarg_0);
				break;
			case 1:
				il.Emit(OpCodes.Ldarg_1);
				break;
			case 2:
				il.Emit(OpCodes.Ldarg_2);
				break;
			case 3:
				il.Emit(OpCodes.Ldarg_3);
				break;
			default:
				il.Emit(OpCodes.Ldarg, index);
				break;
			}
		}
	}
	public static class MixinLoader
	{
		public enum ConflictResolver
		{
			Warn,
			Error,
			SkipConflicts
		}

		public static ConflictResolver ConflictResolutionMethod;

		private static ModuleBuilder _moduleBuilder;

		internal static Dictionary<MethodBase, List<TranspilerConfig>> QueuedTranspilers;

		internal static Dictionary<Assembly, List<TranspilerConfig>> AssemblyTranspilers;

		private static Dictionary<MethodInfo, List<QueuedPatch>> _queuedPatches;

		private static Version LatestBreakingVersion { get; }

		static MixinLoader()
		{
			LatestBreakingVersion = new Version(1, 2, 0);
			ConflictResolutionMethod = ConflictResolver.Warn;
			QueuedTranspilers = new Dictionary<MethodBase, List<TranspilerConfig>>();
			AssemblyTranspilers = new Dictionary<Assembly, List<TranspilerConfig>>();
			_queuedPatches = new Dictionary<MethodInfo, List<QueuedPatch>>();
			AssemblyName name = new AssemblyName("DolfeMixinDynamicAssembly");
			AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
			_moduleBuilder = assemblyBuilder.DefineDynamicModule("MixinWrappers");
		}

		public static void ApplyPatches(Harmony harmony, Assembly assembly)
		{
			WarnOutOfDate();
			ApplyPatches(harmony, assembly, Array.Empty<Type>());
		}

		public static void ApplyPatches(Harmony harmony, Assembly assembly, params Type[] patchTypes)
		{
			WarnOutOfDate();
			HashSet<Type> allowedTypes = ((patchTypes.Length == 0) ? null : new HashSet<Type>(patchTypes));
			ApplyPatches(harmony, assembly, allowedTypes);
		}

		private static void WarnOutOfDate()
		{
			Assembly assembly = new StackTrace().GetFrame(2)?.GetMethod()?.Module.Assembly ?? null;
			if (!(assembly == null))
			{
				AssemblyName assemblyName = assembly.GetReferencedAssemblies().FirstOrDefault((AssemblyName a) => a.Name == Assembly.GetExecutingAssembly().GetName().Name);
				if (assemblyName != null && assemblyName.Version < LatestBreakingVersion)
				{
					Logger.LogError($"{assembly.FullName} is using an outdated version of Harmony.PatchExtensions ({assemblyName.Version}), a breaking update has been introduced since then ({LatestBreakingVersion})");
				}
			}
		}

		private static void ApplyPatches(Harmony harmony, Assembly assembly, HashSet<Type>? allowedTypes)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_0620: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Expected O, but got Unknown
			QueuedTranspilers.Clear();
			_queuedPatches.Clear();
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (allowedTypes != null && !allowedTypes.Contains(type))
				{
					continue;
				}
				MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					IEnumerable<PatchAttribute> customAttributes = methodInfo.GetCustomAttributes<PatchAttribute>();
					foreach (PatchAttribute item2 in customAttributes)
					{
						if (item2.DoNotPatch)
						{
							Logger.LogWarning(methodInfo.Name + " has attribute errors so it has been skipped");
							continue;
						}
						if (item2.TargetMethod == null)
						{
							Logger.LogWarning("You must set TargetMethod in " + methodInfo.Name + " for the Patch to work");
							continue;
						}
						HarmonyMethod harmonyMethod = new HarmonyMethod(methodInfo);
						QueuedPatch item = new QueuedPatch(harmonyMethod, item2.At, item2.Overwriting, methodInfo);
						switch (item2.At)
						{
						case AT.HEAD:
						case AT.POSTFIX:
						case AT.FINALLY:
							if (!_queuedPatches.ContainsKey(item2.TargetMethod))
							{
								_queuedPatches[item2.TargetMethod] = new List<QueuedPatch>();
							}
							_queuedPatches[item2.TargetMethod].Add(item);
							Logger.Log($"Queueing {item2.At} on {item2.TargetMethod.Name}");
							break;
						case AT.LOOP_BEFORE:
						case AT.LOOP_TOP:
						case AT.LOOP_BOTTOM:
						case AT.LOOP_AFTER:
						case AT.BRANCH_TRUE:
						case AT.BRANCH_FALSE:
							AddTranspiler(QueuedTranspilers, item2.TargetMethod, new TranspilerConfig(item2.At, item2.TargetMember, methodInfo, item2.Occurrence, item2.StartIndex, item2.ArgIndex, item2.TargetType));
							break;
						default:
							if (string.IsNullOrEmpty(item2.TargetMember))
							{
								Logger.LogWarning($"You must set 'targetMember' in {methodInfo.Name} when using AT.{item2.At}");
							}
							else
							{
								AddTranspiler(QueuedTranspilers, item2.TargetMethod, new TranspilerConfig(item2.At, item2.TargetMember, methodInfo, item2.Occurrence, item2.StartIndex, item2.ArgIndex, item2.TargetType));
							}
							break;
						}
					}
					IEnumerable<AssemblyPatchAttribute> customAttributes2 = methodInfo.GetCustomAttributes<AssemblyPatchAttribute>();
					foreach (AssemblyPatchAttribute item3 in customAttributes2)
					{
						if (item3.DoNotPatch)
						{
							Logger.LogWarning(methodInfo.Name + " has attribute errors so it has been skipped");
							continue;
						}
						Assembly assembly2 = item3.TargetType.Assembly;
						if (!AssemblyTranspilers.ContainsKey(assembly2))
						{
							AssemblyTranspilers[assembly2] = new List<TranspilerConfig>();
						}
						AssemblyTranspilers[assembly2].Add(new TranspilerConfig(item3.At, item3.TargetMember, methodInfo, item3.Occurrence, 0u, 0u, item3.TargetType));
					}
				}
			}
			foreach (KeyValuePair<Assembly, List<TranspilerConfig>> assemblyTranspiler in AssemblyTranspilers)
			{
				Assembly key = assemblyTranspiler.Key;
				List<TranspilerConfig> value = assemblyTranspiler.Value;
				foreach (TranspilerConfig item4 in value)
				{
					if (string.IsNullOrEmpty(item4.TargetMember))
					{
						Logger.LogError("TargetMember is null or empty in " + item4.PatchMethod.Name);
						continue;
					}
					FieldInfo target = item4.TargetType?.GetField(item4.TargetMember) ?? throw new InvalidOperationException("TargetType required to resolve field '" + item4.TargetMember + "'");
					IEnumerable<Type> enumerable = ((!(item4.TargetType != null)) ? ((IEnumerable<Type>)key.GetTypes()) : ((IEnumerable<Type>)new Type[1] { item4.TargetType }));
					foreach (Type item5 in enumerable)
					{
						foreach (MethodBase item6 in OpCodeHelper.FindMethodsUsingField(item5, target))
						{
							if (!QueuedTranspilers.ContainsKey(item6))
							{
								QueuedTranspilers[item6] = new List<TranspilerConfig>();
							}
							QueuedTranspilers[item6].Add(new TranspilerConfig(item4.Type, null, item4.PatchMethod, item4.Occurrence, 0u, 0u, item4.TargetType));
						}
					}
				}
			}
			HashSet<MethodInfo> hashSet = new HashSet<MethodInfo>();
			HarmonyLib.PatchExtensions.ConflictResolver.DetectPatchConflicts(_queuedPatches, hashSet);
			foreach (MethodInfo item7 in hashSet)
			{
				_queuedPatches.Remove(item7);
			}
			HashSet<MethodBase> hashSet2 = new HashSet<MethodBase>();
			HarmonyLib.PatchExtensions.ConflictResolver.DetectTranspilerConflicts(QueuedTranspilers, hashSet2);
			foreach (MethodBase item8 in hashSet2)
			{
				QueuedTranspilers.Remove(item8);
			}
			MixinApplier.ApplyPatches(_queuedPatches, harmony, _moduleBuilder);
			HarmonyMethod val = new HarmonyMethod(typeof(TranspilerApplier), "TranspilerPiler", (Type[])null);
			foreach (MethodBase key2 in QueuedTranspilers.Keys)
			{
				try
				{
					Logger.Log("Processing patch for " + key2.Name);
					harmony.Patch(key2, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.Log("Processed patch for " + key2.Name);
				}
				catch (Exception ex)
				{
					StackFrame[] frames = new StackTrace().GetFrames();
					string value2 = string.Join(", ", frames.Select((StackFrame _) => $"{_.GetFileName()}:{_.GetFileLineNumber()}"));
					Logger.LogError($"Exception {key2.Name}: {ex.Message}, type: {ex.GetType()}, {value2}");
					Exception ex2 = ex;
					int num = 0;
					while (ex2 != null)
					{
						Logger.LogError($"[{num}] {ex2.GetType()}: {ex2.Message}");
						ex2 = ex2.InnerException;
						num++;
					}
					HarmonyException ex3 = (HarmonyException)(object)((ex is HarmonyException) ? ex : null);
					if (ex3 == null)
					{
						continue;
					}
					foreach (KeyValuePair<int, CodeInstruction> instructionsWithOffset in ex3.GetInstructionsWithOffsets())
					{
						Logger.LogError($"IL[{instructionsWithOffset.Key:X4}] {instructionsWithOffset.Value}");
					}
					Logger.LogError($"ErrorOffset: {ex3.GetErrorOffset()}, ErrorIndex: {ex3.GetErrorIndex()}");
				}
			}
		}

		private static void AddTranspiler<TKey>(Dictionary<TKey, List<TranspilerConfig>> dict, TKey key, TranspilerConfig config)
		{
			if (!dict.TryGetValue(key, out List<TranspilerConfig> value))
			{
				value = (dict[key] = new List<TranspilerConfig>());
			}
			value.Add(config);
		}
	}
	public class OpCodeHelper
	{
		private static readonly HashSet<OpCode> LocalOpcodes = new HashSet<OpCode>
		{
			OpCodes.Ldloc_0,
			OpCodes.Ldloc_1,
			OpCodes.Ldloc_2,
			OpCodes.Ldloc_3,
			OpCodes.Ldloc_S,
			OpCodes.Ldloc,
			OpCodes.Ldloca_S,
			OpCodes.Ldloca,
			OpCodes.Stloc_0,
			OpCodes.Stloc_1,
			OpCodes.Stloc_2,
			OpCodes.Stloc_3,
			OpCodes.Stloc_S,
			OpCodes.Stloc
		};

		private static readonly HashSet<OpCode> ArgLocodes = new HashSet<OpCode>
		{
			OpCodes.Ldarg_0,
			OpCodes.Ldarg_1,
			OpCodes.Ldarg_2,
			OpCodes.Ldarg_3,
			OpCodes.Ldarg,
			OpCodes.Ldarg_S,
			OpCodes.Ldarga,
			OpCodes.Ldarga_S,
			OpCodes.Starg,
			OpCodes.Starg_S
		};

		private static readonly HashSet<OpCode> MethodCallOpcodes = new HashSet<OpCode>
		{
			OpCodes.Call,
			OpCodes.Callvirt,
			OpCodes.Newobj
		};

		private static readonly HashSet<OpCode> FieldOpcodes = new HashSet<OpCode>
		{
			OpCodes.Stfld,
			OpCodes.Ldfld,
			OpCodes.Ldsfld,
			OpCodes.Stsfld,
			OpCodes.Ldflda,
			OpCodes.Ldsflda
		};

		private static readonly HashSet<OpCode> BranchOpcodes = new HashSet<OpCode>
		{
			OpCodes.Brtrue,
			OpCodes.Brtrue_S,
			OpCodes.Brfalse,
			OpCodes.Brfalse_S
		};

		private static readonly HashSet<OpCode> LoopOpcodes = new HashSet<OpCode>
		{
			OpCodes.Br,
			OpCodes.Br_S
		};

		private static readonly HashSet<OpCode> ConditionalOpcodes = new HashSet<OpCode>
		{
			OpCodes.Blt,
			OpCodes.Blt_S,
			OpCodes.Ble,
			OpCodes.Ble_S,
			OpCodes.Bgt,
			OpCodes.Bgt_S,
			OpCodes.Bge,
			OpCodes.Bge_S,
			OpCodes.Brtrue,
			OpCodes.Brtrue_S,
			OpCodes.Brfalse,
			OpCodes.Brfalse_S
		};

		public static bool IsLocalOpcode(OpCode opcode)
		{
			return LocalOpcodes.Contains(opcode);
		}

		public static bool IsArgOpcode(OpCode opcode)
		{
			return ArgLocodes.Contains(opcode);
		}

		public static bool IsMethod(OpCode opcode)
		{
			return MethodCallOpcodes.Contains(opcode);
		}

		public static bool IsField(OpCode opcode)
		{
			return FieldOpcodes.Contains(opcode);
		}

		public static bool IsBranch(OpCode opcode)
		{
			return BranchOpcodes.Contains(opcode);
		}

		public static bool IsLoop(OpCode opcode)
		{
			return LoopOpcodes.Contains(opcode);
		}

		public static bool IsConditional(OpCode opcode)
		{
			return ConditionalOpcodes.Contains(opcode);
		}

		public static bool TryGetLocalIndex(CodeInstruction instruction, out int index, out bool isWrite, out bool isAddress)
		{
			index = -1;
			isWrite = false;
			isAddress = false;
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldloc_0)
			{
				index = 0;
				return true;
			}
			if (opcode == OpCodes.Ldloc_1)
			{
				index = 1;
				return true;
			}
			if (opcode == OpCodes.Ldloc_2)
			{
				index = 2;
				return true;
			}
			if (opcode == OpCodes.Ldloc_3)
			{
				index = 3;
				return true;
			}
			if (opcode == OpCodes.Ldloc_S)
			{
				index = ((LocalBuilder)instruction.operand).LocalIndex;
				return true;
			}
			if (opcode == OpCodes.Ldloc)
			{
				index = ((LocalBuilder)instruction.operand).LocalIndex;
				return true;
			}
			if (opcode == OpCodes.Ldloca_S)
			{
				index = ((LocalBuilder)instruction.operand).LocalIndex;
				isAddress = true;
				return true;
			}
			if (opcode == OpCodes.Ldloca)
			{
				index = ((LocalBuilder)instruction.operand).LocalIndex;
				isAddress = true;
				return true;
			}
			if (opcode == OpCodes.Stloc_0)
			{
				index = 0;
				isWrite = true;
				return true;
			}
			if (opcode == OpCodes.Stloc_1)
			{
				index = 1;
				isWrite = true;
				return true;
			}
			if (opcode == OpCodes.Stloc_2)
			{
				index = 2;
				isWrite = true;
				return true;
			}
			if (opcode == OpCodes.Stloc_3)
			{
				index = 3;
				isWrite = true;
				return true;
			}
			if (opcode == OpCodes.Stloc_S)
			{
				index = ((LocalBuilder)instruction.operand).LocalIndex;
				isWrite = true;
				return true;
			}
			if (opcode == OpCodes.Stloc)
			{
				index = ((LocalBuilder)instruction.operand).LocalIndex;
				isWrite = true;
				return true;
			}
			return false;
		}

		public static bool TryGetArgIndex(CodeInstruction instruction, out int index, out bool isWrite, out bool isAddress)
		{
			index = -1;
			isWrite = false;
			isAddress = false;
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldarg_0)
			{
				index = 0;
				return true;
			}
			if (opcode == OpCodes.Ldarg_1)
			{
				index = 1;
				return true;
			}
			if (opcode == OpCodes.Ldarg_2)
			{
				index = 2;
				return true;
			}
			if (opcode == OpCodes.Ldarg_3)
			{
				index = 3;
				return true;
			}
			if (opcode == OpCodes.Ldarg_S)
			{
				index = (byte)instruction.operand;
				return true;
			}
			if (opcode == OpCodes.Ldarg)
			{
				index = (short)instruction.operand;
				return true;
			}
			if (opcode == OpCodes.Ldarga_S)
			{
				index = (byte)instruction.operand;
				isAddress = true;
				return true;
			}
			if (opcode == OpCodes.Ldarga)
			{
				index = (short)instruction.operand;
				isAddress = true;
				return true;
			}
			if (opcode == OpCodes.Starg_S)
			{
				index = (byte)instruction.operand;
				isWrite = true;
				return true;
			}
			if (opcode == OpCodes.Starg)
			{
				index = (short)instruction.operand;
				isWrite = true;
				return true;
			}
			return false;
		}

		public static bool TryGetFieldInfo(CodeInstruction instruction, out FieldInfo field, out bool isWrite, out bool isAddress, out bool isStatic)
		{
			field = null;
			isWrite = false;
			isAddress = false;
			isStatic = false;
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldfld)
			{
				field = (FieldInfo)instruction.operand;
				return true;
			}
			if (opcode == OpCodes.Ldsfld)
			{
				field = (FieldInfo)instruction.operand;
				isStatic = true;
				return true;
			}
			if (opcode == OpCodes.Ldflda)
			{
				field = (FieldInfo)instruction.operand;
				isAddress = true;
				return true;
			}
			if (opcode == OpCodes.Ldsflda)
			{
				field = (FieldInfo)instruction.operand;
				isAddress = true;
				isStatic = true;
				return true;
			}
			if (opcode == OpCodes.Stfld)
			{
				field = (FieldInfo)instruction.operand;
				isWrite = true;
				return true;
			}
			if (opcode == OpCodes.Stsfld)
			{
				field = (FieldInfo)instruction.operand;
				isWrite = true;
				isStatic = true;
				return true;
			}
			return false;
		}

		public static bool IsLoopEntryBranch(CodeInstruction instruction, List<CodeInstruction> instructions)
		{
			if (IsLoop(instruction.opcode))
			{
				object operand = instruction.operand;
				if (operand is Label)
				{
					Label conditionLabel = (Label)operand;
					int num = instructions.FindIndex((CodeInstruction ci) => ci == instruction);
					int num2 = instructions.FindIndex((CodeInstruction ci) => ci.labels.Contains(conditionLabel));
					if (num == -1 || num2 == -1)
					{
						return false;
					}
					for (int num3 = num2; num3 < instructions.Count; num3++)
					{
						CodeInstruction val = instructions[num3];
						if (IsConditional(val.opcode))
						{
							operand = val.operand;
							if (operand is Label)
							{
								Label bodyLabel = (Label)operand;
								int num4 = instructions.FindIndex((CodeInstruction ci) => ci.labels.Contains(bodyLabel));
								if (num4 != -1)
								{
									return num4 > num;
								}
								return false;
							}
							return false;
						}
						if (val.opcode == OpCodes.Ret || IsLoop(val.opcode))
						{
							return false;
						}
					}
					return false;
				}
			}
			return false;
		}

		public static IEnumerable<MethodBase> FindMethodsUsingField(Type scanType, FieldInfo target)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			foreach (MethodBase item in scanType.GetMethods(bindingAttr).Cast<MethodBase>().Concat(scanType.GetConstructors(bindingAttr)))
			{
				if (item.IsAbstract || item.ContainsGenericParameters)
				{
					continue;
				}
				MethodBody methodBody = item.GetMethodBody();
				if (methodBody == null)
				{
					continue;
				}
				foreach (CodeInstruction originalInstruction in PatchProcessor.GetOriginalInstructions(item, (ILGenerator)null))
				{
					if (TryGetFieldInfo(originalInstruction, out FieldInfo field, out bool _, out bool _, out bool _) && field == target)
					{
						yield return item;
						break;
					}
				}
			}
		}
	}
	public enum AT
	{
		HEAD,
		RETURN,
		POSTFIX,
		INVOKE,
		REDIRECT,
		AFTER,
		ARG,
		LOOP_BEFORE,
		LOOP_TOP,
		LOOP_BOTTOM,
		LOOP_AFTER,
		FINALLY,
		BRANCH_TRUE,
		BRANCH_FALSE,
		LOCAL_WRITE,
		LOCAL_READ,
		[Obsolete("Not yet implemented")]
		ARG_WRITE,
		[Obsolete("Not yet implemented")]
		ARG_READ,
		[Obsolete("Not yet implemented")]
		FIELD_WRITE,
		[Obsolete("Not yet implemented")]
		FIELD_READ,
		[Obsolete("Not yet implemented")]
		TBD
	}
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
	public class PatchAttribute : Attribute
	{
		internal bool DoNotPatch { get; private set; } = true;

		public MethodInfo? TargetMethod { get; }

		public AT At { get; }

		public string TargetMember { get; }

		public bool Overwriting { get; }

		public uint Occurrence { get; }

		public uint StartIndex { get; }

		public uint ArgIndex { get; }

		public Type? TargetType { get; }

		public PatchAttribute(Type type, string methodName, AT at, string? targetMember = null, Type? targetType = null, uint occurrence = 0u, uint startIndex = 0u, uint argIndex = 0u, bool overwriting = false)
		{
			TargetMethod = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? null;
			if (TargetMethod == null)
			{
				Logger.LogError($"Could not find method '{methodName}' in type '{type.FullName}', not running this patch.");
				return;
			}
			bool flag = string.IsNullOrEmpty(targetMember);
			bool flag2 = flag;
			if (flag2)
			{
				flag2 = (((uint)(at - 3) <= 2u || (uint)(at - 14) <= 5u) ? true : false);
			}
			if (flag2)
			{
				Logger.LogError("targetMember is null or empty, not running this patch.");
				return;
			}
			TargetMember = targetMember;
			if (at == AT.ARG && argIndex == 0)
			{
				Logger.LogError("argIndex not set when required for ARG, not running this patch.");
				return;
			}
			ArgIndex = argIndex;
			TargetType = targetType;
			Occurrence = occurrence;
			At = at;
			StartIndex = startIndex;
			if (overwriting && at != AT.HEAD)
			{
				Logger.LogWarning("FYI, overwriting set on a non head AT does nothing");
			}
			Overwriting = overwriting;
			DoNotPatch = false;
		}
	}
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
	public class AssemblyPatchAttribute : Attribute
	{
		public bool DoNotPatch { get; private set; } = true;

		public bool TargetAssembly { get; }

		public Type TargetType { get; }

		public string TargetMember { get; }

		public AT At { get; }

		public bool ScanEntireAssembly { get; }

		public uint Occurrence { get; }

		public AssemblyPatchAttribute(Type? fieldDeclaringType, string fieldName, AT at, bool scanEntireAssembly = false, uint occurrence = 0u)
		{
			DoNotPatch = true;
			TargetAssembly = true;
			TargetType = fieldDeclaringType;
			TargetMember = fieldName;
			At = at;
			ScanEntireAssembly = scanEntireAssembly;
			Occurrence = occurrence;
			if (fieldDeclaringType == null)
			{
				Logger.LogError("fieldDeclaringType is null, not running this patch.");
				return;
			}
			if (string.IsNullOrEmpty(fieldName))
			{
				Logger.LogError("fieldName is null or empty, not running this patch.");
				return;
			}
			if (at != AT.FIELD_READ && at != AT.FIELD_WRITE)
			{
				Logger.LogError($"AssemblyPatchAttribute only supports FIELD_READ/FIELD_WRITE, not {at}.");
			}
			DoNotPatch = false;
		}
	}
	internal class QueuedPatch
	{
		public HarmonyMethod HarmonyMethod;

		public AT Type;

		public bool Overwriting;

		public MethodInfo PatchMethod;

		public QueuedPatch(HarmonyMethod harmonyMethod, AT type, bool overwriting, MethodInfo patchMethod)
		{
			HarmonyMethod = harmonyMethod;
			Type = type;
			Overwriting = overwriting;
			PatchMethod = patchMethod;
		}
	}
	public static class TranspilerApplier
	{
		public static IEnumerable<CodeInstruction> TranspilerPiler(IEnumerable<CodeInstruction> instructions, MethodBase original, ILGenerator generator)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Expected O, but got Unknown
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Expected O, but got Unknown
			if (!MixinLoader.QueuedTranspilers.TryGetValue(original, out List<TranspilerConfig> value))
			{
				return instructions;
			}
			CodeMatcher matcher = new CodeMatcher(instructions, generator);
			foreach (TranspilerConfig config in value)
			{
				matcher.Start();
				int num = 0;
				int num2 = 0;
				var (requiredClass, requiredMethod) = GetRequired(config);
				while (true)
				{
					matcher.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
					{
						new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instruction) => Matcher(instruction, config, requiredMethod, requiredClass, matcher)), (string)null)
					});
					if (matcher.IsInvalid)
					{
						break;
					}
					num++;
					if (config.StartIndex == 0 || num >= config.StartIndex)
					{
						num2++;
						if (config.Occurrence == 0 || num2 == config.Occurrence)
						{
							switch (config.Type)
							{
							case AT.INVOKE:
								matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
								{
									new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
								});
								break;
							case AT.REDIRECT:
								if (ApplyRedirect(matcher, config))
								{
									continue;
								}
								break;
							case AT.AFTER:
								ApplyAfter(matcher, config, generator);
								break;
							case AT.RETURN:
								ApplyReturn(original, generator, matcher, config);
								break;
							case AT.ARG:
								ApplyArg(matcher, config, generator);
								break;
							case AT.BRANCH_TRUE:
								ApplyBranch(matcher, config, generator, wantTrue: true);
								break;
							case AT.BRANCH_FALSE:
								ApplyBranch(matcher, config, generator, wantTrue: false);
								break;
							case AT.LOOP_BEFORE:
								matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
								{
									new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
								});
								break;
							case AT.LOOP_TOP:
								ApplyLoopTop(matcher, config, generator);
								break;
							case AT.LOOP_BOTTOM:
								ApplyLoopBottom(matcher, config, generator);
								break;
							case AT.LOOP_AFTER:
								ApplyLoopAfter(matcher, config, generator);
								break;
							case AT.LOCAL_READ:
								LocalRead(original, matcher, config, generator);
								break;
							case AT.LOCAL_WRITE:
								LocalWrite(original, matcher, config, generator);
								break;
							case AT.ARG_READ:
								ArgRead(original, matcher, config, generator);
								break;
							case AT.ARG_WRITE:
								ArgWrite(original, matcher, config, generator);
								break;
							case AT.FIELD_READ:
								FieldRead(original, matcher, config, generator);
								break;
							case AT.FIELD_WRITE:
								FieldWrite(original, matcher, config, generator);
								break;
							}
							if (config.Occurrence != 0)
							{
								break;
							}
						}
					}
					matcher.Advance(1);
				}
				Logger.LogFile("-- " + config.PatchMethod.Name + " ---");
				foreach (CodeInstruction item in matcher.Instructions())
				{
					Logger.LogFile($"{item.opcode}   {item.operand}");
				}
			}
			return matcher.InstructionEnumeration();
		}

		private static void ArgWrite(MethodBase original, CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			for (int i = 0; i < original.GetParameters().Length; i++)
			{
				ParameterInfo parameterInfo = original.GetParameters()[i];
				dictionary.Add(i, parameterInfo.Name);
			}
			CodeInstruction instruction = matcher.Instruction;
			if (OpCodeHelper.TryGetArgIndex(instruction, out var index, out var isWrite, out var isAddress) && !(!isWrite || isAddress) && dictionary.TryGetValue(index, out var value) && value == config.TargetMember)
			{
				Logger.Log("Writing arg: " + value);
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Dup, (object)null)
				});
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
				});
			}
		}

		private static void ArgRead(MethodBase original, CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			for (int i = 0; i < original.GetParameters().Length; i++)
			{
				ParameterInfo parameterInfo = original.GetParameters()[i];
				dictionary.Add(i, parameterInfo.Name);
			}
			CodeInstruction instruction = matcher.Instruction;
			if (OpCodeHelper.TryGetArgIndex(instruction, out var index, out var isWrite, out var isAddress) && !(isWrite || isAddress) && dictionary.TryGetValue(index, out var value) && value == config.TargetMember)
			{
				matcher.Advance(1);
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Dup, (object)null)
				});
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
				});
			}
		}

		private static void FieldRead(MethodBase original, CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			if (OpCodeHelper.TryGetFieldInfo(instruction, out FieldInfo field, out bool isWrite, out bool isAddress, out bool _) && !(isWrite || isAddress) && field.Name == config.TargetMember && (config.TargetType == null || field.DeclaringType == config.TargetType))
			{
				matcher.Advance(1);
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Dup, (object)null)
				});
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
				});
			}
		}

		private static void FieldWrite(MethodBase original, CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			if (OpCodeHelper.TryGetFieldInfo(instruction, out FieldInfo field, out bool isWrite, out bool isAddress, out bool _) && !(!isWrite || isAddress) && field.Name == config.TargetMember && (config.TargetType == null || field.DeclaringType == config.TargetType))
			{
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Dup, (object)null)
				});
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
				});
			}
		}

		private static void LocalWrite(MethodBase original, CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			string text = original.DeclaringType?.Assembly.Location;
			if (text == null)
			{
				throw new Exception("Unable to get target Assembly path.");
			}
			ModuleDefinition val = ModuleDefinition.ReadModule(text, new ReaderParameters
			{
				ReadSymbols = true
			});
			MethodDefinition val2 = (MethodDefinition)val.LookupToken(original.MetadataToken);
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			Enumerator<VariableDebugInformation> enumerator = val2.DebugInformation.Scope.Variables.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					VariableDebugInformation current = enumerator.Current;
					dictionary.Add(current.Index, current.Name);
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			CodeInstruction instruction = matcher.Instruction;
			if (OpCodeHelper.TryGetLocalIndex(instruction, out var index, out var isWrite, out var isAddress) && !(!isWrite || isAddress) && dictionary.TryGetValue(index, out var value) && value == config.TargetMember)
			{
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Dup, (object)null)
				});
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
				});
			}
		}

		private static void LocalRead(MethodBase original, CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			string text = original.DeclaringType?.Assembly.Location;
			if (text == null)
			{
				throw new Exception("Unable to get target Assembly path.");
			}
			ModuleDefinition val = ModuleDefinition.ReadModule(text, new ReaderParameters
			{
				ReadSymbols = true
			});
			MethodDefinition val2 = (MethodDefinition)val.LookupToken(original.MetadataToken);
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			Enumerator<VariableDebugInformation> enumerator = val2.DebugInformation.Scope.Variables.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					VariableDebugInformation current = enumerator.Current;
					dictionary.Add(current.Index, current.Name);
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			CodeInstruction instruction = matcher.Instruction;
			if (OpCodeHelper.TryGetLocalIndex(instruction, out var index, out var isWrite, out var isAddress) && !(isWrite || isAddress) && dictionary.TryGetValue(index, out var value) && value == config.TargetMember)
			{
				matcher.Advance(1);
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Dup, (object)null)
				});
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
				});
			}
		}

		private static void ApplyLoopTop(CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			Label conditionLabel = (Label)instruction.operand;
			int pos = matcher.Pos;
			int num = matcher.Instructions().FindIndex((CodeInstruction ci) => ci.labels.Contains(conditionLabel));
			if (num == -1)
			{
				throw new Exception("Could not resolve branch target label.");
			}
			matcher.Advance(num - pos);
			ContinueToConditional(matcher);
			CodeInstruction instruction2 = matcher.Instruction;
			Label bodyLabel = (Label)instruction2.operand;
			int pos2 = matcher.Pos;
			int num2 = matcher.Instructions().FindIndex((CodeInstruction ci) => ci.labels.Contains(bodyLabel));
			if (num2 == -1)
			{
				throw new Exception("Could not resolve loop body label.");
			}
			matcher.Advance(num2 - pos2);
			matcher.Advance(1);
			matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
			});
		}

		private static void ApplyLoopBottom(CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			Label conditionLabel = (Label)instruction.operand;
			int pos = matcher.Pos;
			List<CodeInstruction> list = matcher.Instructions();
			int num = list.FindIndex((CodeInstruction codeInstruction) => codeInstruction.labels.Contains(conditionLabel));
			if (num == -1)
			{
				throw new Exception("Could not resolve branch target label.");
			}
			int num2 = num;
			for (int num3 = pos + 1; num3 < num; num3++)
			{
				if (!OpCodeHelper.IsLoop(list[num3].opcode))
				{
					continue;
				}
				object operand = list[num3].operand;
				if (operand is Label)
				{
					Label continueLabel = (Label)operand;
					int num4 = list.FindIndex((CodeInstruction x) => x.labels.Contains(continueLabel));
					if (num4 > num3 && num4 < num)
					{
						num2 = num4;
						break;
					}
				}
			}
			matcher.Advance(num2 - pos);
			matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
			});
		}

		private static void ApplyLoopAfter(CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			Label conditionLabel = (Label)instruction.operand;
			int pos = matcher.Pos;
			int num = matcher.Instructions().FindIndex((CodeInstruction ci) => ci.labels.Contains(conditionLabel));
			if (num == -1)
			{
				throw new Exception("Could not resolve branch target label.");
			}
			matcher.Advance(num - pos);
			ContinueToConditional(matcher);
			matcher.Advance(1);
			CodeInstruction instruction2 = matcher.Instruction;
			CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
			{
				labels = instruction2.labels
			};
			instruction2.labels = new List<Label>();
			matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { val });
		}

		private static void ContinueToConditional(CodeMatcher matcher)
		{
			int num = 0;
			int count = matcher.Instructions().Count;
			while (!OpCodeHelper.IsConditional(matcher.Instruction.opcode))
			{
				matcher.Advance(1);
				if (++num > count)
				{
					throw new Exception("Failed to resolve loop condition branch.");
				}
			}
		}

		private static void ApplyBranch(CodeMatcher matcher, TranspilerConfig config, ILGenerator generator, bool wantTrue)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			OpCode opCode = (wantTrue ? OpCodes.Brfalse_S : OpCodes.Brtrue_S);
			Label label = generator.DefineLabel();
			matcher.Instruction.labels.Add(label);
			matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Dup, (object)null)
			});
			matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(opCode, (object)label)
			});
			matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
			});
		}

		private static void ApplyArg(CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			if (instruction.operand is MethodInfo methodInfo)
			{
				int num = methodInfo.GetParameters().Length;
				if (config.ArgIndex > num)
				{
					Logger.LogWarning($"ARG ArgIndex '{config.ArgIndex}' is bigger than the args on '{methodInfo.Name}' ({num}). Skipped.");
				}
				else
				{
					int num2 = num - (int)config.ArgIndex;
					matcher.Advance(-num2);
					matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
					{
						new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
					});
					matcher.Advance(num2);
				}
			}
		}

		private static void ApplyReturn(MethodBase original, ILGenerator generator, CodeMatcher matcher, TranspilerConfig config)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			if (original is MethodInfo methodInfo && methodInfo.ReturnType != typeof(void))
			{
				LocalBuilder localBuilder = generator.DeclareLocal(((MethodInfo)original).ReturnType);
				matcher.Insert((CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Stloc, (object)localBuilder),
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod),
					new CodeInstruction(OpCodes.Ldloc, (object)localBuilder)
				});
				matcher.Advance(3);
			}
		}

		private static void ApplyAfter(CodeMatcher matcher, TranspilerConfig config, ILGenerator generator)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			bool flag = false;
			Type type = null;
			if (instruction.operand is MethodInfo methodInfo)
			{
				flag = methodInfo.ReturnType != typeof(void);
				type = methodInfo.ReturnType;
			}
			matcher.Advance(1);
			if (flag && type != null)
			{
				LocalBuilder localBuilder = generator.DeclareLocal(type);
				matcher.Insert((CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Stloc, (object)localBuilder),
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod),
					new CodeInstruction(OpCodes.Ldloc, (object)localBuilder)
				});
				matcher.Advance(3);
			}
			else
			{
				matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)config.PatchMethod)
				});
			}
		}

		private static bool ApplyRedirect(CodeMatcher matcher, TranspilerConfig config)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			CodeInstruction instruction = matcher.Instruction;
			if (!(instruction.operand is MethodBase originalMethod))
			{
				Logger.LogWarning("REDIRECT target '" + config.TargetMember + "' is a field, not a method. Skipped.");
				matcher.Advance(1);
				return true;
			}
			if (!DontScrewUpStack(originalMethod, instruction.opcode, config.PatchMethod))
			{
				Logger.LogWarning($"REDIRECT patch '{config.PatchMethod.Name}' doesn't match with '{config.TargetMember}'. Skipped.");
				matcher.Advance(1);
				return true;
			}
			matcher.SetInstruction(new CodeInstruction(OpCodes.Call, (object)config.PatchMethod));
			return false;
		}

		private static (string, string) GetRequired(TranspilerConfig config)
		{
			if (string.IsNullOrEmpty(config.TargetMember))
			{
				return ("", "");
			}
			string item = "";
			string text = config.TargetMember;
			if (text.Contains('.'))
			{
				string[] array = text.Split('.');
				item = array[0];
				text = array[1];
			}
			else if (text.Contains("::"))
			{
				string[] array2 = text.Split(new string[1] { "::" }, StringSplitOptions.None);
				item = array2[0];
				text = array2[1];
			}
			return (item, text);
		}

		private static bool Matcher(CodeInstruction instruction, TranspilerConfig config, string requiredMethod, string requiredClass, CodeMatcher matcher)
		{
			Logger.LogFile($"{instruction.opcode}   {instruction.operand}");
			bool result = instruction.opcode == OpCodes.Ret;
			if (config.Type == AT.RETURN)
			{
				return result;
			}
			bool result2 = OpCodeHelper.IsBranch(instruction.opcode);
			AT type = config.Type;
			if ((uint)(type - 12) <= 1u)
			{
				return result2;
			}
			type = config.Type;
			if ((uint)(type - 7) <= 3u)
			{
				return OpCodeHelper.IsLoopEntryBranch(instruction, matcher.Instructions());
			}
			bool result3 = OpCodeHelper.IsLocalOpcode(instruction.opcode);
			type = config.Type;
			if ((uint)(type - 14) <= 1u)
			{
				return result3;
			}
			bool result4 = OpCodeHelper.IsArgOpcode(instruction.opcode);
			type = config.Type;
			if ((uint)(type - 16) <= 1u)
			{
				return result4;
			}
			bool flag = OpCodeHelper.IsField(instruction.opcode);
			type = config.Type;
			if ((uint)(type - 18) <= 1u)
			{
				return flag;
			}
			bool flag2 = OpCodeHelper.IsMethod(instruction.opcode);
			if (!flag2 && !flag)
			{
				return false;
			}
			string name;
			string text;
			if (flag2 && instruction.operand is MethodInfo methodInfo)
			{
				name = methodInfo.Name;
				text = methodInfo.DeclaringType?.Name;
			}
			else
			{
				if (!flag || !(instruction.operand is FieldInfo fieldInfo))
				{
					return false;
				}
				name = fieldInfo.Name;
				text = fieldInfo.DeclaringType?.Name;
			}
			if (name != requiredMethod)
			{
				return false;
			}
			if (!string.IsNullOrEmpty(requiredClass) && text != requiredClass)
			{
				return false;
			}
			return true;
		}

		private static bool DontScrewUpStack(MethodBase originalMethod, OpCode opCode, MethodInfo patchMethod)
		{
			List<Type> list = (from p in originalMethod.GetParameters()
				select p.ParameterType).ToList();
			if (opCode != OpCodes.Newobj && !originalMethod.IsStatic)
			{
				list.Insert(0, originalMethod.DeclaringType);
			}
			List<Type> list2 = (from p in patchMethod.GetParameters()
				select p.ParameterType).ToList();
			if (list.Count != list2.Count)
			{
				return false;
			}
			for (int num = 0; num < list.Count; num++)
			{
				if (!list[num].IsAssignableFrom(list2[num]))
				{
					return false;
				}
			}
			Type type = ((originalMethod is MethodInfo methodInfo) ? methodInfo.ReturnType : originalMethod.DeclaringType);
			return patchMethod.ReturnType == type;
		}
	}
	internal class TranspilerConfig
	{
		public AT Type;

		public string? TargetMember;

		public Type? TargetType;

		public MethodInfo PatchMethod;

		public uint Occurrence;

		public uint StartIndex;

		public uint ArgIndex;

		public TranspilerConfig(AT type, string targetMember, MethodInfo patchMethod, uint occurrence, uint startIndex, uint argIndex, Type targetType)
		{
			Type = type;
			TargetMember = targetMember;
			PatchMethod = patchMethod;
			Occurrence = occurrence;
			StartIndex = startIndex;
			ArgIndex = argIndex;
			TargetType = targetType;
		}
	}
}

MonoMod.Backports.dll

Decompiled a month ago
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CLSCompliant(true)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("0x0ade, DaNike")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2024 0x0ade, DaNike")]
[assembly: AssemblyDescription("A set of backports of new BCL features to all frameworks which MonoMod supports.")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2+a1b82852b")]
[assembly: AssemblyProduct("MonoMod.Backports")]
[assembly: AssemblyTitle("MonoMod.Backports")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/MonoMod/MonoMod.git")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.0")]
[assembly: TypeForwardedTo(typeof(ArrayPool<>))]
[assembly: TypeForwardedTo(typeof(BuffersExtensions))]
[assembly: TypeForwardedTo(typeof(IBufferWriter<>))]
[assembly: TypeForwardedTo(typeof(IMemoryOwner<>))]
[assembly: TypeForwardedTo(typeof(IPinnable))]
[assembly: TypeForwardedTo(typeof(MemoryHandle))]
[assembly: TypeForwardedTo(typeof(MemoryManager<>))]
[assembly: TypeForwardedTo(typeof(ReadOnlySequence<>))]
[assembly: TypeForwardedTo(typeof(ReadOnlySequenceSegment<>))]
[assembly: TypeForwardedTo(typeof(StandardFormat))]
[assembly: TypeForwardedTo(typeof(ConcurrentBag<>))]
[assembly: TypeForwardedTo(typeof(ConcurrentDictionary<, >))]
[assembly: TypeForwardedTo(typeof(ConcurrentQueue<>))]
[assembly: TypeForwardedTo(typeof(ConcurrentStack<>))]
[assembly: TypeForwardedTo(typeof(EnumerablePartitionerOptions))]
[assembly: TypeForwardedTo(typeof(IProducerConsumerCollection<>))]
[assembly: TypeForwardedTo(typeof(OrderablePartitioner<>))]
[assembly: TypeForwardedTo(typeof(Partitioner))]
[assembly: TypeForwardedTo(typeof(Partitioner<>))]
[assembly: TypeForwardedTo(typeof(IReadOnlyCollection<>))]
[assembly: TypeForwardedTo(typeof(IReadOnlyList<>))]
[assembly: TypeForwardedTo(typeof(IStructuralComparable))]
[assembly: TypeForwardedTo(typeof(IStructuralEquatable))]
[assembly: TypeForwardedTo(typeof(HashCode))]
[assembly: TypeForwardedTo(typeof(Memory<>))]
[assembly: TypeForwardedTo(typeof(MemoryExtensions))]
[assembly: TypeForwardedTo(typeof(ReadOnlyMemory<>))]
[assembly: TypeForwardedTo(typeof(ReadOnlySpan<>))]
[assembly: TypeForwardedTo(typeof(IntrospectionExtensions))]
[assembly: TypeForwardedTo(typeof(IReflectableType))]
[assembly: TypeForwardedTo(typeof(TypeDelegator))]
[assembly: TypeForwardedTo(typeof(TypeInfo))]
[assembly: TypeForwardedTo(typeof(CallerFilePathAttribute))]
[assembly: TypeForwardedTo(typeof(CallerLineNumberAttribute))]
[assembly: TypeForwardedTo(typeof(CallerMemberNameAttribute))]
[assembly: TypeForwardedTo(typeof(ConditionalWeakTable<, >))]
[assembly: TypeForwardedTo(typeof(TupleElementNamesAttribute))]
[assembly: TypeForwardedTo(typeof(Unsafe))]
[assembly: TypeForwardedTo(typeof(DefaultDllImportSearchPathsAttribute))]
[assembly: TypeForwardedTo(typeof(DllImportSearchPath))]
[assembly: TypeForwardedTo(typeof(MemoryMarshal))]
[assembly: TypeForwardedTo(typeof(SequenceMarshal))]
[assembly: TypeForwardedTo(typeof(SequencePosition))]
[assembly: TypeForwardedTo(typeof(Span<>))]
[assembly: TypeForwardedTo(typeof(SpinLock))]
[assembly: TypeForwardedTo(typeof(SpinWait))]
[assembly: TypeForwardedTo(typeof(ThreadLocal<>))]
[assembly: TypeForwardedTo(typeof(Volatile))]
[assembly: TypeForwardedTo(typeof(Tuple))]
[assembly: TypeForwardedTo(typeof(Tuple<>))]
[assembly: TypeForwardedTo(typeof(Tuple<, >))]
[assembly: TypeForwardedTo(typeof(Tuple<, , >))]
[assembly: TypeForwardedTo(typeof(Tuple<, , , >))]
[assembly: TypeForwardedTo(typeof(Tuple<, , , , >))]
[assembly: TypeForwardedTo(typeof(Tuple<, , , , , >))]
[assembly: TypeForwardedTo(typeof(Tuple<, , , , , , >))]
[assembly: TypeForwardedTo(typeof(Tuple<, , , , , , , >))]
[assembly: TypeForwardedTo(typeof(ValueTuple))]
[assembly: TypeForwardedTo(typeof(ValueTuple<>))]
[assembly: TypeForwardedTo(typeof(ValueTuple<, >))]
[assembly: TypeForwardedTo(typeof(ValueTuple<, , >))]
[assembly: TypeForwardedTo(typeof(ValueTuple<, , , >))]
[assembly: TypeForwardedTo(typeof(ValueTuple<, , , , >))]
[assembly: TypeForwardedTo(typeof(ValueTuple<, , , , , >))]
[assembly: TypeForwardedTo(typeof(ValueTuple<, , , , , , >))]
[assembly: TypeForwardedTo(typeof(ValueTuple<, , , , , , , >))]
[assembly: TypeForwardedTo(typeof(WeakReference<>))]
[module: UnverifiableCode]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = 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;
		}
	}
}
internal static class AssemblyInfo
{
	public const string AssemblyName = "MonoMod.Backports";

	public const string AssemblyVersion = "1.1.2";
}
namespace MonoMod.SourceGen.Attributes
{
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class EmitILOverloadsAttribute : Attribute
	{
		public EmitILOverloadsAttribute(string filename, string kind)
		{
		}
	}
	internal static class ILOverloadKind
	{
		public const string Cursor = "ILCursor";

		public const string Matcher = "ILMatcher";
	}
}
namespace MonoMod.Backports
{
	public static class MethodImplOptionsEx
	{
		public const MethodImplOptions Unmanaged = MethodImplOptions.Unmanaged;

		public const MethodImplOptions NoInlining = MethodImplOptions.NoInlining;

		public const MethodImplOptions ForwardRef = MethodImplOptions.ForwardRef;

		public const MethodImplOptions Synchronized = MethodImplOptions.Synchronized;

		public const MethodImplOptions NoOptimization = MethodImplOptions.NoOptimization;

		public const MethodImplOptions PreserveSig = MethodImplOptions.PreserveSig;

		public const MethodImplOptions AggressiveInlining = MethodImplOptions.AggressiveInlining;

		public const MethodImplOptions AggressiveOptimization = MethodImplOptions.AggressiveOptimization;

		public const MethodImplOptions InternalCall = MethodImplOptions.InternalCall;
	}
}
namespace MonoMod.Backports.ILHelpers
{
	[CLSCompliant(false)]
	public static class UnsafeRaw
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static T Read<T>(void* source)
		{
			return Unsafe.Read<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static T ReadUnaligned<T>(void* source)
		{
			return Unsafe.ReadUnaligned<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static T ReadUnaligned<T>(ref byte source)
		{
			return Unsafe.ReadUnaligned<T>(ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void Write<T>(void* destination, T value)
		{
			Unsafe.Write(destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void WriteUnaligned<T>(void* destination, T value)
		{
			Unsafe.WriteUnaligned(destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static void WriteUnaligned<T>(ref byte destination, T value)
		{
			Unsafe.WriteUnaligned(ref destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void Copy<T>(void* destination, ref T source)
		{
			Unsafe.Copy(destination, ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void Copy<T>(ref T destination, void* source)
		{
			Unsafe.Copy(ref destination, source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void* AsPointer<T>(ref T value)
		{
			return Unsafe.AsPointer(ref value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static void SkipInit<T>(out T value)
		{
			Unsafe.SkipInit<T>(out value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void CopyBlock(void* destination, void* source, uint byteCount)
		{
			Unsafe.CopyBlock(destination, source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static void CopyBlock(ref byte destination, ref byte source, uint byteCount)
		{
			Unsafe.CopyBlock(ref destination, ref source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void CopyBlockUnaligned(void* destination, void* source, uint byteCount)
		{
			Unsafe.CopyBlockUnaligned(destination, source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static void CopyBlockUnaligned(ref byte destination, ref byte source, uint byteCount)
		{
			Unsafe.CopyBlockUnaligned(ref destination, ref source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void InitBlock(void* startAddress, byte value, uint byteCount)
		{
			Unsafe.InitBlock(startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static void InitBlock(ref byte startAddress, byte value, uint byteCount)
		{
			Unsafe.InitBlock(ref startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void InitBlockUnaligned(void* startAddress, byte value, uint byteCount)
		{
			Unsafe.InitBlockUnaligned(startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount)
		{
			Unsafe.InitBlockUnaligned(ref startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static T As<T>(object o) where T : class
		{
			return Unsafe.As<T>(o);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static ref T AsRef<T>(void* source)
		{
			return ref Unsafe.AsRef<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T AsRef<T>(in T source)
		{
			return ref Unsafe.AsRef(in source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref TTo As<TFrom, TTo>(ref TFrom source)
		{
			return ref Unsafe.As<TFrom, TTo>(ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T Unbox<T>(object box) where T : struct
		{
			return ref Unsafe.Unbox<T>(box);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T AddByteOffset<T>(ref T source, nint byteOffset)
		{
			return ref Unsafe.AddByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T AddByteOffset<T>(ref T source, nuint byteOffset)
		{
			return ref Unsafe.AddByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T SubtractByteOffset<T>(ref T source, nint byteOffset)
		{
			return ref Unsafe.SubtractByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T SubtractByteOffset<T>(ref T source, nuint byteOffset)
		{
			return ref Unsafe.SubtractByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static nint ByteOffset<T>(ref T origin, ref T target)
		{
			return Unsafe.ByteOffset(ref origin, ref target);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static bool AreSame<T>(ref T left, ref T right)
		{
			return Unsafe.AreSame(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static bool IsAddressGreaterThan<T>(ref T left, ref T right)
		{
			return Unsafe.IsAddressGreaterThan(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static bool IsAddressLessThan<T>(ref T left, ref T right)
		{
			return Unsafe.IsAddressLessThan(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static bool IsNullRef<T>(ref T source)
		{
			return Unsafe.IsNullRef(ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T NullRef<T>()
		{
			return ref Unsafe.NullRef<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static int SizeOf<T>()
		{
			return Unsafe.SizeOf<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T Add<T>(ref T source, int elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void* Add<T>(void* source, int elementOffset)
		{
			return Unsafe.Add<T>(source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T Add<T>(ref T source, nint elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T Add<T>(ref T source, nuint elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T Subtract<T>(ref T source, int elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public unsafe static void* Subtract<T>(void* source, int elementOffset)
		{
			return Unsafe.Subtract<T>(source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T Subtract<T>(ref T source, nint elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[NonVersionable]
		public static ref T Subtract<T>(ref T source, nuint elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}
	}
}
namespace System
{
	public static class ArrayEx
	{
		public static int MaxLength => 1879048191;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static T[] Empty<T>()
		{
			return Array.Empty<T>();
		}
	}
	public static class EnvironmentEx
	{
		public static int CurrentManagedThreadId => Environment.CurrentManagedThreadId;
	}
	public sealed class Gen2GcCallback : CriticalFinalizerObject
	{
		private readonly Func<bool>? _callback0;

		private readonly Func<object, bool>? _callback1;

		private GCHandle _weakTargetObj;

		private Gen2GcCallback(Func<bool> callback)
		{
			_callback0 = callback;
		}

		private Gen2GcCallback(Func<object, bool> callback, object targetObj)
		{
			_callback1 = callback;
			_weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak);
		}

		public static void Register(Func<bool> callback)
		{
			new Gen2GcCallback(callback);
		}

		public static void Register(Func<object, bool> callback, object targetObj)
		{
			new Gen2GcCallback(callback, targetObj);
		}

		~Gen2GcCallback()
		{
			if (_weakTargetObj.IsAllocated)
			{
				object target = _weakTargetObj.Target;
				if (target == null)
				{
					_weakTargetObj.Free();
					return;
				}
				try
				{
					if (!_callback1(target))
					{
						_weakTargetObj.Free();
						return;
					}
				}
				catch
				{
				}
			}
			else
			{
				try
				{
					if (!_callback0())
					{
						return;
					}
				}
				catch
				{
				}
			}
			GC.ReRegisterForFinalize(this);
		}
	}
	public static class MathEx
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static byte Clamp(byte value, byte min, byte max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static decimal Clamp(decimal value, decimal min, decimal max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static double Clamp(double value, double min, double max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static short Clamp(short value, short min, short max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int Clamp(int value, int min, int max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static long Clamp(long value, long min, long max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static nint Clamp(nint value, nint min, nint max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static sbyte Clamp(sbyte value, sbyte min, sbyte max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Clamp(float value, float min, float max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static ushort Clamp(ushort value, ushort min, ushort max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static uint Clamp(uint value, uint min, uint max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static ulong Clamp(ulong value, ulong min, ulong max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static nuint Clamp(nuint value, nuint min, nuint max)
		{
			if (min > max)
			{
				ThrowMinMaxException(min, max);
			}
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[DoesNotReturn]
		private static void ThrowMinMaxException<T>(T min, T max)
		{
			throw new ArgumentException($"Minimum {min} is less than maximum {max}");
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
	internal sealed class NonVersionableAttribute : Attribute
	{
	}
	public static class StringComparerEx
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static StringComparer FromComparison(StringComparison comparisonType)
		{
			return StringComparer.FromComparison(comparisonType);
		}
	}
	public static class StringExtensions
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static string Replace(this string self, string oldValue, string newValue, StringComparison comparison)
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, System.ExceptionArgument.self);
			System.ThrowHelper.ThrowIfArgumentNull(oldValue, System.ExceptionArgument.oldValue);
			System.ThrowHelper.ThrowIfArgumentNull(newValue, System.ExceptionArgument.newValue);
			return self.Replace(oldValue, newValue, comparison);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool Contains(this string self, string value, StringComparison comparison)
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, System.ExceptionArgument.self);
			System.ThrowHelper.ThrowIfArgumentNull(value, System.ExceptionArgument.value);
			return self.Contains(value, comparison);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool Contains(this string self, char value, StringComparison comparison)
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, System.ExceptionArgument.self);
			return self.Contains(value, comparison);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int GetHashCode(this string self, StringComparison comparison)
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, System.ExceptionArgument.self);
			return self.GetHashCode(comparison);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOf(this string self, char value, StringComparison comparison)
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, System.ExceptionArgument.self);
			return self.IndexOf(value, comparison);
		}
	}
	internal static class ThrowHelper
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static void ThrowIfArgumentNull([NotNull] object? obj, System.ExceptionArgument argument)
		{
			if (obj == null)
			{
				ThrowArgumentNullException(argument);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static void ThrowIfArgumentNull([NotNull] object? obj, string argument, string? message = null)
		{
			if (obj == null)
			{
				ThrowArgumentNullException(argument, message);
			}
		}

		[DoesNotReturn]
		internal static void ThrowArgumentNullException(System.ExceptionArgument argument)
		{
			throw CreateArgumentNullException(argument);
		}

		[DoesNotReturn]
		internal static void ThrowArgumentNullException(string argument, string? message = null)
		{
			throw CreateArgumentNullException(argument, message);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentNullException(System.ExceptionArgument argument)
		{
			return CreateArgumentNullException(argument.ToString());
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentNullException(string argument, string? message = null)
		{
			return new ArgumentNullException(argument, message);
		}

		[DoesNotReturn]
		internal static void ThrowArrayTypeMismatchException()
		{
			throw CreateArrayTypeMismatchException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArrayTypeMismatchException()
		{
			return new ArrayTypeMismatchException();
		}

		[DoesNotReturn]
		internal static void ThrowArgumentException_InvalidTypeWithPointersNotSupported(Type type)
		{
			throw CreateArgumentException_InvalidTypeWithPointersNotSupported(type);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentException_InvalidTypeWithPointersNotSupported(Type type)
		{
			return new ArgumentException($"Type {type} with managed pointers cannot be used in a Span");
		}

		[DoesNotReturn]
		internal static void ThrowArgumentException_DestinationTooShort()
		{
			throw CreateArgumentException_DestinationTooShort();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentException_DestinationTooShort()
		{
			return new ArgumentException("Destination too short");
		}

		[DoesNotReturn]
		internal static void ThrowArgumentException(string message, string? argument = null)
		{
			throw CreateArgumentException(message, argument);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentException(string message, string? argument)
		{
			return new ArgumentException(message, argument ?? "");
		}

		[DoesNotReturn]
		internal static void ThrowIndexOutOfRangeException()
		{
			throw CreateIndexOutOfRangeException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateIndexOutOfRangeException()
		{
			return new IndexOutOfRangeException();
		}

		[DoesNotReturn]
		internal static void ThrowArgumentOutOfRangeException()
		{
			throw CreateArgumentOutOfRangeException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException()
		{
			return new ArgumentOutOfRangeException();
		}

		[DoesNotReturn]
		internal static void ThrowArgumentOutOfRangeException(System.ExceptionArgument argument)
		{
			throw CreateArgumentOutOfRangeException(argument);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException(System.ExceptionArgument argument)
		{
			return new ArgumentOutOfRangeException(argument.ToString());
		}

		[DoesNotReturn]
		internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
		{
			throw CreateArgumentOutOfRangeException_PrecisionTooLarge();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_PrecisionTooLarge()
		{
			return new ArgumentOutOfRangeException("precision", $"Precision too large (max: {99})");
		}

		[DoesNotReturn]
		internal static void ThrowArgumentOutOfRangeException_SymbolDoesNotFit()
		{
			throw CreateArgumentOutOfRangeException_SymbolDoesNotFit();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_SymbolDoesNotFit()
		{
			return new ArgumentOutOfRangeException("symbol", "Bad format specifier");
		}

		[DoesNotReturn]
		internal static void ThrowInvalidOperationException()
		{
			throw CreateInvalidOperationException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException()
		{
			return new InvalidOperationException();
		}

		[DoesNotReturn]
		internal static void ThrowInvalidOperationException_OutstandingReferences()
		{
			throw CreateInvalidOperationException_OutstandingReferences();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException_OutstandingReferences()
		{
			return new InvalidOperationException("Outstanding references");
		}

		[DoesNotReturn]
		internal static void ThrowInvalidOperationException_UnexpectedSegmentType()
		{
			throw CreateInvalidOperationException_UnexpectedSegmentType();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException_UnexpectedSegmentType()
		{
			return new InvalidOperationException("Unexpected segment type");
		}

		[DoesNotReturn]
		internal static void ThrowInvalidOperationException_EndPositionNotReached()
		{
			throw CreateInvalidOperationException_EndPositionNotReached();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException_EndPositionNotReached()
		{
			return new InvalidOperationException("End position not reached");
		}

		[DoesNotReturn]
		internal static void ThrowArgumentOutOfRangeException_PositionOutOfRange()
		{
			throw CreateArgumentOutOfRangeException_PositionOutOfRange();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_PositionOutOfRange()
		{
			return new ArgumentOutOfRangeException("position");
		}

		[DoesNotReturn]
		internal static void ThrowArgumentOutOfRangeException_OffsetOutOfRange()
		{
			throw CreateArgumentOutOfRangeException_OffsetOutOfRange();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_OffsetOutOfRange()
		{
			return new ArgumentOutOfRangeException("offset");
		}

		[DoesNotReturn]
		internal static void ThrowObjectDisposedException_ArrayMemoryPoolBuffer()
		{
			throw CreateObjectDisposedException_ArrayMemoryPoolBuffer();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateObjectDisposedException_ArrayMemoryPoolBuffer()
		{
			return new ObjectDisposedException("ArrayMemoryPoolBuffer");
		}

		[DoesNotReturn]
		internal static void ThrowFormatException_BadFormatSpecifier()
		{
			throw CreateFormatException_BadFormatSpecifier();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateFormatException_BadFormatSpecifier()
		{
			return new FormatException("Bad format specifier");
		}

		[DoesNotReturn]
		internal static void ThrowArgumentException_OverlapAlignmentMismatch()
		{
			throw CreateArgumentException_OverlapAlignmentMismatch();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentException_OverlapAlignmentMismatch()
		{
			return new ArgumentException("Overlap alignment mismatch");
		}

		[DoesNotReturn]
		internal static void ThrowNotSupportedException(string? msg = null)
		{
			throw CreateThrowNotSupportedException(msg);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateThrowNotSupportedException(string? msg)
		{
			return new NotSupportedException();
		}

		[DoesNotReturn]
		internal static void ThrowKeyNullException()
		{
			ThrowArgumentNullException(System.ExceptionArgument.key);
		}

		[DoesNotReturn]
		internal static void ThrowValueNullException()
		{
			throw CreateThrowValueNullException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateThrowValueNullException()
		{
			return new ArgumentException("Value is null");
		}

		[DoesNotReturn]
		internal static void ThrowOutOfMemoryException()
		{
			throw CreateOutOfMemoryException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateOutOfMemoryException()
		{
			return new OutOfMemoryException();
		}

		public static bool TryFormatThrowFormatException(out int bytesWritten)
		{
			bytesWritten = 0;
			ThrowFormatException_BadFormatSpecifier();
			return false;
		}

		public static bool TryParseThrowFormatException<T>(out T value, out int bytesConsumed)
		{
			value = default(T);
			bytesConsumed = 0;
			ThrowFormatException_BadFormatSpecifier();
			return false;
		}

		[DoesNotReturn]
		public static void ThrowArgumentValidationException<T>(ReadOnlySequenceSegment<T>? startSegment, int startIndex, ReadOnlySequenceSegment<T>? endSegment)
		{
			throw CreateArgumentValidationException(startSegment, startIndex, endSegment);
		}

		private static Exception CreateArgumentValidationException<T>(ReadOnlySequenceSegment<T>? startSegment, int startIndex, ReadOnlySequenceSegment<T>? endSegment)
		{
			if (startSegment == null)
			{
				return CreateArgumentNullException(System.ExceptionArgument.startSegment);
			}
			if (endSegment == null)
			{
				return CreateArgumentNullException(System.ExceptionArgument.endSegment);
			}
			if (startSegment != endSegment && startSegment.RunningIndex > endSegment.RunningIndex)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.endSegment);
			}
			if ((uint)startSegment.Memory.Length < (uint)startIndex)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.startIndex);
			}
			return CreateArgumentOutOfRangeException(System.ExceptionArgument.endIndex);
		}

		[DoesNotReturn]
		public static void ThrowArgumentValidationException(Array? array, int start)
		{
			throw CreateArgumentValidationException(array, start);
		}

		private static Exception CreateArgumentValidationException(Array? array, int start)
		{
			if (array == null)
			{
				return CreateArgumentNullException(System.ExceptionArgument.array);
			}
			if ((uint)start > (uint)array.Length)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return CreateArgumentOutOfRangeException(System.ExceptionArgument.length);
		}

		[DoesNotReturn]
		internal static void ThrowArgumentException_TupleIncorrectType(object other)
		{
			throw new ArgumentException($"Value tuple of incorrect type (found {other.GetType()})", "other");
		}

		[DoesNotReturn]
		public static void ThrowStartOrEndArgumentValidationException(long start)
		{
			throw CreateStartOrEndArgumentValidationException(start);
		}

		private static Exception CreateStartOrEndArgumentValidationException(long start)
		{
			if (start < 0)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return CreateArgumentOutOfRangeException(System.ExceptionArgument.length);
		}
	}
	internal enum ExceptionArgument
	{
		length,
		start,
		bufferSize,
		minimumBufferSize,
		elementIndex,
		comparable,
		comparer,
		destination,
		offset,
		startSegment,
		endSegment,
		startIndex,
		endIndex,
		array,
		culture,
		manager,
		key,
		collection,
		index,
		type,
		self,
		value,
		oldValue,
		newValue
	}
	public static class TypeExtensions
	{
		public static bool IsByRefLike(this Type type)
		{
			System.ThrowHelper.ThrowIfArgumentNull(type, System.ExceptionArgument.type);
			if ((object)type == null)
			{
				System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.type);
			}
			return type.IsByRefLike;
		}
	}
}
namespace System.Threading
{
	public static class MonitorEx
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void Enter(object obj, ref bool lockTaken)
		{
			Monitor.Enter(obj, ref lockTaken);
		}
	}
}
namespace System.Text
{
	public static class StringBuilderExtensions
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static StringBuilder Clear(this StringBuilder builder)
		{
			System.ThrowHelper.ThrowIfArgumentNull(builder, "builder");
			return builder.Clear();
		}
	}
}
namespace System.Numerics
{
	public static class BitOperations
	{
		private static ReadOnlySpan<byte> TrailingZeroCountDeBruijn => new byte[32]
		{
			0, 1, 28, 2, 29, 14, 24, 3, 30, 22,
			20, 15, 25, 17, 4, 8, 31, 27, 13, 23,
			21, 19, 16, 7, 26, 12, 18, 6, 11, 5,
			10, 9
		};

		private static ReadOnlySpan<byte> Log2DeBruijn => new byte[32]
		{
			0, 9, 1, 10, 13, 21, 2, 29, 11, 14,
			16, 18, 22, 25, 3, 30, 8, 12, 20, 28,
			15, 17, 24, 7, 19, 27, 23, 6, 26, 5,
			4, 31
		};

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int LeadingZeroCount(uint value)
		{
			if (value == 0)
			{
				return 32;
			}
			return 0x1F ^ Log2SoftwareFallback(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int LeadingZeroCount(ulong value)
		{
			uint num = (uint)(value >> 32);
			if (num == 0)
			{
				return 32 + LeadingZeroCount((uint)value);
			}
			return LeadingZeroCount(num);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int Log2(uint value)
		{
			value |= 1u;
			return Log2SoftwareFallback(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int Log2(ulong value)
		{
			value |= 1;
			uint num = (uint)(value >> 32);
			if (num == 0)
			{
				return Log2((uint)value);
			}
			return 32 + Log2(num);
		}

		private static int Log2SoftwareFallback(uint value)
		{
			value |= value >> 1;
			value |= value >> 2;
			value |= value >> 4;
			value |= value >> 8;
			value |= value >> 16;
			return Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(Log2DeBruijn), (IntPtr)(int)(value * 130329821 >> 27));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static int Log2Ceiling(uint value)
		{
			int num = Log2(value);
			if (PopCount(value) != 1)
			{
				num++;
			}
			return num;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static int Log2Ceiling(ulong value)
		{
			int num = Log2(value);
			if (PopCount(value) != 1)
			{
				num++;
			}
			return num;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int PopCount(uint value)
		{
			return SoftwareFallback(value);
			static int SoftwareFallback(uint value)
			{
				value -= (value >> 1) & 0x55555555;
				value = (value & 0x33333333) + ((value >> 2) & 0x33333333);
				value = ((value + (value >> 4)) & 0xF0F0F0F) * 16843009 >> 24;
				return (int)value;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int PopCount(ulong value)
		{
			if (IntPtr.Size == 8)
			{
				return PopCount((uint)value) + PopCount((uint)(value >> 32));
			}
			return SoftwareFallback(value);
			static int SoftwareFallback(ulong value)
			{
				value -= (value >> 1) & 0x5555555555555555L;
				value = (value & 0x3333333333333333L) + ((value >> 2) & 0x3333333333333333L);
				value = ((value + (value >> 4)) & 0xF0F0F0F0F0F0F0FL) * 72340172838076673L >> 56;
				return (int)value;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int TrailingZeroCount(int value)
		{
			return TrailingZeroCount((uint)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int TrailingZeroCount(uint value)
		{
			if (value == 0)
			{
				return 32;
			}
			return Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(TrailingZeroCountDeBruijn), (IntPtr)(int)((value & (0 - value)) * 125613361 >> 27));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int TrailingZeroCount(long value)
		{
			return TrailingZeroCount((ulong)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int TrailingZeroCount(ulong value)
		{
			uint num = (uint)value;
			if (num == 0)
			{
				return 32 + TrailingZeroCount((uint)(value >> 32));
			}
			return TrailingZeroCount(num);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static uint RotateLeft(uint value, int offset)
		{
			return (value << offset) | (value >> 32 - offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static ulong RotateLeft(ulong value, int offset)
		{
			return (value << offset) | (value >> 64 - offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static uint RotateRight(uint value, int offset)
		{
			return (value >> offset) | (value << 32 - offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static ulong RotateRight(ulong value, int offset)
		{
			return (value >> offset) | (value << 64 - offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static uint ResetLowestSetBit(uint value)
		{
			return value & (value - 1);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static uint ResetBit(uint value, int bitPos)
		{
			return value & (uint)(~(1 << bitPos));
		}
	}
	public static class BitOperationsEx
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsPow2(int value)
		{
			if ((value & (value - 1)) == 0)
			{
				return value > 0;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static bool IsPow2(uint value)
		{
			if ((value & (value - 1)) == 0)
			{
				return value != 0;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsPow2(long value)
		{
			if ((value & (value - 1)) == 0L)
			{
				return value > 0;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static bool IsPow2(ulong value)
		{
			if ((value & (value - 1)) == 0L)
			{
				return value != 0;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsPow2(nint value)
		{
			if ((value & (value - 1)) == 0)
			{
				return value > 0;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static bool IsPow2(nuint value)
		{
			if ((value & (value - 1)) == 0)
			{
				return value != 0;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static uint RoundUpToPowerOf2(uint value)
		{
			value--;
			value |= value >> 1;
			value |= value >> 2;
			value |= value >> 4;
			value |= value >> 8;
			value |= value >> 16;
			return value + 1;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static ulong RoundUpToPowerOf2(ulong value)
		{
			value--;
			value |= value >> 1;
			value |= value >> 2;
			value |= value >> 4;
			value |= value >> 8;
			value |= value >> 16;
			value |= value >> 32;
			return value + 1;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static nuint RoundUpToPowerOf2(nuint value)
		{
			if (IntPtr.Size == 8)
			{
				return (nuint)RoundUpToPowerOf2((ulong)value);
			}
			return RoundUpToPowerOf2((uint)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int LeadingZeroCount(uint value)
		{
			return BitOperations.LeadingZeroCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int LeadingZeroCount(ulong value)
		{
			return BitOperations.LeadingZeroCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int LeadingZeroCount(nuint value)
		{
			if (IntPtr.Size == 8)
			{
				return LeadingZeroCount((ulong)value);
			}
			return LeadingZeroCount((uint)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int Log2(uint value)
		{
			return BitOperations.Log2(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int Log2(ulong value)
		{
			return BitOperations.Log2(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int Log2(nuint value)
		{
			if (IntPtr.Size == 8)
			{
				return Log2((ulong)value);
			}
			return Log2((uint)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int PopCount(uint value)
		{
			return BitOperations.PopCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int PopCount(ulong value)
		{
			return BitOperations.PopCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int PopCount(nuint value)
		{
			if (IntPtr.Size == 8)
			{
				return PopCount((ulong)value);
			}
			return PopCount((uint)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int TrailingZeroCount(int value)
		{
			return BitOperations.TrailingZeroCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int TrailingZeroCount(uint value)
		{
			return BitOperations.TrailingZeroCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int TrailingZeroCount(long value)
		{
			return BitOperations.TrailingZeroCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int TrailingZeroCount(ulong value)
		{
			return BitOperations.TrailingZeroCount(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int TrailingZeroCount(nint value)
		{
			if (IntPtr.Size == 8)
			{
				return TrailingZeroCount((long)value);
			}
			return TrailingZeroCount((int)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static int TrailingZeroCount(nuint value)
		{
			if (IntPtr.Size == 8)
			{
				return TrailingZeroCount((ulong)value);
			}
			return TrailingZeroCount((uint)value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static uint RotateLeft(uint value, int offset)
		{
			return BitOperations.RotateLeft(value, offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static ulong RotateLeft(ulong value, int offset)
		{
			return BitOperations.RotateLeft(value, offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static nuint RotateLeft(nuint value, int offset)
		{
			if (IntPtr.Size == 8)
			{
				return (nuint)RotateLeft((ulong)value, offset);
			}
			return RotateLeft((uint)value, offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static uint RotateRight(uint value, int offset)
		{
			return BitOperations.RotateRight(value, offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static ulong RotateRight(ulong value, int offset)
		{
			return BitOperations.RotateRight(value, offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public static nuint RotateRight(nuint value, int offset)
		{
			if (IntPtr.Size == 8)
			{
				return (nuint)RotateRight((ulong)value, offset);
			}
			return RotateRight((uint)value, offset);
		}
	}
}
namespace System.IO
{
	public static class StreamExtensions
	{
		public static void CopyTo(this Stream src, Stream destination)
		{
			System.ThrowHelper.ThrowIfArgumentNull(src, "src");
			src.CopyTo(destination);
		}

		public static void CopyTo(this Stream src, Stream destination, int bufferSize)
		{
			System.ThrowHelper.ThrowIfArgumentNull(src, "src");
			src.CopyTo(destination, bufferSize);
		}
	}
}
namespace System.Collections
{
	internal static class HashHelpers
	{
		public const uint HashCollisionThreshold = 100u;

		public const int MaxPrimeArrayLength = 2147483587;

		public const int HashPrime = 101;

		private static readonly int[] s_primes = new int[72]
		{
			3, 7, 11, 17, 23, 29, 37, 47, 59, 71,
			89, 107, 131, 163, 197, 239, 293, 353, 431, 521,
			631, 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371,
			4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 17519, 21023,
			25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363,
			156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403,
			968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559,
			5999471, 7199369
		};

		public static bool IsPrime(int candidate)
		{
			if (((uint)candidate & (true ? 1u : 0u)) != 0)
			{
				int num = (int)Math.Sqrt(candidate);
				for (int i = 3; i <= num; i += 2)
				{
					if (candidate % i == 0)
					{
						return false;
					}
				}
				return true;
			}
			return candidate == 2;
		}

		public static int GetPrime(int min)
		{
			if (min < 0)
			{
				throw new ArgumentException("Prime minimum cannot be less than zero");
			}
			int[] array = s_primes;
			foreach (int num in array)
			{
				if (num >= min)
				{
					return num;
				}
			}
			for (int j = min | 1; j < int.MaxValue; j += 2)
			{
				if (IsPrime(j) && (j - 1) % 101 != 0)
				{
					return j;
				}
			}
			return min;
		}

		public static int ExpandPrime(int oldSize)
		{
			int num = 2 * oldSize;
			if ((uint)num > 2147483587u && 2147483587 > oldSize)
			{
				return 2147483587;
			}
			return GetPrime(num);
		}

		public static ulong GetFastModMultiplier(uint divisor)
		{
			return ulong.MaxValue / (ulong)divisor + 1;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static uint FastMod(uint value, uint divisor, ulong multiplier)
		{
			return (uint)(((multiplier * value >> 32) + 1) * divisor >> 32);
		}
	}
}
namespace System.Collections.Concurrent
{
	public static class ConcurrentExtensions
	{
		public static void Clear<T>(this ConcurrentBag<T> bag)
		{
			System.ThrowHelper.ThrowIfArgumentNull(bag, "bag");
			bag.Clear();
		}

		public static void Clear<T>(this ConcurrentQueue<T> queue)
		{
			System.ThrowHelper.ThrowIfArgumentNull(queue, "queue");
			queue.Clear();
		}

		public static TValue AddOrUpdate<TKey, TValue, TArg>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TKey, TArg, TValue> addValueFactory, Func<TKey, TValue, TArg, TValue> updateValueFactory, TArg factoryArgument) where TKey : notnull
		{
			System.ThrowHelper.ThrowIfArgumentNull(dict, "dict");
			return dict.AddOrUpdate(key, addValueFactory, updateValueFactory, factoryArgument);
		}

		public static TValue GetOrAdd<TKey, TValue, TArg>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TKey, TArg, TValue> valueFactory, TArg factoryArgument) where TKey : notnull
		{
			System.ThrowHelper.ThrowIfArgumentNull(dict, "dict");
			return dict.GetOrAdd(key, valueFactory, factoryArgument);
		}

		public static bool TryRemove<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, KeyValuePair<TKey, TValue> item) where TKey : notnull
		{
			System.ThrowHelper.ThrowIfArgumentNull(dict, "dict");
			if (dict.TryRemove(item.Key, out TValue value))
			{
				if (EqualityComparer<TValue>.Default.Equals(item.Value, value))
				{
					return true;
				}
				dict.AddOrUpdate(item.Key, (TKey _) => value, (TKey _, TValue _) => value);
				return false;
			}
			return false;
		}
	}
}
namespace System.Runtime
{
	public struct DependentHandle : IDisposable
	{
		private sealed class DependentHolder : CriticalFinalizerObject
		{
			public GCHandle TargetHandle;

			private IntPtr dependent;

			public object? Dependent
			{
				get
				{
					return GCHandle.FromIntPtr(dependent).Target;
				}
				set
				{
					IntPtr value2 = GCHandle.ToIntPtr(GCHandle.Alloc(value, GCHandleType.Normal));
					IntPtr intPtr;
					do
					{
						intPtr = dependent;
					}
					while (Interlocked.CompareExchange(ref dependent, value2, intPtr) == intPtr);
					GCHandle.FromIntPtr(intPtr).Free();
				}
			}

			public DependentHolder(GCHandle targetHandle, object dependent)
			{
				TargetHandle = targetHandle;
				this.dependent = GCHandle.ToIntPtr(GCHandle.Alloc(dependent, GCHandleType.Normal));
			}

			~DependentHolder()
			{
				if (!AppDomain.CurrentDomain.IsFinalizingForUnload() && (!Environment.HasShutdownStarted && (TargetHandle.IsAllocated && TargetHandle.Target != null)))
				{
					GC.ReRegisterForFinalize(this);
				}
				else
				{
					GCHandle.FromIntPtr(dependent).Free();
				}
			}
		}

		private GCHandle dependentHandle;

		private volatile bool allocated;

		public bool IsAllocated => allocated;

		public object? Target
		{
			get
			{
				if (!allocated)
				{
					throw new InvalidOperationException();
				}
				return UnsafeGetTarget();
			}
			set
			{
				if (!allocated || value != null)
				{
					throw new InvalidOperationException();
				}
				UnsafeSetTargetToNull();
			}
		}

		public object? Dependent
		{
			get
			{
				if (!allocated)
				{
					throw new InvalidOperationException();
				}
				return UnsafeGetHolder()?.Dependent;
			}
			set
			{
				if (!allocated)
				{
					throw new InvalidOperationException();
				}
				UnsafeSetDependent(value);
			}
		}

		public (object? Target, object? Dependent) TargetAndDependent
		{
			get
			{
				if (!allocated)
				{
					throw new InvalidOperationException();
				}
				return (UnsafeGetTarget(), Dependent);
			}
		}

		public DependentHandle(object? target, object? dependent)
		{
			GCHandle targetHandle = GCHandle.Alloc(target, GCHandleType.WeakTrackResurrection);
			dependentHandle = AllocDepHolder(targetHandle, dependent);
			GC.KeepAlive(target);
			allocated = true;
		}

		private static GCHandle AllocDepHolder(GCHandle targetHandle, object? dependent)
		{
			return GCHandle.Alloc((dependent != null) ? new DependentHolder(targetHandle, dependent) : null, GCHandleType.WeakTrackResurrection);
		}

		private DependentHolder? UnsafeGetHolder()
		{
			return Unsafe.As<DependentHolder>(dependentHandle.Target);
		}

		internal object? UnsafeGetTarget()
		{
			return UnsafeGetHolder()?.TargetHandle.Target;
		}

		internal object? UnsafeGetTargetAndDependent(out object? dependent)
		{
			dependent = null;
			DependentHolder dependentHolder = UnsafeGetHolder();
			if (dependentHolder == null)
			{
				return null;
			}
			object target = dependentHolder.TargetHandle.Target;
			if (target == null)
			{
				return null;
			}
			dependent = dependentHolder.Dependent;
			return target;
		}

		internal void UnsafeSetTargetToNull()
		{
			Free();
		}

		internal void UnsafeSetDependent(object? value)
		{
			DependentHolder dependentHolder = UnsafeGetHolder();
			if (dependentHolder != null)
			{
				if (!dependentHolder.TargetHandle.IsAllocated)
				{
					Free();
				}
				else
				{
					dependentHolder.Dependent = value;
				}
			}
		}

		private void FreeDependentHandle()
		{
			if (allocated)
			{
				UnsafeGetHolder()?.TargetHandle.Free();
				dependentHandle.Free();
			}
			allocated = false;
		}

		private void Free()
		{
			FreeDependentHandle();
		}

		public void Dispose()
		{
			Free();
			allocated = false;
		}
	}
}
namespace System.Runtime.InteropServices
{
	public static class MarshalEx
	{
		private static readonly MethodInfo? Marshal_SetLastWin32Error_Meth = typeof(Marshal).GetMethod("SetLastPInvokeError", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(Marshal).GetMethod("SetLastWin32Error", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly Action<int>? Marshal_SetLastWin32Error = (((object)Marshal_SetLastWin32Error_Meth == null) ? null : ((Action<int>)Delegate.CreateDelegate(typeof(Action<int>), Marshal_SetLastWin32Error_Meth)));

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int GetLastPInvokeError()
		{
			return Marshal.GetLastWin32Error();
		}

		public static void SetLastPInvokeError(int error)
		{
			(Marshal_SetLastWin32Error ?? throw new PlatformNotSupportedException("Cannot set last P/Invoke error (no method Marshal.SetLastWin32Error or Marshal.SetLastPInvokeError)"))(error);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	public sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	internal interface ICWTEnumerable<T>
	{
		IEnumerable<T> SelfEnumerable { get; }

		IEnumerator<T> GetEnumerator();
	}
	internal sealed class CWTEnumerable<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable where TKey : class where TValue : class?
	{
		private readonly ConditionalWeakTable<TKey, TValue> cwt;

		public CWTEnumerable(ConditionalWeakTable<TKey, TValue> table)
		{
			cwt = table;
		}

		public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
		{
			return cwt.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	public static class ConditionalWeakTableExtensions
	{
		public static IEnumerable<KeyValuePair<TKey, TValue>> AsEnumerable<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> self) where TKey : class where TValue : class?
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, "self");
			if (self != null)
			{
				return self;
			}
			if (self is ICWTEnumerable<KeyValuePair<TKey, TValue>> iCWTEnumerable)
			{
				return iCWTEnumerable.SelfEnumerable;
			}
			return new CWTEnumerable<TKey, TValue>(self);
		}

		public static IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> self) where TKey : class where TValue : class?
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, "self");
			if (self != null)
			{
				return ((IEnumerable<KeyValuePair<TKey, TValue>>)self).GetEnumerator();
			}
			if (self is ICWTEnumerable<KeyValuePair<TKey, TValue>> iCWTEnumerable)
			{
				return iCWTEnumerable.GetEnumerator();
			}
			throw new PlatformNotSupportedException("This version of MonoMod.Backports was built targeting a version of the framework where ConditionalWeakTable is enumerable, but it isn't!");
		}

		public static void Clear<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> self) where TKey : class where TValue : class?
		{
			System.ThrowHelper.ThrowIfArgumentNull(self, "self");
			self.Clear();
		}

		public static bool TryAdd<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> self, TKey key, TValue value) where TKey : class where TValue : class?
		{
			TValue value2 = value;
			System.ThrowHelper.ThrowIfArgumentNull(self, "self");
			bool didAdd = false;
			self.GetValue(key, delegate
			{
				didAdd = true;
				return value2;
			});
			return didAdd;
		}
	}
	[InterpolatedStringHandler]
	public ref struct DefaultInterpolatedStringHandler
	{
		private const int GuessedLengthPerHole = 11;

		private const int MinimumArrayPoolLength = 256;

		private readonly IFormatProvider? _provider;

		private char[]? _arrayToReturnToPool;

		private Span<char> _chars;

		private int _pos;

		private readonly bool _hasCustomFormatter;

		internal ReadOnlySpan<char> Text => _chars.Slice(0, _pos);

		public DefaultInterpolatedStringHandler(int literalLength, int formattedCount)
		{
			_provider = null;
			_chars = (_arrayToReturnToPool = ArrayPool<char>.Shared.Rent(GetDefaultLength(literalLength, formattedCount)));
			_pos = 0;
			_hasCustomFormatter = false;
		}

		public DefaultInterpolatedStringHandler(int literalLength, int formattedCount, IFormatProvider? provider)
		{
			_provider = provider;
			_chars = (_arrayToReturnToPool = ArrayPool<char>.Shared.Rent(GetDefaultLength(literalLength, formattedCount)));
			_pos = 0;
			_hasCustomFormatter = provider != null && HasCustomFormatter(provider);
		}

		public DefaultInterpolatedStringHandler(int literalLength, int formattedCount, IFormatProvider? provider, Span<char> initialBuffer)
		{
			_provider = provider;
			_chars = initialBuffer;
			_arrayToReturnToPool = null;
			_pos = 0;
			_hasCustomFormatter = provider != null && HasCustomFormatter(provider);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static int GetDefaultLength(int literalLength, int formattedCount)
		{
			return Math.Max(256, literalLength + formattedCount * 11);
		}

		public override string ToString()
		{
			return Text.ToString();
		}

		public string ToStringAndClear()
		{
			string result = Text.ToString();
			Clear();
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal void Clear()
		{
			char[] arrayToReturnToPool = _arrayToReturnToPool;
			this = default(DefaultInterpolatedStringHandler);
			if (arrayToReturnToPool != null)
			{
				ArrayPool<char>.Shared.Return(arrayToReturnToPool);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void AppendLiteral(string value)
		{
			if (value.Length == 1)
			{
				Span<char> chars = _chars;
				int pos = _pos;
				if ((uint)pos < (uint)chars.Length)
				{
					chars[pos] = value[0];
					_pos = pos + 1;
				}
				else
				{
					GrowThenCopyString(value);
				}
			}
			else if (value.Length == 2)
			{
				Span<char> chars2 = _chars;
				int pos2 = _pos;
				if ((uint)pos2 < chars2.Length - 1)
				{
					value.AsSpan().CopyTo(chars2.Slice(pos2));
					_pos = pos2 + 2;
				}
				else
				{
					GrowThenCopyString(value);
				}
			}
			else
			{
				AppendStringDirect(value);
			}
		}

		private void AppendStringDirect(string value)
		{
			if (value.AsSpan().TryCopyTo(_chars.Slice(_pos)))
			{
				_pos += value.Length;
			}
			else
			{
				GrowThenCopyString(value);
			}
		}

		public void AppendFormatted<T>(T value)
		{
			if (_hasCustomFormatter)
			{
				AppendCustomFormatter(value, null);
				return;
			}
			if (typeof(T) == typeof(IntPtr))
			{
				AppendFormatted(Unsafe.As<T, IntPtr>(ref value));
				return;
			}
			if (typeof(T) == typeof(UIntPtr))
			{
				AppendFormatted(Unsafe.As<T, UIntPtr>(ref value));
				return;
			}
			string text = ((!(value is IFormattable)) ? value?.ToString() : ((IFormattable)(object)value).ToString(null, _provider));
			if (text != null)
			{
				AppendStringDirect(text);
			}
		}

		public void AppendFormatted<T>(T value, string? format)
		{
			if (_hasCustomFormatter)
			{
				AppendCustomFormatter(value, format);
				return;
			}
			if (typeof(T) == typeof(IntPtr))
			{
				AppendFormatted(Unsafe.As<T, IntPtr>(ref value), format);
				return;
			}
			if (typeof(T) == typeof(UIntPtr))
			{
				AppendFormatted(Unsafe.As<T, UIntPtr>(ref value), format);
				return;
			}
			string text = ((!(value is IFormattable)) ? value?.ToString() : ((IFormattable)(object)value).ToString(format, _provider));
			if (text != null)
			{
				AppendStringDirect(text);
			}
		}

		public void AppendFormatted<T>(T value, int alignment)
		{
			int pos = _pos;
			AppendFormatted(value);
			if (alignment != 0)
			{
				AppendOrInsertAlignmentIfNeeded(pos, alignment);
			}
		}

		public void AppendFormatted<T>(T value, int alignment, string? format)
		{
			int pos = _pos;
			AppendFormatted(value, format);
			if (alignment != 0)
			{
				AppendOrInsertAlignmentIfNeeded(pos, alignment);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void AppendFormatted(IntPtr value)
		{
			if (IntPtr.Size == 4)
			{
				AppendFormatted((int)value);
			}
			else
			{
				AppendFormatted((long)value);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void AppendFormatted(IntPtr value, string? format)
		{
			if (IntPtr.Size == 4)
			{
				AppendFormatted((int)value, format);
			}
			else
			{
				AppendFormatted((long)value, format);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void AppendFormatted(UIntPtr value)
		{
			if (UIntPtr.Size == 4)
			{
				AppendFormatted((uint)value);
			}
			else
			{
				AppendFormatted((ulong)value);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void AppendFormatted(UIntPtr value, string? format)
		{
			if (UIntPtr.Size == 4)
			{
				AppendFormatted((uint)value, format);
			}
			else
			{
				AppendFormatted((ulong)value, format);
			}
		}

		public void AppendFormatted(ReadOnlySpan<char> value)
		{
			if (value.TryCopyTo(_chars.Slice(_pos)))
			{
				_pos += value.Length;
			}
			else
			{
				GrowThenCopySpan(value);
			}
		}

		public void AppendFormatted(ReadOnlySpan<char> value, int alignment = 0, string? format = null)
		{
			bool flag = false;
			if (alignment < 0)
			{
				flag = true;
				alignment = -alignment;
			}
			int num = alignment - value.Length;
			if (num <= 0)
			{
				AppendFormatted(value);
				return;
			}
			EnsureCapacityForAdditionalChars(value.Length + num);
			if (flag)
			{
				value.CopyTo(_chars.Slice(_pos));
				_pos += value.Length;
				_chars.Slice(_pos, num).Fill(' ');
				_pos += num;
			}
			else
			{
				_chars.Slice(_pos, num).Fill(' ');
				_pos += num;
				value.CopyTo(_chars.Slice(_pos));
				_pos += value.Length;
			}
		}

		public void AppendFormatted(string? value)
		{
			if (!_hasCustomFormatter && value != null && value.AsSpan().TryCopyTo(_chars.Slice(_pos)))
			{
				_pos += value.Length;
			}
			else
			{
				AppendFormattedSlow(value);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void AppendFormattedSlow(string? value)
		{
			if (_hasCustomFormatter)
			{
				AppendCustomFormatter(value, null);
			}
			else if (value != null)
			{
				EnsureCapacityForAdditionalChars(value.Length);
				value.AsSpan().CopyTo(_chars.Slice(_pos));
				_pos += value.Length;
			}
		}

		public void AppendFormatted(string? value, int alignment = 0, string? format = null)
		{
			this.AppendFormatted<string>(value, alignment, format);
		}

		public void AppendFormatted(object? value, int alignment = 0, string? format = null)
		{
			this.AppendFormatted<object>(value, alignment, format);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static bool HasCustomFormatter(IFormatProvider provider)
		{
			if (provider.GetType() != typeof(CultureInfo))
			{
				return provider.GetFormat(typeof(ICustomFormatter)) != null;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void AppendCustomFormatter<T>(T value, string? format)
		{
			ICustomFormatter customFormatter = (ICustomFormatter)_provider.GetFormat(typeof(ICustomFormatter));
			if (customFormatter != null)
			{
				string text = customFormatter.Format(format, value, _provider);
				if (text != null)
				{
					AppendStringDirect(text);
				}
			}
		}

		private void AppendOrInsertAlignmentIfNeeded(int startingPos, int alignment)
		{
			int num = _pos - startingPos;
			bool flag = false;
			if (alignment < 0)
			{
				flag = true;
				alignment = -alignment;
			}
			int num2 = alignment - num;
			if (num2 > 0)
			{
				EnsureCapacityForAdditionalChars(num2);
				if (flag)
				{
					_chars.Slice(_pos, num2).Fill(' ');
				}
				else
				{
					_chars.Slice(startingPos, num).CopyTo(_chars.Slice(startingPos + num2));
					_chars.Slice(startingPos, num2).Fill(' ');
				}
				_pos += num2;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void EnsureCapacityForAdditionalChars(int additionalChars)
		{
			if (_chars.Length - _pos < additionalChars)
			{
				Grow(additionalChars);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void GrowThenCopyString(string value)
		{
			Grow(value.Length);
			value.AsSpan().CopyTo(_chars.Slice(_pos));
			_pos += value.Length;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void GrowThenCopySpan(ReadOnlySpan<char> value)
		{
			Grow(value.Length);
			value.CopyTo(_chars.Slice(_pos));
			_pos += value.Length;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void Grow(int additionalChars)
		{
			GrowCore((uint)(_pos + additionalChars));
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void Grow()
		{
			GrowCore((uint)(_chars.Length + 1));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void GrowCore(uint requiredMinCapacity)
		{
			int minimumLength = (int)MathEx.Clamp(Math.Max(requiredMinCapacity, Math.Min((uint)(_chars.Length * 2), uint.MaxValue)), 256u, 2147483647u);
			char[] array = ArrayPool<char>.Shared.Rent(minimumLength);
			_chars.Slice(0, _pos).CopyTo(array);
			char[] arrayToReturnToPool = _arrayToReturnToPool;
			_chars = (_arrayToReturnToPool = array);
			if (arrayToReturnToPool != null)
			{
				ArrayPool<char>.Shared.Return(arrayToReturnToPool);
			}
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
	public sealed class DisableRuntimeMarshallingAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	public sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	public sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	internal interface ITuple
	{
		int Length { get; }

		object? this[int index] { get; }
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	public sealed class ModuleInitializerAttribute : Attribute
	{
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	public static class ExtraDynamicallyAccessedMemberTypes
	{
		public const DynamicallyAccessedMemberTypes Interfaces = (DynamicallyAccessedMemberTypes)8192;
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
	public sealed class DynamicallyAccessedMembersAttribute : Attribute
	{
		public DynamicallyAccessedMemberTypes MemberTypes { get; }

		public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
		{
			MemberTypes = memberTypes;
		}
	}
	[Flags]
	public enum DynamicallyAccessedMemberTypes
	{
		None = 0,
		PublicParameterlessConstructor = 1,
		PublicConstructors = 3,
		NonPublicConstructors = 4,
		PublicMethods = 8,
		NonPublicMethods = 0x10,
		PublicFields = 0x20,
		NonPublicFields = 0x40,
		PublicNestedTypes = 0x80,
		NonPublicNestedTypes = 0x100,
		PublicProperties = 0x200,
		NonPublicProperties = 0x400,
		PublicEvents = 0x800,
		NonPublicEvents = 0x1000,
		All = -1
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	public sealed class UnscopedRefAttribute : Attribute
	{
	}
}

MonoMod.ILHelpers.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;
using MonoMod.Backports.ILHelpers;

[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCopyright("Copyright 2024 0x0ade, DaNike")]
[assembly: CLSCompliant(false)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyTitle("MonoMod.ILHelpers")]
[assembly: AssemblyCompany("0x0ade, DaNike")]
[assembly: AssemblyDescription("Package Description")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: TypeForwardedTo(typeof(UnsafeRaw))]
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
	internal sealed class NonVersionableAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] A_0)
		{
			TransformFlags = A_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte A_0)
		{
			NullableFlags = new byte[1] { A_0 };
		}

		public NullableAttribute(byte[] A_0)
		{
			NullableFlags = A_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte A_0)
		{
			Flag = A_0;
		}
	}
}
namespace MonoMod
{
	public static class ILHelpers
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static T TailCallDelegatePtr<T>(IntPtr source)
		{
			return ((delegate*<T>)source)();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static T TailCallFunc<T>(Func<T> func)
		{
			return func();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static ref T ObjectAsRef<T>(object obj)
		{
			fixed (object obj2 = obj)
			{
				T** ptr = (T**)(&obj2);
				return ref *(*ptr);
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	public static class Unsafe
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static T Read<T>(void* source)
		{
			return Unsafe.Read<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static T ReadUnaligned<T>(void* source)
		{
			return Unsafe.ReadUnaligned<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static T ReadUnaligned<T>(ref byte source)
		{
			return Unsafe.ReadUnaligned<T>(ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void Write<T>(void* destination, T value)
		{
			Unsafe.Write(destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void WriteUnaligned<T>(void* destination, T value)
		{
			Unsafe.WriteUnaligned(destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void WriteUnaligned<T>(ref byte destination, T value)
		{
			Unsafe.WriteUnaligned(ref destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void Copy<T>(void* destination, ref T source)
		{
			Unsafe.Write(destination, source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void Copy<T>(ref T destination, void* source)
		{
			destination = Unsafe.Read<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void* AsPointer<T>(ref T value)
		{
			return Unsafe.AsPointer(ref value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void SkipInit<T>(out T value)
		{
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static int SizeOf<T>()
		{
			return Unsafe.SizeOf<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void CopyBlock(void* destination, void* source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlock(destination, source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void CopyBlock(ref byte destination, ref byte source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlock(ref destination, ref source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void CopyBlockUnaligned(void* destination, void* source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlockUnaligned(destination, source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void CopyBlockUnaligned(ref byte destination, ref byte source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlockUnaligned(ref destination, ref source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void InitBlock(void* startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlock(startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void InitBlock(ref byte startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlock(ref startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void InitBlockUnaligned(void* startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlockUnaligned(startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlockUnaligned(ref startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static T As<T>(object o) where T : class
		{
			return (T)o;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static ref T AsRef<T>(void* source)
		{
			return ref *(T*)source;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T AsRef<T>(in T source)
		{
			return ref source;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref TTo As<TFrom, TTo>(ref TFrom source)
		{
			return ref Unsafe.As<TFrom, TTo>(ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Unbox<T>(object box) where T : struct
		{
			return ref (T)box;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Add<T>(ref T source, int elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void* Add<T>(void* source, int elementOffset)
		{
			return (byte*)source + (nint)elementOffset * (nint)Unsafe.SizeOf<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Add<T>(ref T source, nint elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Add<T>(ref T source, nuint elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T AddByteOffset<T>(ref T source, nint byteOffset)
		{
			return ref Unsafe.AddByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T AddByteOffset<T>(ref T source, nuint byteOffset)
		{
			return ref Unsafe.AddByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Subtract<T>(ref T source, int elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void* Subtract<T>(void* source, int elementOffset)
		{
			return (byte*)source - (nint)elementOffset * (nint)Unsafe.SizeOf<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Subtract<T>(ref T source, nint elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Subtract<T>(ref T source, nuint elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T SubtractByteOffset<T>(ref T source, nint byteOffset)
		{
			return ref Unsafe.SubtractByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T SubtractByteOffset<T>(ref T source, nuint byteOffset)
		{
			return ref Unsafe.SubtractByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static nint ByteOffset<T>(ref T origin, ref T target)
		{
			return Unsafe.ByteOffset(target: ref target, origin: ref origin);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static bool AreSame<T>(ref T left, ref T right)
		{
			return Unsafe.AreSame(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static bool IsAddressGreaterThan<T>(ref T left, ref T right)
		{
			return Unsafe.IsAddressGreaterThan(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static bool IsAddressLessThan<T>(ref T left, ref T right)
		{
			return Unsafe.IsAddressLessThan(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static bool IsNullRef<T>(ref T source)
		{
			return Unsafe.AsPointer(ref source) == null;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static ref T NullRef<T>()
		{
			return ref *(T*)null;
		}
	}
}