-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathPackedArray.cs
More file actions
164 lines (139 loc) · 5.02 KB
/
PackedArray.cs
File metadata and controls
164 lines (139 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#pragma warning disable 1591
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using JSIL.Meta;
namespace JSIL.Runtime {
internal class LinkedTypeAttribute : Attribute {
public readonly Type Type;
public LinkedTypeAttribute (Type type) {
Type = type;
}
}
/// <summary>
/// A packed array that is allocated in the managed heap.
/// Packed arrays always have a dense in-memory representation, even in JS.
/// This allows passing them to APIs like WebGL along with pinning and fast marshalling/unmarshalling.
/// </summary>
public unsafe interface IPackedArray<T> {
T this[int index] {
[JSRuntimeDispatch]
[JSResultIsNew]
[JSIsPure]
get;
// HACK: value technically escapes, but since the packed array stores its raw values instead of its reference, we don't want it to be copied.
[JSRuntimeDispatch]
[JSEscapingArguments()]
[JSMutatedArguments()]
set;
}
/// <summary>
/// Returns a reference to an element of the packed array.
/// </summary>
[JSRuntimeDispatch]
[JSResultIsNew]
[JSIsPure]
void* GetReference (int index);
/// <summary>
/// Returns a proxy for the particular element of the packed array. You can use the proxy's members to manipulate the packed element directly.
/// </summary>
[JSRuntimeDispatch]
[JSResultIsNew]
[JSIsPure]
T GetItemProxy (int index);
/// <summary>
/// Reads an element out of the packed array, into result.
/// </summary>
[JSEscapingArguments()]
[JSMutatedArguments("result")]
[JSRuntimeDispatch]
void GetItemInto (int index, out T result);
[JSIsPure]
[JSRuntimeDispatch]
int Length { get; }
}
/// <summary>
/// A packed array that is allocated in the native (emscripten in JS) heap.
/// Because this array is allocated in the native heap, you must explicitly free it.
/// </summary>
public class NativePackedArray<T> : IDisposable
where T : struct
{
public readonly int Length;
private readonly T[] _Array;
private bool IsNotDisposed;
public NativePackedArray (int length) {
_Array = new T[length];
Length = length;
IsNotDisposed = true;
}
/// <summary>
/// If you load multiple emscripten modules, it's necessary to specify which one's heap you wish to allocate into.
/// </summary>
/// <param name="dllName">The name of the module (the name you pass to DllImport)</param>
public NativePackedArray (string dllName, int length)
: this (length) {
}
public T[] Array {
[JSIsPure]
get {
if (!IsNotDisposed)
throw new ObjectDisposedException("this");
return _Array;
}
}
public GCHandle AllocHandle () {
return GCHandle.Alloc(_Array);
}
public GCHandle AllocHandle (GCHandleType type) {
return GCHandle.Alloc(_Array, type);
}
[JSIsPure]
public static implicit operator T[] (NativePackedArray<T> nativeArray) {
if (!nativeArray.IsNotDisposed)
throw new ObjectDisposedException("nativeArray");
return nativeArray.Array;
}
[JSReplacement("JSIL.PackedArray.Dispose($this)")]
public void Dispose () {
if (!IsNotDisposed)
throw new ObjectDisposedException("this");
IsNotDisposed = false;
}
}
public static class PackedArray {
[JSReplacement("JSIL.PackedArray.New($T, $length)")]
[JSPackedArrayReturnValue]
public static T[] New<T> (int length)
where T : struct
{
return new T[length];
}
}
public static class TypedArrayExtensionMethods {
/// <summary>
/// If the specified array is backed by a typed array, returns its backing array buffer.
/// </summary>
[JSReplacement("JSIL.GetArrayBuffer($array)")]
[JSAllowPackedArrayArguments]
[JSIsPure]
public static dynamic GetArrayBuffer<T> (this T[] array)
where T : struct {
throw new NotImplementedException("Not supported when running as C#");
}
}
public static class PackedArrayExtensionMethods {
/// <summary>
/// If the specified array is a packed array, returns its backing typed array.
/// </summary>
[JSReplacement("JSIL.GetBackingTypedArray($array)")]
[JSAllowPackedArrayArguments]
[JSIsPure]
public static dynamic GetBackingTypedArray<T> (this T[] array)
where T : struct {
throw new NotImplementedException("Not supported when running as C#");
}
}
}