Decompiled source of EnumUtils v1.0.5

LCEnumUtils.dll

Decompiled 5 months ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("MegaPiggy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2023 MegaPiggy")]
[assembly: AssemblyDescription("Lethal Company library for dynamically creating and getting Enums.")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5+0dea91ec0e6ee8c69fe9441a589fda69963c77e6")]
[assembly: AssemblyProduct("LCEnumUtils")]
[assembly: AssemblyTitle("LCEnumUtils")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/MegaPiggy/LethalCompanyEnumUtils.git")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.5.0")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class EnumHolderAttribute : Attribute
{
}
public static class EnumUtils
{
	private static class EnumInfoPatch
	{
		public static void FixEnum(object type, ref ulong[] oldValues, ref string[] oldNames)
		{
			if (!TryGetRawPatch(type as Type, out var patch))
			{
				return;
			}
			List<KeyValuePair<ulong, string>> pairs = patch.GetPairs();
			List<ulong> list = new List<ulong>(oldValues);
			List<string> list2 = new List<string>(oldNames);
			foreach (KeyValuePair<ulong, string> item in pairs)
			{
				list.Add(item.Key);
				list2.Add(item.Value);
			}
			oldValues = list.ToArray();
			oldNames = list2.ToArray();
			Array.Sort(oldValues, oldNames, Comparer<ulong>.Default);
		}

		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			using IEnumerator<CodeInstruction> enumerator = instructions.GetEnumerator();
			while (enumerator.MoveNext())
			{
				CodeInstruction v2 = enumerator.Current;
				if (v2.operand is MethodInfo methodInfo && methodInfo.Name == "Sort")
				{
					yield return v2;
					enumerator.MoveNext();
					v2 = enumerator.Current;
					List<Label> labels = v2.labels;
					v2.labels = new List<Label>();
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null)
					{
						labels = labels
					};
					yield return new CodeInstruction(OpCodes.Ldloca, (object)1);
					yield return new CodeInstruction(OpCodes.Ldloca, (object)2);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(EnumInfoPatch), "FixEnum", (Type[])null, (Type[])null));
					yield return v2;
				}
				else
				{
					yield return v2;
				}
			}
		}
	}

	private class EnumPatch
	{
		private Dictionary<ulong, List<string>> values = new Dictionary<ulong, List<string>>();

		public List<KeyValuePair<ulong, string>> GetPairs()
		{
			List<KeyValuePair<ulong, string>> list = new List<KeyValuePair<ulong, string>>();
			foreach (KeyValuePair<ulong, List<string>> value in values)
			{
				foreach (string item in value.Value)
				{
					list.Add(new KeyValuePair<ulong, string>(value.Key, item));
				}
			}
			return list;
		}

		public bool HasValue(ulong value)
		{
			return values.Keys.Contains(value);
		}

		public bool HasName(string name)
		{
			foreach (string item in values.Values.SelectMany((List<string> l) => l))
			{
				if (name.Equals(item))
				{
					return true;
				}
			}
			return false;
		}

		public void AddValue(ulong enumValue, string name)
		{
			if (values.ContainsKey(enumValue))
			{
				values[enumValue].Add(name);
				return;
			}
			values.Add(enumValue, new List<string> { name });
		}

		public void RemoveValue(ulong enumValue)
		{
			values.Remove(enumValue);
		}

		public void RemoveValue(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return;
			}
			foreach (KeyValuePair<ulong, List<string>> value in values)
			{
				value.Value.Remove(name);
			}
		}
	}

	private static readonly Random Rng = new Random();

	private static Dictionary<Type, EnumPatch> patches = new Dictionary<Type, EnumPatch>();

	private static FieldInfo cache = AccessTools.Field(AccessTools.TypeByName("System.RuntimeType"), "GenericCache");

	internal static void Initialize(Harmony harmony, ManualLogSource logger)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		try
		{
			harmony.Patch((MethodBase)AccessTools.Method(Type.GetType("System.Enum"), "GetCachedValuesAndNames", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(EnumInfoPatch), "Transpiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception arg)
		{
			logger.LogError((object)$"Exception while patching System.Enum.GetCachedValuesAndNames: {arg}");
		}
	}

	private static void ClearEnumCache(Type enumType)
	{
		cache.SetValue(enumType, null);
	}

	public static T Create<T>(string name) where T : Enum
	{
		return (T)Create(typeof(T), name);
	}

	public static T Create<T>(string name, T value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, short value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, ushort value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, int value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, uint value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, long value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, ulong value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, byte value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(string name, sbyte value) where T : Enum
	{
		return Create<T>(value, name);
	}

	public static T Create<T>(short value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(ushort value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(int value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(uint value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(long value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(ulong value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(byte value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(sbyte value, string name) where T : Enum
	{
		return Create<T>(Enum.ToObject(typeof(T), value), name);
	}

	public static T Create<T>(object value, string name) where T : Enum
	{
		Create(typeof(T), value, name);
		return (T)value;
	}

	public static object Create(Type enumType, string name)
	{
		object firstFreeValue = GetFirstFreeValue(enumType);
		Create(enumType, GetFirstFreeValue(enumType), name);
		return firstFreeValue;
	}

	public static void Create(Type enumType, string name, object value)
	{
		Create(enumType, value, name);
	}

	public static void Create(Type enumType, object value, string name)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		if (AlreadyHasName(enumType, name) || IsDefined(enumType, name))
		{
			throw new Exception("The enum (" + enumType.FullName + ") already has a value with the name \"" + name + "\"");
		}
		if (!TryGetRawPatch(enumType, out var patch))
		{
			patch = new EnumPatch();
			patches.Add(enumType, patch);
		}
		patch.AddValue(value.ToFriendlyValue(), name);
		ClearEnumCache(enumType);
	}

	internal static ulong ToFriendlyValue<T>(this T value) where T : Enum
	{
		return (ulong)Convert.ToInt64(value, CultureInfo.InvariantCulture);
	}

	internal static ulong ToFriendlyValue(this object value)
	{
		return (ulong)Convert.ToInt64(value, CultureInfo.InvariantCulture);
	}

	public static void Remove<T>(string name) where T : Enum
	{
		Remove(typeof(T), name);
	}

	public static void Remove<T>(T value) where T : Enum
	{
		Remove(typeof(T), value);
	}

	public static void Remove<T>(object value) where T : Enum
	{
		Remove(typeof(T), value);
	}

	public static void Remove(Type enumType, string name)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		if (TryGetRawPatch(enumType, out var patch) && patch.HasName(name))
		{
			patch.RemoveValue(name);
			ClearEnumCache(enumType);
		}
	}

	public static void Remove(Type enumType, object value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		ulong num = value.ToFriendlyValue();
		if (TryGetRawPatch(enumType, out var patch) && patch.HasValue(num))
		{
			patch.RemoveValue(num);
			ClearEnumCache(enumType);
		}
	}

	public static bool IsDynamic<T>(string name) where T : Enum
	{
		return IsDynamic(typeof(T), name);
	}

	public static bool IsDynamic<T>(this T value) where T : Enum
	{
		return IsDynamic(typeof(T), value);
	}

	public static bool IsDynamic<T>(object value) where T : Enum
	{
		return IsDynamic(typeof(T), value);
	}

	public static bool IsDynamic(Type enumType, string name)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		if (TryGetRawPatch(enumType, out var patch))
		{
			return patch.HasName(name);
		}
		return false;
	}

	public static bool IsDynamic(Type enumType, object value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		ulong value2 = value.ToFriendlyValue();
		if (TryGetRawPatch(enumType, out var patch))
		{
			return patch.HasValue(value2);
		}
		return false;
	}

	public static bool IsStatic<T>(string name) where T : Enum
	{
		return IsStatic(typeof(T), name);
	}

	public static bool IsStatic<T>(this T value) where T : Enum
	{
		return IsStatic(typeof(T), value);
	}

	public static bool IsStatic<T>(object value) where T : Enum
	{
		return IsStatic(typeof(T), value);
	}

	public static bool IsStatic(Type enumType, string name)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return !IsDynamic(enumType, name);
	}

	public static bool IsStatic(Type enumType, object value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return !IsDynamic(enumType, value);
	}

	private static bool TryAsNumber(this object value, Type type, out object result)
	{
		if (type.IsSubclassOf(typeof(IConvertible)))
		{
			throw new ArgumentException("The type must inherit the IConvertible interface", "type");
		}
		result = null;
		if (type.IsInstanceOfType(value))
		{
			result = value;
			return true;
		}
		if (value is IConvertible)
		{
			if (type.IsEnum)
			{
				result = Enum.ToObject(type, value);
				return true;
			}
			NumberFormatInfo currentInfo = NumberFormatInfo.CurrentInfo;
			result = (value as IConvertible).ToType(type, currentInfo);
			return true;
		}
		return false;
	}

	private static bool IsPowerOfTwo(this ulong x)
	{
		if (x != 0)
		{
			return (x & (x - 1)) == 0;
		}
		return false;
	}

	public static bool IsPowerOfTwoEnum<T>() where T : Enum
	{
		return IsFlagsEnum<T>();
	}

	public static bool IsPowerOfTwoEnum(Type enumType)
	{
		return IsFlagsEnum(enumType);
	}

	public static bool IsFlagsEnum<T>() where T : Enum
	{
		return typeof(T).IsDefined(typeof(FlagsAttribute), inherit: false);
	}

	public static bool IsFlagsEnum(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return enumType.IsDefined(typeof(FlagsAttribute), inherit: false);
	}

	public static T GetFirstFreeValue<T>() where T : Enum
	{
		return (T)GetFirstFreeValue(typeof(T));
	}

	public static object GetFirstFreeValue(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		Array values = Enum.GetValues(enumType);
		bool flag = IsPowerOfTwoEnum(enumType);
		long num = 0L;
		for (ulong num2 = 0uL; num2 <= ulong.MaxValue; num2++)
		{
			if (flag && !num2.IsPowerOfTwo())
			{
				continue;
			}
			if (!num2.TryAsNumber(enumType, out var result))
			{
				break;
			}
			while (true)
			{
				if (num < values.LongLength)
				{
					if (values.GetValue(num).Equals(result))
					{
						break;
					}
					num++;
					continue;
				}
				return result;
			}
		}
		if (!flag)
		{
			long num3 = -1L;
			object result2;
			while (num3 >= long.MinValue && num3.TryAsNumber(enumType, out result2))
			{
				while (true)
				{
					if (num < values.LongLength)
					{
						if (values.GetValue(num).Equals(result2))
						{
							break;
						}
						num++;
						continue;
					}
					return result2;
				}
				num3--;
			}
		}
		throw new Exception((flag ? "No unused values in power of two enum " : "No unused values in enum ") + enumType.FullName);
	}

	private static bool TryGetRawPatch<T>(out EnumPatch patch) where T : Enum
	{
		return TryGetRawPatch(typeof(T), out patch);
	}

	private static bool TryGetRawPatch(Type enumType, out EnumPatch patch)
	{
		return patches.TryGetValue(enumType, out patch);
	}

	private static bool AlreadyHasName(Type enumType, string name)
	{
		if (TryGetRawPatch(enumType, out var patch))
		{
			return patch.HasName(name);
		}
		return false;
	}

	public static void RegisterAllEnumHolders(Assembly assembly)
	{
		Type[] types = assembly.GetTypes();
		foreach (Type type in types)
		{
			if (!type.IsDefined(typeof(EnumHolderAttribute), inherit: true))
			{
				continue;
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.FieldType.IsEnum)
				{
					if (Convert.ToInt64(fieldInfo.GetValue(null)) == 0L)
					{
						fieldInfo.SetValue(null, Create(fieldInfo.FieldType, fieldInfo.Name));
					}
					else
					{
						Create(fieldInfo.FieldType, fieldInfo.GetValue(null), fieldInfo.Name);
					}
				}
			}
		}
	}

	public static object Parse(Type enumType, string value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		try
		{
			return Enum.Parse(enumType, value);
		}
		catch
		{
			return null;
		}
	}

	public static object Parse(Type enumType, string value, bool ignoreCase)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		try
		{
			return Enum.Parse(enumType, value, ignoreCase);
		}
		catch
		{
			return null;
		}
	}

	public static bool TryParse(Type enumType, string value, out object result)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		try
		{
			result = Enum.Parse(enumType, value);
			return true;
		}
		catch
		{
			result = null;
			return false;
		}
	}

	public static bool TryParse(Type enumType, string value, bool ignoreCase, out object result)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		try
		{
			result = Enum.Parse(enumType, value, ignoreCase);
			return true;
		}
		catch
		{
			result = null;
			return false;
		}
	}

	public static object FromObject(Type enumType, object value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, sbyte value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, byte value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, short value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, ushort value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, int value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, uint value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, long value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static object FromObject(Type enumType, ulong value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.ToObject(enumType, value);
	}

	public static Type GetUnderlyingType(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.GetUnderlyingType(enumType);
	}

	public static string GetName(Type enumType, object value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.GetName(enumType, value);
	}

	public static string[] GetNames(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.GetNames(enumType);
	}

	public static string[] GetNamesWithoutFirst(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.GetNames(enumType).Skip(1).ToArray();
	}

	public static object[] GetValues(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.GetValues(enumType).Cast<object>().ToArray();
	}

	public static object[] GetValuesWithoutFirst(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.GetValues(enumType).Cast<object>().Skip(1)
			.ToArray();
	}

	public static int Count(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return Enum.GetValues(enumType).Length;
	}

	public static bool IsDefined(Type enumType, object value)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		try
		{
			return Enum.IsDefined(enumType, value);
		}
		catch
		{
			return false;
		}
	}

	public static bool IsDefined(Type enumType, sbyte value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, byte value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, short value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, ushort value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, int value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, uint value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, long value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, ulong value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static bool IsDefined(Type enumType, string value)
	{
		return IsDefined(enumType, (object)value);
	}

	public static object GetMinValue(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return GetValues(enumType).Min();
	}

	public static object GetMaxValue(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		return GetValues(enumType).Max();
	}

	public static object GetRandom(Type enumType)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		Array values = Enum.GetValues(enumType);
		int index = Rng.Next(0, values.Length);
		return values.GetValue(index);
	}

	public static object GetRandom(Type enumType, params object[] excluded)
	{
		if (enumType == null)
		{
			throw new ArgumentNullException("enumType");
		}
		if (!enumType.IsEnum)
		{
			throw new NotAnEnumException(enumType);
		}
		if (excluded == null)
		{
			throw new ArgumentNullException("excluded");
		}
		object[] array = (from object v in Enum.GetValues(enumType)
			where !excluded.Contains(v)
			select v).ToArray();
		int index = Rng.Next(0, array.Length);
		return array.GetValue(index);
	}

	public static T Parse<T>(string value, T errorReturn = default(T)) where T : Enum
	{
		try
		{
			return (T)Enum.Parse(typeof(T), value);
		}
		catch
		{
			return errorReturn;
		}
	}

	public static T Parse<T>(string value, bool ignoreCase, T errorReturn = default(T)) where T : Enum
	{
		try
		{
			return (T)Enum.Parse(typeof(T), value, ignoreCase);
		}
		catch
		{
			return errorReturn;
		}
	}

	public static bool TryParse<T>(string value, out T result) where T : Enum
	{
		try
		{
			result = (T)Enum.Parse(typeof(T), value);
			return true;
		}
		catch
		{
			result = default(T);
			return false;
		}
	}

	public static bool TryParse<T>(string value, bool ignoreCase, out T result) where T : Enum
	{
		try
		{
			result = (T)Enum.Parse(typeof(T), value, ignoreCase);
			return true;
		}
		catch
		{
			result = default(T);
			return false;
		}
	}

	public static T FromObject<T>(object value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(sbyte value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(byte value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(short value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(ushort value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(int value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(uint value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(long value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static T FromObject<T>(ulong value) where T : Enum
	{
		return (T)Enum.ToObject(typeof(T), value);
	}

	public static Type GetUnderlyingType<T>() where T : Enum
	{
		return Enum.GetUnderlyingType(typeof(T));
	}

	public static string GetName<T>(this T value) where T : Enum
	{
		return Enum.GetName(typeof(T), value);
	}

	public static string[] GetNames<T>() where T : Enum
	{
		return Enum.GetNames(typeof(T));
	}

	public static string[] GetNamesWithoutFirst<T>() where T : Enum
	{
		return Enum.GetNames(typeof(T)).Skip(1).ToArray();
	}

	public static string[] GetNames<T>(params T[] excluded) where T : Enum
	{
		return GetValues(excluded).Select(GetName).ToArray();
	}

	public static T[] GetValues<T>() where T : Enum
	{
		return Enum.GetValues(typeof(T)).Cast<T>().ToArray();
	}

	public static T[] GetValuesWithoutFirst<T>() where T : Enum
	{
		return Enum.GetValues(typeof(T)).Cast<T>().Skip(1)
			.ToArray();
	}

	public static T[] GetValues<T>(params T[] excluded) where T : Enum
	{
		return (from T v in Enum.GetValues(typeof(T))
			where !excluded.Contains(v)
			select v).ToArray();
	}

	public static T[] GetDynamicValues<T>() where T : Enum
	{
		return Enum.GetValues(typeof(T)).Cast<T>().Where(IsDynamic)
			.ToArray();
	}

	public static T[] GetStaticValues<T>() where T : Enum
	{
		return Enum.GetValues(typeof(T)).Cast<T>().Where(IsStatic)
			.ToArray();
	}

	public static int Count<T>() where T : Enum
	{
		return Enum.GetValues(typeof(T)).Length;
	}

	public static bool IsDefined<T>(object value) where T : Enum
	{
		try
		{
			return Enum.IsDefined(typeof(T), value);
		}
		catch
		{
			return false;
		}
	}

	public static bool IsDefined<T>(sbyte value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(byte value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(short value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(ushort value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(int value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(uint value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(long value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(ulong value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(string value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static bool IsDefined<T>(this T value) where T : Enum
	{
		return EnumUtils.IsDefined<T>((object)value);
	}

	public static T GetMinValue<T>() where T : Enum
	{
		return GetValues<T>().Min();
	}

	public static T GetMaxValue<T>() where T : Enum
	{
		return GetValues<T>().Max();
	}

	public static string Format<T>(this T value, string format) where T : Enum
	{
		return Enum.Format(typeof(T), value, format);
	}

	public static T GetRandom<T>() where T : Enum
	{
		T[] values = GetValues<T>();
		int index = Rng.Next(0, values.Length);
		return (T)values.GetValue(index);
	}

	public static T GetRandom<T>(params T[] excluded) where T : Enum
	{
		T[] array = (from T v in Enum.GetValues(typeof(T))
			where !excluded.Contains(v)
			select v).ToArray();
		int index = Rng.Next(0, array.Length);
		return (T)array.GetValue(index);
	}

	public static string GetRandomName<T>() where T : Enum
	{
		string[] names = GetNames<T>();
		int index = Rng.Next(0, names.Length);
		return (string)names.GetValue(index);
	}

	public static string GetRandomName<T>(params T[] excluded) where T : Enum
	{
		T[] array = (from T v in Enum.GetNames(typeof(T))
			where !excluded.Contains(v)
			select v).ToArray();
		int index = Rng.Next(0, array.Length);
		return (string)array.GetValue(index);
	}

	public static IDictionary<T, string> GetDescriptions<T>() where T : Enum
	{
		Type typeFromHandle = typeof(T);
		Dictionary<T, string> dictionary = new Dictionary<T, string>();
		T[] values = GetValues<T>();
		foreach (T val in values)
		{
			FieldInfo? field = typeFromHandle.GetField($"{val}");
			string value = null;
			if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute descriptionAttribute)
			{
				value = descriptionAttribute.Description;
			}
			dictionary.Add(val, value);
		}
		return dictionary;
	}

	public static void ThrowIfNotEnum(Type type)
	{
		if (type == null)
		{
			throw new ArgumentNullException("type");
		}
		if (!type.IsEnum)
		{
			throw new NotAnEnumException(type);
		}
	}

	public static void ThrowIfNotEnum<T>()
	{
		if (!typeof(T).IsEnum)
		{
			throw new NotAnEnumException(typeof(T));
		}
	}

	public static T EnumCast<T>(this Enum value) where T : Enum
	{
		if (value.GetType() != typeof(T))
		{
			throw new InvalidCastException("Enums are not of the same type");
		}
		return (T)value;
	}

	public static IEnumerable<T> EnumCast<T>(this IEnumerable<Enum> values) where T : Enum
	{
		return values.Select((Enum e) => e.EnumCast<T>());
	}

	public static bool HasFlag<T>(T flags, T flag) where T : Enum
	{
		return flags.HasFlag(flag);
	}

	public static T SetFlag<T>(this T flags, T flag, bool setBit) where T : Enum
	{
		if (!setBit)
		{
			return flags.RemoveFlag(flag);
		}
		return flags.AddFlag(flag);
	}

	public static T AddFlag<T>(this T flags, T flag) where T : Enum
	{
		return FromObject<T>(flags.ToFriendlyValue() | flag.ToFriendlyValue());
	}

	public static T RemoveFlag<T>(this T flags, T flag) where T : Enum
	{
		return FromObject<T>(flags.ToFriendlyValue() & ~flag.ToFriendlyValue());
	}

	public static T ToggleFlag<T>(this T flags, T flag) where T : Enum
	{
		return FromObject<T>(flags.ToFriendlyValue() ^ flag.ToFriendlyValue());
	}

	public static T GetFlagsValue<T>(int index) where T : Enum
	{
		return FromObject<T>(1 << index);
	}

	public static T GetNoFlags<T>() where T : Enum
	{
		return FromObject<T>(0);
	}

	public static T GetAllFlags<T>() where T : Enum
	{
		return FromObject<T>(-1);
	}

	public static T[] GetFlagsValues<T>(this T flags) where T : Enum
	{
		if (!IsFlagsEnum<T>())
		{
			throw new ArgumentException($"The type '{typeof(T)}' must have an attribute '{typeof(FlagsAttribute)}'.");
		}
		Type underlyingType = GetUnderlyingType<T>();
		ulong num = flags.ToFriendlyValue();
		IEnumerable<ulong> enumerable = GetValues<T>().Select(ToFriendlyValue);
		IList<T> list = new List<T>();
		foreach (ulong item in enumerable)
		{
			if ((num & item) == item && item != 0L)
			{
				list.Add((T)Convert.ChangeType(item, underlyingType, CultureInfo.CurrentCulture));
			}
		}
		if (list.Count == 0 && enumerable.SingleOrDefault((ulong v) => v == 0) != 0L)
		{
			list.Add(default(T));
		}
		return list.ToArray();
	}

	public static T CombineFlagsValues<T>(this T[] values) where T : Enum
	{
		if (!IsFlagsEnum<T>())
		{
			throw new ArgumentException($"The type '{typeof(T)}' must have an attribute '{typeof(FlagsAttribute)}'.");
		}
		T val = default(T);
		if (values != null && values.Length != 0)
		{
			foreach (T flag in values)
			{
				val = val.AddFlag(flag);
			}
		}
		return val;
	}
}
public class NotAnEnumException : Exception
{
	private Type _type;

	public Type Type => _type;

	public NotAnEnumException(Type type)
		: base("The given type isn't an enum (" + type.FullName + " isn't an Enum)")
	{
		_type = type;
	}

	public NotAnEnumException(Type type, Exception innerException)
		: base("The given type isn't an enum (" + type.FullName + " isn't an Enum)", innerException)
	{
		_type = type;
	}
}
namespace LCEnumUtils
{
	[BepInPlugin("MegaPiggy.EnumUtils", "Enum Utils", "1.0.5")]
	internal class Initializer : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("MegaPiggy.EnumUtils");

		private static Initializer Instance;

		private static ManualLogSource LoggerInstance => ((BaseUnityPlugin)Instance).Logger;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			EnumUtils.Initialize(harmony, ((BaseUnityPlugin)this).Logger);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Enum Utils is loaded with version 1.0.5!");
		}
	}
	public static class PluginInfo
	{
		public const string ModGUID = "MegaPiggy.EnumUtils";

		public const string ModName = "Enum Utils";

		public const string ModVersion = "1.0.5";
	}
}