First "usable" version zig on spacetimedb
This commit is contained in:
parent
31de354ce4
commit
ba5cadfb1b
5 changed files with 568 additions and 254 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
spacetime logout
|
spacetime logout
|
||||||
spacetime login --server-issued-login local
|
spacetime login --server-issued-login local
|
||||||
spacetime publish -y --server local --bin-path=zig-out/bin/stdb-zig-helloworld.wasm
|
spacetime publish -y --server local --bin-path=zig-out/bin/stdb-zig-helloworld.wasm
|
||||||
|
DB_HASH=$(spacetime list 2>/dev/null | tail -1)
|
||||||
|
spacetime logs $DB_HASH
|
||||||
5
spacetimedb.sh
Executable file
5
spacetimedb.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
DB_HASH=$(spacetime list 2>/dev/null | tail -1)
|
||||||
|
func=$1;
|
||||||
|
shift;
|
||||||
|
spacetime "$func" $DB_HASH "$@"
|
||||||
163
src/main.zig
163
src/main.zig
|
|
@ -1,151 +1,66 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const spacetime = @import("spacetime.zig");
|
const spacetime = @import("spacetime.zig");
|
||||||
|
|
||||||
pub fn print(fmt: []const u8) void {
|
pub export fn spacetime_includes() void {
|
||||||
spacetime.console_log(2, null, 0, null, 0, 0, fmt.ptr, fmt.len);
|
_ = &spacetime.__describe_module__;
|
||||||
|
_ = &spacetime.__call_reducer__;
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleTablesDef = .{
|
pub const moduleTablesDef = .{
|
||||||
.Person = spacetime.Table(Person){ .name = "person" },
|
.Person = Person,
|
||||||
};
|
};
|
||||||
|
|
||||||
const moduleReducersDef = .{
|
pub const moduleReducersDef = .{
|
||||||
.Init = spacetime.Reducer(Init){ .lifecycle = .Init },
|
.Init = spacetime.Reducer(Init){ .lifecycle = .Init },
|
||||||
.OnConnect = spacetime.Reducer(OnConnect){ .lifecycle = .OnConnect },
|
.OnConnect = spacetime.Reducer(OnConnect){ .lifecycle = .OnConnect },
|
||||||
.OnDisconnect = spacetime.Reducer(OnDisconnect){ .lifecycle = .OnDisconnect },
|
.OnDisconnect = spacetime.Reducer(OnDisconnect){ .lifecycle = .OnDisconnect },
|
||||||
.add = spacetime.Reducer(add){ .param_names = &[_][]const u8{ "name" }},
|
.add = spacetime.Reducer(add){ .param_names = &[_][:0]const u8{ "name", "age", "blah" }},
|
||||||
.say_hello = spacetime.Reducer(say_hello){},
|
.say_hello = spacetime.Reducer(say_hello){},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn callReducer(comptime mdef: anytype, id: usize, args: anytype) void {
|
pub const Person = spacetime.Struct(.{
|
||||||
comptime var i = 0;
|
.name = "person",
|
||||||
inline for(std.meta.fields(@TypeOf(mdef))) |field| {
|
.fields = &[_]spacetime.StructFieldDecl{
|
||||||
if( comptime std.mem.endsWith(u8, @typeName(field.type), "spacetime_10.0__reducer_")) {
|
.{ .name = "name", .type = .String, },
|
||||||
if(id == i) {
|
.{ .name = "age", .type = .U32, },
|
||||||
const func = @as(*const field.type, @alignCast(@ptrCast(field.default_value.?))).*.func;
|
.{ .name = "blah", .type = .U64, },
|
||||||
if(std.meta.fields(@TypeOf(args)).len == @typeInfo(@TypeOf(func)).@"fn".params.len) {
|
},
|
||||||
return @call(.auto, func, args);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const name: []const u8 = @as(*const field.type, @alignCast(@ptrCast(field.default_value.?))).*.name orelse field.name;
|
|
||||||
var buf: [128]u8 = undefined;
|
|
||||||
print(std.fmt.bufPrint(&buf, "invalid number of args passed to {s}, expected {} got {}", .{name, @typeInfo(@TypeOf(func)).@"fn".params.len, std.meta.fields(@TypeOf(args)).len}) catch "!!!Error while printing last error!!!");
|
|
||||||
@panic("invalid number of args passed to func");
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn __describe_module__(description: spacetime.BytesSink) void {
|
pub fn Init(ctx: *spacetime.ReducerContext) void {
|
||||||
const allocator = std.heap.wasm_allocator;
|
|
||||||
print("Hello from Zig!");
|
|
||||||
|
|
||||||
var moduleDefBytes = std.ArrayList(u8).init(allocator);
|
|
||||||
defer moduleDefBytes.deinit();
|
|
||||||
|
|
||||||
spacetime.serialize_module(&moduleDefBytes, comptime spacetime.compile(moduleTablesDef, moduleReducersDef) catch |err| {
|
|
||||||
var buf: [1024]u8 = undefined;
|
|
||||||
const fmterr = std.fmt.bufPrint(&buf, "Error: {}", .{err}) catch {
|
|
||||||
@compileError("ERROR2: No Space Left! Expand error buffer size!");
|
|
||||||
};
|
|
||||||
@compileError(fmterr);
|
|
||||||
}) catch {
|
|
||||||
print("Allocator Error: Cannot continue!");
|
|
||||||
@panic("Allocator Error: Cannot continue!");
|
|
||||||
};
|
|
||||||
|
|
||||||
spacetime.write_to_sink(description, moduleDefBytes.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readStringArg(allocator: std.mem.Allocator, args: spacetime.BytesSource) ![]const u8 {
|
|
||||||
var maxbuf: [4]u8 = undefined;
|
|
||||||
const len_buf = try spacetime.read_bytes_source(args, &maxbuf);
|
|
||||||
const len: usize = std.mem.bytesToValue(u32, len_buf);
|
|
||||||
const string_buf = try allocator.alloc(u8, len);
|
|
||||||
return try spacetime.read_bytes_source(args, string_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn __call_reducer__(
|
|
||||||
id: usize,
|
|
||||||
sender_0: u64,
|
|
||||||
sender_1: u64,
|
|
||||||
sender_2: u64,
|
|
||||||
sender_3: u64,
|
|
||||||
conn_id_0: u64,
|
|
||||||
conn_id_1: u64,
|
|
||||||
timestamp: u64,
|
|
||||||
args: spacetime.BytesSource,
|
|
||||||
err: spacetime.BytesSink,
|
|
||||||
) i16 {
|
|
||||||
const allocator = std.heap.wasm_allocator;
|
|
||||||
_ = err;
|
|
||||||
//_ = args;
|
|
||||||
|
|
||||||
var ctx: spacetime.ReducerContext = .{
|
|
||||||
.indentity = std.mem.bytesAsValue(u256, std.mem.sliceAsBytes(&[_]u64{ sender_0, sender_1, sender_2, sender_3})).*,
|
|
||||||
.timestamp = timestamp,
|
|
||||||
.connection_id = std.mem.bytesAsValue(u128, std.mem.sliceAsBytes(&[_]u64{ conn_id_0, conn_id_1})).*,
|
|
||||||
.db = undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
switch(id) {
|
|
||||||
0...2, 4 => {
|
|
||||||
callReducer(moduleReducersDef, id, .{ &ctx });
|
|
||||||
},
|
|
||||||
3 => {
|
|
||||||
//var maxbuf: [1024]u8 = undefined;
|
|
||||||
//const buf = spacetime.read_bytes_source(args, &maxbuf) catch unreachable;
|
|
||||||
//const fmtbuf = std.fmt.allocPrint(allocator, "{any}", .{buf}) catch unreachable;
|
|
||||||
//defer allocator.free(fmtbuf);
|
|
||||||
//print(fmtbuf);
|
|
||||||
//manually parse args
|
|
||||||
const name: []const u8 = readStringArg(allocator, args) catch unreachable;
|
|
||||||
callReducer(moduleReducersDef, id, .{ &ctx, name });
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const Person = struct{
|
|
||||||
name: []u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn Init(_ctx: *spacetime.ReducerContext) void {
|
|
||||||
// Called when the module is initially published
|
// Called when the module is initially published
|
||||||
_ = _ctx;
|
_ = ctx;
|
||||||
print("Hello, Init!");
|
spacetime.print("[Init]");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn OnConnect(_ctx: *spacetime.ReducerContext) void {
|
pub fn OnConnect(ctx: *spacetime.ReducerContext) void {
|
||||||
// Called everytime a new client connects
|
// Called everytime a new client connects
|
||||||
_ = _ctx;
|
_ = ctx;
|
||||||
print("Hello, OnConnect!");
|
spacetime.print("[OnConnect]");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn OnDisconnect(_ctx: *spacetime.ReducerContext) void {
|
pub fn OnDisconnect(ctx: *spacetime.ReducerContext) void {
|
||||||
// Called everytime a client disconnects
|
// Called everytime a client disconnects
|
||||||
_ = _ctx;
|
_ = ctx;
|
||||||
print("Hello, OnDisconnect!");
|
spacetime.print("[OnDisconnect]");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(ctx: *spacetime.ReducerContext, name: []const u8) void {
|
pub fn add(ctx: *spacetime.ReducerContext, name: []const u8, age: u32, blah: u64) void {
|
||||||
//@compileLog(.{@typeInfo(@TypeOf(ctx.db))});// .person().insert(Person { name });
|
const personTable = ctx.*.db.get(moduleTablesDef.Person);
|
||||||
_ = ctx.db.get(moduleTablesDef.Person);
|
personTable.insert(Person{ .name = name, .age = age, .blah = blah });
|
||||||
//ctx.db.person().insert(Person{ .name = name });
|
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
print(std.fmt.bufPrint(&buf, "Hello, add({s})!", .{ name }) catch "[add] Error: name to long");
|
spacetime.print(std.fmt.bufPrint(&buf, "[add] {{{s}, {}}}!", .{ name, age }) catch "[add] Error: name to long");
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[spacetimedb::reducer]
|
pub fn say_hello(ctx: *spacetime.ReducerContext) void {
|
||||||
pub fn say_hello(_ctx: *spacetime.ReducerContext) void {
|
var personIter = ctx.*.db.get(moduleTablesDef.Person).iter();
|
||||||
//for person in ctx.db.person().iter() {
|
while(personIter.next() catch {
|
||||||
// log::info!("Hello, {}!", person.name);
|
@panic("person Iter errored!");
|
||||||
//}
|
}) |person| {
|
||||||
//log::info!("Hello, World!");
|
var buffer: [512]u8 = undefined;
|
||||||
_ = _ctx;
|
const msg = std.fmt.bufPrint(&buffer, "Hello, {s} (age: {})!", .{ person.name, person.age }) catch "<Unknown>";
|
||||||
print("Hello, World!");
|
spacetime.print(msg);
|
||||||
|
}
|
||||||
|
spacetime.print("Hello, World!");
|
||||||
}
|
}
|
||||||
|
|
@ -1,37 +1,37 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub const types = @import("spacetime/types.zig");
|
pub const st_types = @import("spacetime/types.zig");
|
||||||
pub const serializer = @import("spacetime/serializer.zig");
|
pub const serializer = @import("spacetime/serializer.zig");
|
||||||
|
|
||||||
pub const SumTypeVariant = types.SumTypeVariant;
|
pub const SumTypeVariant = st_types.SumTypeVariant;
|
||||||
pub const SumType = types.SumType;
|
pub const SumType = st_types.SumType;
|
||||||
pub const ArrayType = types.ArrayType;
|
pub const ArrayType = st_types.ArrayType;
|
||||||
pub const AlgebraicType = types.AlgebraicType;
|
pub const AlgebraicType = st_types.AlgebraicType;
|
||||||
pub const Typespace = types.Typespace;
|
pub const Typespace = st_types.Typespace;
|
||||||
pub const RawIdentifier = types.RawIdentifier;
|
pub const RawIdentifier = st_types.RawIdentifier;
|
||||||
pub const AlgebraicTypeRef = types.AlgebraicTypeRef;
|
pub const AlgebraicTypeRef = st_types.AlgebraicTypeRef;
|
||||||
pub const RawIndexAlgorithm = types.RawIndexAlgorithm;
|
pub const RawIndexAlgorithm = st_types.RawIndexAlgorithm;
|
||||||
pub const RawIndexDefV9 = types.RawIndexDefV9;
|
pub const RawIndexDefV9 = st_types.RawIndexDefV9;
|
||||||
pub const RawUniqueConstraintDataV9 = types.RawUniqueConstraintDataV9;
|
pub const RawUniqueConstraintDataV9 = st_types.RawUniqueConstraintDataV9;
|
||||||
pub const RawConstraintDataV9 = types.RawConstraintDataV9;
|
pub const RawConstraintDataV9 = st_types.RawConstraintDataV9;
|
||||||
pub const RawConstraintDefV9 = types.RawConstraintDefV9;
|
pub const RawConstraintDefV9 = st_types.RawConstraintDefV9;
|
||||||
pub const RawSequenceDefV9 = types.RawSequenceDefV9;
|
pub const RawSequenceDefV9 = st_types.RawSequenceDefV9;
|
||||||
pub const RawScheduleDefV9 = types.RawScheduleDefV9;
|
pub const RawScheduleDefV9 = st_types.RawScheduleDefV9;
|
||||||
pub const TableType = types.TableType;
|
pub const TableType = st_types.TableType;
|
||||||
pub const TableAccess = types.TableAccess;
|
pub const TableAccess = st_types.TableAccess;
|
||||||
pub const RawTableDefV9 = types.RawTableDefV9;
|
pub const RawTableDefV9 = st_types.RawTableDefV9;
|
||||||
pub const ProductTypeElement = types.ProductTypeElement;
|
pub const ProductTypeElement = st_types.ProductTypeElement;
|
||||||
pub const ProductType = types.ProductType;
|
pub const ProductType = st_types.ProductType;
|
||||||
pub const Lifecycle = types.Lifecycle;
|
pub const Lifecycle = st_types.Lifecycle;
|
||||||
pub const ReducerContext = types.ReducerContext;
|
pub const ReducerContext = st_types.ReducerContext;
|
||||||
pub const ReducerFn = types.ReducerFn;
|
pub const ReducerFn = st_types.ReducerFn;
|
||||||
pub const RawReducerDefV9 = types.RawReducerDefV9;
|
pub const RawReducerDefV9 = st_types.RawReducerDefV9;
|
||||||
pub const RawScopedTypeNameV9 = types.RawScopedTypeNameV9;
|
pub const RawScopedTypeNameV9 = st_types.RawScopedTypeNameV9;
|
||||||
pub const RawTypeDefV9 = types.RawTypeDefV9;
|
pub const RawTypeDefV9 = st_types.RawTypeDefV9;
|
||||||
pub const RawMiscModuleExportV9 = types.RawMiscModuleExportV9;
|
pub const RawMiscModuleExportV9 = st_types.RawMiscModuleExportV9;
|
||||||
pub const RawSql = types.RawSql;
|
pub const RawSql = st_types.RawSql;
|
||||||
pub const RawRowLevelSecurityDefV9 = types.RawRowLevelSecurityDefV9;
|
pub const RawRowLevelSecurityDefV9 = st_types.RawRowLevelSecurityDefV9;
|
||||||
pub const RawModuleDefV9 = types.RawModuleDefV9;
|
pub const RawModuleDefV9 = st_types.RawModuleDefV9;
|
||||||
|
|
||||||
pub const serialize_module = serializer.serialize_module;
|
pub const serialize_module = serializer.serialize_module;
|
||||||
|
|
||||||
|
|
@ -46,16 +46,31 @@ pub extern "spacetime_10.0" fn console_log(
|
||||||
message_len: usize,
|
message_len: usize,
|
||||||
) void;
|
) void;
|
||||||
|
|
||||||
|
pub fn print(fmt: []const u8) void {
|
||||||
|
console_log(2, null, 0, null, 0, 0, fmt.ptr, fmt.len);
|
||||||
|
}
|
||||||
|
|
||||||
pub const BytesSink = extern struct { inner: u32 };
|
pub const BytesSink = extern struct { inner: u32 };
|
||||||
pub const BytesSource = extern struct { inner: u32 };
|
pub const BytesSource = extern struct { inner: u32 };
|
||||||
|
|
||||||
pub extern "spacetime_10.0" fn bytes_sink_write(sink: BytesSink, buffer_ptr: [*c]const u8, buffer_len_ptr: *usize) u16;
|
pub extern "spacetime_10.0" fn bytes_sink_write(sink: BytesSink, buffer_ptr: [*c]const u8, buffer_len_ptr: *usize) u16;
|
||||||
pub extern "spacetime_10.0" fn bytes_source_read(source: BytesSource, buffer_ptr: [*c]u8, buffer_len_ptr: *usize) i16;
|
pub extern "spacetime_10.0" fn bytes_source_read(source: BytesSource, buffer_ptr: [*c]u8, buffer_len_ptr: *usize) i16;
|
||||||
|
|
||||||
const NO_SUCH_BYTES = 8;
|
pub const TableId = extern struct { _inner: u32, };
|
||||||
const NO_SPACE = 9;
|
pub extern "spacetime_10.0" fn table_id_from_name(name: [*c]const u8, name_len: usize, out: *TableId) u16;
|
||||||
|
pub extern "spacetime_10.0" fn datastore_insert_bsatn(table_id: TableId, row_ptr: [*c]const u8, row_len_ptr: *usize) u16;
|
||||||
|
|
||||||
|
pub const RowIter = extern struct { _inner: u32, pub const INVALID = RowIter{ ._inner = 0}; };
|
||||||
|
pub extern "spacetime_10.0" fn row_iter_bsatn_advance(iter: RowIter, buffer_ptr: [*c]u8, buffer_len_ptr: *usize) i16;
|
||||||
|
pub extern "spacetime_10.0" fn datastore_table_scan_bsatn(table_id: TableId, out: [*c]RowIter) u16;
|
||||||
|
|
||||||
|
pub const EXHAUSTED = -1;
|
||||||
|
pub const OK = 0;
|
||||||
|
pub const NO_SUCH_ITER = 6;
|
||||||
|
pub const NO_SUCH_BYTES = 8;
|
||||||
|
pub const NO_SPACE = 9;
|
||||||
|
pub const BUFFER_TOO_SMALL = 11;
|
||||||
|
|
||||||
/// Read `source` from the host fully into `buf`.
|
|
||||||
pub fn read_bytes_source(source: BytesSource, buf: []u8) ![]u8 {
|
pub fn read_bytes_source(source: BytesSource, buf: []u8) ![]u8 {
|
||||||
const INVALID: i16 = NO_SUCH_BYTES;
|
const INVALID: i16 = NO_SUCH_BYTES;
|
||||||
|
|
||||||
|
|
@ -63,7 +78,7 @@ pub fn read_bytes_source(source: BytesSource, buf: []u8) ![]u8 {
|
||||||
const ret = bytes_source_read(source, @ptrCast(buf), &buf_len);
|
const ret = bytes_source_read(source, @ptrCast(buf), &buf_len);
|
||||||
switch(ret) {
|
switch(ret) {
|
||||||
-1, 0 => {},
|
-1, 0 => {},
|
||||||
INVALID => @panic("invalid source passed"),
|
INVALID => return error.InvalidSource,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +91,6 @@ pub fn write_to_sink(sink: BytesSink, _buf: []const u8) void {
|
||||||
const len: *usize = &buf.len;
|
const len: *usize = &buf.len;
|
||||||
switch(bytes_sink_write(sink, buf.ptr, len)) {
|
switch(bytes_sink_write(sink, buf.ptr, len)) {
|
||||||
0 => {
|
0 => {
|
||||||
// Set `buf` to remainder and bail if it's empty.
|
|
||||||
buf = buf[len.*..];
|
buf = buf[len.*..];
|
||||||
if(buf.len == 0) {
|
if(buf.len == 0) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -89,40 +103,6 @@ pub fn write_to_sink(sink: BytesSink, _buf: []const u8) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn parse_reducers(root: type) []const RawReducerDefV9 {
|
|
||||||
// const decls = std.meta.declarations(root);
|
|
||||||
// //@compileLog(.{ decls });
|
|
||||||
|
|
||||||
// var reducers : []const RawReducerDefV9 = &[_]RawReducerDefV9{};
|
|
||||||
// _ = &reducers;
|
|
||||||
|
|
||||||
// inline for(decls) |decl| {
|
|
||||||
|
|
||||||
// const temp = @field(root, decl.name);
|
|
||||||
// const temp_type = @typeInfo(@TypeOf(temp));
|
|
||||||
// if(temp_type != .@"fn") continue;
|
|
||||||
// if(temp_type.@"fn".params[0].type.? != *ReducerContext) continue;
|
|
||||||
|
|
||||||
// const lifecycle: ?Lifecycle = blk: {
|
|
||||||
// if(std.mem.eql(u8, decl.name, "Init")) break :blk .Init;
|
|
||||||
// if(std.mem.eql(u8, decl.name, "OnConnect")) break :blk .OnConnect;
|
|
||||||
// if(std.mem.eql(u8, decl.name, "OnDisconnect")) break :blk .OnDisconnect;
|
|
||||||
// break :blk null;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// reducers = reducers ++ &[_]RawReducerDefV9{
|
|
||||||
// .{
|
|
||||||
// .name = decl.name,
|
|
||||||
// .params = .{ .elements = &[_]ProductTypeElement{} },
|
|
||||||
// .lifecycle = lifecycle,
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return reducers;
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub const Param = struct {
|
pub const Param = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
};
|
};
|
||||||
|
|
@ -132,29 +112,107 @@ pub fn Reducer(comptime func: anytype) type {
|
||||||
name: ?[]const u8 = null,
|
name: ?[]const u8 = null,
|
||||||
func: @TypeOf(func) = func,
|
func: @TypeOf(func) = func,
|
||||||
lifecycle: ?Lifecycle = null,
|
lifecycle: ?Lifecycle = null,
|
||||||
param_names: []const []const u8 = &[_][]const u8{},
|
param_names: []const [:0]const u8 = &[_][:0]const u8{},
|
||||||
};
|
};
|
||||||
|
|
||||||
//@compileLog(.{@TypeOf(func)});
|
|
||||||
|
|
||||||
return @"spacetime_10.0__reducer_";
|
return @"spacetime_10.0__reducer_";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Table(comptime table: anytype) type {
|
pub const StructFieldDecl = struct {
|
||||||
_ = table;
|
name: [:0]const u8,
|
||||||
|
type: AlgebraicType,
|
||||||
|
isPrimaryKey: bool = false,
|
||||||
|
autoInc: bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const StructDecl = struct {
|
||||||
|
name: []const u8,
|
||||||
|
fields: []const StructFieldDecl,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn spacetimeType2ZigType(t: AlgebraicType) type {
|
||||||
|
return switch (t) {
|
||||||
|
.String => []const u8,
|
||||||
|
.U32 => u32,
|
||||||
|
.U64 => u64,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Struct(comptime decl: StructDecl) type {
|
||||||
const @"spacetime_10.0__table_" = struct {
|
const @"spacetime_10.0__table_" = struct {
|
||||||
name: ?[]const u8 = null,
|
name: ?[]const u8 = decl.name,
|
||||||
table_type: TableType = .User,
|
table_type: TableType = .User,
|
||||||
table_access: TableAccess = .Private,
|
table_access: TableAccess = .Private,
|
||||||
};
|
};
|
||||||
return @"spacetime_10.0__table_";
|
|
||||||
|
var zigStructMembers: []const std.builtin.Type.StructField = &[_]std.builtin.Type.StructField{
|
||||||
|
std.builtin.Type.StructField{
|
||||||
|
.name = "spacetime_10.0__table_",
|
||||||
|
.type = @"spacetime_10.0__table_",
|
||||||
|
.default_value = @as(?*const anyopaque, &@"spacetime_10.0__table_"{}),
|
||||||
|
.is_comptime = false,
|
||||||
|
.alignment = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
inline for(decl.fields) |field| {
|
||||||
|
zigStructMembers = zigStructMembers ++ &[_]std.builtin.Type.StructField{
|
||||||
|
std.builtin.Type.StructField{
|
||||||
|
.name = field.name,
|
||||||
|
.type = spacetimeType2ZigType(field.type),
|
||||||
|
.default_value = null,
|
||||||
|
.is_comptime = false,
|
||||||
|
.alignment = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return @Type(.{
|
||||||
|
.@"struct" = std.builtin.Type.Struct{
|
||||||
|
.decls = &[_]std.builtin.Type.Declaration{},
|
||||||
|
.fields = zigStructMembers,
|
||||||
|
.is_tuple = false,
|
||||||
|
.layout = .@"auto",
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zigTypeToSpacetimeType(comptime param: ?type) !AlgebraicType {
|
pub fn readArg(allocator: std.mem.Allocator, args: BytesSource, comptime t: AlgebraicType) !spacetimeType2ZigType(t) {
|
||||||
|
switch(t) {
|
||||||
|
.String => {
|
||||||
|
var maxbuf: [4]u8 = undefined;
|
||||||
|
const len_buf = try read_bytes_source(args, &maxbuf);
|
||||||
|
const len: usize = std.mem.bytesToValue(u32, len_buf);
|
||||||
|
const string_buf = try allocator.alloc(u8, len);
|
||||||
|
return try read_bytes_source(args, string_buf);
|
||||||
|
},
|
||||||
|
.U32 => {
|
||||||
|
var maxbuf: [4]u8 = undefined;
|
||||||
|
const len_buf = try read_bytes_source(args, &maxbuf);
|
||||||
|
const len: u32 = std.mem.bytesToValue(u32, len_buf);
|
||||||
|
return len;
|
||||||
|
},
|
||||||
|
.U64 => {
|
||||||
|
var maxbuf: [8]u8 = undefined;
|
||||||
|
const len_buf = try read_bytes_source(args, &maxbuf);
|
||||||
|
const len: u64 = std.mem.bytesToValue(u64, len_buf);
|
||||||
|
return len;
|
||||||
|
},
|
||||||
|
else => @compileError("unsupported type in readArg!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zigTypeToSpacetimeType(comptime param: ?type) AlgebraicType {
|
||||||
if(param == null) @compileError("Null parameter type passed to zigParamsToSpacetimeParams");
|
if(param == null) @compileError("Null parameter type passed to zigParamsToSpacetimeParams");
|
||||||
return switch(param.?) {
|
return switch(param.?) {
|
||||||
[]const u8 => .{ .String = {} },
|
[]const u8 => .{ .String = {} },
|
||||||
else => error.ZigTypeNotSupported,
|
u32 => .{ .U32 = {}, },
|
||||||
|
u64 => .{ .U64 = {}, },
|
||||||
|
else => {
|
||||||
|
@compileLog(param.?);
|
||||||
|
@compileError("Unmatched type passed to zigTypeToSpacetimeType!");
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,32 +220,74 @@ pub fn compile(comptime moduleTables : anytype, comptime moduleReducers : anytyp
|
||||||
var def : RawModuleDefV9 = undefined;
|
var def : RawModuleDefV9 = undefined;
|
||||||
_ = &def;
|
_ = &def;
|
||||||
|
|
||||||
//def.reducers = def.reducers ++ &[_]RawReducerDefV9{};
|
|
||||||
var tables: []const RawTableDefV9 = &[_]RawTableDefV9{};
|
var tables: []const RawTableDefV9 = &[_]RawTableDefV9{};
|
||||||
var reducers: []const RawReducerDefV9 = &[_]RawReducerDefV9{};
|
var reducers: []const RawReducerDefV9 = &[_]RawReducerDefV9{};
|
||||||
|
|
||||||
|
var raw_types: []const AlgebraicType = &[_]AlgebraicType{};
|
||||||
|
var types: []const RawTypeDefV9 = &[_]RawTypeDefV9{};
|
||||||
|
|
||||||
inline for(std.meta.fields(@TypeOf(moduleTables))) |field| {
|
inline for(std.meta.fields(@TypeOf(moduleTables))) |field| {
|
||||||
const default_values = @as(*const field.type, @alignCast(@ptrCast(field.default_value.?))).*;
|
const default_values = @as(*const field.type, @alignCast(@ptrCast(field.default_value.?))).*;
|
||||||
const name: []const u8 = default_values.name orelse field.name;
|
const structInfo = blk: {
|
||||||
if( std.mem.endsWith(u8, @typeName(field.type), "spacetime_10.0__table_")) {
|
for(@typeInfo(default_values).@"struct".fields) |structInfoField| {
|
||||||
const table_type: TableType = default_values.table_type;
|
if(std.mem.eql(u8, structInfoField.name, "spacetime_10.0__table_")) {
|
||||||
const table_access: TableAccess = default_values.table_access;
|
break :blk structInfoField.type{};
|
||||||
tables = tables ++ &[_]RawTableDefV9{
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var product_type_ref: AlgebraicTypeRef = undefined;
|
||||||
|
{
|
||||||
|
var product_elements: []const ProductTypeElement = &[_]ProductTypeElement{};
|
||||||
|
|
||||||
|
inline for(@typeInfo(default_values).@"struct".fields, 0..) |table_field, i| {
|
||||||
|
if(i == 0) continue;
|
||||||
|
product_elements = product_elements ++ &[_]ProductTypeElement{
|
||||||
|
.{
|
||||||
|
.name = table_field.name,
|
||||||
|
.algebraic_type = zigTypeToSpacetimeType(table_field.type)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_types = raw_types ++ &[_]AlgebraicType{
|
||||||
.{
|
.{
|
||||||
.name = name,
|
.Product = .{
|
||||||
.product_type_ref = .{ .inner = 0, },
|
.elements = product_elements,
|
||||||
.primary_key = &[_]u16{},
|
}
|
||||||
.indexes = &[_]RawIndexDefV9{},
|
},
|
||||||
.constraints = &[_]RawConstraintDefV9{},
|
};
|
||||||
.sequences = &[_]RawSequenceDefV9{},
|
|
||||||
.schedule = null,
|
types = types ++ &[_]RawTypeDefV9{
|
||||||
.table_type = table_type,
|
.{
|
||||||
.table_access = table_access,
|
.name = .{
|
||||||
|
.scope = &[_][]u8{},
|
||||||
|
.name = field.name
|
||||||
|
},
|
||||||
|
.ty = .{ .inner = raw_types.len-1, },
|
||||||
|
.custom_ordering = true,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
continue;
|
|
||||||
|
product_type_ref.inner = types.len-1;
|
||||||
}
|
}
|
||||||
@compileLog(.{ field });
|
|
||||||
|
const name: []const u8 = structInfo.name.?;
|
||||||
|
const table_type: TableType = structInfo.table_type;
|
||||||
|
const table_access: TableAccess = structInfo.table_access;
|
||||||
|
tables = tables ++ &[_]RawTableDefV9{
|
||||||
|
.{
|
||||||
|
.name = name,
|
||||||
|
.product_type_ref = product_type_ref,
|
||||||
|
.primary_key = &[_]u16{},
|
||||||
|
.indexes = &[_]RawIndexDefV9{},
|
||||||
|
.constraints = &[_]RawConstraintDefV9{},
|
||||||
|
.sequences = &[_]RawSequenceDefV9{},
|
||||||
|
.schedule = null,
|
||||||
|
.table_type = table_type,
|
||||||
|
.table_access = table_access,
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline for(std.meta.fields(@TypeOf(moduleReducers))) |field| {
|
inline for(std.meta.fields(@TypeOf(moduleReducers))) |field| {
|
||||||
|
|
@ -196,17 +296,14 @@ pub fn compile(comptime moduleTables : anytype, comptime moduleReducers : anytyp
|
||||||
if( std.mem.endsWith(u8, @typeName(field.type), "spacetime_10.0__reducer_")) {
|
if( std.mem.endsWith(u8, @typeName(field.type), "spacetime_10.0__reducer_")) {
|
||||||
const lifecycle: ?Lifecycle = default_values.lifecycle;
|
const lifecycle: ?Lifecycle = default_values.lifecycle;
|
||||||
|
|
||||||
//parse the arguments
|
|
||||||
var params: []const ProductTypeElement = &[_]ProductTypeElement{};
|
var params: []const ProductTypeElement = &[_]ProductTypeElement{};
|
||||||
const param_names = default_values.param_names;
|
const param_names = default_values.param_names;
|
||||||
|
|
||||||
//@compileLog(.{@typeInfo(@TypeOf(default_values.func)).@"fn"});
|
|
||||||
for(@typeInfo(@TypeOf(default_values.func)).@"fn".params[1..], param_names) |param, param_name| {
|
for(@typeInfo(@TypeOf(default_values.func)).@"fn".params[1..], param_names) |param, param_name| {
|
||||||
//@compileLog(.{ name, param });
|
|
||||||
params = params ++ &[_]ProductTypeElement{
|
params = params ++ &[_]ProductTypeElement{
|
||||||
.{
|
.{
|
||||||
.name = param_name,
|
.name = param_name,
|
||||||
.algebraic_type = try zigTypeToSpacetimeType(param.type),
|
.algebraic_type = zigTypeToSpacetimeType(param.type),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -225,32 +322,161 @@ pub fn compile(comptime moduleTables : anytype, comptime moduleReducers : anytyp
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.typespace = .{
|
.typespace = .{
|
||||||
.types = &[_]AlgebraicType{
|
.types = raw_types,
|
||||||
.{
|
|
||||||
.Product = .{
|
|
||||||
.elements = &[_]ProductTypeElement{
|
|
||||||
.{
|
|
||||||
.name = "name",
|
|
||||||
.algebraic_type = .String,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
.tables = tables,
|
.tables = tables,
|
||||||
.reducers = reducers,
|
.reducers = reducers,
|
||||||
.types = &[_]RawTypeDefV9{
|
.types = types,
|
||||||
.{
|
|
||||||
.name = .{
|
|
||||||
.scope = &[_][]u8{},
|
|
||||||
.name = "Person"
|
|
||||||
},
|
|
||||||
.ty = .{ .inner = 0, },
|
|
||||||
.custom_ordering = true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.misc_exports = &[_]RawMiscModuleExportV9{},
|
.misc_exports = &[_]RawMiscModuleExportV9{},
|
||||||
.row_level_security = &[_]RawRowLevelSecurityDefV9{},
|
.row_level_security = &[_]RawRowLevelSecurityDefV9{},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn callReducer(comptime mdef: anytype, id: usize, args: anytype) void {
|
||||||
|
comptime var i = 0;
|
||||||
|
inline for(std.meta.fields(@TypeOf(mdef))) |field| {
|
||||||
|
if( comptime std.mem.endsWith(u8, @typeName(field.type), "spacetime_10.0__reducer_")) {
|
||||||
|
if(id == i) {
|
||||||
|
const func = @as(*const field.type, @alignCast(@ptrCast(field.default_value.?))).*.func;
|
||||||
|
if(std.meta.fields(@TypeOf(args)).len == @typeInfo(@TypeOf(func)).@"fn".params.len) {
|
||||||
|
return @call(.auto, func, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
const name: []const u8 = @as(*const field.type, @alignCast(@ptrCast(field.default_value.?))).*.name orelse field.name;
|
||||||
|
var buf: [128]u8 = undefined;
|
||||||
|
print(std.fmt.bufPrint(&buf, "invalid number of args passed to {s}, expected {} got {}", .{name, @typeInfo(@TypeOf(func)).@"fn".params.len, std.meta.fields(@TypeOf(args)).len}) catch "!!!Error while printing last error!!!");
|
||||||
|
@panic("invalid number of args passed to func");
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const moduleTablesDef = @import("root").moduleTablesDef;
|
||||||
|
const moduleReducersDef = @import("root").moduleReducersDef;
|
||||||
|
|
||||||
|
pub export fn __describe_module__(description: BytesSink) void {
|
||||||
|
const allocator = std.heap.wasm_allocator;
|
||||||
|
print("Hello from Zig!");
|
||||||
|
|
||||||
|
var moduleDefBytes = std.ArrayList(u8).init(allocator);
|
||||||
|
defer moduleDefBytes.deinit();
|
||||||
|
|
||||||
|
serialize_module(&moduleDefBytes, comptime compile(moduleTablesDef, moduleReducersDef) catch |err| {
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
const fmterr = std.fmt.bufPrint(&buf, "Error: {}", .{err}) catch {
|
||||||
|
@compileError("ERROR2: No Space Left! Expand error buffer size!");
|
||||||
|
};
|
||||||
|
@compileError(fmterr);
|
||||||
|
}) catch {
|
||||||
|
print("Allocator Error: Cannot continue!");
|
||||||
|
@panic("Allocator Error: Cannot continue!");
|
||||||
|
};
|
||||||
|
|
||||||
|
write_to_sink(description, moduleDefBytes.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn itoa(comptime value: anytype) [:0]const u8 {
|
||||||
|
comptime var s: []const u8 = &[_]u8{};
|
||||||
|
comptime var n = value;
|
||||||
|
if (n == 0) {
|
||||||
|
s = s ++ .{'0'};
|
||||||
|
} else {
|
||||||
|
comptime while (n != 0) {
|
||||||
|
s = s ++ .{'0' + (n % 10)};
|
||||||
|
n = n / 10;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return @ptrCast(s ++ .{0});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub export fn __call_reducer__(
|
||||||
|
id: usize,
|
||||||
|
sender_0: u64,
|
||||||
|
sender_1: u64,
|
||||||
|
sender_2: u64,
|
||||||
|
sender_3: u64,
|
||||||
|
conn_id_0: u64,
|
||||||
|
conn_id_1: u64,
|
||||||
|
timestamp: u64,
|
||||||
|
args: BytesSource,
|
||||||
|
err: BytesSink,
|
||||||
|
) i16 {
|
||||||
|
_ = err;
|
||||||
|
|
||||||
|
const allocator = std.heap.wasm_allocator;
|
||||||
|
|
||||||
|
var ctx: ReducerContext = .{
|
||||||
|
.indentity = std.mem.bytesAsValue(u256, std.mem.sliceAsBytes(&[_]u64{ sender_0, sender_1, sender_2, sender_3})).*,
|
||||||
|
.timestamp = timestamp,
|
||||||
|
.connection_id = std.mem.bytesAsValue(u128, std.mem.sliceAsBytes(&[_]u64{ conn_id_0, conn_id_1})).*,
|
||||||
|
.db = .{
|
||||||
|
.allocator = allocator,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
inline for(std.meta.fields(@TypeOf(moduleReducersDef))) |field| {
|
||||||
|
if( comptime std.mem.endsWith(u8, @typeName(field.type), "spacetime_10.0__reducer_")) {
|
||||||
|
defer i += 1;
|
||||||
|
if(id == i) {
|
||||||
|
const func = std.meta.fields(field.type)[std.meta.fieldIndex(field.type, "func").?].type;
|
||||||
|
const params = @typeInfo(func).@"fn".params;
|
||||||
|
const param_names = @field(moduleReducersDef, field.name).param_names;
|
||||||
|
comptime var argCount = 1;
|
||||||
|
comptime var argList: []const std.builtin.Type.StructField = &[_]std.builtin.Type.StructField{
|
||||||
|
std.builtin.Type.StructField{
|
||||||
|
.alignment = 0,
|
||||||
|
.default_value = null,
|
||||||
|
.is_comptime = false,
|
||||||
|
.name = "0",
|
||||||
|
.type = *ReducerContext,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline for(params[1..], param_names) |param, name| {
|
||||||
|
_ = name;
|
||||||
|
argList = argList ++ &[_]std.builtin.Type.StructField{
|
||||||
|
std.builtin.Type.StructField{
|
||||||
|
.alignment = 0,
|
||||||
|
.default_value = null,
|
||||||
|
.is_comptime = false,
|
||||||
|
.name = comptime itoa(argCount),
|
||||||
|
.type = param.type.?,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
argCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const argsStruct = @Type(.{
|
||||||
|
.@"struct" = std.builtin.Type.Struct{
|
||||||
|
.backing_integer = null,
|
||||||
|
.decls = &[_]std.builtin.Type.Declaration{},
|
||||||
|
.fields = argList,
|
||||||
|
.is_tuple = true,
|
||||||
|
.layout = .auto,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var constructedArg: argsStruct = undefined;
|
||||||
|
|
||||||
|
@field(constructedArg, "0") = &ctx;
|
||||||
|
|
||||||
|
if(args.inner != 0) {
|
||||||
|
inline for(params, 0..) |param, name| {
|
||||||
|
comptime if(name == 0) continue;
|
||||||
|
@field(constructedArg, itoa(name)) = readArg(allocator, args, zigTypeToSpacetimeType(param.type.?)) catch |err2| {
|
||||||
|
var buf: [512]u8 = undefined;
|
||||||
|
print(std.fmt.bufPrint(&buf, "Error: {}", .{err2}) catch "Expand Error Buffer!");
|
||||||
|
@panic("blah");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callReducer(moduleReducersDef, i, constructedArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const spacetime = @import("../spacetime.zig");
|
||||||
|
const console_log = spacetime.console_log;
|
||||||
|
const TableId = spacetime.TableId;
|
||||||
|
|
||||||
pub const Str = []const u8;
|
pub const Str = []const u8;
|
||||||
|
|
||||||
|
|
@ -12,7 +15,6 @@ pub const SumType = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ArrayType = struct {
|
pub const ArrayType = struct {
|
||||||
/// The base type every element of the array has.
|
|
||||||
elem_ty: []const AlgebraicType,
|
elem_ty: []const AlgebraicType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -126,18 +128,181 @@ pub const Lifecycle = enum {
|
||||||
OnDisconnect,
|
OnDisconnect,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn Table2Struct(comptime table_type: type) type {
|
pub fn StructSerializer(struct_type: type) fn(std.mem.Allocator, struct_type) std.mem.Allocator.Error![]u8 {
|
||||||
_ = table_type;
|
|
||||||
return struct {
|
|
||||||
|
|
||||||
|
const @"spacetime_10.0__table_" = std.meta.fields(struct_type)[std.meta.fieldIndex(struct_type, "spacetime_10.0__table_").?].type;
|
||||||
|
|
||||||
|
return struct {
|
||||||
|
pub fn serialize(allocator: std.mem.Allocator, data: struct_type) ![]u8 {
|
||||||
|
const fields = std.meta.fields(@TypeOf(data));
|
||||||
|
var size: usize = 0;
|
||||||
|
inline for(fields) |field| {
|
||||||
|
switch(field.type) {
|
||||||
|
[]const u8 => {
|
||||||
|
const val = @field(data, field.name);
|
||||||
|
size += 4 + val.len;
|
||||||
|
},
|
||||||
|
u32 => {
|
||||||
|
size += 4;
|
||||||
|
},
|
||||||
|
u64 => {
|
||||||
|
size += 8;
|
||||||
|
},
|
||||||
|
@"spacetime_10.0__table_" => {},
|
||||||
|
else => {
|
||||||
|
@compileLog(field.type);
|
||||||
|
@compileError("Unsupported type in StructSerializer");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mem = try allocator.alloc(u8, size);
|
||||||
|
var offset_mem = mem;
|
||||||
|
inline for(fields) |field| {
|
||||||
|
switch(field.type) {
|
||||||
|
[]const u8 => {
|
||||||
|
const val = @field(data, field.name);
|
||||||
|
std.mem.bytesAsValue(u32, offset_mem[0..4]).* = val.len;
|
||||||
|
std.mem.copyForwards(u8, offset_mem[4..], val);
|
||||||
|
offset_mem = offset_mem[4 + val.len ..];
|
||||||
|
},
|
||||||
|
u32 => {
|
||||||
|
const val = @field(data, field.name);
|
||||||
|
std.mem.bytesAsValue(u32, offset_mem[0..4]).* = val;
|
||||||
|
offset_mem = offset_mem[4..];
|
||||||
|
},
|
||||||
|
u64 => {
|
||||||
|
const val = @field(data, field.name);
|
||||||
|
std.mem.bytesAsValue(u64, offset_mem[0..4]).* = val;
|
||||||
|
offset_mem = offset_mem[8..];
|
||||||
|
},
|
||||||
|
@"spacetime_10.0__table_" => {},
|
||||||
|
else => @compileError("Unsupported type in StructSerializer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
}.serialize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn StructDeserializer(struct_type: type) fn(allocator: std.mem.Allocator, *[]const u8) std.mem.Allocator.Error!*struct_type {
|
||||||
|
|
||||||
|
const @"spacetime_10.0__table_" = std.meta.fields(struct_type)[std.meta.fieldIndex(struct_type, "spacetime_10.0__table_").?].type;
|
||||||
|
|
||||||
|
return struct {
|
||||||
|
pub fn deserialize(allocator: std.mem.Allocator, data: *[]const u8) std.mem.Allocator.Error!*struct_type {
|
||||||
|
const ret = try allocator.create(struct_type);
|
||||||
|
var offset_mem = data.*;
|
||||||
|
const fields = std.meta.fields(struct_type);
|
||||||
|
inline for(fields) |field| {
|
||||||
|
switch(field.type) {
|
||||||
|
[]const u8 => {
|
||||||
|
const len = std.mem.bytesAsValue(u32, offset_mem[0..4]).*;
|
||||||
|
const str = try allocator.dupe(u8, offset_mem[4..(4+len)]);
|
||||||
|
@field(ret.*, field.name) = str;
|
||||||
|
offset_mem = offset_mem[4+len ..];
|
||||||
|
},
|
||||||
|
u32 => {
|
||||||
|
@field(ret.*, field.name) = std.mem.bytesAsValue(u32, offset_mem[0..4]).*;
|
||||||
|
offset_mem = offset_mem[4..];
|
||||||
|
},
|
||||||
|
u64 => {
|
||||||
|
@field(ret.*, field.name) = std.mem.bytesAsValue(u64, offset_mem[0..4]).*;
|
||||||
|
offset_mem = offset_mem[8..];
|
||||||
|
},
|
||||||
|
@"spacetime_10.0__table_" => {},
|
||||||
|
else => @compileError("Unsupported type in StructDeserializer"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.* = offset_mem;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}.deserialize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Table2Struct(comptime table_type: type) type {
|
||||||
|
|
||||||
|
const fields = std.meta.fields(table_type);
|
||||||
|
const field = fields[std.meta.fieldIndex(table_type, "spacetime_10.0__table_").?];
|
||||||
|
const struct_type = @as(*const field.type, @alignCast(@ptrCast(field.default_value.?))).*;
|
||||||
|
const table_name: []const u8 = struct_type.name.?;
|
||||||
|
|
||||||
|
return struct {
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
pub const Iter = struct {
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
handle: spacetime.RowIter,
|
||||||
|
buffer: [0x20_000]u8 = undefined,
|
||||||
|
contents: []u8 = undefined,
|
||||||
|
last_ret: i16 = spacetime.OK,
|
||||||
|
|
||||||
|
pub fn next(self: *@This()) !?*table_type {
|
||||||
|
var buffer_len: usize = undefined;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
var ret = self.last_ret;
|
||||||
|
if(self.contents.len == 0) {
|
||||||
|
if(self.handle._inner == spacetime.RowIter.INVALID._inner) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
buffer_len = self.buffer.len;
|
||||||
|
ret = spacetime.row_iter_bsatn_advance(self.handle, @constCast(@ptrCast(&self.buffer)), &buffer_len);
|
||||||
|
self.contents = self.buffer[0..buffer_len];
|
||||||
|
|
||||||
|
if(ret == spacetime.EXHAUSTED) {
|
||||||
|
self.handle = spacetime.RowIter.INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ret) {
|
||||||
|
spacetime.EXHAUSTED, spacetime.OK => {
|
||||||
|
return StructDeserializer(table_type)(self.allocator, &self.contents);
|
||||||
|
},
|
||||||
|
spacetime.BUFFER_TOO_SMALL => {
|
||||||
|
return error.BUFFER_TOO_SMALL;
|
||||||
|
},
|
||||||
|
spacetime.NO_SUCH_ITER => {
|
||||||
|
return error.NO_SUCH_ITER;
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
var buffer: [512]u8 = undefined;
|
||||||
|
const msg = try std.fmt.bufPrint(&buffer, "Iter Err: {}!", .{ ret });
|
||||||
|
console_log(2, null, 0, null, 0, 0, msg.ptr, msg.len);
|
||||||
|
@panic("Fix Me!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn insert(self: @This(), data: table_type) void {
|
||||||
|
var id: TableId = undefined;
|
||||||
|
_ = spacetime.table_id_from_name(table_name.ptr, table_name.len, &id);
|
||||||
|
const raw_data = StructSerializer(table_type)(self.allocator, data) catch return;
|
||||||
|
defer self.allocator.free(raw_data);
|
||||||
|
var raw_data_len: usize = raw_data.len;
|
||||||
|
_ = spacetime.datastore_insert_bsatn(id, raw_data.ptr, &raw_data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(self: @This()) Iter {
|
||||||
|
var id: TableId = undefined;
|
||||||
|
_ = spacetime.table_id_from_name(table_name.ptr, table_name.len, &id);
|
||||||
|
var rowIter: spacetime.RowIter = undefined;
|
||||||
|
_ = spacetime.datastore_table_scan_bsatn(id, &rowIter);
|
||||||
|
return Iter{
|
||||||
|
.allocator = self.allocator,
|
||||||
|
.handle = rowIter,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Local = struct {
|
pub const Local = struct {
|
||||||
pub fn get(self: @This(), table: anytype) Table2Struct(@TypeOf(table)) {
|
allocator: std.mem.Allocator,
|
||||||
_ = self;
|
|
||||||
|
pub fn get(self: @This(), table: anytype) Table2Struct(table) {
|
||||||
return .{
|
return .{
|
||||||
//.name = "blahsss",
|
.allocator = self.allocator,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue