// 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."); } }