From d8e8b3fe4d5867a9a4294395e593c64b136dd414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Tue, 9 Apr 2019 10:12:50 -0700 Subject: [PATCH] Add SelectAsArray, DangerousCreateFromUnderlyingArray (#34559) * Add SelectAsArray, DangerousCreateFromUnderlyingArray * Add SerializableBytes.ToImmutableArray --- ...ts.cs => ImmutableArrayExtensionsTests.cs} | 24 ++++++++++++- .../Collections/ImmutableArrayExtensions.cs | 35 +++++++++++++++++++ .../Portable/Utilities/SerializableBytes.cs | 7 ++++ 3 files changed, 65 insertions(+), 1 deletion(-) rename src/Compilers/Core/CodeAnalysisTest/Collections/{ReadOnlyArrayTests.cs => ImmutableArrayExtensionsTests.cs} (94%) diff --git a/src/Compilers/Core/CodeAnalysisTest/Collections/ReadOnlyArrayTests.cs b/src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableArrayExtensionsTests.cs similarity index 94% rename from src/Compilers/Core/CodeAnalysisTest/Collections/ReadOnlyArrayTests.cs rename to src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableArrayExtensionsTests.cs index 42caa5f284b..f23c3ad71d3 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Collections/ReadOnlyArrayTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableArrayExtensionsTests.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.UnitTests.Collections { - public class ReadOnlyArrayTests + public class ImmutableArrayExtensionsTests { [Fact] public void CreateFrom() @@ -365,6 +365,28 @@ public void SelectAsArray() AssertEx.Equal(new[] { 10, 20, 30, 40, 50 }, ImmutableArray.Create(1, 2, 3, 4, 5).SelectAsArray(i => 10 * i)); } + [Fact] + public void SelectAsArrayWithPredicate() + { + Assert.Empty(ImmutableArray.Empty.SelectAsArray(item => throw null, item => throw null)); + + var array = ImmutableArray.Create(1, 2, 3, 4, 5); + AssertEx.Equal(new[] { 2, 3, 4, 5, 6 }, array.SelectAsArray(item => true, item => item + 1)); + AssertEx.Equal(new[] { 3, 5 }, array.SelectAsArray(item => item % 2 == 0, item => item + 1)); + Assert.Empty(array.SelectAsArray(item => item < 0, item => throw null)); + } + + [Fact] + public void DangerousCreateFromUnderlyingArray() + { + var array = new[] { 1, 2, 3, 4 }; + var copy = array; + var immutable = ImmutableArrayExtensions.DangerousCreateFromUnderlyingArray(ref copy); + Assert.Null(copy); + AssertEx.Equal(array, immutable); + Assert.Same(array, ImmutableArrayExtensions.DangerousGetUnderlyingArray(immutable)); + } + [Fact] public void ZipAsArray() { diff --git a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs index b0272a3c4ca..33a185f9f19 100644 --- a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs @@ -188,6 +188,34 @@ public static ImmutableArray ToImmutable(this MemoryStream stream) } } + /// + /// Maps a subset of immutable array to another immutable array. + /// + /// Type of the source array items + /// Type of the transformed array items + /// The array to transform + /// The condition to use for filtering the array content. + /// A transform function to apply to each element that is not filtered out by . + /// If the items's length is 0, this will return an empty immutable array. + public static ImmutableArray SelectAsArray(this ImmutableArray array, Func predicate, Func selector) + { + if (array.Length == 0) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + foreach (var item in array) + { + if (predicate(item)) + { + builder.Add(selector(item)); + } + } + + return builder.ToImmutableAndFree(); + } + /// /// Zips two immutable arrays together through a mapping function, producing another immutable array. /// @@ -513,6 +541,13 @@ internal static T[] DangerousGetUnderlyingArray(this ImmutableArray array) internal static ReadOnlySpan AsSpan(this ImmutableArray array) => array.DangerousGetUnderlyingArray(); + internal static ImmutableArray DangerousCreateFromUnderlyingArray(ref T[] array) + { + var proxy = new ImmutableArrayProxy { MutableArray = array }; + array = null; + return Unsafe.As, ImmutableArray>(ref proxy); + } + internal static Dictionary> ToDictionary(this ImmutableArray items, Func keySelector, IEqualityComparer comparer = null) { if (items.Length == 1) diff --git a/src/Workspaces/Core/Portable/Utilities/SerializableBytes.cs b/src/Workspaces/Core/Portable/Utilities/SerializableBytes.cs index be4d43faa45..7c6d0f69bdf 100644 --- a/src/Workspaces/Core/Portable/Utilities/SerializableBytes.cs +++ b/src/Workspaces/Core/Portable/Utilities/SerializableBytes.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -244,6 +245,12 @@ public byte[] ToArray() return array; } + public ImmutableArray ToImmutableArray() + { + var array = ToArray(); + return ImmutableArrayExtensions.DangerousCreateFromUnderlyingArray(ref array); + } + protected int CurrentChunkIndex { get { return GetChunkIndex(this.position); } } protected int CurrentChunkOffset { get { return GetChunkOffset(this.position); } } -- GitLab