using System; using System.Runtime.InteropServices; using System.Text; namespace Foodsoft.Alpm { internal readonly struct UTF8InMarshaler : ICustomMarshaler { private static readonly UTF8InMarshaler _instance = default; public void CleanUpManagedData(object managedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return; Marshal.FreeHGlobal(pNativeData); } public int GetNativeDataSize() => -1; public unsafe IntPtr MarshalManagedToNative(object? managedObj) { if (managedObj is null) return IntPtr.Zero; var s = (string) managedObj; var nb = Encoding.UTF8.GetMaxByteCount(s.Length); var pMem = Marshal.AllocHGlobal(nb + 1); var pbMem = (byte*) pMem; int nbWritten; fixed (char* firstChar = s) { nbWritten = Encoding.UTF8.GetBytes(firstChar, s.Length, pbMem, nb); } pbMem[nbWritten] = 0; return pMem; } public object MarshalNativeToManaged(IntPtr pNativeData) { return Marshal.PtrToStringUTF8(pNativeData)!; } // ReSharper disable once UnusedMember.Local // ReSharper disable once UnusedParameter.Local private static ICustomMarshaler GetInstance(string cookie) { return _instance; } } }