Skip to content

Commit 3ade47b

Browse files
authored
Merge pull request #1488 from Unity-Technologies/unity-master-aot-friendly-linq
Use An AOT-friendly Linq implementation
2 parents 972b407 + 4126e50 commit 3ade47b

7 files changed

+173
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../external/corefx/src/System.Linq/src/System/Linq/*.cs

mcs/class/System.Core/linux_unityaot_System.Core.dll.sources

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ System.Security.Cryptography/SHA512Cng.cs
1313
../referencesource/System.Core/System/Security/Cryptography/AesManaged.cs
1414
../referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs
1515
../referencesource/System.Core/System/Security/Cryptography/ECKeyXmlFormat.cs
16+
17+
../referencesource/System.Core/System/Linq/Enumerable.cs
18+
corefx/SR.cs
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../external/corefx/src/System.Linq/src/System/Linq/*.cs

mcs/class/System.Core/macos_unityaot_System.Core.dll.sources

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ System.Security.Cryptography/SHA512Cng.cs
1313
../referencesource/System.Core/System/Security/Cryptography/AesManaged.cs
1414
../referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs
1515
../referencesource/System.Core/System/Security/Cryptography/ECKeyXmlFormat.cs
16+
17+
../referencesource/System.Core/System/Linq/Enumerable.cs
18+
corefx/SR.cs
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
../../../external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.Unix.cs
22
../../../external/corefx/src/Common/src/Interop/Unix/System.Native/Interop.GetDomainSocketSizes.cs
33
../../../external/corefx/src/Common/src/Interop/Unix/Interop.Libraries.cs
4+
../../../external/corefx/src/System.Linq/src/System/Linq/*.cs
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
#include orbis_System.Core.dll.sources
22

33
../../../external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.Windows.cs
4+
../referencesource/System.Core/System/Linq/Enumerable.cs
5+
corefx/SR.cs

mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,7 +2776,11 @@ public string Empty
27762776
{
27772777
get
27782778
{
2779+
#if UNITY_AOT
2780+
return SR.EmptyEnumerable;
2781+
#else
27792782
return Strings.EmptyEnumerable;
2783+
#endif
27802784
}
27812785
}
27822786
}
@@ -2829,4 +2833,162 @@ public object[] Items
28292833
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
28302834
private int count;
28312835
}
2836+
2837+
2838+
#if UNITY_AOT
2839+
// <summary>
2840+
/// An iterator that can produce an array or <see cref="List{TElement}"/> through an optimized path.
2841+
/// </summary>
2842+
internal interface IIListProvider<TElement> : IEnumerable<TElement>
2843+
{
2844+
/// <summary>
2845+
/// Produce an array of the sequence through an optimized path.
2846+
/// </summary>
2847+
/// <returns>The array.</returns>
2848+
TElement[] ToArray();
2849+
2850+
/// <summary>
2851+
/// Produce a <see cref="List{TElement}"/> of the sequence through an optimized path.
2852+
/// </summary>
2853+
/// <returns>The <see cref="List{TElement}"/>.</returns>
2854+
List<TElement> ToList();
2855+
2856+
/// <summary>
2857+
/// Returns the count of elements in the sequence.
2858+
/// </summary>
2859+
/// <param name="onlyIfCheap">If true then the count should only be calculated if doing
2860+
/// so is quick (sure or likely to be constant time), otherwise -1 should be returned.</param>
2861+
/// <returns>The number of elements.</returns>
2862+
int GetCount(bool onlyIfCheap);
2863+
}
2864+
2865+
internal static partial class Error
2866+
{
2867+
internal static Exception ArgumentNull(string s) => new ArgumentNullException(s);
2868+
2869+
internal static Exception ArgumentOutOfRange(string s) => new ArgumentOutOfRangeException(s);
2870+
2871+
internal static Exception MoreThanOneElement() => new InvalidOperationException(SR.MoreThanOneElement);
2872+
2873+
internal static Exception MoreThanOneMatch() => new InvalidOperationException(SR.MoreThanOneMatch);
2874+
2875+
internal static Exception NoElements() => new InvalidOperationException(SR.NoElements);
2876+
2877+
internal static Exception NoMatch() => new InvalidOperationException(SR.NoMatch);
2878+
2879+
internal static Exception NotSupported() => new NotSupportedException();
2880+
}
2881+
2882+
public static partial class Enumerable
2883+
{
2884+
public static IEnumerable<TSource> SkipLast<TSource>(this IEnumerable<TSource> source, int count)
2885+
{
2886+
if (source == null)
2887+
{
2888+
throw Error.ArgumentNull(nameof(source));
2889+
}
2890+
2891+
if (count <= 0)
2892+
{
2893+
return source.Skip(0);
2894+
}
2895+
2896+
return SkipLastIterator(source, count);
2897+
}
2898+
2899+
private static IEnumerable<TSource> SkipLastIterator<TSource>(IEnumerable<TSource> source, int count)
2900+
{
2901+
var queue = new Queue<TSource>();
2902+
2903+
using (IEnumerator<TSource> e = source.GetEnumerator())
2904+
{
2905+
while (e.MoveNext())
2906+
{
2907+
if (queue.Count == count)
2908+
{
2909+
do
2910+
{
2911+
yield return queue.Dequeue();
2912+
queue.Enqueue(e.Current);
2913+
}
2914+
while (e.MoveNext());
2915+
break;
2916+
}
2917+
else
2918+
{
2919+
queue.Enqueue(e.Current);
2920+
}
2921+
}
2922+
}
2923+
}
2924+
2925+
public static IEnumerable<TSource> TakeLast<TSource>(this IEnumerable<TSource> source, int count)
2926+
{
2927+
if (source == null)
2928+
{
2929+
throw Error.ArgumentNull(nameof(source));
2930+
}
2931+
2932+
if (count <= 0)
2933+
{
2934+
return EmptyEnumerable<TSource>.Instance;
2935+
}
2936+
2937+
return TakeLastIterator(source, count);
2938+
}
2939+
2940+
private static IEnumerable<TSource> TakeLastIterator<TSource>(IEnumerable<TSource> source, int count)
2941+
{
2942+
Queue<TSource> queue;
2943+
2944+
using (IEnumerator<TSource> e = source.GetEnumerator())
2945+
{
2946+
if (!e.MoveNext())
2947+
{
2948+
yield break;
2949+
}
2950+
2951+
queue = new Queue<TSource>();
2952+
queue.Enqueue(e.Current);
2953+
2954+
while (e.MoveNext())
2955+
{
2956+
if (queue.Count < count)
2957+
{
2958+
queue.Enqueue(e.Current);
2959+
}
2960+
else
2961+
{
2962+
do
2963+
{
2964+
queue.Dequeue();
2965+
queue.Enqueue(e.Current);
2966+
}
2967+
while (e.MoveNext());
2968+
break;
2969+
}
2970+
}
2971+
}
2972+
2973+
do
2974+
{
2975+
yield return queue.Dequeue();
2976+
}
2977+
while (queue.Count > 0);
2978+
}
2979+
2980+
public static HashSet<TSource> ToHashSet<TSource>(this IEnumerable<TSource> source) => source.ToHashSet(comparer: null);
2981+
2982+
public static HashSet<TSource> ToHashSet<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
2983+
{
2984+
if (source == null)
2985+
{
2986+
throw Error.ArgumentNull(nameof(source));
2987+
}
2988+
2989+
// Don't pre-allocate based on knowledge of size, as potentially many elements will be dropped.
2990+
return new HashSet<TSource>(source, comparer);
2991+
}
2992+
}
2993+
#endif
28322994
}

0 commit comments

Comments
 (0)