Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ImmutableArray<T>.Builder.DrainToImmutable() #79385

Merged
merged 3 commits into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ public void CopyTo(T[] array, int index) { }
public void CopyTo(T[] destination) { throw null; }
public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { throw null; }
public void CopyTo(System.Span<T> destination) { }
public System.Collections.Immutable.ImmutableArray<T> DrainToImmutable() { throw null; }
public System.Collections.Generic.IEnumerator<T> GetEnumerator() { throw null; }
public int IndexOf(T item) { throw null; }
public int IndexOf(T item, int startIndex) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,33 @@ public ImmutableArray<T> MoveToImmutable()
return new ImmutableArray<T>(temp);
}

/// <summary>
/// Returns the current contents as an <see cref="ImmutableArray{T}"/> and sets the collection to a zero length array.
/// </summary>
/// <remarks>
/// If <see cref="Capacity"/> equals <see cref="Count"/>, the internal array will be extracted
/// as an <see cref="ImmutableArray{T}"/> without copying the contents. Otherwise, the contents
/// will be copied into a new array. The collection will then be set to a zero length array.
/// </remarks>
/// <returns>An immutable array.</returns>
public ImmutableArray<T> DrainToImmutable()
{
ImmutableArray<T> result;

if (Capacity == Count)
{
result = MoveToImmutable();
}
else
{
result = ToImmutable();
_elements = ImmutableArray<T>.Empty.array!;
stephentoub marked this conversation as resolved.
Show resolved Hide resolved
_count = 0;
}

return result;
jeffhandley marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
/// Removes all items from the <see cref="ICollection{T}"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,107 @@ public void MoveToImmutableAddRemoveAddToCapacity()
Assert.Equal(new[] { 0, 1, 2 }, builder.MoveToImmutable());
}

[Fact]
public void DrainToImmutableAtCapacity()
{
var builder = CreateBuilderWithCount<string>(2);
Assert.Equal(2, builder.Count);
Assert.Equal(2, builder.Capacity);
builder[1] = "b";
builder[0] = "a";
var array = builder.DrainToImmutable();
Assert.Equal(new[] { "a", "b" }, array);
Assert.Equal(0, builder.Count);
Assert.Equal(0, builder.Capacity);
}

[Fact]
public void DrainToImmutablePartialFill()
{
var builder = ImmutableArray.CreateBuilder<int>(4);
builder.Add(42);
builder.Add(13);
Assert.Equal(4, builder.Capacity);
Assert.Equal(2, builder.Count);
var array = builder.DrainToImmutable();
Assert.Equal(new[] { 42, 13 }, array);
Assert.Equal(0, builder.Capacity);
Assert.Equal(0, builder.Count);
}

[Fact]
public void DrainToImmutablePartialFillWithCountUpdate()
{
var builder = ImmutableArray.CreateBuilder<int>(4);
builder.Add(42);
builder.Add(13);
Assert.Equal(4, builder.Capacity);
Assert.Equal(2, builder.Count);
builder.Count = builder.Capacity;
var array = builder.DrainToImmutable();
Assert.Equal(new[] { 42, 13, 0, 0 }, array);
Assert.Equal(0, builder.Capacity);
Assert.Equal(0, builder.Count);
}

[Fact]
public void DrainToImmutableRepeat()
{
var builder = CreateBuilderWithCount<string>(2);
builder[0] = "a";
builder[1] = "b";
var array1 = builder.DrainToImmutable();
var array2 = builder.DrainToImmutable();
Assert.Equal(new[] { "a", "b" }, array1);
Assert.Equal(0, array2.Length);
}

[Fact]
public void DrainToImmutableThenUse()
{
var builder = CreateBuilderWithCount<string>(2);
Assert.Equal(2, builder.DrainToImmutable().Length);
Assert.Equal(0, builder.Capacity);
builder.Add("a");
builder.Add("b");
Assert.Equal(2, builder.Count);
Assert.True(builder.Capacity >= 2);
Assert.Equal(new[] { "a", "b" }, builder.DrainToImmutable());
}

[Fact]
public void DrainToImmutableAfterClear()
{
var builder = CreateBuilderWithCount<string>(2);
builder[0] = "a";
builder[1] = "b";
builder.Clear();
var array = builder.DrainToImmutable();
Assert.Equal(0, array.Length);
Assert.Equal(0, builder.Capacity);
Assert.Equal(0, builder.Count);
}

[Fact]
public void DrainToImmutableAtCapacityClearsCollection()
{
var builder = CreateBuilderWithCount<int>(2);
builder.AddRange(1, 2);
builder.DrainToImmutable();
builder.Count = 4;
Assert.Equal(new[] { 0, 0, 0, 0 }, builder.DrainToImmutable());
}

[Fact]
public void DrainToImmutablePartialFillClearsCollection()
{
var builder = CreateBuilderWithCount<int>(4);
builder.AddRange(1, 2);
builder.DrainToImmutable();
builder.Count = 6;
Assert.Equal(new[] { 0, 0, 0, 0, 0, 0 }, builder.DrainToImmutable());
}
jeffhandley marked this conversation as resolved.
Show resolved Hide resolved

[Fact]
public void CapacitySetToZero()
{
Expand Down