Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PurenailUtil v1.0.0
Silksong.PurenailUtil.dll
Decompiled 3 months agousing 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); } } } }