Skip to content

Commit bcf880c

Browse files
authored
Add ImmutableCollectionsMarshal.AsMemory (#112177)
1 parent 99d48c2 commit bcf880c

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs

+1
Original file line numberDiff line numberDiff line change
@@ -1302,5 +1302,6 @@ public static partial class ImmutableCollectionsMarshal
13021302
{
13031303
public static System.Collections.Immutable.ImmutableArray<T> AsImmutableArray<T>(T[]? array) { throw null; }
13041304
public static T[]? AsArray<T>(System.Collections.Immutable.ImmutableArray<T> array) { throw null; }
1305+
public static System.Memory<T> AsMemory<T>(System.Collections.Immutable.ImmutableArray<T>.Builder? builder) { throw null; }
13051306
}
13061307
}

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs

+3
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,9 @@ private void RemoveAtRange(ICollection<int> indicesToRemove)
10951095

10961096
_count -= indicesToRemove.Count;
10971097
}
1098+
1099+
/// <summary>Gets a <see cref="Memory{T}"/> for the filled portion of the backing array.</summary>
1100+
internal Memory<T> AsMemory() => new(_elements, 0, _count);
10981101
}
10991102
}
11001103
}

src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Collections;
45
using System.Collections.Immutable;
56

67
namespace System.Runtime.InteropServices
@@ -54,5 +55,19 @@ public static ImmutableArray<T> AsImmutableArray<T>(T[]? array)
5455
{
5556
return array.array;
5657
}
58+
59+
/// <summary>
60+
/// Gets a <see cref="Memory{T}"/> for the <typeparamref name="T"/> array underlying an input <see cref="ImmutableArray{T}.Builder"/>.
61+
/// </summary>
62+
/// <typeparam name="T">The type of elements in the input <see cref="ImmutableArray{T}.Builder"/> value.</typeparam>
63+
/// <param name="builder">The builder.</param>
64+
/// <returns>
65+
/// A <see cref="Memory{T}"/> for the filled portion of <typeparamref name="T"/> array underlying
66+
/// the input <see cref="ImmutableArray{T}.Builder"/>.
67+
/// </returns>
68+
public static Memory<T> AsMemory<T>(ImmutableArray<T>.Builder? builder)
69+
{
70+
return builder?.AsMemory() ?? default;
71+
}
5772
}
5873
}

src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs

+53
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,59 @@ static void Test<T>()
135135
Test<UnmanagedCustomStruct?>();
136136
}
137137

138+
[Fact]
139+
public void AsMemoryFromNullBuilder()
140+
{
141+
Memory<Guid> m = ImmutableCollectionsMarshal.AsMemory<Guid>(null);
142+
Assert.True(m.IsEmpty);
143+
Assert.True(MemoryMarshal.TryGetArray(m, out ArraySegment<Guid> segment));
144+
Assert.NotNull(segment.Array);
145+
Assert.Equal(0, segment.Array.Length);
146+
Assert.Equal(0, segment.Offset);
147+
Assert.Equal(0, segment.Count);
148+
}
149+
150+
[Fact]
151+
public void AsMemoryFromEmptyBuilder()
152+
{
153+
Memory<string> m = ImmutableCollectionsMarshal.AsMemory(ImmutableArray.CreateBuilder<string>());
154+
Assert.True(m.IsEmpty);
155+
Assert.True(MemoryMarshal.TryGetArray(m, out ArraySegment<string> segment));
156+
Assert.NotNull(segment.Array);
157+
Assert.Equal(0, segment.Offset);
158+
Assert.Equal(0, segment.Count);
159+
}
160+
161+
[Fact]
162+
public void AsMemoryFromNonEmptyBuilder()
163+
{
164+
ImmutableArray<int>.Builder builder = ImmutableArray.CreateBuilder<int>(1);
165+
builder.Add(42);
166+
builder.Add(43);
167+
builder.Add(44);
168+
169+
Memory<int> m1 = ImmutableCollectionsMarshal.AsMemory(builder);
170+
Assert.Equal(3, m1.Length);
171+
172+
Assert.True(MemoryMarshal.TryGetArray(m1, out ArraySegment<int> segment1));
173+
Assert.NotNull(segment1.Array);
174+
Assert.Equal(0, segment1.Offset);
175+
Assert.Equal(3, segment1.Count);
176+
177+
Span<int> span = m1.Span;
178+
Assert.Equal(42, span[0]);
179+
Assert.Equal(43, span[1]);
180+
Assert.Equal(44, span[2]);
181+
182+
Memory<int> m2 = ImmutableCollectionsMarshal.AsMemory(builder);
183+
Assert.Equal(3, m2.Length);
184+
Assert.True(MemoryMarshal.TryGetArray(m2, out ArraySegment<int> segment2));
185+
186+
Assert.Same(segment1.Array, segment2.Array);
187+
Assert.Equal(segment1.Offset, segment2.Offset);
188+
Assert.Equal(segment1.Count, segment2.Count);
189+
}
190+
138191
public class CustomClass
139192
{
140193
public object Foo;

0 commit comments

Comments
 (0)