// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
namespace CommunityToolkit.HighPerformance;
///
/// Helpers for working with the type.
///
public static class ArrayPoolExtensions
{
///
/// Changes the number of elements of a rented one-dimensional array to the specified new size.
///
/// The type of items into the target array to resize.
/// The target instance to use to resize the array.
/// The rented array to resize, or to create a new array.
/// The size of the new array.
/// Indicates whether the contents of the array should be cleared before reuse.
/// Thrown when is less than 0.
/// When this method returns, the caller must not use any references to the old array anymore.
public static void Resize(this ArrayPool pool, [NotNull] ref T[]? array, int newSize, bool clearArray = false)
{
// If the old array is null, just create a new one with the requested size
if (array is null)
{
array = pool.Rent(newSize);
return;
}
// If the new size is the same as the current size, do nothing
if (array.Length == newSize)
{
return;
}
// Rent a new array with the specified size, and copy as many items from the current array
// as possible to the new array. This mirrors the behavior of the Array.Resize API from
// the BCL: if the new size is greater than the length of the current array, copy all the
// items from the original array into the new one. Otherwise, copy as many items as possible,
// until the new array is completely filled, and ignore the remaining items in the first array.
T[] newArray = pool.Rent(newSize);
int itemsToCopy = Math.Min(array.Length, newSize);
Array.Copy(array, 0, newArray, 0, itemsToCopy);
pool.Return(array, clearArray);
array = newArray;
}
///
/// Ensures that when the method returns is not null and is at least in length.
/// Contents of are not copied if a new array is rented.
///
/// The type of items into the target array given as input.
/// The target instance used to rent and/or return the array.
/// The rented array to ensure capacity for, or to rent a new array.
/// The minimum length of when the method returns.
/// Indicates whether the contents of the array should be cleared if returned to the pool.
/// Thrown when is less than 0.
/// When this method returns, the caller must not use any references to the old array anymore.
public static void EnsureCapacity(this ArrayPool pool, [NotNull] ref T[]? array, int capacity, bool clearArray = false)
{
if (capacity < 0)
{
ThrowArgumentOutOfRangeExceptionForNegativeArrayCapacity();
}
if (array is null)
{
array = pool.Rent(capacity);
}
else if (array.Length < capacity)
{
// Ensure rent succeeds before returning the original array to the pool
T[] newArray = pool.Rent(capacity);
pool.Return(array, clearArray);
array = newArray;
}
}
///
/// Throws an when the "capacity" parameter is negative.
///
private static void ThrowArgumentOutOfRangeExceptionForNegativeArrayCapacity()
{
throw new ArgumentOutOfRangeException("capacity", "The array capacity must be a positive number.");
}
}