Decompiled source of PurenailUtil v1.0.0

Silksong.PurenailUtil.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Silksong.PurenailUtil.Collections.Json;

[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("Silksong.PurenailUtil")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b7cb0d9058072d52a56416004d6690c2d17d360b")]
[assembly: AssemblyProduct("Silksong.PurenailUtil")]
[assembly: AssemblyTitle("PurenailUtil")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dplochcoder/Silksong.PurenailUtil")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

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

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	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]
	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;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace Silksong.PurenailUtil.Collections
{
	public static class EmptyCollection<T>
	{
		public static readonly IReadOnlyList<T> Instance = Array.Empty<T>();
	}
	[JsonConverter(typeof(AbstractJsonConvertibleConverter))]
	public class HashMultimap<K, V> : AbstractJsonConvertible<Dictionary<K, HashSet<V>>>, IEnumerable<(K, IReadOnlyCollection<V>)>, IEnumerable
	{
		private readonly Dictionary<K, HashSet<V>> dict = new Dictionary<K, HashSet<V>>();

		public IReadOnlyCollection<K> Keys => dict.Keys;

		public IEnumerable<V> Values => dict.Values.SelectMany((HashSet<V> v) => v);

		internal override Dictionary<K, HashSet<V>> ConvertToRep()
		{
			return dict;
		}

		internal override void ReadRep(Dictionary<K, HashSet<V>> value)
		{
			foreach (KeyValuePair<K, HashSet<V>> item in value)
			{
				Add(item.Key, item.Value);
			}
		}

		public bool TryGetValues(K key, out IReadOnlyCollection<V> values)
		{
			if (dict.TryGetValue(key, out HashSet<V> value))
			{
				values = value;
				return true;
			}
			values = EmptyCollection<V>.Instance;
			return false;
		}

		public IReadOnlyCollection<V> Get(K key)
		{
			if (!dict.TryGetValue(key, out HashSet<V> value))
			{
				return EmptyCollection<V>.Instance;
			}
			return value;
		}

		public void Clear()
		{
			dict.Clear();
		}

		public bool Add(K key, V value)
		{
			if (dict.TryGetValue(key, out HashSet<V> value2))
			{
				return value2.Add(value);
			}
			dict.Add(key, new HashSet<V> { value });
			return true;
		}

		public bool Add(K key, IEnumerable<V> values)
		{
			if (dict.TryGetValue(key, out HashSet<V> value))
			{
				bool flag = false;
				{
					foreach (V value2 in values)
					{
						flag |= value.Add(value2);
					}
					return flag;
				}
			}
			HashSet<V> hashSet = new HashSet<V>();
			foreach (V value3 in values)
			{
				hashSet.Add(value3);
			}
			value = hashSet;
			if (value.Count == 0)
			{
				return false;
			}
			dict[key] = value;
			return true;
		}

		public bool Remove(K key)
		{
			return dict.Remove(key);
		}

		public bool Remove(K key, V value)
		{
			if (dict.TryGetValue(key, out HashSet<V> value2) && value2.Remove(value))
			{
				if (value2.Count == 0)
				{
					dict.Remove(key);
				}
				return true;
			}
			return false;
		}

		public bool Remove(K key, IEnumerable<V> values)
		{
			if (dict.TryGetValue(key, out HashSet<V> value))
			{
				bool flag = false;
				foreach (V value2 in values)
				{
					flag |= value.Remove(value2);
				}
				if (value.Count == 0)
				{
					dict.Remove(key);
				}
				return flag;
			}
			return false;
		}

		private IEnumerable<(K, IReadOnlyCollection<V>)> EnumeateSets()
		{
			return dict.Select<KeyValuePair<K, HashSet<V>>, (K, IReadOnlyCollection<V>)>((KeyValuePair<K, HashSet<V>> e) => (e.Key, e.Value));
		}

		public IEnumerator<(K, IReadOnlyCollection<V>)> GetEnumerator()
		{
			return EnumeateSets().GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return EnumeateSets().GetEnumerator();
		}
	}
	[JsonConverter(typeof(AbstractJsonConvertibleConverter))]
	public class HashMultiset<T> : AbstractJsonConvertible<List<(T, int)>>, ICollection<T>, IEnumerable<T>, IEnumerable
	{
		[CompilerGenerated]
		private sealed class <Enumerate>d__27 : IEnumerable<T>, IEnumerable, IEnumerator<T>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private T <>2__current;

			private int <>l__initialThreadId;

			public HashMultiset<T> <>4__this;

			private Dictionary<T, int>.Enumerator <>7__wrap1;

			private KeyValuePair<T, int> <e>5__3;

			private int <i>5__4;

			T IEnumerator<T>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Enumerate>d__27(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(Dictionary<T, int>.Enumerator);
				<e>5__3 = default(KeyValuePair<T, int>);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					int num = <>1__state;
					HashMultiset<T> hashMultiset = <>4__this;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -3;
						<i>5__4++;
						goto IL_008c;
					}
					<>1__state = -1;
					<>7__wrap1 = hashMultiset.elements.GetEnumerator();
					<>1__state = -3;
					goto IL_00ab;
					IL_008c:
					if (<i>5__4 < <e>5__3.Value)
					{
						<>2__current = <e>5__3.Key;
						<>1__state = 1;
						return true;
					}
					<e>5__3 = default(KeyValuePair<T, int>);
					goto IL_00ab;
					IL_00ab:
					if (<>7__wrap1.MoveNext())
					{
						<e>5__3 = <>7__wrap1.Current;
						<i>5__4 = 0;
						goto IL_008c;
					}
					<>m__Finally1();
					<>7__wrap1 = default(Dictionary<T, int>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<T> IEnumerable<T>.GetEnumerator()
			{
				<Enumerate>d__27 result;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					result = this;
				}
				else
				{
					result = new <Enumerate>d__27(0)
					{
						<>4__this = <>4__this
					};
				}
				return result;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<T>)this).GetEnumerator();
			}
		}

		private readonly Dictionary<T, int> elements = new Dictionary<T, int>();

		private int total;

		public IReadOnlyCollection<T> Distinct => elements.Keys;

		public IEnumerable<(T, int)> Counts => elements.Select((KeyValuePair<T, int> e) => (e.Key, e.Value));

		public bool IsEmpty => elements.Count == 0;

		int ICollection<T>.Count => total;

		public bool IsReadOnly => false;

		internal override List<(T, int)> ConvertToRep()
		{
			return elements.Select((KeyValuePair<T, int> e) => (e.Key, e.Value)).ToList();
		}

		internal override void ReadRep(List<(T, int)> value)
		{
			foreach (var (element, count) in value)
			{
				Add(element, count);
			}
		}

		public HashMultiset()
		{
		}

		public HashMultiset(HashMultiset<T> copy)
		{
			foreach (KeyValuePair<T, int> element in copy.elements)
			{
				elements[element.Key] = element.Value;
			}
			total = copy.total;
		}

		public HashMultiset(IEnumerable<T> elements)
		{
			foreach (T element in elements)
			{
				Add(element);
			}
		}

		public bool Contains(T element)
		{
			return elements.ContainsKey(element);
		}

		public int Count(T element)
		{
			if (!elements.TryGetValue(element, out var value))
			{
				return 0;
			}
			return value;
		}

		public void Clear()
		{
			elements.Clear();
		}

		public void Add(T element, int count)
		{
			if (count != 0)
			{
				if (count < 0)
				{
					throw new ArgumentException(string.Format("{0}: {1}", "count", count));
				}
				elements[element] = Count(element) + count;
				total += count;
			}
		}

		public void Add(T element)
		{
			Add(element, 1);
		}

		public void AddRange(IEnumerable<T> elements)
		{
			foreach (T element in elements)
			{
				Add(element);
			}
		}

		public bool Set(T element, int count)
		{
			if (count < 0)
			{
				throw new ArgumentException(string.Format("{0}: {1}", "count", count));
			}
			int num = Count(element);
			if (count == num)
			{
				return false;
			}
			total += count - num;
			if (count == 0)
			{
				elements.Remove(element);
			}
			else
			{
				elements[element] = count;
			}
			return true;
		}

		public int Remove(T element, int count)
		{
			if (count == 0)
			{
				return 0;
			}
			if (count < 0)
			{
				throw new ArgumentException(string.Format("{0}: {1}", "count", count));
			}
			int num = Count(element);
			if (num == 0)
			{
				return 0;
			}
			if (count >= num)
			{
				elements.Remove(element);
				total -= num;
				return num;
			}
			elements[element] = num - count;
			total -= count;
			return count;
		}

		public bool Remove(T item)
		{
			return Remove(item, 1) > 0;
		}

		public void CopyTo(T[] array, int arrayIndex)
		{
			using IEnumerator<T> enumerator = GetEnumerator();
			while (enumerator.MoveNext())
			{
				T current = enumerator.Current;
				array[arrayIndex++] = current;
			}
		}

		[IteratorStateMachine(typeof(HashMultiset<>.<Enumerate>d__27))]
		private IEnumerable<T> Enumerate()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Enumerate>d__27(-2)
			{
				<>4__this = this
			};
		}

		public IEnumerator<T> GetEnumerator()
		{
			return Enumerate().GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return Enumerate().GetEnumerator();
		}
	}
	[JsonConverter(typeof(AbstractJsonConvertibleConverter))]
	public class HashMultitable<K1, K2, V> : AbstractJsonConvertible<HashTable<K1, K2, HashSet<V>>>, IEnumerable<((K1, K2), IReadOnlyCollection<V>)>, IEnumerable
	{
		private readonly HashTable<K1, K2, HashSet<V>> table = new HashTable<K1, K2, HashSet<V>>();

		internal override HashTable<K1, K2, HashSet<V>> ConvertToRep()
		{
			return table;
		}

		internal override void ReadRep(HashTable<K1, K2, HashSet<V>> value)
		{
			foreach (var (tuple2, values) in value)
			{
				Add(tuple2.Item1, tuple2.Item2, values);
			}
		}

		public void Clear()
		{
			table.Clear();
		}

		public bool TryGetValues(K1 key1, K2 key2, out IReadOnlyCollection<V> values)
		{
			if (table.TryGetValue(key1, key2, out HashSet<V> value))
			{
				values = value;
				return true;
			}
			values = EmptyCollection<V>.Instance;
			return false;
		}

		public IReadOnlyCollection<V> Get(K1 key1, K2 key2)
		{
			if (!TryGetValues(key1, key2, out IReadOnlyCollection<V> values))
			{
				return EmptyCollection<V>.Instance;
			}
			return values;
		}

		public bool Add(K1 key1, K2 key2, V value)
		{
			if (table.TryGetValue(key1, key2, out HashSet<V> value2))
			{
				return value2.Add(value);
			}
			table.Set(key1, key2, new HashSet<V> { value });
			return true;
		}

		public bool Add(K1 key1, K2 key2, IEnumerable<V> values)
		{
			if (table.TryGetValue(key1, key2, out HashSet<V> value))
			{
				bool flag = false;
				{
					foreach (V value2 in values)
					{
						flag |= value.Add(value2);
					}
					return flag;
				}
			}
			HashSet<V> hashSet = new HashSet<V>();
			foreach (V value3 in values)
			{
				hashSet.Add(value3);
			}
			value = hashSet;
			if (value.Count == 0)
			{
				return false;
			}
			table.Set(key1, key2, value);
			return true;
		}

		public bool Remove(K1 key)
		{
			return table.Remove(key);
		}

		public bool Remove(K1 key1, K2 key2)
		{
			return table.Remove(key1, key2);
		}

		public bool Remove(K1 key1, K2 key2, V value)
		{
			if (table.TryGetValue(key1, key2, out HashSet<V> value2) && value2.Remove(value))
			{
				if (value2.Count == 0)
				{
					table.Remove(key1, key2);
				}
				return true;
			}
			return false;
		}

		public bool Remove(K1 key1, K2 key2, IEnumerable<V> values)
		{
			if (table.TryGetValue(key1, key2, out HashSet<V> value))
			{
				bool flag = false;
				foreach (V value2 in values)
				{
					flag |= value.Remove(value2);
				}
				if (value.Count == 0)
				{
					table.Remove(key1, key2);
				}
				return flag;
			}
			return false;
		}

		private IEnumerable<((K1, K2), IReadOnlyCollection<V>)> EnumerateEntries()
		{
			return table.Select<((K1, K2), HashSet<V>), ((K1, K2), IReadOnlyCollection<V>)>((((K1, K2), HashSet<V>) e) => (e.Item1, e.Item2));
		}

		public IEnumerator<((K1, K2), IReadOnlyCollection<V>)> GetEnumerator()
		{
			return EnumerateEntries().GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return EnumerateEntries().GetEnumerator();
		}
	}
	[JsonConverter(typeof(AbstractJsonConvertibleConverter))]
	public class HashTable<K1, K2, V> : AbstractJsonConvertible<Dictionary<K1, Dictionary<K2, V>>>, IEnumerable<((K1, K2), V)>, IEnumerable
	{
		[CompilerGenerated]
		private sealed class <EnumerateEntries>d__11 : IEnumerable<((K1, K2), V)>, IEnumerable, IEnumerator<((K1, K2), V)>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private ((K1, K2), V) <>2__current;

			private int <>l__initialThreadId;

			public HashTable<K1, K2, V> <>4__this;

			private Dictionary<K1, Dictionary<K2, V>>.Enumerator <>7__wrap1;

			private KeyValuePair<K1, Dictionary<K2, V>> <e1>5__3;

			private Dictionary<K2, V>.Enumerator <>7__wrap3;

			((K1, K2), V) IEnumerator<((K1, K2), V)>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnumerateEntries>d__11(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if ((uint)(num - -4) <= 1u || num == 1)
				{
					try
					{
						if (num == -4 || num == 1)
						{
							try
							{
							}
							finally
							{
								<>m__Finally2();
							}
						}
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(Dictionary<K1, Dictionary<K2, V>>.Enumerator);
				<e1>5__3 = default(KeyValuePair<K1, Dictionary<K2, V>>);
				<>7__wrap3 = default(Dictionary<K2, V>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					int num = <>1__state;
					HashTable<K1, K2, V> hashTable = <>4__this;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -4;
						goto IL_00bd;
					}
					<>1__state = -1;
					<>7__wrap1 = hashTable.table.GetEnumerator();
					<>1__state = -3;
					goto IL_00e8;
					IL_00bd:
					if (<>7__wrap3.MoveNext())
					{
						KeyValuePair<K2, V> current = <>7__wrap3.Current;
						<>2__current = ((<e1>5__3.Key, current.Key), current.Value);
						<>1__state = 1;
						return true;
					}
					<>m__Finally2();
					<>7__wrap3 = default(Dictionary<K2, V>.Enumerator);
					<e1>5__3 = default(KeyValuePair<K1, Dictionary<K2, V>>);
					goto IL_00e8;
					IL_00e8:
					if (<>7__wrap1.MoveNext())
					{
						<e1>5__3 = <>7__wrap1.Current;
						<>7__wrap3 = <e1>5__3.Value.GetEnumerator();
						<>1__state = -4;
						goto IL_00bd;
					}
					<>m__Finally1();
					<>7__wrap1 = default(Dictionary<K1, Dictionary<K2, V>>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

			private void <>m__Finally2()
			{
				<>1__state = -3;
				((IDisposable)<>7__wrap3).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<((K1, K2), V)> IEnumerable<((K1, K2), V)>.GetEnumerator()
			{
				<EnumerateEntries>d__11 result;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					result = this;
				}
				else
				{
					result = new <EnumerateEntries>d__11(0)
					{
						<>4__this = <>4__this
					};
				}
				return result;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<((K1, K2), V)>)this).GetEnumerator();
			}
		}

		private readonly Dictionary<K1, Dictionary<K2, V>> table = new Dictionary<K1, Dictionary<K2, V>>();

		public V this[K1 key1, K2 key2]
		{
			get
			{
				if (!TryGetValue(key1, key2, out var value))
				{
					throw new KeyNotFoundException($"({key1}, {key2})");
				}
				return value;
			}
			set
			{
				Set(key1, key2, value);
			}
		}

		internal override Dictionary<K1, Dictionary<K2, V>> ConvertToRep()
		{
			return table;
		}

		internal override void ReadRep(Dictionary<K1, Dictionary<K2, V>> value)
		{
			foreach (KeyValuePair<K1, Dictionary<K2, V>> item in value)
			{
				foreach (KeyValuePair<K2, V> item2 in item.Value)
				{
					Set(item.Key, item2.Key, item2.Value);
				}
			}
		}

		public void Clear()
		{
			table.Clear();
		}

		public bool TryGetValue(K1 key1, K2 key2, [MaybeNullWhen(false)] out V value)
		{
			if (table.TryGetValue(key1, out Dictionary<K2, V> value2) && value2.TryGetValue(key2, out value))
			{
				return true;
			}
			value = default(V);
			return false;
		}

		public void Set(K1 key1, K2 key2, V value)
		{
			if (table.TryGetValue(key1, out Dictionary<K2, V> value2))
			{
				value2[key2] = value;
				return;
			}
			value2 = new Dictionary<K2, V>();
			value2.Add(key2, value);
			table.Add(key1, value2);
		}

		public bool Remove(K1 key)
		{
			return table.Remove(key);
		}

		public bool Remove(K1 key1, K2 key2)
		{
			if (table.TryGetValue(key1, out Dictionary<K2, V> value) && value.Remove(key2))
			{
				if (value.Count == 0)
				{
					table.Remove(key1);
				}
				return true;
			}
			return false;
		}

		[IteratorStateMachine(typeof(HashTable<, , >.<EnumerateEntries>d__11))]
		private IEnumerable<((K1, K2), V)> EnumerateEntries()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnumerateEntries>d__11(-2)
			{
				<>4__this = this
			};
		}

		public IEnumerator<((K1, K2), V)> GetEnumerator()
		{
			return EnumerateEntries().GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return EnumerateEntries().GetEnumerator();
		}
	}
	[JsonConverter(typeof(AbstractJsonConvertibleConverter))]
	public class ListMultimap<K, V> : AbstractJsonConvertible<Dictionary<K, List<V>>>, IEnumerable<(K, IReadOnlyList<V>)>, IEnumerable
	{
		private readonly Dictionary<K, List<V>> dict = new Dictionary<K, List<V>>();

		public IReadOnlyCollection<K> Keys => dict.Keys;

		public IEnumerable<V> Values => dict.Values.SelectMany((List<V> v) => v);

		internal override Dictionary<K, List<V>> ConvertToRep()
		{
			return dict;
		}

		internal override void ReadRep(Dictionary<K, List<V>> value)
		{
			foreach (KeyValuePair<K, List<V>> item in value)
			{
				Add(item.Key, item.Value);
			}
		}

		public bool TryGetValues(K key, out IReadOnlyList<V> values)
		{
			if (dict.TryGetValue(key, out List<V> value))
			{
				values = value;
				return true;
			}
			values = EmptyCollection<V>.Instance;
			return false;
		}

		public IReadOnlyList<V> Get(K key)
		{
			if (!dict.TryGetValue(key, out List<V> value))
			{
				return EmptyCollection<V>.Instance;
			}
			return value;
		}

		public void Clear()
		{
			dict.Clear();
		}

		public void Add(K key, V value)
		{
			if (dict.TryGetValue(key, out List<V> value2))
			{
				value2.Add(value);
				return;
			}
			dict.Add(key, new List<V>(1) { value });
		}

		public void Add(K key, IEnumerable<V> values)
		{
			if (dict.TryGetValue(key, out List<V> value))
			{
				value.AddRange(values);
			}
			else
			{
				dict.Add(key, values.ToList());
			}
		}

		public bool Remove(K key)
		{
			return dict.Remove(key);
		}

		public bool Remove(K key, V value)
		{
			if (dict.TryGetValue(key, out List<V> value2) && value2.Remove(value))
			{
				if (value2.Count == 0)
				{
					dict.Remove(key);
				}
				return true;
			}
			return false;
		}

		public bool Remove(K key, IEnumerable<V> values)
		{
			if (dict.TryGetValue(key, out List<V> value))
			{
				bool flag = false;
				foreach (V value2 in values)
				{
					flag |= value.Remove(value2);
				}
				if (value.Count == 0)
				{
					dict.Remove(key);
				}
				return flag;
			}
			return false;
		}

		private IEnumerable<(K, IReadOnlyList<V>)> EnumeateLists()
		{
			return dict.Select<KeyValuePair<K, List<V>>, (K, IReadOnlyList<V>)>((KeyValuePair<K, List<V>> e) => (e.Key, e.Value));
		}

		public IEnumerator<(K, IReadOnlyList<V>)> GetEnumerator()
		{
			return EnumeateLists().GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return EnumeateLists().GetEnumerator();
		}
	}
}
namespace Silksong.PurenailUtil.Collections.Json
{
	public abstract class AbstractJsonConvertible
	{
		internal abstract Type GetRepType();

		internal abstract object ConvertToRepRaw();

		internal abstract void ReadRepRaw(object value);
	}
	public abstract class AbstractJsonConvertible<RepT> : AbstractJsonConvertible where RepT : class
	{
		internal override Type GetRepType()
		{
			return typeof(RepT);
		}

		internal override object ConvertToRepRaw()
		{
			return ConvertToRep();
		}

		internal abstract RepT ConvertToRep();

		internal override void ReadRepRaw(object value)
		{
			ReadRep((RepT)value);
		}

		internal abstract void ReadRep(RepT value);
	}
	internal class AbstractJsonConvertibleConverter : JsonConverter<AbstractJsonConvertible>
	{
		public override AbstractJsonConvertible? ReadJson(JsonReader reader, Type objectType, AbstractJsonConvertible? existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)reader.TokenType == 11)
			{
				return null;
			}
			AbstractJsonConvertible abstractJsonConvertible = (hasExistingValue ? existingValue : ((AbstractJsonConvertible)Activator.CreateInstance(objectType)));
			object value = serializer.Deserialize(reader, abstractJsonConvertible.GetRepType());
			abstractJsonConvertible.ReadRepRaw(value);
			return abstractJsonConvertible;
		}

		public override void WriteJson(JsonWriter writer, AbstractJsonConvertible? value, JsonSerializer serializer)
		{
			if (value != null)
			{
				serializer.Serialize(writer, value.ConvertToRepRaw(), value.GetRepType());
			}
			else
			{
				serializer.Serialize(writer, (object)null);
			}
		}
	}
}