sn_bindgen 0.13.18

A library to automatically generate C, Java, and C# files from Rust source files.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace @Namespace
{
    public class FfiException : Exception
    {
        public readonly int ErrorCode;

        public FfiException(int code, string description)
            : base($"Error Code: {code}. Description: {description}")
        {
            ErrorCode = code;
        }
    }

    public struct FfiResult
    {
        public int ErrorCode;
        [MarshalAs(UnmanagedType.LPStr)]
        public string Description;

        public FfiException ToException()
        {
            return new FfiException(ErrorCode, Description);
        }
    }

    public class @Class
    {
        private static void CompleteTask<T>(TaskCompletionSource<T> tcs, FfiResult result, Func<T> argFunc)
        {
            if (result.ErrorCode != 0)
            {
                tcs.SetException(result.ToException());
            }
            else
            {
                tcs.SetResult(argFunc());
            }
        }

        public static void CompleteTask<T>(IntPtr userData, FfiResult result, Func<T> argFunc)
        {
            var tcs = FromHandlePtr<TaskCompletionSource<T>>(userData);
            CompleteTask(tcs, result, argFunc);
        }

        public static void CompleteTask(IntPtr userData, FfiResult result)
        {
            CompleteTask(userData, result, () => true);
        }

        public static IntPtr CopyFromByteList(List<byte> list)
        {
            if (list == null || list.Count == 0)
            {
                return IntPtr.Zero;
            }

            var array = list.ToArray();
            var size = Marshal.SizeOf(array[0]) * array.Length;
            var ptr = Marshal.AllocHGlobal(size);
            Marshal.Copy(array, 0, ptr, array.Length);

            return ptr;
        }

        public static IntPtr CopyFromObjectList<T>(List<T> list)
        {
            if (list == null || list.Count == 0)
            {
                return IntPtr.Zero;
            }

            var size = Marshal.SizeOf(list[0]) * list.Count;
            var ptr = Marshal.AllocHGlobal(size);
            for (var i = 0; i < list.Count; ++i)
            {
                Marshal.StructureToPtr(list[i], IntPtr.Add(ptr, Marshal.SizeOf<T>() * i), false);
            }

            return ptr;
        }

        public static byte[] CopyToByteArray(IntPtr ptr, int len)
        {
            var array = new byte[len];
            if (len > 0)
            {
                Marshal.Copy(ptr, array, 0, len);
            }

            return array;
        }

        public static List<byte> CopyToByteList(IntPtr ptr, int len)
        {
            return new List<byte>(CopyToByteArray(ptr, len));
        }

        public static List<T> CopyToObjectList<T>(IntPtr ptr, int len)
        {
            var list = new List<T>(len);
            for (var i = 0; i < len; ++i)
            {
                list.Add(Marshal.PtrToStructure<T>(IntPtr.Add(ptr, Marshal.SizeOf<T>() * i)));
            }

            return list;
        }

        public static List<string> CopyToStringList(IntPtr ptr, int len)
        {
            if (ptr == IntPtr.Zero || len <= 0)
                return null;

            var list = new List<string>();

            for (int count = 0; count < len && Marshal.ReadIntPtr(ptr, count * IntPtr.Size) != IntPtr.Zero; ++count)
            {
                list.Add(PtrToString(Marshal.ReadIntPtr(ptr, count * IntPtr.Size)));
            }
            return list;
        }

        internal static string PtrToString(IntPtr handle)
        {
            if (handle == IntPtr.Zero)
                return string.Empty;

            var data = new List<byte>();
            var offset = 0;

            while (true)
            {
                var ch = Marshal.ReadByte(handle, offset++);

                if (ch == 0)
                    break;

                data.Add(ch);
            }

            return Encoding.UTF8.GetString(data.ToArray());
        }

        public static IntPtr CopyFromStringList(List<string> str)
        {
            var unmanagedPointer = Marshal.AllocHGlobal(str.Count * IntPtr.Size);
            var ptrList = StringArrayToIntPtrArray(str.ToArray());
            Marshal.Copy(ptrList, 0, unmanagedPointer, str.Count);
            return unmanagedPointer;
        }

        public static IntPtr[] StringArrayToIntPtrArray(string[] str)
        {
            int length = str.Length;
            IntPtr[] arr = new IntPtr[length];
            for (int i = 0; i < length; i++)
            {
                arr[i] = Utf8StringToIntPtr(str[i]);
            }
            return arr;
        }

        public static IntPtr Utf8StringToIntPtr(string str)
        {
            var len = Encoding.UTF8.GetByteCount(str);
            var buffer = new byte[len + 1];
            Encoding.UTF8.GetBytes(str, 0, str.Length, buffer, 0);
            var nativeUtf8 = Marshal.AllocHGlobal(buffer.Length);
            Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length);
            return nativeUtf8;
        }

        public static void FreeList(ref IntPtr ptr, ref UIntPtr len)
        {
            if (ptr != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(ptr);
            }

            ptr = IntPtr.Zero;
            len = UIntPtr.Zero;
        }

        public static T FromHandlePtr<T>(IntPtr ptr, bool free = true)
        {
            var handle = GCHandle.FromIntPtr(ptr);
            var result = (T)handle.Target;

            if (free)
            {
                handle.Free();
            }

            return result;
        }

        public static (Task<T>, IntPtr) PrepareTask<T>()
        {
            var tcs = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
            var userData = ToHandlePtr(tcs);

            return (tcs.Task, userData);
        }

        public static (Task, IntPtr) PrepareTask()
        {
            return PrepareTask<bool>();
        }

        public static IntPtr ToHandlePtr<T>(T obj)
        {
            return GCHandle.ToIntPtr(GCHandle.Alloc(obj));
        }
    }
}