Skip to content

Commit

Permalink
Update test cases and docs to show that LPWStr is UTF-32 on non-Windows
Browse files Browse the repository at this point in the history
See #2377
  • Loading branch information
Exanite committed Dec 6, 2024
1 parent 7f57f49 commit e2737e1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 42 deletions.
69 changes: 28 additions & 41 deletions src/Core/Silk.NET.Core.Tests/TestSilkMarshal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Silk.NET.Core.Native;
using Xunit;

Expand All @@ -19,63 +20,49 @@ public class TestSilkMarshal
NativeStringEncoding.LPUTF8Str,
NativeStringEncoding.LPWStr,
};

private readonly Encoding lpwStrEncoding = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Encoding.Unicode
: Encoding.UTF32;

private readonly int lpwStrCharacterWidth = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 2 : 4;

[Fact]
public unsafe void TestEncodingToLPWStr()
{
var input = "Hello world";
var input = "Hello world 🧵";

// LPWStr is 2 bytes on Windows, 4 bytes elsewhere (usually)
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var pointer = SilkMarshal.StringToPtr(input, NativeStringEncoding.LPWStr);

Assert.Equal(input.Length, (int)SilkMarshal.StringLength(pointer, NativeStringEncoding.LPWStr));

// Use short for comparison
Assert.Equal(new short[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x00 }, new Span<short>((void*)pointer, input.Length + 1));
}
else
{
var pointer = SilkMarshal.StringToPtr(input, NativeStringEncoding.LPWStr);

Assert.Equal(input.Length, (int)SilkMarshal.StringLength(pointer, NativeStringEncoding.LPWStr));

// Use int for comparison
Assert.Equal(new int[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x00 }, new Span<int>((void*)pointer, input.Length + 1));
}
var expectedByteCount = lpwStrEncoding.GetByteCount(input);
var expected = new byte[expectedByteCount + lpwStrCharacterWidth];
lpwStrEncoding.GetBytes(input, expected);

var pointer = SilkMarshal.StringToPtr(input, NativeStringEncoding.LPWStr);
var pointerByteCount = lpwStrCharacterWidth * (int) SilkMarshal.StringLength(pointer, NativeStringEncoding.LPWStr);

Assert.Equal(expected, new Span<byte>((void*)pointer, pointerByteCount + lpwStrCharacterWidth));
}

[Fact]
public unsafe void TestEncodingFromLPWStr()
{
var expected = "Hello world";
var expected = "Hello world 🧵";

// LPWStr is 2 bytes on Windows, 4 bytes elsewhere (usually)
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var characters = new short[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64 };
fixed (short* pCharacters = characters)
{
var output = SilkMarshal.PtrToString((nint)pCharacters, NativeStringEncoding.LPWStr);
Assert.Equal(expected, output);
}
}
else
var inputByteCount = lpwStrEncoding.GetByteCount(expected);
var input = new byte[inputByteCount + lpwStrCharacterWidth];
lpwStrEncoding.GetBytes(expected, input);

fixed (byte* pInput = input)
{
var characters = new int[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64 };
fixed (int* pCharacters = characters)
{
var output = SilkMarshal.PtrToString((nint)pCharacters, NativeStringEncoding.LPWStr);
Assert.Equal(expected, output);
}
var output = SilkMarshal.PtrToString((nint)pInput, NativeStringEncoding.LPWStr);

Assert.Equal(expected, output);
}
}

[Fact]
public void TestEncodingString()
{
var input = "Hello world";
var input = "Hello world 🧵";
foreach (var encoding in encodings)
{
var pointer = SilkMarshal.StringToPtr(input, encoding);
Expand All @@ -89,7 +76,7 @@ public void TestEncodingStringArray()
{
var inputs = new List<string>()
{
"Hello world",
"Hello world 🧵",
"Foo",
"Bar",
"123",
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Silk.NET.Core/Native/NativeStringEncoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public enum NativeStringEncoding
LPTStr = UnmanagedType.LPTStr,
LPUTF8Str = UnmanagedType.LPUTF8Str,
/// <summary>
/// On Windows, a 2-byte, null-terminated Unicode character string. On other platforms, each character will be 4 bytes instead.
/// On Windows, a null-terminated UTF-16 string. On other platforms, a null-terminated UTF-32 string.
/// </summary>
LPWStr = UnmanagedType.LPWStr,
WinString = UnmanagedType.WinString,
Expand Down

0 comments on commit e2737e1

Please sign in to comment.