diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs index 24f0119fcc29cd..5df454fe3b3bf7 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs @@ -1302,5 +1302,6 @@ public static partial class ImmutableCollectionsMarshal { public static System.Collections.Immutable.ImmutableArray AsImmutableArray(T[]? array) { throw null; } public static T[]? AsArray(System.Collections.Immutable.ImmutableArray array) { throw null; } + public static System.Memory AsMemory(System.Collections.Immutable.ImmutableArray.Builder? builder) { throw null; } } } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs index e6e36c81339bd8..9f596e8f7578a7 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs @@ -1095,6 +1095,9 @@ private void RemoveAtRange(ICollection indicesToRemove) _count -= indicesToRemove.Count; } + + /// Gets a for the filled portion of the backing array. + internal Memory AsMemory() => new(_elements, 0, _count); } } } diff --git a/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs b/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs index 737a3a862a2d47..cb751a4283df5e 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Immutable; namespace System.Runtime.InteropServices @@ -54,5 +55,19 @@ public static ImmutableArray AsImmutableArray(T[]? array) { return array.array; } + + /// + /// Gets a for the array underlying an input . + /// + /// The type of elements in the input value. + /// The builder. + /// + /// A for the filled portion of array underlying + /// the input . + /// + public static Memory AsMemory(ImmutableArray.Builder? builder) + { + return builder?.AsMemory() ?? default; + } } } diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs index 76ed476ee571ef..6fc463bfd9268c 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs @@ -135,6 +135,59 @@ static void Test() Test(); } + [Fact] + public void AsMemoryFromNullBuilder() + { + Memory m = ImmutableCollectionsMarshal.AsMemory(null); + Assert.True(m.IsEmpty); + Assert.True(MemoryMarshal.TryGetArray(m, out ArraySegment segment)); + Assert.NotNull(segment.Array); + Assert.Equal(0, segment.Array.Length); + Assert.Equal(0, segment.Offset); + Assert.Equal(0, segment.Count); + } + + [Fact] + public void AsMemoryFromEmptyBuilder() + { + Memory m = ImmutableCollectionsMarshal.AsMemory(ImmutableArray.CreateBuilder()); + Assert.True(m.IsEmpty); + Assert.True(MemoryMarshal.TryGetArray(m, out ArraySegment segment)); + Assert.NotNull(segment.Array); + Assert.Equal(0, segment.Offset); + Assert.Equal(0, segment.Count); + } + + [Fact] + public void AsMemoryFromNonEmptyBuilder() + { + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(1); + builder.Add(42); + builder.Add(43); + builder.Add(44); + + Memory m1 = ImmutableCollectionsMarshal.AsMemory(builder); + Assert.Equal(3, m1.Length); + + Assert.True(MemoryMarshal.TryGetArray(m1, out ArraySegment segment1)); + Assert.NotNull(segment1.Array); + Assert.Equal(0, segment1.Offset); + Assert.Equal(3, segment1.Count); + + Span span = m1.Span; + Assert.Equal(42, span[0]); + Assert.Equal(43, span[1]); + Assert.Equal(44, span[2]); + + Memory m2 = ImmutableCollectionsMarshal.AsMemory(builder); + Assert.Equal(3, m2.Length); + Assert.True(MemoryMarshal.TryGetArray(m2, out ArraySegment segment2)); + + Assert.Same(segment1.Array, segment2.Array); + Assert.Equal(segment1.Offset, segment2.Offset); + Assert.Equal(segment1.Count, segment2.Count); + } + public class CustomClass { public object Foo;