// ---------------------------------------------------------------------------
// BT.Framework
// EnumToInt.cs — boxing-free enum ↔ int 변환 유틸리티
// ---------------------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;

namespace BurningTimes.Core.Util
{
    /// <summary>
    /// <c>enum</c> 값을 <see cref="int"/>로 변환할 때 발생하는 박싱을 회피하는 유틸리티.
    /// </summary>
    /// <remarks>
    /// <para>설계 문서 §5 Tier 1 (C11 자원 효율성). <c>Convert.ToInt32((object)e)</c> 또는
    /// <c>(int)(object)e</c> 는 박싱을 유발하지만, <c>Unsafe.As&lt;TEnum, int&gt;</c> 를 이용하면
    /// JIT 단계에서 직접 변환되어 힙 할당이 전혀 발생하지 않는다.</para>
    /// <para>사용 전제:</para>
    /// <list type="bullet">
    ///   <item><description>대상 enum의 기저 타입이 <see cref="int"/>여야 한다(<see cref="long"/>·<see cref="byte"/>는 미지원).</description></item>
    ///   <item><description>hot-path(매 프레임 수백~수천 회 호출)에서 사용해 효과가 크다.</description></item>
    ///   <item><description>Dictionary·HashSet의 key로 enum을 쓸 때는 별도 <c>IEqualityComparer</c>로 감싸서 박싱을 함께 회피한다.</description></item>
    /// </list>
    /// <para>사용 예:</para>
    /// <code>
    /// int id = EnumToInt.Convert(CardType.Attack);
    /// CardType t = EnumToInt.FromInt&lt;CardType&gt;(id);
    /// </code>
    /// </remarks>
    public static class EnumToInt
    {
        /// <summary>enum을 int로 변환한다(박싱 없음).</summary>
        /// <typeparam name="TEnum">기저 타입 <see cref="int"/>인 enum.</typeparam>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int Convert<TEnum>(TEnum value) where TEnum : struct, Enum
        {
            return Unsafe.As<TEnum, int>(ref value);
        }

        /// <summary>int 값을 enum으로 변환한다(박싱 없음).</summary>
        /// <typeparam name="TEnum">기저 타입 <see cref="int"/>인 enum.</typeparam>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static TEnum FromInt<TEnum>(int value) where TEnum : struct, Enum
        {
            return Unsafe.As<int, TEnum>(ref value);
        }

        /// <summary>두 enum 값의 동등성을 박싱 없이 비교한다.</summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool Equals<TEnum>(TEnum a, TEnum b) where TEnum : struct, Enum
        {
            return Unsafe.As<TEnum, int>(ref a) == Unsafe.As<TEnum, int>(ref b);
        }
    }
}
