Skip to content

Commit

Permalink
wasm abi: impl row_iter_bsatn_advance & row_iter_bsatn_close
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Aug 26, 2024
1 parent fd209d1 commit b62234a
Show file tree
Hide file tree
Showing 15 changed files with 291 additions and 148 deletions.
9 changes: 7 additions & 2 deletions crates/bindings-csharp/Runtime/Exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public class BufferTooSmallException : StdbException
public override string Message => "The provided buffer is not large enough to store the data";
}

public class NoSuchIterException : StdbException
{
public override string Message => "The provided row iterator does not exist";
}

public class NoSuchBytesException : StdbException
{
public override string Message => "The provided bytes source or sink does not exist";
Expand All @@ -39,9 +44,9 @@ public class NoSpaceException : StdbException

public class UnknownException : StdbException
{
private readonly FFI.Errno code;
private readonly Errno code;

internal UnknownException(FFI.Errno code) => this.code = code;
internal UnknownException(Errno code) => this.code = code;

public override string Message => $"SpacetimeDB error code {code}";
}
34 changes: 18 additions & 16 deletions crates/bindings-csharp/Runtime/Internal/FFI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ public readonly record struct BytesSource(uint Handle)
[StructLayout(LayoutKind.Sequential)]
public readonly record struct BytesSink(uint Handle) { }

public enum Errno : short
{
EXHAUSTED = -1,
OK = 0,
HOST_CALL_FAILURE = 1,
NO_SUCH_TABLE = 4,
LOOKUP_NOT_FOUND = 2,
NO_SUCH_ITER = 6,
NO_SUCH_BYTES = 8,
NO_SPACE = 9,
BUFFER_TOO_SMALL = 11,
UNIQUE_ALREADY_EXISTS = 12,
}

#pragma warning disable IDE1006 // Naming Styles - Not applicable to FFI stuff.
internal static partial class FFI
{
Expand All @@ -32,18 +46,6 @@ internal static partial class FFI
#endif
;

public enum Errno : ushort
{
OK = 0,
HOST_CALL_FAILURE = 1,
NO_SUCH_TABLE = 4,
LOOKUP_NOT_FOUND = 2,
NO_SUCH_BYTES = 8,
NO_SPACE = 9,
BUFFER_TOO_SMALL = 11,
UNIQUE_ALREADY_EXISTS = 12,
}

[NativeMarshalling(typeof(Marshaller))]
public struct CheckedStatus
{
Expand Down Expand Up @@ -108,7 +110,7 @@ public readonly struct LogLevel(byte log_level)
[StructLayout(LayoutKind.Sequential)]
public readonly record struct RowIter(uint Handle)
{
public static readonly RowIter INVALID = new(uint.MaxValue);
public static readonly RowIter INVALID = new(0);
}

[LibraryImport(StdbNamespace)]
Expand Down Expand Up @@ -159,14 +161,14 @@ out RowIter out_
);

[LibraryImport(StdbNamespace)]
public static partial CheckedStatus _iter_advance(
public static partial Errno _row_iter_bsatn_advance(
RowIter iter_handle,
[MarshalUsing(CountElementName = nameof(buffer_len))] [Out] byte[] buffer,
ref uint buffer_len
);

[LibraryImport(StdbNamespace)]
public static partial void _iter_drop(RowIter iter_handle);
public static partial CheckedStatus _row_iter_bsatn_close(RowIter iter_handle);

[LibraryImport(StdbNamespace)]
public static partial void _volatile_nonatomic_schedule_immediate(
Expand All @@ -189,7 +191,7 @@ uint message_len
);

[LibraryImport(StdbNamespace)]
public static partial short _bytes_source_read(
public static partial Errno _bytes_source_read(
BytesSource source,
Span<byte> buffer,
ref uint buffer_len
Expand Down
44 changes: 33 additions & 11 deletions crates/bindings-csharp/Runtime/Internal/ITable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,53 @@ public class Enumerator(FFI.RowIter handle) : IDisposable

public bool MoveNext()
{
if (handle == FFI.RowIter.INVALID)
{
return false;
}

uint buffer_len;
while (true)
{
buffer_len = (uint)buffer.Length;
try
var ret = FFI._row_iter_bsatn_advance(handle, buffer, ref buffer_len);
if (ret == Errno.EXHAUSTED)
{
FFI._iter_advance(handle, buffer, ref buffer_len);
handle = FFI.RowIter.INVALID;
}
catch (BufferTooSmallException)
// On success, the only way `buffer_len == 0` is for the iterator to be exhausted.
// This happens when the host iterator was empty from the start.
System.Diagnostics.Debug.Assert(!(ret == Errno.OK && buffer_len == 0));
switch (ret)
{
buffer = new byte[buffer_len];
continue;
// Iterator advanced and may also be `EXHAUSTED`.
// When `OK`, we'll need to advance the iterator in the next call to `MoveNext`.
// In both cases, copy over the row data to `Current` from the scratch `buffer`.
case Errno.EXHAUSTED
or Errno.OK:
Current = new byte[buffer_len];
Array.Copy(buffer, 0, Current, 0, buffer_len);
return buffer_len != 0;
// Couldn't find the iterator, error!
case Errno.NO_SUCH_ITER:
throw new NoSuchIterException();
// The scratch `buffer` is too small to fit a row / chunk.
// Grow `buffer` and try again.
// The `buffer_len` will have been updated with the necessary size.
case Errno.BUFFER_TOO_SMALL:
buffer = new byte[buffer_len];
continue;
default:
throw new UnknownException(ret);
}
break;
}
Current = new byte[buffer_len];
Array.Copy(buffer, 0, Current, 0, buffer_len);
return buffer_len != 0;
}

public void Dispose()
{
if (!handle.Equals(FFI.RowIter.INVALID))
if (handle != FFI.RowIter.INVALID)
{
FFI._iter_drop(handle);
FFI._row_iter_bsatn_close(handle);
handle = FFI.RowIter.INVALID;
// Avoid running ~RowIter if Dispose was executed successfully.
GC.SuppressFinalize(this);
Expand Down
16 changes: 8 additions & 8 deletions crates/bindings-csharp/Runtime/Internal/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,24 +238,24 @@ private static byte[] Consume(this BytesSource source)
switch (ret)
{
// Host side source exhausted, we're done.
case -1:
case Errno.EXHAUSTED:
Array.Resize(ref buffer, (int)written);
return buffer;
// Wrote the entire spare capacity.
// Need to reserve more space in the buffer.
case 0 when written == buffer.Length:
case Errno.OK when written == buffer.Length:
Array.Resize(ref buffer, buffer.Length + 1024);
break;
// Host didn't write as much as possible.
// Try to read some more.
// The host will likely not trigger this branch (current host doesn't),
// but a module should be prepared for it.
case 0:
case Errno.OK:
break;
case (short)(ushort)FFI.Errno.NO_SUCH_BYTES:
case Errno.NO_SUCH_BYTES:
throw new NoSuchBytesException();
default:
throw new UnknownException((FFI.Errno)(ushort)ret);
throw new UnknownException(ret);
}
}
}
Expand Down Expand Up @@ -291,7 +291,7 @@ public static void __describe_module__(BytesSink description)
}
}

public static short __call_reducer__(
public static Errno __call_reducer__(
uint id,
ulong sender_0,
ulong sender_1,
Expand Down Expand Up @@ -323,14 +323,14 @@ BytesSink error
{
throw new Exception("Unrecognised extra bytes in the reducer arguments");
}
return 0; /* no exception */
return Errno.OK; /* no exception */
}
catch (Exception e)
{
var error_str = e.ToString();
var error_bytes = System.Text.Encoding.UTF8.GetBytes(error_str);
error.Write(error_bytes);
return (short)(ushort)FFI.Errno.HOST_CALL_FAILURE;
return Errno.HOST_CALL_FAILURE;
}
}
}
8 changes: 4 additions & 4 deletions crates/bindings-csharp/Runtime/bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ IMPORT(Status, _iter_start_filtered,
(TableId table_id, const uint8_t* filter, uint32_t filter_len,
RowIter* iter),
(table_id, filter, filter_len, iter));
IMPORT(Status, _iter_advance,
(RowIter iter, uint8_t* buffer, size_t* buffer_len),
(iter, buffer, buffer_len));
IMPORT(void, _iter_drop, (RowIter iter), (iter));
IMPORT(int16_t, _row_iter_bsatn_advance,
(RowIter iter, uint8_t* buffer_ptr, size_t* buffer_len_ptr),
(iter, buffer_ptr, buffer_len_ptr));
IMPORT(uint16_t, _row_iter_bsatn_close, (RowIter iter), (iter));
IMPORT(void, _volatile_nonatomic_schedule_immediate,
(uint8_t* name, size_t name_len, uint8_t* args, size_t args_len),
(name, name_len, args, args_len));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
<UnmanagedEntryPointsAssembly Include="SpacetimeDB.Runtime" />
<WasmImport Include="$(SpacetimeNamespace)!_console_log" />
<WasmImport Include="$(SpacetimeNamespace)!_get_table_id" />
<WasmImport Include="$(SpacetimeNamespace)!_create_index" />
<WasmImport Include="$(SpacetimeNamespace)!_iter_by_col_eq" />
<WasmImport Include="$(SpacetimeNamespace)!_insert" />
<WasmImport Include="$(SpacetimeNamespace)!_delete_by_col_eq" />
<WasmImport Include="$(SpacetimeNamespace)!_delete_by_rel" />
<WasmImport Include="$(SpacetimeNamespace)!_iter_start" />
<WasmImport Include="$(SpacetimeNamespace)!_iter_start_filtered" />
<WasmImport Include="$(SpacetimeNamespace)!_iter_next" />
<WasmImport Include="$(SpacetimeNamespace)!_iter_drop" />
<WasmImport Include="$(SpacetimeNamespace)!_row_iter_bsatn_advance" />
<WasmImport Include="$(SpacetimeNamespace)!_row_iter_bsatn_close" />
<WasmImport Include="$(SpacetimeNamespace)!_bytes_source_read" />
<WasmImport Include="$(SpacetimeNamespace)!_bytes_sink_write" />

Expand Down
Loading

0 comments on commit b62234a

Please sign in to comment.