using System.Runtime.CompilerServices;
using System.Text;
namespace Ghost.Nvtt;
///
/// Internal helpers for converting between managed and unmanaged types.
///
internal static unsafe class NvttInterop
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static NvttBoolean ToNvtt(bool value)
=> value ? NvttBoolean.NVTT_True : NvttBoolean.NVTT_False;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool ToBool(NvttBoolean value)
=> value != NvttBoolean.NVTT_False;
// -------------------------------------------------------------------------
// String to UTF-8 sbyte*
//
// Usage pattern:
// fixed (byte* ptr = NvttInterop.ToUtf8(str, stackalloc byte[MaxStack]))
// Api.nvttSomething((sbyte*)ptr);
//
// For paths longer than MaxStack bytes the helper falls back to a heap
// allocation via Encoding.UTF8.GetBytes. The Span overload lets the
// caller decide the stackalloc size.
// -------------------------------------------------------------------------
internal const int _MAX_STACK_PATH = 512;
///
/// Encode as null-terminated UTF-8 into
/// . Returns the used portion (including the
/// null terminator). If the buffer is too small a new heap array is
/// returned instead.
///
internal static Span ToUtf8(string value, Span buffer)
{
var needed = Encoding.UTF8.GetByteCount(value) + 1; // +1 for null term
if (needed > buffer.Length)
{
buffer = new byte[needed];
}
var written = Encoding.UTF8.GetBytes(value, buffer);
buffer[written] = 0; // null terminator
return buffer[..(written + 1)];
}
internal static string? FromUtf8(sbyte* ptr)
{
if (ptr == null)
{
return null;
}
var len = 0;
while (ptr[len] != 0)
{
len++;
}
return Encoding.UTF8.GetString((byte*)ptr, len);
}
}