using System;
using System.Runtime.InteropServices;

namespace FastArena
{
    public static class StructBinaryConverter
    {
        public static byte[] GetBytes<T>(T s) where T : unmanaged
        {
            return GetBytes(ref s);
        }
        
        public static byte[] GetBytes<T>(ref T s) where T : unmanaged
        {
            int size = Marshal.SizeOf(typeof(T));
            byte[] buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(Marshal.SizeOf<T>());
            
            var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);

            unsafe
            {
                fixed (T* s_ptr = &s)
                {
                    Marshal.Copy((IntPtr)s_ptr, buffer, 0, size);
                    Marshal.StructureToPtr();
                }
            }
            try
            {
                Marshal.StructureToPtr(msg_struct, handle.AddrOfPinnedObject(), false);
                return buffer;
            }
            finally
            {
                handle.Free();
                ArrayPool<byte>.Shared.Return(buffer);
            }

        }

        public static T ReadStruct<T>(byte[] buffer) where T : unmanaged
        {
            GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            try
            {
                T s = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
                return s;
            }
            finally
            {
                handle.Free();
            }
        }
    }
}