diff --git a/ExternalProjects/NLua/NLua.csproj b/ExternalProjects/NLua/NLua.csproj index be621ecfa8..a01032d2ef 100644 --- a/ExternalProjects/NLua/NLua.csproj +++ b/ExternalProjects/NLua/NLua.csproj @@ -26,4 +26,8 @@ disable true + + + + diff --git a/ExternalProjects/NLua/src/Native/LuaNativeMethods.cs b/ExternalProjects/NLua/src/Native/LuaNativeMethods.cs index e44ab6142a..7688b487f0 100644 --- a/ExternalProjects/NLua/src/Native/LuaNativeMethods.cs +++ b/ExternalProjects/NLua/src/Native/LuaNativeMethods.cs @@ -1,4 +1,5 @@ -using System.Runtime.CompilerServices; +using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Text; @@ -184,7 +185,7 @@ namespace NLua.Native internal delegate* unmanaged[Cdecl] lua_pushlstring; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public charptr_t PushLString(lua_State luaState, byte[] s, size_t len) + public charptr_t PushLString(lua_State luaState, ReadOnlySpan s, size_t len) { fixed (byte* _s = s) { diff --git a/ExternalProjects/NLua/src/Native/LuaState.cs b/ExternalProjects/NLua/src/Native/LuaState.cs index 71b93be434..fcf6815e7c 100644 --- a/ExternalProjects/NLua/src/Native/LuaState.cs +++ b/ExternalProjects/NLua/src/Native/LuaState.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -355,7 +356,7 @@ namespace NLua.Native /// Pushes binary buffer onto the stack (usually UTF encoded string) or any arbitraty binary data /// /// - public void PushBuffer(byte[] buffer) + public void PushBuffer(ReadOnlySpan buffer) { if (buffer == null) { @@ -378,8 +379,11 @@ namespace NLua.Native return; } - var buffer = Encoding.UTF8.GetBytes(value); - PushBuffer(buffer); + // could also use GetByteCount here, but why iterate twice when we're renting the memory anyway? + byte[] buffer = ArrayPool.Shared.Rent(Encoding.UTF8.GetMaxByteCount(value.Length)); + int actualLength = Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, 0); + PushBuffer(buffer.AsSpan(0, actualLength)); + ArrayPool.Shared.Return(buffer); } /// @@ -556,13 +560,7 @@ namespace NLua.Native public long ToInteger(int index) => NativeMethods.ToIntegerX(Handle, index, out _); - /// - /// Converts the Lua value at the given index to a byte array. - /// - /// - /// Calls __tostring field if present - /// - public byte[] ToBuffer(int index, bool callMetamethod = true) + private IntPtr ToLString(int index, bool callMetamethod, out int stringLength) { UIntPtr len; IntPtr buff; @@ -577,19 +575,26 @@ namespace NLua.Native buff = NativeMethods.ToLString(Handle, index, out len); } - if (buff == IntPtr.Zero) - { - return null; - } + stringLength = (int)len; - var length = (int)len; - if (length == 0) - { - return Array.Empty(); - } + return buff; + } + + /// + /// Converts the Lua value at the given index to a byte array. + /// + /// + /// Calls __tostring field if present + /// + public byte[] ToBuffer(int index, bool callMetamethod = true) + { + IntPtr buffer = ToLString(index, callMetamethod, out int length); + + if (buffer == IntPtr.Zero) return null; + if (length == 0) return Array.Empty(); var output = new byte[length]; - Marshal.Copy(buff, output, 0, length); + Marshal.Copy(buffer, output, 0, length); return output; } @@ -601,8 +606,15 @@ namespace NLua.Native /// public string ToString(int index, bool callMetamethod = true) { - var buffer = ToBuffer(index, callMetamethod); - return buffer == null ? null : Encoding.UTF8.GetString(buffer); + var buffer = ToLString(index, callMetamethod, out int length); + + if (buffer == IntPtr.Zero) return null; + if (length == 0) return ""; + + unsafe + { + return Encoding.UTF8.GetString((byte*)buffer.ToPointer(), length); + } } /// diff --git a/References/NLua.dll b/References/NLua.dll index 07a5627d2a..281a5f76b0 100644 Binary files a/References/NLua.dll and b/References/NLua.dll differ