File: System\Numerics\BigInteger.RentedBuffer.cs
Web Access
Project: src\src\libraries\System.Runtime.Numerics\src\System.Runtime.Numerics.csproj (System.Runtime.Numerics)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Buffers;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
 
namespace System.Numerics
{
    public readonly partial struct BigInteger
    {
        /// <summary>
        /// Provides temporary buffer management for <see cref="BigInteger"/> operations, using either stack-allocated inline storage or pooled arrays depending on size requirements.
        /// </summary>
        internal ref struct RentedBuffer : IDisposable
        {
            private const int InlineBufferSize = 64;
            private InlineBuffer _inline;
            private nuint[]? _array;
 
            /// <summary>
            /// Creates a buffer of the specified size and returns a span to it.
            /// </summary>
            /// <param name="size">The number of <see cref="nuint"/> elements required in the buffer.</param>
            /// <param name="rentedBuffer">When this method returns, contains the <see cref="RentedBuffer"/> instance that manages the buffer lifetime. This parameter is treated as uninitialized.</param>
            /// <returns>A span of <see cref="nuint"/> elements with the requested size, initialized to zero.</returns>
            public static Span<nuint> Create(int size, [UnscopedRef] out RentedBuffer rentedBuffer)
            {
                if (size <= InlineBufferSize)
                {
                    rentedBuffer = default;
                    return ((Span<nuint>)rentedBuffer._inline)[..size];
                }
                else
                {
                    nuint[] array = ArrayPool<nuint>.Shared.Rent(size);
 
                    rentedBuffer._array = array;
                    Unsafe.SkipInit(out rentedBuffer._inline);
 
                    Span<nuint> resultBuffer = array.AsSpan(0, size);
                    resultBuffer.Clear();
 
                    return resultBuffer;
                }
            }
 
            /// <summary>
            /// Returns the rented array to the pool, if one was allocated.
            /// </summary>
            /// <remarks>
            /// This method returns the underlying array to <see cref="ArrayPool{T}.Shared"/> if it was rented.
            /// If inline storage was used, this method does nothing.
            /// </remarks>
            public void Dispose()
            {
                nuint[]? array = _array;
                if (array is not null)
                {
                    _array = null;
                    ArrayPool<nuint>.Shared.Return(array);
                }
            }
 
            [InlineArray(InlineBufferSize)]
            private struct InlineBuffer
            {
                private nuint _value0;
            }
        }
    }
}