Skip to content

Commit af0f880

Browse files
authored
.NET Standard 2.0 support (#246)
* .NET Standard 2.0 support * remove GetSpan from .NET Standard 2.0 due to potential safety issues
1 parent d11e748 commit af0f880

16 files changed

+199
-45
lines changed

src/Config.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ private static class Native
430430
public static extern void wasmtime_config_dynamic_memory_guard_size_set(Handle config, ulong size);
431431

432432
[DllImport(Engine.LibraryName)]
433-
public static extern IntPtr wasmtime_config_cache_config_load(Handle config, [MarshalAs(UnmanagedType.LPUTF8Str)] string? path);
433+
public static extern IntPtr wasmtime_config_cache_config_load(Handle config, [MarshalAs(Extensions.LPUTF8Str)] string? path);
434434
}
435435

436436
private readonly Handle handle;

src/Export.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ internal Export(IntPtr exportType)
8484
}
8585
else
8686
{
87-
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
87+
Name = Extensions.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
8888
}
8989
}
9090
}

src/Extensions.cs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using System;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
using System.Text;
5+
6+
namespace Wasmtime
7+
{
8+
internal static class Extensions
9+
{
10+
public const UnmanagedType LPUTF8Str =
11+
#if NETSTANDARD2_0
12+
(UnmanagedType)48;
13+
#else
14+
UnmanagedType.LPUTF8Str;
15+
#endif
16+
17+
#if NETSTANDARD2_0
18+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
19+
public static unsafe string GetString(this Encoding encoding, Span<byte> bytes)
20+
{
21+
fixed (byte* bytesPtr = bytes)
22+
{
23+
return encoding.GetString(bytesPtr, bytes.Length);
24+
}
25+
}
26+
27+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
28+
public static unsafe string GetString(this Encoding encoding, ReadOnlySpan<byte> bytes)
29+
{
30+
fixed (byte* bytesPtr = bytes)
31+
{
32+
return encoding.GetString(bytesPtr, bytes.Length);
33+
}
34+
}
35+
36+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
37+
public static unsafe int GetBytes(this Encoding encoding, Span<char> chars, Span<byte> bytes)
38+
{
39+
fixed (char* charsPtr = chars)
40+
fixed (byte* bytesPtr = bytes)
41+
{
42+
return encoding.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
43+
}
44+
}
45+
46+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
47+
public static unsafe int GetBytes(this Encoding encoding, ReadOnlySpan<char> chars, Span<byte> bytes)
48+
{
49+
fixed (char* charsPtr = chars)
50+
fixed (byte* bytesPtr = bytes)
51+
{
52+
return encoding.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
53+
}
54+
}
55+
56+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
57+
public static unsafe int GetBytes(this Encoding encoding, string chars, Span<byte> bytes)
58+
{
59+
fixed (char* charsPtr = chars)
60+
fixed (byte* bytesPtr = bytes)
61+
{
62+
return encoding.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
63+
}
64+
}
65+
#endif
66+
67+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
68+
public static bool IsTupleType(this Type type)
69+
{
70+
#if NETSTANDARD2_0
71+
return type.FullName.StartsWith("System.ValueTuple`");
72+
#else
73+
return typeof(ITuple).IsAssignableFrom(type);
74+
#endif
75+
}
76+
77+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
78+
public static float Int32BitsToSingle(int value)
79+
{
80+
#if NETSTANDARD2_0
81+
unsafe
82+
{
83+
return *(float*)&value;
84+
}
85+
#else
86+
return BitConverter.Int32BitsToSingle(value);
87+
#endif
88+
}
89+
90+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
91+
public static int SingleToInt32Bits(float value)
92+
{
93+
#if NETSTANDARD2_0
94+
unsafe
95+
{
96+
return *(int*)&value;
97+
}
98+
#else
99+
return BitConverter.SingleToInt32Bits(value);
100+
#endif
101+
}
102+
103+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
104+
public static string PtrToStringUTF8(IntPtr ptr, int byteLen)
105+
{
106+
#if NETSTANDARD2_0
107+
unsafe
108+
{
109+
return Encoding.UTF8.GetString((byte*)ptr, byteLen);
110+
}
111+
#else
112+
return Marshal.PtrToStringUTF8(ptr, byteLen);
113+
#endif
114+
}
115+
}
116+
}

src/Function.Wrap.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ public partial class Function
10981098
// Fetch a converter for each parameter type to box it
10991099

11001100
// Create a factory for the return type
1101-
var factory = IReturnTypeFactory<TResult>.Create();
1101+
var factory = ReturnTypeFactory<TResult>.Create();
11021102

11031103
// Determine how much space to allocate for params/results
11041104
var allocCount = Math.Max(0, Results.Count);
@@ -1148,7 +1148,7 @@ public partial class Function
11481148
var convT = ValueRaw.Converter<T>();
11491149

11501150
// Create a factory for the return type
1151-
var factory = IReturnTypeFactory<TResult>.Create();
1151+
var factory = ReturnTypeFactory<TResult>.Create();
11521152

11531153
// Determine how much space to allocate for params/results
11541154
var allocCount = Math.Max(1, Results.Count);
@@ -1200,7 +1200,7 @@ public partial class Function
12001200
var convT2 = ValueRaw.Converter<T2>();
12011201

12021202
// Create a factory for the return type
1203-
var factory = IReturnTypeFactory<TResult>.Create();
1203+
var factory = ReturnTypeFactory<TResult>.Create();
12041204

12051205
// Determine how much space to allocate for params/results
12061206
var allocCount = Math.Max(2, Results.Count);
@@ -1254,7 +1254,7 @@ public partial class Function
12541254
var convT3 = ValueRaw.Converter<T3>();
12551255

12561256
// Create a factory for the return type
1257-
var factory = IReturnTypeFactory<TResult>.Create();
1257+
var factory = ReturnTypeFactory<TResult>.Create();
12581258

12591259
// Determine how much space to allocate for params/results
12601260
var allocCount = Math.Max(3, Results.Count);
@@ -1310,7 +1310,7 @@ public partial class Function
13101310
var convT4 = ValueRaw.Converter<T4>();
13111311

13121312
// Create a factory for the return type
1313-
var factory = IReturnTypeFactory<TResult>.Create();
1313+
var factory = ReturnTypeFactory<TResult>.Create();
13141314

13151315
// Determine how much space to allocate for params/results
13161316
var allocCount = Math.Max(4, Results.Count);
@@ -1368,7 +1368,7 @@ public partial class Function
13681368
var convT5 = ValueRaw.Converter<T5>();
13691369

13701370
// Create a factory for the return type
1371-
var factory = IReturnTypeFactory<TResult>.Create();
1371+
var factory = ReturnTypeFactory<TResult>.Create();
13721372

13731373
// Determine how much space to allocate for params/results
13741374
var allocCount = Math.Max(5, Results.Count);
@@ -1428,7 +1428,7 @@ public partial class Function
14281428
var convT6 = ValueRaw.Converter<T6>();
14291429

14301430
// Create a factory for the return type
1431-
var factory = IReturnTypeFactory<TResult>.Create();
1431+
var factory = ReturnTypeFactory<TResult>.Create();
14321432

14331433
// Determine how much space to allocate for params/results
14341434
var allocCount = Math.Max(6, Results.Count);
@@ -1490,7 +1490,7 @@ public partial class Function
14901490
var convT7 = ValueRaw.Converter<T7>();
14911491

14921492
// Create a factory for the return type
1493-
var factory = IReturnTypeFactory<TResult>.Create();
1493+
var factory = ReturnTypeFactory<TResult>.Create();
14941494

14951495
// Determine how much space to allocate for params/results
14961496
var allocCount = Math.Max(7, Results.Count);
@@ -1554,7 +1554,7 @@ public partial class Function
15541554
var convT8 = ValueRaw.Converter<T8>();
15551555

15561556
// Create a factory for the return type
1557-
var factory = IReturnTypeFactory<TResult>.Create();
1557+
var factory = ReturnTypeFactory<TResult>.Create();
15581558

15591559
// Determine how much space to allocate for params/results
15601560
var allocCount = Math.Max(8, Results.Count);
@@ -1620,7 +1620,7 @@ public partial class Function
16201620
var convT9 = ValueRaw.Converter<T9>();
16211621

16221622
// Create a factory for the return type
1623-
var factory = IReturnTypeFactory<TResult>.Create();
1623+
var factory = ReturnTypeFactory<TResult>.Create();
16241624

16251625
// Determine how much space to allocate for params/results
16261626
var allocCount = Math.Max(9, Results.Count);
@@ -1688,7 +1688,7 @@ public partial class Function
16881688
var convT10 = ValueRaw.Converter<T10>();
16891689

16901690
// Create a factory for the return type
1691-
var factory = IReturnTypeFactory<TResult>.Create();
1691+
var factory = ReturnTypeFactory<TResult>.Create();
16921692

16931693
// Determine how much space to allocate for params/results
16941694
var allocCount = Math.Max(10, Results.Count);
@@ -1758,7 +1758,7 @@ public partial class Function
17581758
var convT11 = ValueRaw.Converter<T11>();
17591759

17601760
// Create a factory for the return type
1761-
var factory = IReturnTypeFactory<TResult>.Create();
1761+
var factory = ReturnTypeFactory<TResult>.Create();
17621762

17631763
// Determine how much space to allocate for params/results
17641764
var allocCount = Math.Max(11, Results.Count);
@@ -1830,7 +1830,7 @@ public partial class Function
18301830
var convT12 = ValueRaw.Converter<T12>();
18311831

18321832
// Create a factory for the return type
1833-
var factory = IReturnTypeFactory<TResult>.Create();
1833+
var factory = ReturnTypeFactory<TResult>.Create();
18341834

18351835
// Determine how much space to allocate for params/results
18361836
var allocCount = Math.Max(12, Results.Count);
@@ -1904,7 +1904,7 @@ public partial class Function
19041904
var convT13 = ValueRaw.Converter<T13>();
19051905

19061906
// Create a factory for the return type
1907-
var factory = IReturnTypeFactory<TResult>.Create();
1907+
var factory = ReturnTypeFactory<TResult>.Create();
19081908

19091909
// Determine how much space to allocate for params/results
19101910
var allocCount = Math.Max(13, Results.Count);
@@ -1980,7 +1980,7 @@ public partial class Function
19801980
var convT14 = ValueRaw.Converter<T14>();
19811981

19821982
// Create a factory for the return type
1983-
var factory = IReturnTypeFactory<TResult>.Create();
1983+
var factory = ReturnTypeFactory<TResult>.Create();
19841984

19851985
// Determine how much space to allocate for params/results
19861986
var allocCount = Math.Max(14, Results.Count);
@@ -2058,7 +2058,7 @@ public partial class Function
20582058
var convT15 = ValueRaw.Converter<T15>();
20592059

20602060
// Create a factory for the return type
2061-
var factory = IReturnTypeFactory<TResult>.Create();
2061+
var factory = ReturnTypeFactory<TResult>.Create();
20622062

20632063
// Determine how much space to allocate for params/results
20642064
var allocCount = Math.Max(15, Results.Count);
@@ -2138,7 +2138,7 @@ public partial class Function
21382138
var convT16 = ValueRaw.Converter<T16>();
21392139

21402140
// Create a factory for the return type
2141-
var factory = IReturnTypeFactory<TResult>.Create();
2141+
var factory = ReturnTypeFactory<TResult>.Create();
21422142

21432143
// Determine how much space to allocate for params/results
21442144
var allocCount = Math.Max(16, Results.Count);

src/Function.Wrap.tt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ var parameterTypes = new Type[] { <#= callbackParameterTypeExpressions #>};
7373
{
7474
#>
7575
// Create a factory for the return type
76-
var factory = IReturnTypeFactory<TResult>.Create();
76+
var factory = ReturnTypeFactory<TResult>.Create();
7777

7878
<#
7979
}

src/Function.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@ public bool CheckTypeSignature(Type? returnType = null, params Type[] parameters
132132
}
133133

134134
// Validate the return type(s)
135-
if (returnType != null)
135+
if(returnType != null)
136136
{
137137
// Multiple return types are represented by a tuple.
138-
if (typeof(ITuple).IsAssignableFrom(returnType))
138+
if (returnType.IsTupleType())
139139
{
140140
// Get the types from the tuple
141141
var returnTypes = returnType.GetGenericArguments();

src/Import.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ internal Import(IntPtr importType)
9191
}
9292
else
9393
{
94-
ModuleName = Marshal.PtrToStringUTF8((IntPtr)moduleName->data, checked((int)moduleName->size));
94+
ModuleName = Extensions.PtrToStringUTF8((IntPtr)moduleName->data, checked((int)moduleName->size));
9595
}
9696

9797
var name = Native.wasm_importtype_name(importType);
@@ -101,7 +101,7 @@ internal Import(IntPtr importType)
101101
}
102102
else
103103
{
104-
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
104+
Name = Extensions.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
105105
}
106106
}
107107
}

src/Memory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ public void WriteIntPtr(long address, IntPtr value)
481481
/// <returns>Returns the single read from memory.</returns>
482482
public float ReadSingle(long address)
483483
{
484-
return BitConverter.Int32BitsToSingle(ReadInt32(address));
484+
return Extensions.Int32BitsToSingle(ReadInt32(address));
485485
}
486486

487487
/// <summary>
@@ -491,7 +491,7 @@ public float ReadSingle(long address)
491491
/// <param name="value">The single to write.</param>
492492
public void WriteSingle(long address, float value)
493493
{
494-
WriteInt32(address, BitConverter.SingleToInt32Bits(value));
494+
WriteInt32(address, Extensions.SingleToInt32Bits(value));
495495
}
496496

497497
/// <summary>

src/Module.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ internal static class Native
438438
public static extern unsafe IntPtr wasmtime_module_deserialize(Engine.Handle engine, byte* bytes, UIntPtr size, out IntPtr handle);
439439

440440
[DllImport(Engine.LibraryName)]
441-
public static extern IntPtr wasmtime_module_deserialize_file(Engine.Handle engine, [MarshalAs(UnmanagedType.LPUTF8Str)] string path, out IntPtr handle);
441+
public static extern IntPtr wasmtime_module_deserialize_file(Engine.Handle engine, [MarshalAs(Extensions.LPUTF8Str)] string path, out IntPtr handle);
442442
}
443443

444444
private readonly Handle handle;

src/ReturnTypeFactory.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ namespace Wasmtime
99
interface IReturnTypeFactory<out TReturn>
1010
{
1111
TReturn? Create(StoreContext storeContext, Store store, IntPtr trap, Span<ValueRaw> values);
12+
}
1213

13-
static IReturnTypeFactory<TReturn> Create()
14+
internal static class ReturnTypeFactory<TReturn>
15+
{
16+
public static IReturnTypeFactory<TReturn> Create()
1417
{
1518
// First, check if the value is a result builder
1619
var resultInterface = typeof(TReturn).TryGetResultInterface();
@@ -76,7 +79,7 @@ private static Type GetTupleFactoryType(int arity)
7679
/// <returns></returns>
7780
private static List<Type>? GetTupleTypes()
7881
{
79-
if (typeof(ITuple).IsAssignableFrom(typeof(TReturn)))
82+
if (typeof(TReturn).IsTupleType())
8083
{
8184
return typeof(TReturn).GetGenericArguments().ToList();
8285
}
@@ -115,7 +118,7 @@ internal class FunctionResultFactory<TResult, TValue, TBuilder>
115118

116119
public FunctionResultFactory()
117120
{
118-
_valueFactory = IReturnTypeFactory<TValue>.Create();
121+
_valueFactory = ReturnTypeFactory<TValue>.Create();
119122
}
120123

121124
public TResult Create(StoreContext storeContext, Store store, IntPtr trap, Span<ValueRaw> values)
@@ -165,8 +168,10 @@ protected BaseTupleFactory()
165168
// Get all the generic arguments of TFunc. All of the Parameters, followed by the return type
166169
var args = typeof(TFunc).GetGenericArguments();
167170

168-
Factory = (TFunc)GetCreateMethodInfo(args.Length - 1)
169-
.MakeGenericMethod(args[..^1])
171+
Array.Resize(ref args, args.Length - 1);
172+
173+
Factory = (TFunc)GetCreateMethodInfo(args.Length)
174+
.MakeGenericMethod(args)
170175
.CreateDelegate(typeof(TFunc));
171176
}
172177

0 commit comments

Comments
 (0)