Decompiled source of System Collections Immutable v5.0.0
BepInEx/core/System.Reflection.Metadata/netstandard2.1/System.Collections.Immutable.dll
Decompiled 8 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Threading; using FxResources.System.Collections.Immutable; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("System.Collections.Immutable.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: CLSCompliant(true)] [assembly: AssemblyDefaultAlias("System.Collections.Immutable")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyMetadata(".NETFrameworkAssembly", "")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyMetadata("PreferInbox", "True")] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyDescription("System.Collections.Immutable")] [assembly: AssemblyFileVersion("5.0.20.51904")] [assembly: AssemblyInformationalVersion("5.0.0+cf258a14b70ad9069470a108f13765e0e5988f51")] [assembly: AssemblyProduct("Microsoft® .NET")] [assembly: AssemblyTitle("System.Collections.Immutable")] [assembly: AssemblyMetadata("RepositoryUrl", "git://github.com/dotnet/runtime")] [assembly: AssemblyVersion("5.0.0.0")] [module: System.Runtime.CompilerServices.NullablePublicOnly(true)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [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 NullablePublicOnlyAttribute : Attribute { public readonly bool IncludesInternals; public NullablePublicOnlyAttribute(bool P_0) { IncludesInternals = P_0; } } } namespace FxResources.System.Collections.Immutable { internal static class SR { } } namespace System { internal static class SR { private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled; private static ResourceManager s_resourceManager; internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR))); internal static string Arg_KeyNotFoundWithKey => GetResourceString("Arg_KeyNotFoundWithKey"); internal static string ArrayInitializedStateNotEqual => GetResourceString("ArrayInitializedStateNotEqual"); internal static string ArrayLengthsNotEqual => GetResourceString("ArrayLengthsNotEqual"); internal static string CannotFindOldValue => GetResourceString("CannotFindOldValue"); internal static string CapacityMustBeGreaterThanOrEqualToCount => GetResourceString("CapacityMustBeGreaterThanOrEqualToCount"); internal static string CapacityMustEqualCountOnMove => GetResourceString("CapacityMustEqualCountOnMove"); internal static string CollectionModifiedDuringEnumeration => GetResourceString("CollectionModifiedDuringEnumeration"); internal static string DuplicateKey => GetResourceString("DuplicateKey"); internal static string InvalidEmptyOperation => GetResourceString("InvalidEmptyOperation"); internal static string InvalidOperationOnDefaultArray => GetResourceString("InvalidOperationOnDefaultArray"); private static bool UsingResourceKeys() { return s_usingResourceKeys; } internal static string GetResourceString(string resourceKey, string? defaultString = null) { if (UsingResourceKeys()) { return defaultString ?? resourceKey; } string text = null; try { text = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } if (defaultString != null && resourceKey.Equals(text)) { return defaultString; } return text; } internal static string Format(string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } internal static string Format(string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(provider, resourceFormat, p1); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(provider, resourceFormat, p1, p2); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(provider, resourceFormat, p1, p2, p3); } internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(provider, resourceFormat, args); } return resourceFormat; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] internal sealed class NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Method, Inherited = false)] internal sealed class DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] 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)] 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; } } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class NonVersionableAttribute : Attribute { } } namespace System.Linq { public static class ImmutableArrayExtensions { public static IEnumerable<TResult> Select<T, TResult>(this ImmutableArray<T> immutableArray, Func<T, TResult> selector) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Select(selector); } public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this ImmutableArray<TSource> immutableArray, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector) { immutableArray.ThrowNullRefIfNotInitialized(); if (collectionSelector == null || resultSelector == null) { return Enumerable.SelectMany(immutableArray, collectionSelector, resultSelector); } if (immutableArray.Length != 0) { return immutableArray.SelectManyIterator(collectionSelector, resultSelector); } return Enumerable.Empty<TResult>(); } public static IEnumerable<T> Where<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Where(predicate); } public static bool Any<T>(this ImmutableArray<T> immutableArray) { return immutableArray.Length > 0; } public static bool Any<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T arg in array) { if (predicate(arg)) { return true; } } return false; } public static bool All<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T arg in array) { if (!predicate(arg)) { return false; } } return true; } public static bool SequenceEqual<TDerived, TBase>(this ImmutableArray<TBase> immutableArray, ImmutableArray<TDerived> items, IEqualityComparer<TBase>? comparer = null) where TDerived : TBase { immutableArray.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); if (immutableArray.array == items.array) { return true; } if (immutableArray.Length != items.Length) { return false; } if (comparer == null) { comparer = EqualityComparer<TBase>.Default; } for (int i = 0; i < immutableArray.Length; i++) { if (!comparer.Equals(immutableArray.array[i], (TBase)(object)items.array[i])) { return false; } } return true; } public static bool SequenceEqual<TDerived, TBase>(this ImmutableArray<TBase> immutableArray, IEnumerable<TDerived> items, IEqualityComparer<TBase>? comparer = null) where TDerived : TBase { Requires.NotNull(items, "items"); if (comparer == null) { comparer = EqualityComparer<TBase>.Default; } int num = 0; int length = immutableArray.Length; foreach (TDerived item in items) { if (num == length) { return false; } if (!comparer.Equals(immutableArray[num], (TBase)(object)item)) { return false; } num++; } return num == length; } public static bool SequenceEqual<TDerived, TBase>(this ImmutableArray<TBase> immutableArray, ImmutableArray<TDerived> items, Func<TBase, TBase, bool> predicate) where TDerived : TBase { Requires.NotNull(predicate, "predicate"); immutableArray.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); if (immutableArray.array == items.array) { return true; } if (immutableArray.Length != items.Length) { return false; } int i = 0; for (int length = immutableArray.Length; i < length; i++) { if (!predicate(immutableArray[i], (TBase)(object)items[i])) { return false; } } return true; } public static T? Aggregate<T>(this ImmutableArray<T> immutableArray, Func<T, T, T> func) { Requires.NotNull(func, "func"); if (immutableArray.Length == 0) { return default(T); } T val = immutableArray[0]; int i = 1; for (int length = immutableArray.Length; i < length; i++) { val = func(val, immutableArray[i]); } return val; } public static TAccumulate Aggregate<TAccumulate, T>(this ImmutableArray<T> immutableArray, TAccumulate seed, Func<TAccumulate, T, TAccumulate> func) { Requires.NotNull(func, "func"); TAccumulate val = seed; T[] array = immutableArray.array; foreach (T arg in array) { val = func(val, arg); } return val; } public static TResult Aggregate<TAccumulate, TResult, T>(this ImmutableArray<T> immutableArray, TAccumulate seed, Func<TAccumulate, T, TAccumulate> func, Func<TAccumulate, TResult> resultSelector) { Requires.NotNull(resultSelector, "resultSelector"); return resultSelector(immutableArray.Aggregate(seed, func)); } public static T ElementAt<T>(this ImmutableArray<T> immutableArray, int index) { return immutableArray[index]; } public static T? ElementAtOrDefault<T>(this ImmutableArray<T> immutableArray, int index) { if (index < 0 || index >= immutableArray.Length) { return default(T); } return immutableArray[index]; } public static T First<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { return val; } } return Enumerable.Empty<T>().First(); } public static T First<T>(this ImmutableArray<T> immutableArray) { if (immutableArray.Length <= 0) { return immutableArray.array.First(); } return immutableArray[0]; } public static T? FirstOrDefault<T>(this ImmutableArray<T> immutableArray) { if (immutableArray.array.Length == 0) { return default(T); } return immutableArray.array[0]; } public static T? FirstOrDefault<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { return val; } } return default(T); } public static T Last<T>(this ImmutableArray<T> immutableArray) { if (immutableArray.Length <= 0) { return immutableArray.array.Last(); } return immutableArray[immutableArray.Length - 1]; } public static T Last<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); for (int num = immutableArray.Length - 1; num >= 0; num--) { if (predicate(immutableArray[num])) { return immutableArray[num]; } } return Enumerable.Empty<T>().Last(); } public static T? LastOrDefault<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.LastOrDefault(); } public static T? LastOrDefault<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); for (int num = immutableArray.Length - 1; num >= 0; num--) { if (predicate(immutableArray[num])) { return immutableArray[num]; } } return default(T); } public static T Single<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Single(); } public static T Single<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); bool flag = true; T result = default(T); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { if (!flag) { ImmutableArray.TwoElementArray.Single(); } flag = false; result = val; } } if (flag) { Enumerable.Empty<T>().Single(); } return result; } public static T? SingleOrDefault<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.SingleOrDefault(); } public static T? SingleOrDefault<T>(this ImmutableArray<T> immutableArray, Func<T, bool> predicate) { Requires.NotNull(predicate, "predicate"); bool flag = true; T result = default(T); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { if (!flag) { ImmutableArray.TwoElementArray.Single(); } flag = false; result = val; } } return result; } public static Dictionary<TKey, T> ToDictionary<TKey, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector) where TKey : notnull { return immutableArray.ToDictionary(keySelector, EqualityComparer<TKey>.Default); } public static Dictionary<TKey, TElement> ToDictionary<TKey, TElement, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector, Func<T, TElement> elementSelector) where TKey : notnull { return immutableArray.ToDictionary(keySelector, elementSelector, EqualityComparer<TKey>.Default); } public static Dictionary<TKey, T> ToDictionary<TKey, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector, IEqualityComparer<TKey>? comparer) where TKey : notnull { Requires.NotNull(keySelector, "keySelector"); Dictionary<TKey, T> dictionary = new Dictionary<TKey, T>(immutableArray.Length, comparer); ImmutableArray<T>.Enumerator enumerator = immutableArray.GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; dictionary.Add(keySelector(current), current); } return dictionary; } public static Dictionary<TKey, TElement> ToDictionary<TKey, TElement, T>(this ImmutableArray<T> immutableArray, Func<T, TKey> keySelector, Func<T, TElement> elementSelector, IEqualityComparer<TKey>? comparer) where TKey : notnull { Requires.NotNull(keySelector, "keySelector"); Requires.NotNull(elementSelector, "elementSelector"); Dictionary<TKey, TElement> dictionary = new Dictionary<TKey, TElement>(immutableArray.Length, comparer); T[] array = immutableArray.array; foreach (T arg in array) { dictionary.Add(keySelector(arg), elementSelector(arg)); } return dictionary; } public static T[] ToArray<T>(this ImmutableArray<T> immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); if (immutableArray.array.Length == 0) { return ImmutableArray<T>.Empty.array; } return (T[])immutableArray.array.Clone(); } public static T First<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { throw new InvalidOperationException(); } return builder[0]; } public static T? FirstOrDefault<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { return default(T); } return builder[0]; } public static T Last<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { throw new InvalidOperationException(); } return builder[builder.Count - 1]; } public static T? LastOrDefault<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { return default(T); } return builder[builder.Count - 1]; } public static bool Any<T>(this ImmutableArray<T>.Builder builder) { Requires.NotNull(builder, "builder"); return builder.Count > 0; } private static IEnumerable<TResult> SelectManyIterator<TSource, TCollection, TResult>(this ImmutableArray<TSource> immutableArray, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector) { TSource[] array = immutableArray.array; foreach (TSource item in array) { foreach (TCollection item2 in collectionSelector(item)) { yield return resultSelector(item, item2); } } } } } namespace System.Collections.Immutable { internal static class AllocFreeConcurrentStack<T> { private const int MaxSize = 35; private static readonly Type s_typeOfT = typeof(T); private static Stack<RefAsValueType<T>> ThreadLocalStack { get { Dictionary<Type, object> dictionary = AllocFreeConcurrentStack.t_stacks; if (dictionary == null) { dictionary = (AllocFreeConcurrentStack.t_stacks = new Dictionary<Type, object>()); } if (!dictionary.TryGetValue(s_typeOfT, out var value)) { value = new Stack<RefAsValueType<T>>(35); dictionary.Add(s_typeOfT, value); } return (Stack<RefAsValueType<T>>)value; } } public static void TryAdd(T item) { Stack<RefAsValueType<T>> threadLocalStack = ThreadLocalStack; if (threadLocalStack.Count < 35) { threadLocalStack.Push(new RefAsValueType<T>(item)); } } public static bool TryTake([MaybeNullWhen(false)] out T item) { Stack<RefAsValueType<T>> threadLocalStack = ThreadLocalStack; if (threadLocalStack != null && threadLocalStack.Count > 0) { item = threadLocalStack.Pop().Value; return true; } item = default(T); return false; } } internal static class AllocFreeConcurrentStack { [ThreadStatic] internal static Dictionary<Type, object>? t_stacks; } internal sealed class DictionaryEnumerator<TKey, TValue> : IDictionaryEnumerator, IEnumerator where TKey : notnull { private readonly IEnumerator<KeyValuePair<TKey, TValue>> _inner; public DictionaryEntry Entry => new DictionaryEntry(_inner.Current.Key, _inner.Current.Value); public object Key => _inner.Current.Key; public object? Value => _inner.Current.Value; public object Current => Entry; internal DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> inner) { Requires.NotNull(inner, "inner"); _inner = inner; } public bool MoveNext() { return _inner.MoveNext(); } public void Reset() { _inner.Reset(); } } internal struct DisposableEnumeratorAdapter<T, TEnumerator> : IDisposable where TEnumerator : struct, IEnumerator<T> { private readonly IEnumerator<T> _enumeratorObject; private TEnumerator _enumeratorStruct; public T Current { get { if (_enumeratorObject == null) { return _enumeratorStruct.Current; } return _enumeratorObject.Current; } } internal DisposableEnumeratorAdapter(TEnumerator enumerator) { _enumeratorStruct = enumerator; _enumeratorObject = null; } internal DisposableEnumeratorAdapter(IEnumerator<T> enumerator) { _enumeratorStruct = default(TEnumerator); _enumeratorObject = enumerator; } public bool MoveNext() { if (_enumeratorObject == null) { return _enumeratorStruct.MoveNext(); } return _enumeratorObject.MoveNext(); } public void Dispose() { if (_enumeratorObject != null) { _enumeratorObject.Dispose(); } else { _enumeratorStruct.Dispose(); } } public DisposableEnumeratorAdapter<T, TEnumerator> GetEnumerator() { return this; } } internal interface IBinaryTree { int Height { get; } bool IsEmpty { get; } int Count { get; } IBinaryTree? Left { get; } IBinaryTree? Right { get; } } internal interface IBinaryTree<out T> : IBinaryTree { T Value { get; } new IBinaryTree<T>? Left { get; } new IBinaryTree<T>? Right { get; } } internal interface IImmutableArray { Array? Array { get; } } public interface IImmutableDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyCollection<KeyValuePair<TKey, TValue>> { IImmutableDictionary<TKey, TValue> Clear(); IImmutableDictionary<TKey, TValue> Add(TKey key, TValue value); IImmutableDictionary<TKey, TValue> AddRange(IEnumerable<KeyValuePair<TKey, TValue>> pairs); IImmutableDictionary<TKey, TValue> SetItem(TKey key, TValue value); IImmutableDictionary<TKey, TValue> SetItems(IEnumerable<KeyValuePair<TKey, TValue>> items); IImmutableDictionary<TKey, TValue> RemoveRange(IEnumerable<TKey> keys); IImmutableDictionary<TKey, TValue> Remove(TKey key); bool Contains(KeyValuePair<TKey, TValue> pair); bool TryGetKey(TKey equalKey, out TKey actualKey); } internal interface IImmutableDictionaryInternal<TKey, TValue> { bool ContainsValue(TValue value); } public interface IImmutableList<T> : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T> { IImmutableList<T> Clear(); int IndexOf(T item, int index, int count, IEqualityComparer<T>? equalityComparer); int LastIndexOf(T item, int index, int count, IEqualityComparer<T>? equalityComparer); IImmutableList<T> Add(T value); IImmutableList<T> AddRange(IEnumerable<T> items); IImmutableList<T> Insert(int index, T element); IImmutableList<T> InsertRange(int index, IEnumerable<T> items); IImmutableList<T> Remove(T value, IEqualityComparer<T>? equalityComparer); IImmutableList<T> RemoveAll(Predicate<T> match); IImmutableList<T> RemoveRange(IEnumerable<T> items, IEqualityComparer<T>? equalityComparer); IImmutableList<T> RemoveRange(int index, int count); IImmutableList<T> RemoveAt(int index); IImmutableList<T> SetItem(int index, T value); IImmutableList<T> Replace(T oldValue, T newValue, IEqualityComparer<T>? equalityComparer); } internal interface IImmutableListQueries<T> : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T> { ImmutableList<TOutput> ConvertAll<TOutput>(Func<T, TOutput> converter); void ForEach(Action<T> action); ImmutableList<T> GetRange(int index, int count); void CopyTo(T[] array); void CopyTo(T[] array, int arrayIndex); void CopyTo(int index, T[] array, int arrayIndex, int count); bool Exists(Predicate<T> match); T? Find(Predicate<T> match); ImmutableList<T> FindAll(Predicate<T> match); int FindIndex(Predicate<T> match); int FindIndex(int startIndex, Predicate<T> match); int FindIndex(int startIndex, int count, Predicate<T> match); T? FindLast(Predicate<T> match); int FindLastIndex(Predicate<T> match); int FindLastIndex(int startIndex, Predicate<T> match); int FindLastIndex(int startIndex, int count, Predicate<T> match); bool TrueForAll(Predicate<T> match); int BinarySearch(T item); int BinarySearch(T item, IComparer<T>? comparer); int BinarySearch(int index, int count, T item, IComparer<T>? comparer); } public interface IImmutableQueue<T> : IEnumerable<T>, IEnumerable { bool IsEmpty { get; } IImmutableQueue<T> Clear(); T Peek(); IImmutableQueue<T> Enqueue(T value); IImmutableQueue<T> Dequeue(); } public interface IImmutableSet<T> : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable { IImmutableSet<T> Clear(); bool Contains(T value); IImmutableSet<T> Add(T value); IImmutableSet<T> Remove(T value); bool TryGetValue(T equalValue, out T actualValue); IImmutableSet<T> Intersect(IEnumerable<T> other); IImmutableSet<T> Except(IEnumerable<T> other); IImmutableSet<T> SymmetricExcept(IEnumerable<T> other); IImmutableSet<T> Union(IEnumerable<T> other); bool SetEquals(IEnumerable<T> other); bool IsProperSubsetOf(IEnumerable<T> other); bool IsProperSupersetOf(IEnumerable<T> other); bool IsSubsetOf(IEnumerable<T> other); bool IsSupersetOf(IEnumerable<T> other); bool Overlaps(IEnumerable<T> other); } public interface IImmutableStack<T> : IEnumerable<T>, IEnumerable { bool IsEmpty { get; } IImmutableStack<T> Clear(); IImmutableStack<T> Push(T value); IImmutableStack<T> Pop(); T Peek(); } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] public sealed class ImmutableHashSet<T> : IImmutableSet<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable, IHashKeyCollection<T>, ICollection<T>, ISet<T>, ICollection, IStrongEnumerable<T, ImmutableHashSet<T>.Enumerator> { private class HashBucketByValueEqualityComparer : IEqualityComparer<HashBucket> { private static readonly IEqualityComparer<HashBucket> s_defaultInstance = new HashBucketByValueEqualityComparer(EqualityComparer<T>.Default); private readonly IEqualityComparer<T> _valueComparer; internal static IEqualityComparer<HashBucket> DefaultInstance => s_defaultInstance; internal HashBucketByValueEqualityComparer(IEqualityComparer<T> valueComparer) { Requires.NotNull(valueComparer, "valueComparer"); _valueComparer = valueComparer; } public bool Equals(HashBucket x, HashBucket y) { return x.EqualsByValue(y, _valueComparer); } public int GetHashCode(HashBucket obj) { throw new NotSupportedException(); } } private class HashBucketByRefEqualityComparer : IEqualityComparer<HashBucket> { private static readonly IEqualityComparer<HashBucket> s_defaultInstance = new HashBucketByRefEqualityComparer(); internal static IEqualityComparer<HashBucket> DefaultInstance => s_defaultInstance; private HashBucketByRefEqualityComparer() { } public bool Equals(HashBucket x, HashBucket y) { return x.EqualsByRef(y); } public int GetHashCode(HashBucket obj) { throw new NotSupportedException(); } } [DebuggerDisplay("Count = {Count}")] public sealed class Builder : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable, ISet<T>, ICollection<T> { private SortedInt32KeyNode<HashBucket> _root = SortedInt32KeyNode<HashBucket>.EmptyNode; private IEqualityComparer<T> _equalityComparer; private readonly IEqualityComparer<HashBucket> _hashBucketEqualityComparer; private int _count; private ImmutableHashSet<T> _immutable; private int _version; public int Count => _count; bool ICollection<T>.IsReadOnly => false; public IEqualityComparer<T> KeyComparer { get { return _equalityComparer; } set { Requires.NotNull(value, "value"); if (value != _equalityComparer) { MutationResult mutationResult = ImmutableHashSet<T>.Union((IEnumerable<T>)this, new MutationInput(SortedInt32KeyNode<HashBucket>.EmptyNode, value, _hashBucketEqualityComparer, 0)); _immutable = null; _equalityComparer = value; Root = mutationResult.Root; _count = mutationResult.Count; } } } internal int Version => _version; private MutationInput Origin => new MutationInput(Root, _equalityComparer, _hashBucketEqualityComparer, _count); private SortedInt32KeyNode<HashBucket> Root { get { return _root; } set { _version++; if (_root != value) { _root = value; _immutable = null; } } } internal Builder(ImmutableHashSet<T> set) { Requires.NotNull(set, "set"); _root = set._root; _count = set._count; _equalityComparer = set._equalityComparer; _hashBucketEqualityComparer = set._hashBucketEqualityComparer; _immutable = set; } public Enumerator GetEnumerator() { return new Enumerator(_root, this); } public ImmutableHashSet<T> ToImmutable() { if (_immutable == null) { _immutable = ImmutableHashSet<T>.Wrap(_root, _equalityComparer, _count); } return _immutable; } public bool TryGetValue(T equalValue, out T actualValue) { int key = ((equalValue != null) ? _equalityComparer.GetHashCode(equalValue) : 0); if (_root.TryGetValue(key, out var value)) { return value.TryExchange(equalValue, _equalityComparer, out actualValue); } actualValue = equalValue; return false; } public bool Add(T item) { MutationResult result = ImmutableHashSet<T>.Add(item, Origin); Apply(result); return result.Count != 0; } public bool Remove(T item) { MutationResult result = ImmutableHashSet<T>.Remove(item, Origin); Apply(result); return result.Count != 0; } public bool Contains(T item) { return ImmutableHashSet<T>.Contains(item, Origin); } public void Clear() { _count = 0; Root = SortedInt32KeyNode<HashBucket>.EmptyNode; } public void ExceptWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.Except(other, _equalityComparer, _hashBucketEqualityComparer, _root); Apply(result); } public void IntersectWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.Intersect(other, Origin); Apply(result); } public bool IsProperSubsetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsProperSubsetOf(other, Origin); } public bool IsProperSupersetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsProperSupersetOf(other, Origin); } public bool IsSubsetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsSubsetOf(other, Origin); } public bool IsSupersetOf(IEnumerable<T> other) { return ImmutableHashSet<T>.IsSupersetOf(other, Origin); } public bool Overlaps(IEnumerable<T> other) { return ImmutableHashSet<T>.Overlaps(other, Origin); } public bool SetEquals(IEnumerable<T> other) { if (this == other) { return true; } return ImmutableHashSet<T>.SetEquals(other, Origin); } public void SymmetricExceptWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.SymmetricExcept(other, Origin); Apply(result); } public void UnionWith(IEnumerable<T> other) { MutationResult result = ImmutableHashSet<T>.Union(other, Origin); Apply(result); } void ICollection<T>.Add(T item) { Add(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private void Apply(MutationResult result) { Root = result.Root; if (result.CountType == CountType.Adjustment) { _count += result.Count; } else { _count = result.Count; } } } public struct Enumerator : IEnumerator<T>, IEnumerator, IDisposable, IStrongEnumerator<T> { private readonly Builder _builder; private SortedInt32KeyNode<HashBucket>.Enumerator _mapEnumerator; private HashBucket.Enumerator _bucketEnumerator; private int _enumeratingBuilderVersion; public T Current { get { _mapEnumerator.ThrowIfDisposed(); return _bucketEnumerator.Current; } } object? IEnumerator.Current => Current; internal Enumerator(SortedInt32KeyNode<HashBucket> root, Builder? builder = null) { _builder = builder; _mapEnumerator = new SortedInt32KeyNode<HashBucket>.Enumerator(root); _bucketEnumerator = default(HashBucket.Enumerator); _enumeratingBuilderVersion = builder?.Version ?? (-1); } public bool MoveNext() { ThrowIfChanged(); if (_bucketEnumerator.MoveNext()) { return true; } if (_mapEnumerator.MoveNext()) { _bucketEnumerator = new HashBucket.Enumerator(_mapEnumerator.Current.Value); return _bucketEnumerator.MoveNext(); } return false; } public void Reset() { _enumeratingBuilderVersion = ((_builder != null) ? _builder.Version : (-1)); _mapEnumerator.Reset(); _bucketEnumerator.Dispose(); _bucketEnumerator = default(HashBucket.Enumerator); } public void Dispose() { _mapEnumerator.Dispose(); _bucketEnumerator.Dispose(); } private void ThrowIfChanged() { if (_builder != null && _builder.Version != _enumeratingBuilderVersion) { throw new InvalidOperationException(System.SR.CollectionModifiedDuringEnumeration); } } } internal enum OperationResult { SizeChanged, NoChangeRequired } internal readonly struct HashBucket { internal struct Enumerator : IEnumerator<T>, IEnumerator, IDisposable { private enum Position { BeforeFirst, First, Additional, End } private readonly HashBucket _bucket; private bool _disposed; private Position _currentPosition; private ImmutableList<T>.Enumerator _additionalEnumerator; object? IEnumerator.Current => Current; public T Current { get { ThrowIfDisposed(); return _currentPosition switch { Position.First => _bucket._firstValue, Position.Additional => _additionalEnumerator.Current, _ => throw new InvalidOperationException(), }; } } internal Enumerator(HashBucket bucket) { _disposed = false; _bucket = bucket; _currentPosition = Position.BeforeFirst; _additionalEnumerator = default(ImmutableList<T>.Enumerator); } public bool MoveNext() { ThrowIfDisposed(); if (_bucket.IsEmpty) { _currentPosition = Position.End; return false; } switch (_currentPosition) { case Position.BeforeFirst: _currentPosition = Position.First; return true; case Position.First: if (_bucket._additionalElements.IsEmpty) { _currentPosition = Position.End; return false; } _currentPosition = Position.Additional; _additionalEnumerator = new ImmutableList<T>.Enumerator(_bucket._additionalElements); return _additionalEnumerator.MoveNext(); case Position.Additional: return _additionalEnumerator.MoveNext(); case Position.End: return false; default: throw new InvalidOperationException(); } } public void Reset() { ThrowIfDisposed(); _additionalEnumerator.Dispose(); _currentPosition = Position.BeforeFirst; } public void Dispose() { _disposed = true; _additionalEnumerator.Dispose(); } private void ThrowIfDisposed() { if (_disposed) { Requires.FailObjectDisposed(this); } } } private readonly T _firstValue; private readonly ImmutableList<T>.Node _additionalElements; internal bool IsEmpty => _additionalElements == null; private HashBucket(T firstElement, ImmutableList<T>.Node additionalElements = null) { _firstValue = firstElement; _additionalElements = additionalElements ?? ImmutableList<T>.Node.EmptyNode; } public Enumerator GetEnumerator() { return new Enumerator(this); } public override bool Equals(object? obj) { throw new NotSupportedException(); } public override int GetHashCode() { throw new NotSupportedException(); } internal bool EqualsByRef(HashBucket other) { if ((object)_firstValue == (object)other._firstValue) { return _additionalElements == other._additionalElements; } return false; } internal bool EqualsByValue(HashBucket other, IEqualityComparer<T> valueComparer) { if (valueComparer.Equals(_firstValue, other._firstValue)) { return _additionalElements == other._additionalElements; } return false; } internal HashBucket Add(T value, IEqualityComparer<T> valueComparer, out OperationResult result) { if (IsEmpty) { result = OperationResult.SizeChanged; return new HashBucket(value); } if (valueComparer.Equals(value, _firstValue) || _additionalElements.IndexOf(value, valueComparer) >= 0) { result = OperationResult.NoChangeRequired; return this; } result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.Add(value)); } internal bool Contains(T value, IEqualityComparer<T> valueComparer) { if (IsEmpty) { return false; } if (!valueComparer.Equals(value, _firstValue)) { return _additionalElements.IndexOf(value, valueComparer) >= 0; } return true; } internal bool TryExchange(T value, IEqualityComparer<T> valueComparer, out T existingValue) { if (!IsEmpty) { if (valueComparer.Equals(value, _firstValue)) { existingValue = _firstValue; return true; } int num = _additionalElements.IndexOf(value, valueComparer); if (num >= 0) { existingValue = _additionalElements.ItemRef(num); return true; } } existingValue = value; return false; } internal HashBucket Remove(T value, IEqualityComparer<T> equalityComparer, out OperationResult result) { if (IsEmpty) { result = OperationResult.NoChangeRequired; return this; } if (equalityComparer.Equals(_firstValue, value)) { if (_additionalElements.IsEmpty) { result = OperationResult.SizeChanged; return default(HashBucket); } int count = _additionalElements.Left.Count; result = OperationResult.SizeChanged; return new HashBucket(_additionalElements.Key, _additionalElements.RemoveAt(count)); } int num = _additionalElements.IndexOf(value, equalityComparer); if (num < 0) { result = OperationResult.NoChangeRequired; return this; } result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.RemoveAt(num)); } internal void Freeze() { if (_additionalElements != null) { _additionalElements.Freeze(); } } } private readonly struct MutationInput { private readonly SortedInt32KeyNode<HashBucket> _root; private readonly IEqualityComparer<T> _equalityComparer; private readonly int _count; private readonly IEqualityComparer<HashBucket> _hashBucketEqualityComparer; internal SortedInt32KeyNode<HashBucket> Root => _root; internal IEqualityComparer<T> EqualityComparer => _equalityComparer; internal int Count => _count; internal IEqualityComparer<HashBucket> HashBucketEqualityComparer => _hashBucketEqualityComparer; internal MutationInput(ImmutableHashSet<T> set) { Requires.NotNull(set, "set"); _root = set._root; _equalityComparer = set._equalityComparer; _count = set._count; _hashBucketEqualityComparer = set._hashBucketEqualityComparer; } internal MutationInput(SortedInt32KeyNode<HashBucket> root, IEqualityComparer<T> equalityComparer, IEqualityComparer<HashBucket> hashBucketEqualityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.Range(count >= 0, "count"); Requires.NotNull(hashBucketEqualityComparer, "hashBucketEqualityComparer"); _root = root; _equalityComparer = equalityComparer; _count = count; _hashBucketEqualityComparer = hashBucketEqualityComparer; } } private enum CountType { Adjustment, FinalValue } private readonly struct MutationResult { private readonly SortedInt32KeyNode<HashBucket> _root; private readonly int _count; private readonly CountType _countType; internal SortedInt32KeyNode<HashBucket> Root => _root; internal int Count => _count; internal CountType CountType => _countType; internal MutationResult(SortedInt32KeyNode<HashBucket> root, int count, CountType countType = CountType.Adjustment) { Requires.NotNull(root, "root"); _root = root; _count = count; _countType = countType; } internal ImmutableHashSet<T> Finalize(ImmutableHashSet<T> priorSet) { Requires.NotNull(priorSet, "priorSet"); int num = Count; if (CountType == CountType.Adjustment) { num += priorSet._count; } return priorSet.Wrap(Root, num); } } private readonly struct NodeEnumerable : IEnumerable<T>, IEnumerable { private readonly SortedInt32KeyNode<HashBucket> _root; internal NodeEnumerable(SortedInt32KeyNode<HashBucket> root) { Requires.NotNull(root, "root"); _root = root; } public Enumerator GetEnumerator() { return new Enumerator(_root); } [ExcludeFromCodeCoverage] IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public static readonly ImmutableHashSet<T> Empty = new ImmutableHashSet<T>(SortedInt32KeyNode<HashBucket>.EmptyNode, EqualityComparer<T>.Default, 0); private static readonly Action<KeyValuePair<int, HashBucket>> s_FreezeBucketAction = delegate(KeyValuePair<int, HashBucket> kv) { kv.Value.Freeze(); }; private readonly IEqualityComparer<T> _equalityComparer; private readonly int _count; private readonly SortedInt32KeyNode<HashBucket> _root; private readonly IEqualityComparer<HashBucket> _hashBucketEqualityComparer; public int Count => _count; public bool IsEmpty => Count == 0; public IEqualityComparer<T> KeyComparer => _equalityComparer; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; internal IBinaryTree Root => _root; private MutationInput Origin => new MutationInput(this); bool ICollection<T>.IsReadOnly => true; internal ImmutableHashSet(IEqualityComparer<T> equalityComparer) : this(SortedInt32KeyNode<HashBucket>.EmptyNode, equalityComparer, 0) { } private ImmutableHashSet(SortedInt32KeyNode<HashBucket> root, IEqualityComparer<T> equalityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); root.Freeze(s_FreezeBucketAction); _root = root; _count = count; _equalityComparer = equalityComparer; _hashBucketEqualityComparer = GetHashBucketEqualityComparer(equalityComparer); } public ImmutableHashSet<T> Clear() { if (!IsEmpty) { return Empty.WithComparer(_equalityComparer); } return this; } IImmutableSet<T> IImmutableSet<T>.Clear() { return Clear(); } public Builder ToBuilder() { return new Builder(this); } public ImmutableHashSet<T> Add(T item) { return Add(item, Origin).Finalize(this); } public ImmutableHashSet<T> Remove(T item) { return Remove(item, Origin).Finalize(this); } public bool TryGetValue(T equalValue, out T actualValue) { int key = ((equalValue != null) ? _equalityComparer.GetHashCode(equalValue) : 0); if (_root.TryGetValue(key, out var value)) { return value.TryExchange(equalValue, _equalityComparer, out actualValue); } actualValue = equalValue; return false; } public ImmutableHashSet<T> Union(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Union(other, avoidWithComparer: false); } public ImmutableHashSet<T> Intersect(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Intersect(other, Origin).Finalize(this); } public ImmutableHashSet<T> Except(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Except(other, _equalityComparer, _hashBucketEqualityComparer, _root).Finalize(this); } public ImmutableHashSet<T> SymmetricExcept(IEnumerable<T> other) { Requires.NotNull(other, "other"); return SymmetricExcept(other, Origin).Finalize(this); } public bool SetEquals(IEnumerable<T> other) { Requires.NotNull(other, "other"); if (this == other) { return true; } return SetEquals(other, Origin); } public bool IsProperSubsetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsProperSubsetOf(other, Origin); } public bool IsProperSupersetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsProperSupersetOf(other, Origin); } public bool IsSubsetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsSubsetOf(other, Origin); } public bool IsSupersetOf(IEnumerable<T> other) { Requires.NotNull(other, "other"); return IsSupersetOf(other, Origin); } public bool Overlaps(IEnumerable<T> other) { Requires.NotNull(other, "other"); return Overlaps(other, Origin); } IImmutableSet<T> IImmutableSet<T>.Add(T item) { return Add(item); } IImmutableSet<T> IImmutableSet<T>.Remove(T item) { return Remove(item); } IImmutableSet<T> IImmutableSet<T>.Union(IEnumerable<T> other) { return Union(other); } IImmutableSet<T> IImmutableSet<T>.Intersect(IEnumerable<T> other) { return Intersect(other); } IImmutableSet<T> IImmutableSet<T>.Except(IEnumerable<T> other) { return Except(other); } IImmutableSet<T> IImmutableSet<T>.SymmetricExcept(IEnumerable<T> other) { return SymmetricExcept(other); } public bool Contains(T item) { return Contains(item, Origin); } public ImmutableHashSet<T> WithComparer(IEqualityComparer<T>? equalityComparer) { if (equalityComparer == null) { equalityComparer = EqualityComparer<T>.Default; } if (equalityComparer == _equalityComparer) { return this; } ImmutableHashSet<T> immutableHashSet = new ImmutableHashSet<T>(equalityComparer); return immutableHashSet.Union(this, avoidWithComparer: true); } bool ISet<T>.Add(T item) { throw new NotSupportedException(); } void ISet<T>.ExceptWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ISet<T>.IntersectWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ISet<T>.SymmetricExceptWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ISet<T>.UnionWith(IEnumerable<T> other) { throw new NotSupportedException(); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array.SetValue(current, arrayIndex++); } } public Enumerator GetEnumerator() { return new Enumerator(_root); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { if (!IsEmpty) { return GetEnumerator(); } return Enumerable.Empty<T>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static bool IsSupersetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { if (!Contains(item, origin)) { return false; } } return true; } private static MutationResult Add(T item, MutationInput origin) { int num = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); OperationResult result; HashBucket newBucket = origin.Root.GetValueOrDefault(num).Add(item, origin.EqualityComparer, out result); if (result == OperationResult.NoChangeRequired) { return new MutationResult(origin.Root, 0); } SortedInt32KeyNode<HashBucket> root = UpdateRoot(origin.Root, num, origin.HashBucketEqualityComparer, newBucket); return new MutationResult(root, 1); } private static MutationResult Remove(T item, MutationInput origin) { OperationResult result = OperationResult.NoChangeRequired; int num = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); SortedInt32KeyNode<HashBucket> root = origin.Root; if (origin.Root.TryGetValue(num, out var value)) { HashBucket newBucket = value.Remove(item, origin.EqualityComparer, out result); if (result == OperationResult.NoChangeRequired) { return new MutationResult(origin.Root, 0); } root = UpdateRoot(origin.Root, num, origin.HashBucketEqualityComparer, newBucket); } return new MutationResult(root, (result == OperationResult.SizeChanged) ? (-1) : 0); } private static bool Contains(T item, MutationInput origin) { int key = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); if (origin.Root.TryGetValue(key, out var value)) { return value.Contains(item, origin.EqualityComparer); } return false; } private static MutationResult Union(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); int num = 0; SortedInt32KeyNode<HashBucket> sortedInt32KeyNode = origin.Root; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { int num2 = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); OperationResult result; HashBucket newBucket = sortedInt32KeyNode.GetValueOrDefault(num2).Add(item, origin.EqualityComparer, out result); if (result == OperationResult.SizeChanged) { sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, num2, origin.HashBucketEqualityComparer, newBucket); num++; } } return new MutationResult(sortedInt32KeyNode, num); } private static bool Overlaps(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return false; } foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { if (Contains(item, origin)) { return true; } } return false; } private static bool SetEquals(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); HashSet<T> hashSet = new HashSet<T>(other, origin.EqualityComparer); if (origin.Count != hashSet.Count) { return false; } foreach (T item in hashSet) { if (!Contains(item, origin)) { return false; } } return true; } private static SortedInt32KeyNode<HashBucket> UpdateRoot(SortedInt32KeyNode<HashBucket> root, int hashCode, IEqualityComparer<HashBucket> hashBucketEqualityComparer, HashBucket newBucket) { bool mutated; if (newBucket.IsEmpty) { return root.Remove(hashCode, out mutated); } bool replacedExistingValue; return root.SetItem(hashCode, newBucket, hashBucketEqualityComparer, out replacedExistingValue, out mutated); } private static MutationResult Intersect(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); SortedInt32KeyNode<HashBucket> root = SortedInt32KeyNode<HashBucket>.EmptyNode; int num = 0; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { if (Contains(item, origin)) { MutationResult mutationResult = Add(item, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult.Root; num += mutationResult.Count; } } return new MutationResult(root, num, CountType.FinalValue); } private static MutationResult Except(IEnumerable<T> other, IEqualityComparer<T> equalityComparer, IEqualityComparer<HashBucket> hashBucketEqualityComparer, SortedInt32KeyNode<HashBucket> root) { Requires.NotNull(other, "other"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.NotNull(root, "root"); int num = 0; SortedInt32KeyNode<HashBucket> sortedInt32KeyNode = root; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { int num2 = ((item != null) ? equalityComparer.GetHashCode(item) : 0); if (sortedInt32KeyNode.TryGetValue(num2, out var value)) { OperationResult result; HashBucket newBucket = value.Remove(item, equalityComparer, out result); if (result == OperationResult.SizeChanged) { num--; sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, num2, hashBucketEqualityComparer, newBucket); } } } return new MutationResult(sortedInt32KeyNode, num); } private static MutationResult SymmetricExcept(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); ImmutableHashSet<T> immutableHashSet = ImmutableHashSet.CreateRange(origin.EqualityComparer, other); int num = 0; SortedInt32KeyNode<HashBucket> root = SortedInt32KeyNode<HashBucket>.EmptyNode; foreach (T item in new NodeEnumerable(origin.Root)) { if (!immutableHashSet.Contains(item)) { MutationResult mutationResult = Add(item, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult.Root; num += mutationResult.Count; } } foreach (T item2 in immutableHashSet) { if (!Contains(item2, origin)) { MutationResult mutationResult2 = Add(item2, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult2.Root; num += mutationResult2.Count; } } return new MutationResult(root, num, CountType.FinalValue); } private static bool IsProperSubsetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return other.Any(); } HashSet<T> hashSet = new HashSet<T>(other, origin.EqualityComparer); if (origin.Count >= hashSet.Count) { return false; } int num = 0; bool flag = false; foreach (T item in hashSet) { if (Contains(item, origin)) { num++; } else { flag = true; } if (num == origin.Count && flag) { return true; } } return false; } private static bool IsProperSupersetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return false; } int num = 0; foreach (T item in other.GetEnumerableDisposable<T, Enumerator>()) { num++; if (!Contains(item, origin)) { return false; } } return origin.Count > num; } private static bool IsSubsetOf(IEnumerable<T> other, MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return true; } HashSet<T> hashSet = new HashSet<T>(other, origin.EqualityComparer); int num = 0; foreach (T item in hashSet) { if (Contains(item, origin)) { num++; } } return num == origin.Count; } private static ImmutableHashSet<T> Wrap(SortedInt32KeyNode<HashBucket> root, IEqualityComparer<T> equalityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.Range(count >= 0, "count"); return new ImmutableHashSet<T>(root, equalityComparer, count); } private static IEqualityComparer<HashBucket> GetHashBucketEqualityComparer(IEqualityComparer<T> valueComparer) { if (!ImmutableExtensions.IsValueType<T>()) { return HashBucketByRefEqualityComparer.DefaultInstance; } if (valueComparer == EqualityComparer<T>.Default) { return HashBucketByValueEqualityComparer.DefaultInstance; } return new HashBucketByValueEqualityComparer(valueComparer); } private ImmutableHashSet<T> Wrap(SortedInt32KeyNode<HashBucket> root, int adjustedCountIfDifferentRoot) { if (root == _root) { return this; } return new ImmutableHashSet<T>(root, _equalityComparer, adjustedCountIfDifferentRoot); } private ImmutableHashSet<T> Union(IEnumerable<T> items, bool avoidWithComparer) { Requires.NotNull(items, "items"); if (IsEmpty && !avoidWithComparer && items is ImmutableHashSet<T> immutableHashSet) { return immutableHashSet.WithComparer(KeyComparer); } return Union(items, Origin).Finalize(this); } } internal interface IStrongEnumerable<out T, TEnumerator> where TEnumerator : struct, IStrongEnumerator<T> { TEnumerator GetEnumerator(); } internal interface IStrongEnumerator<T> { T Current { get; } bool MoveNext(); } internal interface IOrderedCollection<out T> : IEnumerable<T>, IEnumerable { int Count { get; } T this[int index] { get; } } public static class ImmutableArray { internal static readonly byte[] TwoElementArray = new byte[2]; public static ImmutableArray<T> Create<T>() { return ImmutableArray<T>.Empty; } public static ImmutableArray<T> Create<T>(T item) { T[] items = new T[1] { item }; return new ImmutableArray<T>(items); } public static ImmutableArray<T> Create<T>(T item1, T item2) { T[] items = new T[2] { item1, item2 }; return new ImmutableArray<T>(items); } public static ImmutableArray<T> Create<T>(T item1, T item2, T item3) { T[] items = new T[3] { item1, item2, item3 }; return new ImmutableArray<T>(items); } public static ImmutableArray<T> Create<T>(T item1, T item2, T item3, T item4) { T[] items = new T[4] { item1, item2, item3, item4 }; return new ImmutableArray<T>(items); } public static ImmutableArray<T> CreateRange<T>(IEnumerable<T> items) { Requires.NotNull(items, "items"); if (items is IImmutableArray immutableArray) { Array array = immutableArray.Array; if (array == null) { throw new InvalidOperationException(System.SR.InvalidOperationOnDefaultArray); } return new ImmutableArray<T>((T[])array); } if (items.TryGetCount(out var count)) { return new ImmutableArray<T>(items.ToArray(count)); } return new ImmutableArray<T>(items.ToArray()); } public static ImmutableArray<T> Create<T>(params T[]? items) { if (items == null || items.Length == 0) { return ImmutableArray<T>.Empty; } T[] array = new T[items.Length]; Array.Copy(items, array, items.Length); return new ImmutableArray<T>(array); } public static ImmutableArray<T> Create<T>(T[] items, int start, int length) { Requires.NotNull(items, "items"); Requires.Range(start >= 0 && start <= items.Length, "start"); Requires.Range(length >= 0 && start + length <= items.Length, "length"); if (length == 0) { return Create<T>(); } T[] array = new T[length]; for (int i = 0; i < array.Length; i++) { array[i] = items[start + i]; } return new ImmutableArray<T>(array); } public static ImmutableArray<T> Create<T>(ImmutableArray<T> items, int start, int length) { Requires.Range(start >= 0 && start <= items.Length, "start"); Requires.Range(length >= 0 && start + length <= items.Length, "length"); if (length == 0) { return Create<T>(); } if (start == 0 && length == items.Length) { return items; } T[] array = new T[length]; Array.Copy(items.array, start, array, 0, length); return new ImmutableArray<T>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TResult>(ImmutableArray<TSource> items, Func<TSource, TResult> selector) { Requires.NotNull(selector, "selector"); int length = items.Length; if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i]); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TResult>(ImmutableArray<TSource> items, int start, int length, Func<TSource, TResult> selector) { int length2 = items.Length; Requires.Range(start >= 0 && start <= length2, "start"); Requires.Range(length >= 0 && start + length <= length2, "length"); Requires.NotNull(selector, "selector"); if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i + start]); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TArg, TResult>(ImmutableArray<TSource> items, Func<TSource, TArg, TResult> selector, TArg arg) { Requires.NotNull(selector, "selector"); int length = items.Length; if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i], arg); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<TResult> CreateRange<TSource, TArg, TResult>(ImmutableArray<TSource> items, int start, int length, Func<TSource, TArg, TResult> selector, TArg arg) { int length2 = items.Length; Requires.Range(start >= 0 && start <= length2, "start"); Requires.Range(length >= 0 && start + length <= length2, "length"); Requires.NotNull(selector, "selector"); if (length == 0) { return Create<TResult>(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i + start], arg); } return new ImmutableArray<TResult>(array); } public static ImmutableArray<T>.Builder CreateBuilder<T>() { return Create<T>().ToBuilder(); } public static ImmutableArray<T>.Builder CreateBuilder<T>(int initialCapacity) { return new ImmutableArray<T>.Builder(initialCapacity); } public static ImmutableArray<TSource> ToImmutableArray<TSource>(this IEnumerable<TSource> items) { if (items is ImmutableArray<TSource>) { return (ImmutableArray<TSource>)(object)items; } return CreateRange(items); } public static ImmutableArray<TSource> ToImmutableArray<TSource>(this ImmutableArray<TSource>.Builder builder) { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } public static int BinarySearch<T>(this ImmutableArray<T> array, T value) { return Array.BinarySearch(array.array, value); } public static int BinarySearch<T>(this ImmutableArray<T> array, T value, IComparer<T>? comparer) { return Array.BinarySearch(array.array, value, comparer); } public static int BinarySearch<T>(this ImmutableArray<T> array, int index, int length, T value) { return Array.BinarySearch(array.array, index, length, value); } public static int BinarySearch<T>(this ImmutableArray<T> array, int index, int length, T value, IComparer<T>? comparer) { return Array.BinarySearch(array.array, index, length, value, comparer); } } [DebuggerDisplay("{DebuggerDisplay,nq}")] [System.Runtime.Versioning.NonVersionable] public struct ImmutableArray<T> : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T>, IList<T>, ICollection<T>, IEquatable<ImmutableArray<T>>, IList, ICollection, IImmutableArray, IStructuralComparable, IStructuralEquatable, IImmutableList<T> { [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableArrayBuilderDebuggerProxy<>))] public sealed class Builder : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IReadOnlyList<T>, IReadOnlyCollection<T> { private T[] _elements; private int _count; public int Capacity { get { return _elements.Length; } set { if (value < _count) { throw new ArgumentException(System.SR.CapacityMustBeGreaterThanOrEqualToCount, "value"); } if (value == _elements.Length) { return; } if (value > 0) { T[] array = new T[value]; if (_count > 0) { Array.Copy(_elements, array, _count); } _elements = array; } else { _elements = ImmutableArray<T>.Empty.array; } } } public int Count { get { return _count; } set { Requires.Range(value >= 0, "value"); if (value < _count) { if (_count - value > 64) { Array.Clear(_elements, value, _count - value); } else { for (int i = value; i < Count; i++) { _elements[i] = default(T); } } } else if (value > _count) { EnsureCapacity(value); } _count = value; } } public T this[int index] { get { if (index >= Count) { ThrowIndexOutOfRangeException(); } return _elements[index]; } set { if (index >= Count) { ThrowIndexOutOfRangeException(); } _elements[index] = value; } } bool ICollection<T>.IsReadOnly => false; internal Builder(int capacity) { Requires.Range(capacity >= 0, "capacity"); _elements = new T[capacity]; _count = 0; } internal Builder() : this(8) { } private static void ThrowIndexOutOfRangeException() { throw new IndexOutOfRangeException(); } public ref readonly T ItemRef(int index) { if (index >= Count) { ThrowIndexOutOfRangeException(); } return ref _elements[index]; } public ImmutableArray<T> ToImmutable() { return new ImmutableArray<T>(ToArray()); } public ImmutableArray<T> MoveToImmutable() { if (Capacity != Count) { throw new InvalidOperationException(System.SR.CapacityMustEqualCountOnMove); } T[] elements = _elements; _elements = ImmutableArray<T>.Empty.array; _count = 0; return new ImmutableArray<T>(elements); } public void Clear() { Count = 0; } public void Insert(int index, T item) { Requires.Range(index >= 0 && index <= Count, "index"); EnsureCapacity(Count + 1); if (index < Count) { Array.Copy(_elements, index, _elements, index + 1, Count - index); } _count++; _elements[index] = item; } public void Add(T item) { int num = _count + 1; EnsureCapacity(num); _elements[_count] = item; _count = num; } public void AddRange(IEnumerable<T> items) { Requires.NotNull(items, "items"); if (items.TryGetCount(out var count)) { EnsureCapacity(Count + count); if (items.TryCopyTo(_elements, _count)) { _count += count; return; } } foreach (T item in items) { Add(item); } } public void AddRange(params T[] items) { Requires.NotNull(items, "items"); int count = Count; Count += items.Length; Array.Copy(items, 0, _elements, count, items.Length); } public void AddRange<TDerived>(TDerived[] items) where TDerived : T { Requires.NotNull(items, "items"); int count = Count; Count += items.Length; Array.Copy(items, 0, _elements, count, items.Length); } public void AddRange(T[] items, int length) { Requires.NotNull(items, "items"); Requires.Range(length >= 0 && length <= items.Length, "length"); int count = Count; Count += length; Array.Copy(items, 0, _elements, count, length); } public void AddRange(ImmutableArray<T> items) { AddRange(items, items.Length); } public void AddRange(ImmutableArray<T> items, int length) { Requires.Range(length >= 0, "length"); if (items.array != null) { AddRange(items.array, length); } } public void AddRange<TDerived>(ImmutableArray<TDerived> items) where TDerived : T { if (items.array != null) { this.AddRange<TDerived>(items.array); } } public void AddRange(Builder items) { Requires.NotNull(items, "items"); AddRange(items._elements, items.Count); } public void AddRange<TDerived>(ImmutableArray<TDerived>.Builder items) where TDerived : T { Requires.NotNull(items, "items"); AddRange<TDerived>(items._elements, items.Count); } public bool Remove(T element) { int num = IndexOf(element); if (num >= 0) { RemoveAt(num); return true; } return false; } public void RemoveAt(int index) { Requires.Range(index >= 0 && index < Count, "index"); if (index < Count - 1) { Array.Copy(_elements, index + 1, _elements, index, Count - index - 1); } Count--; } public bool Contains(T item) { return IndexOf(item) >= 0; } public T[] ToArray() { if (Count == 0) { return ImmutableArray<T>.Empty.array; } T[] array = new T[Count]; Array.Copy(_elements, array, Count); return array; } public void CopyTo(T[] array, int index) { Requires.NotNull(array, "array"); Requires.Range(index >= 0 && index + Count <= array.Length, "index"); Array.Copy(_elements, 0, array, index, Count); } private void EnsureCapacity(int capacity) { if (_elements.Length < capacity) { int newSize = Math.Max(_elements.Length * 2, capacity); Array.Resize(ref _elements, newSize); } } public int IndexOf(T item) { return IndexOf(item, 0, _count, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex) { return IndexOf(item, startIndex, Count - startIndex, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count) { return IndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equalityComparer) { if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); Requires.Range(count >= 0 && startIndex + count <= Count, "count"); equalityComparer = equalityComparer ?? EqualityComparer<T>.Default; if (equalityComparer == EqualityComparer<T>.Default) { return Array.IndexOf(_elements, item, startIndex, count); } for (int i = startIndex; i < startIndex + count; i++) { if (equalityComparer.Equals(_elements[i], item)) { return i; } } return -1; } public int LastIndexOf(T item) { if (Count == 0) { return -1; } return LastIndexOf(item, Count - 1, Count, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex) { if (Count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); return LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count) { return LastIndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equalityComparer) { if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); Requires.Range(count >= 0 && startIndex - count + 1 >= 0, "count"); equalityComparer = equalityComparer ?? EqualityComparer<T>.Default; if (equalityComparer == EqualityComparer<T>.Default) { return Array.LastIndexOf(_elements, item, startIndex, count); } for (int num = startIndex; num >= startIndex - count + 1; num--) { if (equalityComparer.Equals(item, _elements[num])) { return num; } } return -1; } public void Reverse() { int num = 0; int num2 = _count - 1; T[] elements = _elements; while (num < num2) { T val = elements[num]; elements[num] = elements[num2]; elements[num2] = val; num++; num2--; } } public void Sort() { if (Count > 1) { Array.Sort(_elements, 0, Count, Comparer<T>.Default); } } public void Sort(Comparison<T> comparison) { Requires.NotNull(comparison, "comparison"); if (Count > 1) { Array.Sort(_elements, 0, _count, Comparer<T>.Create(comparison)); } } public void Sort(IComparer<T>? comparer) { if (Count > 1) { Array.Sort(_elements, 0, _count, comparer); } } public void Sort(int index, int count, IComparer<T>? comparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0 && index + count <= Count, "count"); if (count > 1) { Array.Sort(_elements, index, count, comparer); } } public IEnumerator<T> GetEnumerator() { for (int i = 0; i < Count; i++) { yield return this[i]; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private void AddRange<TDerived>(TDerived[] items, int length) where TDerived : T { EnsureCapacity(Count + length); int count = Count; Count += length; T[] elements = _elements; for (int i = 0; i < length; i++) { elements[count + i] = (T)(object)items[i]; } } } public struct Enumerator { private readonly T[] _array; private int _index; public T Current => _array[_index]; internal Enumerator(T[] array) { _array = array; _index = -1; } public bool MoveNext() { return ++_index < _array.Length; } } private class EnumeratorObject : IEnumerator<T>, IEnumerator, IDisposable { private static readonly IEnumerator<T> s_EmptyEnumerator = new EnumeratorObject(ImmutableArray<T>.Empty.array); private readonly T[] _array; private int _index; public T Current { get { if ((uint)_index < (uint)_array.Length) { return _array[_index]; } throw new InvalidOperationException(); } } object IEnumerator.Current => Current; private EnumeratorObject(T[] array) { _index = -1; _array = array; } public bool MoveNext() { int num = _index + 1; int num2 = _array.Length; if ((uint)num <= (uint)num2) { _index = num; return (uint)num < (uint)num2; } return false; } void IEnumerator.Reset() { _index = -1; } public void Dispose() { } internal static IEnumerator<T> Create(T[] array) { if (array.Length != 0) { return new EnumeratorObject(array); } return s_EmptyEnumerator; } } public static readonly ImmutableArray<T> Empty = new ImmutableArray<T>(new T[0]); [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] internal T[]? array; T IList<T>.this[int index] { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } set { throw new NotSupportedException(); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection<T>.IsReadOnly => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] int ICollection<T>.Count { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] int IReadOnlyCollection<T>.Count { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } T IReadOnlyList<T>.this[int index] { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool IList.IsFixedSize => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool IList.IsReadOnly => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] int ICollection.Count { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { throw new NotSupportedException(); } } object? IList.this[int index] { get { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } set { throw new NotSupportedException(); } } public T this[int index] { [System.Runtime.Versioning.NonVersionable] get { return array[index]; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsEmpty { [System.Runtime.Versioning.NonVersionable] get { return array.Length == 0; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public int Length { [System.Runtime.Versioning.NonVersionable] get { return array.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsDefault => array == null; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsDefaultOrEmpty { get { ImmutableArray<T> immutableArray = this; if (immutableArray.array != null) { return immutableArray.array.Length == 0; } return true; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] Array? IImmutableArray.Array => array; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay { get { ImmutableArray<T> immutableArray = this; if (!immutableArray.IsDefault) { return string.Format(CultureInfo.CurrentCulture, "Length = {0}", immutableArray.Length); } return "Uninitialized"; } } public ReadOnlySpan<T> AsSpan() { return new ReadOnlySpan<T>(array); } public ReadOnlyMemory<T> AsMemory() { return new ReadOnlyMemory<T>(array); } public int IndexOf(T item) { ImmutableArray<T> immutableArray = this; return immutableArray.IndexOf(item, 0, immutableArray.Length, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> immutableArray = this; return immutableArray.IndexOf(item, startIndex, immutableArray.Length - startIndex, equalityComparer); } public int IndexOf(T item, int startIndex) { ImmutableArray<T> immutableArray = this; return immutableArray.IndexOf(item, startIndex, immutableArray.Length - startIndex, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count) { return IndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int IndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < immutableArray.Length, "startIndex"); Requires.Range(count >= 0 && startIndex + count <= immutableArray.Length, "count"); equalityComparer = equalityComparer ?? EqualityComparer<T>.Default; if (equalityComparer == EqualityComparer<T>.Default) { return Array.IndexOf(immutableArray.array, item, startIndex, count); } for (int i = startIndex; i < startIndex + count; i++) { if (equalityComparer.Equals(immutableArray.array[i], item)) { return i; } } return -1; } public int LastIndexOf(T item) { ImmutableArray<T> immutableArray = this; if (immutableArray.Length == 0) { return -1; } return immutableArray.LastIndexOf(item, immutableArray.Length - 1, immutableArray.Length, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex) { ImmutableArray<T> immutableArray = this; if (immutableArray.Length == 0 && startIndex == 0) { return -1; } return immutableArray.LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count) { return LastIndexOf(item, startIndex, count, EqualityComparer<T>.Default); } public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); if (startIndex == 0 && count == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < immutableArray.Length, "startIndex"); Requires.Range(count >= 0 && startIndex - count + 1 >= 0, "count"); equalityComparer = equalityComparer ?? EqualityComparer<T>.Default; if (equalityComparer == EqualityComparer<T>.Default) { return Array.LastIndexOf(immutableArray.array, item, startIndex, count); } for (int num = startIndex; num >= startIndex - count + 1; num--) { if (equalityComparer.Equals(item, immutableArray.array[num])) { return num; } } return -1; } public bool Contains(T item) { return IndexOf(item) >= 0; } public ImmutableArray<T> Insert(int index, T item) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= immutableArray.Length, "index"); if (immutableArray.Length == 0) { return ImmutableArray.Create(item); } T[] array = new T[immutableArray.Length + 1]; array[index] = item; if (index != 0) { Array.Copy(immutableArray.array, array, index); } if (index != immutableArray.Length) { Array.Copy(immutableArray.array, index, array, index + 1, immutableArray.Length - index); } return new ImmutableArray<T>(array); } public ImmutableArray<T> InsertRange(int index, IEnumerable<T> items) { ImmutableArray<T> result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); Requires.NotNull(items, "items"); if (result.Length == 0) { return ImmutableArray.CreateRange(items); } int count = ImmutableExtensions.GetCount(ref items); if (count == 0) { return result; } T[] array = new T[result.Length + count]; if (index != 0) { Array.Copy(result.array, array, index); } if (index != result.Length) { Array.Copy(result.array, index, array, index + count, result.Length - index); } if (!items.TryCopyTo(array, index)) { int num = index; foreach (T item in items) { array[num++] = item; } } return new ImmutableArray<T>(array); } public ImmutableArray<T> InsertRange(int index, ImmutableArray<T> items) { ImmutableArray<T> result = this; result.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); if (result.IsEmpty) { return items; } if (items.IsEmpty) { return result; } T[] array = new T[result.Length + items.Length]; if (index != 0) { Array.Copy(result.array, array, index); } if (index != result.Length) { Array.Copy(result.array, index, array, index + items.Length, result.Length - index); } Array.Copy(items.array, 0, array, index, items.Length); return new ImmutableArray<T>(array); } public ImmutableArray<T> Add(T item) { ImmutableArray<T> immutableArray = this; if (immutableArray.Length == 0) { return ImmutableArray.Create(item); } return immutableArray.Insert(immutableArray.Length, item); } public ImmutableArray<T> AddRange(IEnumerable<T> items) { ImmutableArray<T> immutableArray = this; return immutableArray.InsertRange(immutableArray.Length, items); } public ImmutableArray<T> AddRange(ImmutableArray<T> items) { ImmutableArray<T> immutableArray = this; return immutableArray.InsertRange(immutableArray.Length, items); } public ImmutableArray<T> SetItem(int index, T item) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index < immutableArray.Length, "index"); T[] array = new T[immutableArray.Length]; Array.Copy(immutableArray.array, array, immutableArray.Length); array[index] = item; return new ImmutableArray<T>(array); } public ImmutableArray<T> Replace(T oldValue, T newValue) { return Replace(oldValue, newValue, EqualityComparer<T>.Default); } public ImmutableArray<T> Replace(T oldValue, T newValue, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> immutableArray = this; int num = immutableArray.IndexOf(oldValue, 0, immutableArray.Length, equalityComparer); if (num < 0) { throw new ArgumentException(System.SR.CannotFindOldValue, "oldValue"); } return immutableArray.SetItem(num, newValue); } public ImmutableArray<T> Remove(T item) { return Remove(item, EqualityComparer<T>.Default); } public ImmutableArray<T> Remove(T item, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> result = this; result.ThrowNullRefIfNotInitialized(); int num = result.IndexOf(item, 0, result.Length, equalityComparer); if (num >= 0) { return result.RemoveAt(num); } return result; } public ImmutableArray<T> RemoveAt(int index) { return RemoveRange(index, 1); } public ImmutableArray<T> RemoveRange(int index, int length) { ImmutableArray<T> result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); Requires.Range(length >= 0 && index + length <= result.Length, "length"); if (length == 0) { return result; } T[] array = new T[result.Length - length]; Array.Copy(result.array, array, index); Array.Copy(result.array, index + length, array, index, result.Length - index - length); return new ImmutableArray<T>(array); } public ImmutableArray<T> RemoveRange(IEnumerable<T> items) { return RemoveRange(items, EqualityComparer<T>.Default); } public ImmutableArray<T> RemoveRange(IEnumerable<T> items, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(items, "items"); SortedSet<int> sortedSet = new SortedSet<int>(); foreach (T item in items) { int num = immutableArray.IndexOf(item, 0, immutableArray.Length, equalityComparer); while (num >= 0 && !sortedSet.Add(num) && num + 1 < immutableArray.Length) { num = immutableArray.IndexOf(item, num + 1, equalityComparer); } } return immutableArray.RemoveAtRange(sortedSet); } public ImmutableArray<T> RemoveRange(ImmutableArray<T> items) { return RemoveRange(items, EqualityComparer<T>.Default); } public ImmutableArray<T> RemoveRange(ImmutableArray<T> items, IEqualityComparer<T>? equalityComparer) { ImmutableArray<T> result = this; Requires.NotNull(items.array, "items"); if (items.IsEmpty) { result.ThrowNullRefIfNotInitialized(); return result; } if (items.Length == 1) { return result.Remove(items[0], equalityComparer); } return result.RemoveRange(items.array, equalityComparer); } public ImmutableArray<T> RemoveAll(Predicate<T> match) { ImmutableArray<T> result = this; result.ThrowNullRefIfNotInitialized(); Requires.NotNull(match, "match"); if (result.IsEmpty) { return result; } List<int> list = null; for (int i = 0; i < result.array.Length; i++) { if (match(result.array[i])) { if (list == null) { list = new List<int>(); } list.Add(i); } } if (list == null) { return result; } return result.RemoveAtRange(list); } public ImmutableArray<T> Clear() { return Empty; } public ImmutableArray<T> Sort() { ImmutableArray<T> immutableArray = this; return immutableArray.Sort(0, immutableArray.Length, Comparer<T>.Default); } public ImmutableArray<T> Sort(Comparison<T> comparison) { Requires.NotNull(comparison, "comparison"); ImmutableArray<T> immutableArray = this; return immutableArray.Sort(Comparer<T>.Create(comparison)); } public ImmutableArray<T> Sort(IComparer<T>? comparer) { ImmutableArray<T> immutableArray = this; return immutableArray.Sort(0, immutableArray.Length, comparer); } public ImmutableArray<T> Sort(int index, int count, IComparer<T>? comparer) { ImmutableArray<T> result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0, "index"); Requires.Range(count >= 0 && index + count <= result.Length, "count"); if (count > 1) { if (comparer == null) { comparer = Comparer<T>.Default; } bool flag = false; for (int i = index + 1; i < index + count; i++) { if (comparer.Compare(result.array[i - 1], result.array[i]) > 0) { flag = true; break; } } if (flag) { T[] array = new T[result.Length]; Array.Copy(result.array, array, result.Length); Array.Sort(array, index, count, comparer); return new ImmutableArray<T>(array); } } return result; } public IEnumerable<TResult> OfType<TResult>() { ImmutableArray<T> immutableArray = this; if (immutableArray.array == null || immutableArray.array.Length == 0) { return Enumerable.Empty<TResult>(); } return immutableArray.array.OfType<TResult>(); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } IImmutableList<T> IImmutableList<T>.Clear() { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Clear(); } IImmutableList<T> IImmutableList<T>.Add(T value) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Add(value); } IImmutableList<T> IImmutableList<T>.AddRange(IEnumerable<T> items) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.AddRange(items); } IImmutableList<T> IImmutableList<T>.Insert(int index, T element) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Insert(index, element); } IImmutableList<T> IImmutableList<T>.InsertRange(int index, IEnumerable<T> items) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.InsertRange(index, items); } IImmutableList<T> IImmutableList<T>.Remove(T value, IEqualityComparer<T> equalityComparer) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Remove(value, equalityComparer); } IImmutableList<T> IImmutableList<T>.RemoveAll(Predicate<T> match) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveAll(match); } IImmutableList<T> IImmutableList<T>.RemoveRange(IEnumerable<T> items, IEqualityComparer<T> equalityComparer) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveRange(items, equalityComparer); } IImmutableList<T> IImmutableList<T>.RemoveRange(int index, int count) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveRange(index, count); } IImmutableList<T> IImmutableList<T>.RemoveAt(int index) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveAt(index); } IImmutableList<T> IImmutableList<T>.SetItem(int index, T value) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.SetItem(index, value); } IImmutableList<T> IImmutableList<T>.Replace(T oldValue, T newValue, IEqualityComparer<T> equalityComparer) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Replace(oldValue, newValue, equalityComparer); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Contains((T)value); } int IList.IndexOf(object value) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.IndexOf((T)value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int index) { ImmutableArray<T> immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); Array.Copy(immutableArray.array, 0, array, index, immutableArray.Length); } bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) { ImmutableArray<T> immutableArray = this; Array array = other as Array; if (array == null && other is IImmutableArray immutableArray2) { array = immutableArray2.Array; if (immutableArray.array == null && array == null) { return true; } if (immutableArray.array == null) { return false; } } IStructuralEquatable structuralEquatable = immutableArray.array; return structuralEquatable.Equals(array, comparer); } int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { ImmutableArray<T> immutableArray = this; return ((IStructuralEquatable)immutableArray.array)?.GetHashCode(comparer) ?? immutableArray.GetHashCode(); } int IStructuralComparable.CompareTo(object other, IComparer comparer) { ImmutableArray<T> immutableArray = this; Array array = other as Array; if (array == null && other is IImmutableArray immutableArray2) { array = immutableArray2.Array; if (immutableArray.array == null && array == null) { return 0; } if ((immutableArray.array == null) ^ (array == null)) { throw new ArgumentException(S