namespace UniversalNetFrame451;

public class StructConverter
{
    public static bool TryGetBytes<T_Struct>(T_Struct structure, out byte[] bytes) where T_Struct : struct
    {
        bytes = default;
        int size = Marshal.SizeOf(structure);
        nint buffer = Marshal.AllocHGlobal(size);
        try
        {
            Marshal.StructureToPtr(structure, buffer, false);
            bytes = new byte[size];
            Marshal.Copy(buffer, bytes, 0, size);
            return true;
        }
        catch
        {
            return false;
        }
        finally
        {
            Marshal.FreeHGlobal(buffer);
        }
    }

    public static bool TryGetStruct<T_Struct>(byte[] bytes, out T_Struct? structData) where T_Struct : struct
    {
        nint buffer = Marshal.AllocHGlobal(bytes.Length);
        try
        {
            Marshal.Copy(bytes, 0, buffer, bytes.Length);
            structData = Marshal.PtrToStructure<T_Struct>(buffer);
            return true;
        }
        catch
        {
            structData = null;
            return false;
        }
        finally
        {
            Marshal.FreeHGlobal(buffer);
        }
    }

    public static T_Struct? GetStruct<T_Struct>(byte[] bytes) where T_Struct : struct
    {
        nint buffer = Marshal.AllocHGlobal(bytes.Length);
        try
        {
            Marshal.Copy(bytes, 0, buffer, bytes.Length);
            return Marshal.PtrToStructure<T_Struct>(buffer);
        }
        catch
        {
            return null;
        }
        finally
        {
            Marshal.FreeHGlobal(buffer);
        }
    }
}
