-
Notifications
You must be signed in to change notification settings - Fork 101
/
RawBindings.cs
239 lines (197 loc) · 7.37 KB
/
RawBindings.cs
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
namespace SpacetimeDB;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using static System.Text.Encoding;
public static partial class RawBindings
{
// For now this must match the name of the `.c` file (`bindings.c`).
// In the future C# will allow to specify Wasm import namespace in
// `LibraryImport` directly.
const string StdbNamespace =
#if EXPERIMENTAL_WASM_AOT
"spacetime_7.0"
#else
"bindings"
#endif
;
// This custom marshaller takes care of checking the status code
// returned from the host and throwing an exception if it's not 0.
// The only reason it doesn't return `void` is because the C# compiler
// doesn't treat `void` as a real type and doesn't allow it to be returned
// from custom marshallers, so we resort to an empty struct instead.
[CustomMarshaller(
typeof(CheckedStatus),
MarshalMode.ManagedToUnmanagedOut,
typeof(StatusMarshaller)
)]
static class StatusMarshaller
{
public static CheckedStatus ConvertToManaged(ushort status)
{
if (status != 0)
{
throw new Exception(
status switch
{
1 => "No such table",
2 => "Value or range provided not found in table",
3 => "Value with given unique identifier already exists",
_ => $"SpacetimeDB error code {status}",
}
);
}
return default;
}
}
[NativeMarshalling(typeof(StatusMarshaller))]
public struct CheckedStatus;
[StructLayout(LayoutKind.Sequential)]
public readonly struct TableId
{
private readonly uint table_id;
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct ColId(uint col_id)
{
private readonly uint col_id = col_id;
public static explicit operator uint(ColId col_id) => col_id.col_id;
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct IndexType
{
private readonly byte index_type;
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct LogLevel(byte log_level)
{
private readonly byte log_level = log_level;
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct ScheduleToken
{
private readonly ulong schedule_token;
}
// We need custom marshaller for `Buffer` because we return it by value
// instead of passing an `out` reference, and C# currently doesn't match
// the common Wasm C ABI in that a struct with a single field is supposed
// to have the same ABI as the field itself.
[CustomMarshaller(typeof(Buffer), MarshalMode.Default, typeof(BufferMarshaller))]
static class BufferMarshaller
{
public static Buffer ConvertToManaged(uint buf_handle) => new(buf_handle);
public static uint ConvertToUnmanaged(Buffer buf) => (uint)buf;
}
[StructLayout(LayoutKind.Sequential)]
[NativeMarshalling(typeof(BufferMarshaller))]
public readonly struct Buffer(uint handle) : IEquatable<Buffer>
{
private readonly uint handle = handle;
public static readonly Buffer INVALID = new(uint.MaxValue);
public bool Equals(Buffer other) => handle == other.handle;
public static explicit operator uint(Buffer buf) => buf.handle;
public override bool Equals(object? obj) => obj is Buffer other && Equals(other);
public override int GetHashCode() => handle.GetHashCode();
public static bool operator ==(Buffer left, Buffer right) => left.Equals(right);
public static bool operator !=(Buffer left, Buffer right) => !(left == right);
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct BufferIter(uint handle) : IEquatable<BufferIter>
{
private readonly uint handle = handle;
public static readonly BufferIter INVALID = new(uint.MaxValue);
public bool Equals(BufferIter other) => handle == other.handle;
public static explicit operator uint(BufferIter buf) => buf.handle;
public override bool Equals(object? obj) => obj is BufferIter other && Equals(other);
public override int GetHashCode() => handle.GetHashCode();
public static bool operator ==(BufferIter left, BufferIter right) => left.Equals(right);
public static bool operator !=(BufferIter left, BufferIter right) => !(left == right);
}
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _get_table_id(
[In] byte[] name,
uint name_len,
out TableId out_
);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _create_index(
[In] byte[] index_name,
uint index_name_len,
TableId table_id,
IndexType index_type,
[In] ColId[] col_ids,
uint col_len
);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _iter_by_col_eq(
TableId table_id,
ColId col_id,
[In] byte[] value,
uint value_len,
out Buffer out_
);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _insert(TableId table_id, byte[] row, uint row_len);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _delete_by_col_eq(
TableId table_id,
ColId col_id,
[In] byte[] value,
uint value_len,
out uint out_
);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _delete_by_rel(
TableId table_id,
[In] byte[] relation,
uint relation_len,
out uint out_
);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _iter_start(TableId table_id, out BufferIter out_);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _iter_start_filtered(
TableId table_id,
[In] byte[] filter,
uint filter_len,
out BufferIter out_
);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _iter_next(BufferIter iter_handle, out Buffer out_);
[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _iter_drop(BufferIter iter_handle);
[LibraryImport(StdbNamespace)]
public static partial void _console_log(
byte level,
[In] byte[] target,
uint target_len,
[In] byte[] filename,
uint filename_len,
uint line_number,
[In] byte[] message,
uint message_len
);
[LibraryImport(StdbNamespace)]
public static partial void _schedule_reducer(
[In] byte[] name,
uint name_len,
[In] byte[] args,
uint args_len,
ulong time,
out ScheduleToken out_
);
[LibraryImport(StdbNamespace)]
public static partial void _cancel_reducer(ScheduleToken schedule_token_handle);
[LibraryImport(StdbNamespace)]
public static partial uint _buffer_len(Buffer buf_handle);
[LibraryImport(StdbNamespace)]
public static partial void _buffer_consume(
Buffer buf_handle,
[MarshalUsing(CountElementName = nameof(dst_len))] [Out] byte[] dst,
uint dst_len
);
[LibraryImport(StdbNamespace)]
public static partial Buffer _buffer_alloc([In] byte[] data, uint data_len);
}