using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace View_by_Distance.ThumbHash.Models;

internal readonly ref struct SpanOwner<T>
{

    private static ArrayPool<T> DefaultPool
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get => ArrayPool<T>.Shared;
    }

    private readonly T[] _Buffer;
    private readonly int _Length;

    public static SpanOwner<T> Empty
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get => new(0);
    }

    public Span<T> Span
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get
        {
            ref T r0 = ref MemoryMarshal.GetArrayDataReference(_Buffer);
            return MemoryMarshal.CreateSpan(ref r0, _Length);
        }
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public SpanOwner<T> WithLength(int length) => new(length, _Buffer);

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public SpanOwner(int length) : this(length, DefaultPool.Rent(length))
    { }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private SpanOwner(int length, T[] buffer)
    {
        _Length = length;
        _Buffer = buffer;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Dispose() =>
        DefaultPool.Return(_Buffer);

}