Some changes with more on the way
This commit is contained in:
parent
acadefcaa5
commit
d144069dbe
5 changed files with 622 additions and 252 deletions
|
|
@ -2,4 +2,15 @@
|
||||||
DB_HASH=$(spacetime list 2>/dev/null | tail -1)
|
DB_HASH=$(spacetime list 2>/dev/null | tail -1)
|
||||||
func=$1;
|
func=$1;
|
||||||
shift;
|
shift;
|
||||||
|
|
||||||
|
if [[ "$func" == "publish" ]]; then
|
||||||
|
zig build -freference-trace=100 || exit 1
|
||||||
|
spacetime logout
|
||||||
|
spacetime login --server-issued-login local
|
||||||
|
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
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
|
||||||
spacetime "$func" $DB_HASH "$@"
|
spacetime "$func" $DB_HASH "$@"
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const spacetime = @import("spacetime.zig");
|
const spacetime = @import("spacetime.zig");
|
||||||
|
comptime { _ = spacetime; }
|
||||||
|
|
||||||
pub export fn spacetime_includes() void {
|
pub const std_options = std.Options{
|
||||||
_ = &spacetime.__describe_module__;
|
.log_level = .debug,
|
||||||
_ = &spacetime.__call_reducer__;
|
.logFn = spacetime.logFn,
|
||||||
}
|
};
|
||||||
|
|
||||||
pub const DbVector2 = struct {
|
pub const DbVector2 = struct {
|
||||||
x: f32,
|
x: f32,
|
||||||
|
|
|
||||||
|
|
@ -47,74 +47,122 @@ pub extern "spacetime_10.0" fn console_log(
|
||||||
message_len: usize,
|
message_len: usize,
|
||||||
) void;
|
) void;
|
||||||
|
|
||||||
pub fn print(fmt: []const u8) void {
|
pub fn logFn(comptime level: std.log.Level, comptime _: @TypeOf(.enum_literal), comptime fmt: []const u8, args: anytype) void {
|
||||||
console_log(2, null, 0, null, 0, 0, fmt.ptr, fmt.len);
|
const allocator = std.heap.wasm_allocator;
|
||||||
}
|
const msg = std.fmt.allocPrint(allocator, fmt, args) catch "debug_print allocation failure!";
|
||||||
|
defer allocator.free(msg);
|
||||||
pub fn debug_print(comptime fmt: []const u8, args: anytype) void {
|
const outLevel = switch(level) {
|
||||||
var buf: [512]u8 = undefined;
|
.err => 0,
|
||||||
var fbs = std.io.fixedBufferStream(&buf);
|
.warn => 1,
|
||||||
std.fmt.format(fbs.writer().any(), fmt, args) catch {
|
.info => 2,
|
||||||
return print("Expand the buf in debug_print!");
|
.debug => 3,
|
||||||
};
|
};
|
||||||
return print(fbs.getWritten());
|
console_log(outLevel, null, 0, null, 0, 0, msg.ptr, msg.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 const TableId = extern struct { _inner: u32, };
|
||||||
|
pub const RowIter = extern struct { _inner: u32, pub const INVALID = RowIter{ ._inner = 0}; };
|
||||||
|
pub const IndexId = extern struct{ _inner: u32 };
|
||||||
|
pub const ColId = extern struct { _inner: u16 };
|
||||||
|
|
||||||
|
pub const Identity = struct {
|
||||||
|
__identity__: u256,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Timestamp = struct {
|
||||||
|
__timestamp_micros_since_unix_epoch__: i64
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TimeDuration = struct {
|
||||||
|
__time_duration_micros__: i64
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ScheduleAt = union(enum){
|
||||||
|
Interval: TimeDuration,
|
||||||
|
Time: Timestamp,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ConnectionId = struct {
|
||||||
|
__connection_id__: u128,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SpacetimeValue = enum(u1) {
|
||||||
|
OK = 0,
|
||||||
|
EXHAUSTED = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SpacetimeError = error {
|
||||||
|
HOST_CALL_FAILURE,
|
||||||
|
NOT_IN_TRANSACTION,
|
||||||
|
BSATN_DECODE_ERROR,
|
||||||
|
NO_SUCH_TABLE,
|
||||||
|
NO_SUCH_INDEX,
|
||||||
|
NO_SUCH_ITER,
|
||||||
|
NO_SUCH_BYTES,
|
||||||
|
NO_SPACE,
|
||||||
|
BUFFER_TOO_SMALL,
|
||||||
|
UNIQUE_ALREADY_EXISTS,
|
||||||
|
SCHEDULE_AT_DELAY_TOO_LONG,
|
||||||
|
INDEX_NOT_UNIQUE,
|
||||||
|
NO_SUCH_ROW,
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
pub const TableId = extern struct { _inner: u32, };
|
|
||||||
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 table_id_from_name(name: [*c]const u8, name_len: usize, out: *TableId) u16;
|
||||||
|
pub extern "spacetime_10.0" fn index_id_from_name(name_ptr: [*c]const u8, name_len: usize, out: *IndexId) u16;
|
||||||
|
|
||||||
pub extern "spacetime_10.0" fn datastore_insert_bsatn(table_id: TableId, row_ptr: [*c]const u8, row_len_ptr: *usize) 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 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 extern "spacetime_10.0" fn datastore_table_scan_bsatn(table_id: TableId, out: [*c]RowIter) u16;
|
||||||
|
pub extern "spacetime_10.0" fn datastore_index_scan_range_bsatn( index_id: IndexId, prefix_ptr: [*c]const u8, prefix_len: usize, prefix_elems: ColId, rstart_ptr: [*c]const u8, rstart_len: usize, rend_ptr: [*c]const u8, rend_len: usize, out: *RowIter) u16;
|
||||||
|
pub extern "spacetime_10.0" fn row_iter_bsatn_close(iter: RowIter) u16;
|
||||||
|
|
||||||
pub const ScheduleAt = union(enum){
|
pub extern "spacetime_10.0" fn datastore_delete_by_index_scan_range_bsatn(index_id: IndexId, prefix_ptr: [*c]const u8, prefix_len: usize, prefix_elems: ColId, rstart_ptr: [*c]const u8, rstart_len: usize, rend_ptr: [*c]const u8, rend_len: usize, out: [*c]u32) u16;
|
||||||
Interval: struct{ __time_duration_micros__: i64 },
|
|
||||||
Time: struct{ __timestamp_micros_since_unix_epoch__: i64 },
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const EXHAUSTED = -1;
|
pub fn retMap(errVal: i17) !SpacetimeValue {
|
||||||
pub const OK = 0;
|
return switch(errVal) {
|
||||||
pub const NO_SUCH_ITER = 6;
|
-1 => SpacetimeValue.EXHAUSTED,
|
||||||
pub const NO_SUCH_BYTES = 8;
|
0 => SpacetimeValue.OK,
|
||||||
pub const NO_SPACE = 9;
|
1 => SpacetimeError.HOST_CALL_FAILURE,
|
||||||
pub const BUFFER_TOO_SMALL = 11;
|
2 => SpacetimeError.NOT_IN_TRANSACTION,
|
||||||
|
3 => SpacetimeError.BSATN_DECODE_ERROR,
|
||||||
|
4 => SpacetimeError.NO_SUCH_TABLE,
|
||||||
|
5 => SpacetimeError.NO_SUCH_INDEX,
|
||||||
|
6 => SpacetimeError.NO_SUCH_ITER,
|
||||||
|
8 => SpacetimeError.NO_SUCH_BYTES,
|
||||||
|
9 => SpacetimeError.NO_SPACE,
|
||||||
|
11 => SpacetimeError.BUFFER_TOO_SMALL,
|
||||||
|
12 => SpacetimeError.UNIQUE_ALREADY_EXISTS,
|
||||||
|
13 => SpacetimeError.SCHEDULE_AT_DELAY_TOO_LONG,
|
||||||
|
14 => SpacetimeError.INDEX_NOT_UNIQUE,
|
||||||
|
15 => SpacetimeError.NO_SUCH_ROW,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ReducerError = SpacetimeError || std.mem.Allocator.Error || std.fmt.BufPrintError;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
var buf_len = buf.len;
|
var buf_len = buf.len;
|
||||||
const ret = bytes_source_read(source, @ptrCast(buf), &buf_len);
|
_ = try retMap(bytes_source_read(source, @ptrCast(buf), &buf_len));
|
||||||
switch(ret) {
|
|
||||||
-1, 0 => {},
|
|
||||||
INVALID => return error.InvalidSource,
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf[0..buf_len];
|
return buf[0..buf_len];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_sink(sink: BytesSink, _buf: []const u8) void {
|
pub fn write_to_sink(sink: BytesSink, _buf: []const u8) !void {
|
||||||
var buf: []const u8 = _buf;
|
var buf: []const u8 = _buf;
|
||||||
while(true) {
|
while(true) {
|
||||||
const len: *usize = &buf.len;
|
const len: *usize = &buf.len;
|
||||||
switch(bytes_sink_write(sink, buf.ptr, len)) {
|
_ = try retMap(bytes_sink_write(sink, buf.ptr, len));
|
||||||
0 => {
|
|
||||||
buf = buf[len.*..];
|
buf = buf[len.*..];
|
||||||
if(buf.len == 0) {
|
if(buf.len == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
NO_SUCH_BYTES => @panic("invalid sink passed"),
|
|
||||||
NO_SPACE => @panic("no space left at sink"),
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,11 +181,25 @@ pub const StructDecl = struct {
|
||||||
fn spacetimeType2ZigType(t: AlgebraicType) type {
|
fn spacetimeType2ZigType(t: AlgebraicType) type {
|
||||||
return switch (t) {
|
return switch (t) {
|
||||||
.String => []const u8,
|
.String => []const u8,
|
||||||
.U32 => u32,
|
.Bool => bool,
|
||||||
.U64 => u64,
|
.I8 => i8,
|
||||||
|
.U8 => u8,
|
||||||
|
.I16 => i16,
|
||||||
|
.U16 => u16,
|
||||||
.I32 => i32,
|
.I32 => i32,
|
||||||
|
.U32 => u32,
|
||||||
.I64 => i64,
|
.I64 => i64,
|
||||||
else => unreachable,
|
.U64 => u64,
|
||||||
|
.I128 => i128,
|
||||||
|
.U128 => u128,
|
||||||
|
.I256 => i256,
|
||||||
|
.U256 => u256,
|
||||||
|
.F32 => f32,
|
||||||
|
.F64 => f64,
|
||||||
|
else => {
|
||||||
|
@compileLog(t);
|
||||||
|
@compileError("spacetimeType2ZigType: unsupported type!");
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,23 +208,54 @@ const StructFieldImpl = struct {
|
||||||
type: AlgebraicType,
|
type: AlgebraicType,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn readArg(allocator: std.mem.Allocator, args: BytesSource, comptime t: AlgebraicType) !spacetimeType2ZigType(t) {
|
pub fn readArg(allocator: std.mem.Allocator, args: BytesSource, comptime t: type) !t {
|
||||||
switch(t) {
|
switch(t) {
|
||||||
.String => {
|
[]const u8 => {
|
||||||
var maxbuf: [4]u8 = undefined;
|
var maxbuf: [4]u8 = undefined;
|
||||||
const len_buf = try read_bytes_source(args, &maxbuf);
|
const len_buf = try read_bytes_source(args, &maxbuf);
|
||||||
const len: usize = std.mem.bytesToValue(u32, len_buf);
|
const len: usize = std.mem.bytesToValue(u32, len_buf);
|
||||||
const string_buf = try allocator.alloc(u8, len);
|
const string_buf = try allocator.alloc(u8, len);
|
||||||
return try read_bytes_source(args, string_buf);
|
return try read_bytes_source(args, string_buf);
|
||||||
},
|
},
|
||||||
.U32, .U64, .I32, .I64 => {
|
i8, u8, i16, u16, i32, u32,
|
||||||
const read_type = spacetimeType2ZigType(t);
|
i64, u64, i128, u128, i256, u256,
|
||||||
|
f32, f64 => {
|
||||||
|
const read_type = t;
|
||||||
var maxbuf: [@sizeOf(read_type)]u8 = undefined;
|
var maxbuf: [@sizeOf(read_type)]u8 = undefined;
|
||||||
const len_buf = try read_bytes_source(args, &maxbuf);
|
const len_buf = try read_bytes_source(args, &maxbuf);
|
||||||
const len: read_type = std.mem.bytesToValue(read_type, len_buf);
|
return std.mem.bytesToValue(t, len_buf);
|
||||||
return len;
|
},
|
||||||
|
else => {
|
||||||
|
switch(@typeInfo(t)) {
|
||||||
|
.@"struct" => {
|
||||||
|
const fields = std.meta.fields(t);
|
||||||
|
var temp: t = undefined;
|
||||||
|
inline for(fields) |field| {
|
||||||
|
@field(temp, field.name) = try readArg(allocator, args, field.type);
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
},
|
||||||
|
.@"union" => {
|
||||||
|
const tagType = std.meta.Tag(t);
|
||||||
|
const intType = u8;
|
||||||
|
const tag: tagType = @enumFromInt(try readArg(allocator, args, intType));
|
||||||
|
var temp: t = undefined;//@unionInit(t, @tagName(tag), undefined);
|
||||||
|
switch(tag) {
|
||||||
|
inline else => |tag_field| {
|
||||||
|
const field = std.meta.fields(t)[@intFromEnum(tag_field)];
|
||||||
|
@field(temp, field.name) = (try readArg(allocator, args, field.type));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//@field(temp, field.name) = try readArg(allocator, args, @TypeOf(field));
|
||||||
|
return temp;
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
@compileLog(t);
|
||||||
|
@compileError("unsupported type in readArg!");
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
else => @compileError("unsupported type in readArg!"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,7 +268,7 @@ pub fn zigTypeToSpacetimeType(comptime param: ?type) AlgebraicType {
|
||||||
u32 => .{ .U32 = {}, },
|
u32 => .{ .U32 = {}, },
|
||||||
u64 => .{ .U64 = {}, },
|
u64 => .{ .U64 = {}, },
|
||||||
f32 => .{ .F32 = {}, },
|
f32 => .{ .F32 = {}, },
|
||||||
//Identity => .{ .U256 = {}, },
|
u256 => .{ .U256 = {}, },
|
||||||
else => blk: {
|
else => blk: {
|
||||||
if(@typeInfo(param.?) == .@"struct") {
|
if(@typeInfo(param.?) == .@"struct") {
|
||||||
var elements: []const ProductTypeElement = &.{};
|
var elements: []const ProductTypeElement = &.{};
|
||||||
|
|
@ -194,6 +287,23 @@ pub fn zigTypeToSpacetimeType(comptime param: ?type) AlgebraicType {
|
||||||
.elements = elements
|
.elements = elements
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} else if(@typeInfo(param.?) == .@"union") {
|
||||||
|
var variants: []const SumTypeVariant = &.{};
|
||||||
|
const fields = std.meta.fields(param.?);
|
||||||
|
for(fields) |field| {
|
||||||
|
variants = variants ++ &[_]SumTypeVariant{
|
||||||
|
SumTypeVariant{
|
||||||
|
.name = field.name,
|
||||||
|
.algebraic_type = zigTypeToSpacetimeType(field.type),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
break :blk .{
|
||||||
|
.Sum = SumType{
|
||||||
|
.variants = variants
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@compileLog(param.?);
|
@compileLog(param.?);
|
||||||
@compileError("Unmatched type passed to zigTypeToSpacetimeType!");
|
@compileError("Unmatched type passed to zigTypeToSpacetimeType!");
|
||||||
|
|
@ -277,6 +387,27 @@ pub fn addStructImpl(structImpls: *[]const StructImpl, layout: anytype) u32 {
|
||||||
return structImpls.len - 1;
|
return structImpls.len - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getStructImplOrType(structImpls: []const StructImpl, layout: type) AlgebraicType {
|
||||||
|
const name = blk: {
|
||||||
|
var temp: []const u8 = @typeName(layout);
|
||||||
|
if(std.mem.lastIndexOf(u8, temp, ".")) |idx|
|
||||||
|
temp = temp[idx+1..];
|
||||||
|
break :blk temp;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline for(structImpls, 0..) |structImpl, i| {
|
||||||
|
if(std.mem.eql(u8, structImpl.name, name)) {
|
||||||
|
return .{
|
||||||
|
.Ref = AlgebraicTypeRef{
|
||||||
|
.inner = i,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zigTypeToSpacetimeType(layout);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn compile(comptime moduleTables : []const Table, comptime moduleReducers : []const Reducer) !RawModuleDefV9 {
|
pub fn compile(comptime moduleTables : []const Table, comptime moduleReducers : []const Reducer) !RawModuleDefV9 {
|
||||||
var def : RawModuleDefV9 = undefined;
|
var def : RawModuleDefV9 = undefined;
|
||||||
_ = &def;
|
_ = &def;
|
||||||
|
|
@ -290,22 +421,67 @@ pub fn compile(comptime moduleTables : []const Table, comptime moduleReducers :
|
||||||
var structDecls: []const StructImpl = &[_]StructImpl{};
|
var structDecls: []const StructImpl = &[_]StructImpl{};
|
||||||
|
|
||||||
inline for(moduleTables) |table| {
|
inline for(moduleTables) |table| {
|
||||||
//const table: @as(*const field.type, @alignCast(@ptrCast(field.default_value))).* = .{};
|
const table_name: []const u8 = table.name.?;
|
||||||
const name: []const u8 = table.name.?;
|
|
||||||
const table_type: TableType = table.type;
|
const table_type: TableType = table.type;
|
||||||
const table_access: TableAccess = table.access;
|
const table_access: TableAccess = table.access;
|
||||||
const product_type_ref: AlgebraicTypeRef = AlgebraicTypeRef{
|
const product_type_ref: AlgebraicTypeRef = AlgebraicTypeRef{
|
||||||
.inner = addStructImpl(&structDecls, table.schema),
|
.inner = addStructImpl(&structDecls, table.schema),
|
||||||
};
|
};
|
||||||
|
const primary_key: []const u16 = blk: {
|
||||||
|
if(table.primary_key) |key| {
|
||||||
|
break :blk &[_]u16{ std.meta.fieldIndex(table.schema, key).?, };
|
||||||
|
}
|
||||||
|
break :blk &[_]u16{};
|
||||||
|
};
|
||||||
|
|
||||||
|
var indexes: []const RawIndexDefV9 = &[_]RawIndexDefV9{};
|
||||||
|
if(table.primary_key) |key| {
|
||||||
|
indexes = indexes ++ &[_]RawIndexDefV9{
|
||||||
|
RawIndexDefV9{
|
||||||
|
.name = null,
|
||||||
|
.accessor_name = key,
|
||||||
|
.algorithm = .{
|
||||||
|
.BTree = &.{ 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var constraints: []const RawConstraintDefV9 = &[_]RawConstraintDefV9{};
|
||||||
|
if(table.primary_key) |_| {
|
||||||
|
constraints = constraints ++ &[_]RawConstraintDefV9{
|
||||||
|
RawConstraintDefV9{
|
||||||
|
.name = null,
|
||||||
|
.data = .{ .unique = .{ .Columns = &.{ primary_key[0] } } },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const schedule: ?RawScheduleDefV9 = schedule_blk: {
|
||||||
|
if(table.schedule_reducer == null) break :schedule_blk null;
|
||||||
|
const column = column_blk: for(std.meta.fields(table.schema), 0..) |field, i| {
|
||||||
|
if(field.type == ScheduleAt) break :column_blk i;
|
||||||
|
};
|
||||||
|
const resolvedReducer = blk: for(moduleReducers) |reducer| {
|
||||||
|
if(reducer.func == table.schedule_reducer.?.func)
|
||||||
|
break :blk reducer;
|
||||||
|
};
|
||||||
|
break :schedule_blk RawScheduleDefV9{
|
||||||
|
.name = table_name ++ "_sched",
|
||||||
|
.reducer_name = resolvedReducer.name.?,
|
||||||
|
.scheduled_at_column = column,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
tableDefs = tableDefs ++ &[_]RawTableDefV9{
|
tableDefs = tableDefs ++ &[_]RawTableDefV9{
|
||||||
.{
|
.{
|
||||||
.name = name,
|
.name = table_name,
|
||||||
.product_type_ref = product_type_ref,
|
.product_type_ref = product_type_ref,
|
||||||
.primary_key = &[_]u16{},
|
.primary_key = primary_key,
|
||||||
.indexes = &[_]RawIndexDefV9{},
|
.indexes = indexes,
|
||||||
.constraints = &[_]RawConstraintDefV9{},
|
.constraints = constraints,
|
||||||
.sequences = &[_]RawSequenceDefV9{},
|
.sequences = &[_]RawSequenceDefV9{},
|
||||||
.schedule = null,
|
.schedule = schedule,
|
||||||
.table_type = table_type,
|
.table_type = table_type,
|
||||||
.table_access = table_access,
|
.table_access = table_access,
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +532,7 @@ pub fn compile(comptime moduleTables : []const Table, comptime moduleReducers :
|
||||||
params = params ++ &[_]ProductTypeElement{
|
params = params ++ &[_]ProductTypeElement{
|
||||||
.{
|
.{
|
||||||
.name = param_name,
|
.name = param_name,
|
||||||
.algebraic_type = zigTypeToSpacetimeType(param.type),
|
.algebraic_type = getStructImplOrType(structDecls, param.type.?),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -382,7 +558,7 @@ pub fn compile(comptime moduleTables : []const Table, comptime moduleReducers :
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callReducer(comptime mdef: []const Reducer, id: usize, args: anytype) void {
|
pub fn callReducer(comptime mdef: []const Reducer, id: usize, args: anytype) ReducerError!void {
|
||||||
inline for(mdef, 0..) |field, i| {
|
inline for(mdef, 0..) |field, i| {
|
||||||
if(id == i) {
|
if(id == i) {
|
||||||
const func = field.func_type;
|
const func = field.func_type;
|
||||||
|
|
@ -392,8 +568,7 @@ pub fn callReducer(comptime mdef: []const Reducer, id: usize, args: anytype) voi
|
||||||
}
|
}
|
||||||
|
|
||||||
const name: []const u8 = field.name.?;
|
const name: []const u8 = field.name.?;
|
||||||
var buf: [128]u8 = undefined;
|
std.log.err("invalid number of args passed to {s}, expected {} got {}", .{name, @typeInfo(func).@"fn".params.len, std.meta.fields(@TypeOf(args)).len});
|
||||||
print(std.fmt.bufPrint(&buf, "invalid number of args passed to {s}, expected {} got {}", .{name, @typeInfo(func).@"fn".params.len, std.meta.fields(@TypeOf(args)).len}) catch "!!!Error while printing last error!!!");
|
|
||||||
@panic("invalid number of args passed to func");
|
@panic("invalid number of args passed to func");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -401,7 +576,7 @@ pub fn callReducer(comptime mdef: []const Reducer, id: usize, args: anytype) voi
|
||||||
|
|
||||||
pub fn PrintModule(data: anytype) void {
|
pub fn PrintModule(data: anytype) void {
|
||||||
var buf: [64]u8 = undefined;
|
var buf: [64]u8 = undefined;
|
||||||
print(std.fmt.bufPrint(&buf, "\"{s}\": {{", .{@typeName(@TypeOf(data))}) catch "<Error>");
|
std.log.debug(std.fmt.bufPrint(&buf, "\"{s}\": {{", .{@typeName(@TypeOf(data))}) catch "<Error>");
|
||||||
switch(@TypeOf(data)) {
|
switch(@TypeOf(data)) {
|
||||||
RawModuleDefV9 => {
|
RawModuleDefV9 => {
|
||||||
PrintModule(data.typespace);
|
PrintModule(data.typespace);
|
||||||
|
|
@ -457,16 +632,16 @@ pub fn PrintModule(data: anytype) void {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[]const u8 => {
|
[]const u8 => {
|
||||||
print(std.fmt.bufPrint(&buf, "\"{s}\"", .{data}) catch "<Error>");
|
std.log.debug(std.fmt.bufPrint(&buf, "\"{s}\"", .{data}) catch "<Error>");
|
||||||
},
|
},
|
||||||
u32 => {
|
u32 => {
|
||||||
print(std.fmt.bufPrint(&buf, "{}", .{data}) catch "<Error>");
|
std.log.debug(std.fmt.bufPrint(&buf, "{}", .{data}) catch "<Error>");
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
print("\"...\"");
|
std.log.debug("\"...\"");
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
print("},");
|
std.log.debug("},");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Param = struct {
|
pub const Param = struct {
|
||||||
|
|
@ -487,6 +662,11 @@ pub const Table = struct {
|
||||||
schema: type,
|
schema: type,
|
||||||
type: TableType = .User,
|
type: TableType = .User,
|
||||||
access: TableAccess = .Private,
|
access: TableAccess = .Private,
|
||||||
|
primary_key: ?[]const u8 = null,
|
||||||
|
schedule_reducer: ?*const Reducer = null,
|
||||||
|
indexes: ?[]const []const u8 = null,
|
||||||
|
unique: ?[]const []const u8 = null,
|
||||||
|
autoinc: ?[]const []const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const reducers: []const Reducer = blk: {
|
pub const reducers: []const Reducer = blk: {
|
||||||
|
|
@ -521,6 +701,11 @@ pub const tables: []const Table = blk: {
|
||||||
.access = field.access,
|
.access = field.access,
|
||||||
.schema = field.schema,
|
.schema = field.schema,
|
||||||
.name = field.name orelse decl.name,
|
.name = field.name orelse decl.name,
|
||||||
|
.primary_key = field.primary_key,
|
||||||
|
.schedule_reducer = field.schedule_reducer,
|
||||||
|
.indexes = field.indexes,
|
||||||
|
.autoinc = field.autoinc,
|
||||||
|
.unique = field.unique,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -530,7 +715,7 @@ pub const tables: []const Table = blk: {
|
||||||
|
|
||||||
pub export fn __describe_module__(description: BytesSink) void {
|
pub export fn __describe_module__(description: BytesSink) void {
|
||||||
const allocator = std.heap.wasm_allocator;
|
const allocator = std.heap.wasm_allocator;
|
||||||
print("Hello from Zig!");
|
std.log.debug("Hello from Zig!", .{});
|
||||||
|
|
||||||
var moduleDefBytes = std.ArrayList(u8).init(allocator);
|
var moduleDefBytes = std.ArrayList(u8).init(allocator);
|
||||||
defer moduleDefBytes.deinit();
|
defer moduleDefBytes.deinit();
|
||||||
|
|
@ -543,12 +728,14 @@ pub export fn __describe_module__(description: BytesSink) void {
|
||||||
@compileError(fmterr);
|
@compileError(fmterr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//PrintModule(compiledModule);
|
||||||
|
|
||||||
serialize_module(&moduleDefBytes, compiledModule) catch {
|
serialize_module(&moduleDefBytes, compiledModule) catch {
|
||||||
print("Allocator Error: Cannot continue!");
|
std.log.err("Allocator Error: Cannot continue!", .{});
|
||||||
@panic("Allocator Error: Cannot continue!");
|
@panic("Allocator Error: Cannot continue!");
|
||||||
};
|
};
|
||||||
|
|
||||||
write_to_sink(description, moduleDefBytes.items);
|
write_to_sink(description, moduleDefBytes.items) catch @panic("Failed to write Module Descripton to SpacetimeDB!");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn __call_reducer__(
|
pub export fn __call_reducer__(
|
||||||
|
|
@ -568,9 +755,9 @@ pub export fn __call_reducer__(
|
||||||
const allocator = std.heap.wasm_allocator;
|
const allocator = std.heap.wasm_allocator;
|
||||||
|
|
||||||
var ctx: ReducerContext = .{
|
var ctx: ReducerContext = .{
|
||||||
.indentity = std.mem.bytesAsValue(u256, std.mem.sliceAsBytes(&[_]u64{ sender_0, sender_1, sender_2, sender_3})).*,
|
.sender = std.mem.bytesAsValue(Identity, std.mem.sliceAsBytes(&[_]u64{ sender_0, sender_1, sender_2, sender_3})).*,
|
||||||
.timestamp = timestamp,
|
.timestamp = Timestamp{ .__timestamp_micros_since_unix_epoch__ = @intCast(timestamp), },
|
||||||
.connection_id = std.mem.bytesAsValue(u128, std.mem.sliceAsBytes(&[_]u64{ conn_id_0, conn_id_1})).*,
|
.connection_id = std.mem.bytesAsValue(ConnectionId, std.mem.sliceAsBytes(&[_]u64{ conn_id_0, conn_id_1})).*,
|
||||||
.db = .{
|
.db = .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
},
|
},
|
||||||
|
|
@ -623,15 +810,19 @@ pub export fn __call_reducer__(
|
||||||
if(args.inner != 0) {
|
if(args.inner != 0) {
|
||||||
inline for(params, 0..) |param, name| {
|
inline for(params, 0..) |param, name| {
|
||||||
comptime if(name == 0) continue;
|
comptime if(name == 0) continue;
|
||||||
@field(constructedArg, utils.itoa(name)) = readArg(allocator, args, zigTypeToSpacetimeType(param.type.?)) catch |err2| {
|
@field(constructedArg, utils.itoa(name)) = readArg(allocator, args, param.type.?) catch |err2| {
|
||||||
var buf: [512]u8 = undefined;
|
std.log.err("Error: {}", .{err2});
|
||||||
print(std.fmt.bufPrint(&buf, "Error: {}", .{err2}) catch "Expand Error Buffer!");
|
|
||||||
@panic("blah");
|
@panic("blah");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callReducer(reducers, i, constructedArg);
|
callReducer(reducers, i, constructedArg) catch |errRet| {
|
||||||
|
std.log.debug("{s}", .{@errorName(errRet)});
|
||||||
|
if (@errorReturnTrace()) |trace| {
|
||||||
|
std.debug.dumpStackTrace(trace.*);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,16 +114,42 @@ fn serialize_raw_row_level_security_def_v9(array: *std.ArrayList(u8), val: RawRo
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn serialize_raw_index_algorithm(array: *std.ArrayList(u8), val: RawIndexAlgorithm) !void {
|
||||||
|
try array.appendSlice(&[_]u8{@intFromEnum(val)});
|
||||||
|
switch(val) {
|
||||||
|
.BTree, .Hash => |deref| {
|
||||||
|
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(deref.len))));
|
||||||
|
try array.appendSlice(std.mem.sliceAsBytes(deref.ptr[0..deref.len]));
|
||||||
|
},
|
||||||
|
.Direct => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn serialize_raw_index_def_v9(array: *std.ArrayList(u8), val: RawIndexDefV9) !void {
|
fn serialize_raw_index_def_v9(array: *std.ArrayList(u8), val: RawIndexDefV9) !void {
|
||||||
_ = array;
|
try array.appendSlice(&[_]u8{ @intFromBool(val.name == null) });
|
||||||
_ = val;
|
if(val.name) |name| {
|
||||||
unreachable;
|
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(name.len))));
|
||||||
|
try array.appendSlice(name);
|
||||||
|
}
|
||||||
|
try array.appendSlice(&[_]u8{ @intFromBool(val.accessor_name == null) });
|
||||||
|
if(val.accessor_name) |accessor_name| {
|
||||||
|
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(accessor_name.len))));
|
||||||
|
try array.appendSlice(accessor_name);
|
||||||
|
}
|
||||||
|
try serialize_raw_index_algorithm(array, val.algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_raw_constraint_def_v9(array: *std.ArrayList(u8), val: RawConstraintDefV9) !void {
|
fn serialize_raw_constraint_def_v9(array: *std.ArrayList(u8), val: RawConstraintDefV9) !void {
|
||||||
_ = array;
|
try array.appendSlice(&[_]u8{ @intFromBool(val.name == null) });
|
||||||
_ = val;
|
if(val.name) |name| {
|
||||||
unreachable;
|
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(name.len))));
|
||||||
|
try array.appendSlice(name);
|
||||||
|
}
|
||||||
|
// I have no idea what union this applies to, could be data or unique
|
||||||
|
// Both only have 1 option so right now it doesn't matter though.
|
||||||
|
try array.appendSlice(&.{ 0 });
|
||||||
|
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.data.unique.Columns.len))));
|
||||||
|
try array.appendSlice(std.mem.sliceAsBytes(val.data.unique.Columns.ptr[0..val.data.unique.Columns.len]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_raw_sequence_def_v9(array: *std.ArrayList(u8), val: RawSequenceDefV9) !void {
|
fn serialize_raw_sequence_def_v9(array: *std.ArrayList(u8), val: RawSequenceDefV9) !void {
|
||||||
|
|
@ -133,9 +159,15 @@ fn serialize_raw_sequence_def_v9(array: *std.ArrayList(u8), val: RawSequenceDefV
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_raw_schedule_def_v9(array: *std.ArrayList(u8), val: RawScheduleDefV9) !void {
|
fn serialize_raw_schedule_def_v9(array: *std.ArrayList(u8), val: RawScheduleDefV9) !void {
|
||||||
_ = array;
|
try array.appendSlice(&[_]u8{ @intFromBool(val.name == null) });
|
||||||
_ = val;
|
if(val.name) |name| {
|
||||||
unreachable;
|
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(name.len))));
|
||||||
|
try array.appendSlice(name);
|
||||||
|
}
|
||||||
|
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.reducer_name.len))));
|
||||||
|
try array.appendSlice(val.reducer_name);
|
||||||
|
|
||||||
|
try array.appendSlice(&std.mem.toBytes(@as(u16, @intCast(val.scheduled_at_column))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_table_type(array: *std.ArrayList(u8), val: TableType) !void {
|
fn serialize_table_type(array: *std.ArrayList(u8), val: TableType) !void {
|
||||||
|
|
@ -177,20 +209,18 @@ fn serialize_product_type(array: *std.ArrayList(u8), val: ProductType) std.mem.A
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_algebraic_type(array: *std.ArrayList(u8), val: AlgebraicType) !void {
|
fn serialize_algebraic_type(array: *std.ArrayList(u8), val: AlgebraicType) !void {
|
||||||
|
try array.appendSlice(&[_]u8{@intFromEnum(val)});
|
||||||
switch(val) {
|
switch(val) {
|
||||||
AlgebraicType.Product => |product| {
|
AlgebraicType.Product => |product| {
|
||||||
try array.appendSlice(&[_]u8{@intFromEnum(val)});
|
|
||||||
try serialize_product_type(array, product);
|
try serialize_product_type(array, product);
|
||||||
},
|
},
|
||||||
AlgebraicType.Ref => |ref| {
|
AlgebraicType.Ref => |ref| {
|
||||||
try array.appendSlice(&[_]u8{@intFromEnum(val)});
|
|
||||||
try array.appendSlice(&std.mem.toBytes(ref.inner));
|
try array.appendSlice(&std.mem.toBytes(ref.inner));
|
||||||
},
|
},
|
||||||
AlgebraicType.Sum => |sum| {
|
AlgebraicType.Sum => |sum| {
|
||||||
try array.appendSlice(&[_]u8{@intFromEnum(val)});
|
|
||||||
try serialize_sum_type(array, sum);
|
try serialize_sum_type(array, sum);
|
||||||
},
|
},
|
||||||
else => try array.appendSlice(&[_]u8{@intFromEnum(val)}),
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ const spacetime = @import("../spacetime.zig");
|
||||||
const console_log = spacetime.console_log;
|
const console_log = spacetime.console_log;
|
||||||
const TableId = spacetime.TableId;
|
const TableId = spacetime.TableId;
|
||||||
|
|
||||||
|
const SpacetimeValue = spacetime.SpacetimeValue;
|
||||||
|
const SpacetimeError = spacetime.SpacetimeError;
|
||||||
|
|
||||||
pub const Str = []const u8;
|
pub const Str = []const u8;
|
||||||
|
|
||||||
pub const SumTypeVariant = struct {
|
pub const SumTypeVariant = struct {
|
||||||
|
|
@ -52,7 +55,7 @@ pub const AlgebraicTypeRef = struct {
|
||||||
inner: u32,
|
inner: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RawIndexAlgorithm = union {
|
pub const RawIndexAlgorithm = union(enum) {
|
||||||
BTree: []const u16,
|
BTree: []const u16,
|
||||||
Hash: []const u16,
|
Hash: []const u16,
|
||||||
Direct: u16,
|
Direct: u16,
|
||||||
|
|
@ -64,11 +67,11 @@ pub const RawIndexDefV9 = struct {
|
||||||
algorithm: RawIndexAlgorithm,
|
algorithm: RawIndexAlgorithm,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RawUniqueConstraintDataV9 = union {
|
pub const RawUniqueConstraintDataV9 = union(enum) {
|
||||||
Columns: u16,
|
Columns: []const u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RawConstraintDataV9 = union {
|
pub const RawConstraintDataV9 = union(enum) {
|
||||||
unique: RawUniqueConstraintDataV9,
|
unique: RawUniqueConstraintDataV9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -78,18 +81,18 @@ pub const RawConstraintDefV9 = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RawSequenceDefV9 = struct {
|
pub const RawSequenceDefV9 = struct {
|
||||||
Name: ?Str,
|
name: ?Str,
|
||||||
Column: u16,
|
column: u16,
|
||||||
Start: ?i128,
|
start: ?i128,
|
||||||
MinValue: ?i128,
|
min_value: ?i128,
|
||||||
MaxValue: ?i128,
|
max_value: ?i128,
|
||||||
Increment: i128
|
increment: i128
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RawScheduleDefV9 = struct {
|
pub const RawScheduleDefV9 = struct {
|
||||||
Name: ?Str,
|
name: ?Str,
|
||||||
ReducerName: Str,
|
reducer_name: Str,
|
||||||
ScheduledAtColumn: u16
|
scheduled_at_column: u16
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const TableType = enum {
|
pub const TableType = enum {
|
||||||
|
|
@ -131,115 +134,105 @@ pub const Lifecycle = enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getUnionSize(data: anytype) usize {
|
fn getUnionSize(data: anytype) usize {
|
||||||
//const fields = std.meta.fields(@TypeOf(data));
|
return 1 + switch(data) {
|
||||||
var size: usize = 0;
|
inline else => |field| getDataSize(field),
|
||||||
|
};
|
||||||
switch(data) {
|
|
||||||
inline else => |field| {
|
|
||||||
switch(@TypeOf(field)) {
|
|
||||||
[]const u8 => {
|
|
||||||
const val = @field(data, field.name);
|
|
||||||
size = @max(size, 4 + val.len);
|
|
||||||
},
|
|
||||||
i64, u32, u64, f32 => {
|
|
||||||
size = @max(size, @sizeOf(field.type));
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
switch(@typeInfo(@TypeOf(field))) {
|
|
||||||
.@"struct" => {
|
|
||||||
size = @max(size, getStructSize(field));
|
|
||||||
},
|
|
||||||
.@"union" => {
|
|
||||||
size = @max(size, 1 + getUnionSize(field));
|
|
||||||
},
|
|
||||||
else => @compileError("Unsupported type in getUnionSize"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getStructSize(data: anytype) usize {
|
fn getStructSize(data: anytype) usize {
|
||||||
const fields = std.meta.fields(@TypeOf(data));
|
|
||||||
var size: usize = 0;
|
var size: usize = 0;
|
||||||
inline for(fields) |field| {
|
inline for(std.meta.fields(@TypeOf(data))) |field| {
|
||||||
switch(field.type) {
|
size += getDataSize(@field(data, field.name));
|
||||||
[]const u8 => {
|
|
||||||
const val = @field(data, field.name);
|
|
||||||
size += 4 + val.len;
|
|
||||||
},
|
|
||||||
i64, u32, u64, f32 => {
|
|
||||||
size += @sizeOf(field.type);
|
|
||||||
},
|
|
||||||
else => blk: {
|
|
||||||
if(@typeInfo(field.type) == .@"struct") {
|
|
||||||
size += getStructSize(@field(data, field.name));
|
|
||||||
break :blk;
|
|
||||||
} else if(@typeInfo(field.type) == .@"union") {
|
|
||||||
size += 1 + getUnionSize(@field(data, field.name));
|
|
||||||
break :blk;
|
|
||||||
}
|
}
|
||||||
@compileError("Unsupported type in getStructSize");
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getUnionData(data: anytype, mem: []u8) []u8 {
|
fn getDataSize(data: anytype) usize {
|
||||||
var offset_mem = mem;
|
return switch(@TypeOf(data)) {
|
||||||
switch(data) {
|
[]const u8 => 4 + data.len,
|
||||||
inline else => |field| {
|
i8, u8, i16, u16, i32, u32,
|
||||||
std.mem.bytesAsValue(u8, offset_mem[0..@sizeOf(u8)]).* = @intFromEnum(data);
|
i64, u64, i128, u128, i256, u256,
|
||||||
offset_mem = offset_mem[@sizeOf(u8)..];
|
f32, f64 => |data_type| @sizeOf(data_type),
|
||||||
offset_mem = getStructData(field, offset_mem);
|
else => |data_type| switch(@typeInfo(data_type)) {
|
||||||
|
.@"struct" => getStructSize(data),
|
||||||
|
.@"union" => getUnionSize(data),
|
||||||
|
.@"enum" => @sizeOf(data_type),
|
||||||
|
.@"enum_literal" => @compileError("enum literals can't be supported without the type info"),
|
||||||
|
.@"optional" => 1 + getDataSize(data),
|
||||||
|
else => {
|
||||||
|
@compileLog(data_type);
|
||||||
|
@compileError("Unsupported type in getStructSize");
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
return offset_mem;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getStructData(data: anytype, mem: []u8) []u8 {
|
fn getUnionData(data: anytype, mem: *[]u8) void {
|
||||||
const fields = std.meta.fields(@TypeOf(data));
|
const tag: u8 = @intFromEnum(data);
|
||||||
var offset_mem = mem;
|
appendValue(tag, mem);
|
||||||
inline for(fields) |field| {
|
switch(data) {
|
||||||
switch(field.type) {
|
inline else => |field| {
|
||||||
[]const u8 => {
|
appendValue(field, mem);
|
||||||
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 ..];
|
|
||||||
},
|
},
|
||||||
i32, i64, u32, u64, f32 => {
|
}
|
||||||
const val = @field(data, field.name);
|
}
|
||||||
std.mem.bytesAsValue(field.type, offset_mem[0..@sizeOf(field.type)]).* = val;
|
|
||||||
offset_mem = offset_mem[@sizeOf(field.type)..];
|
fn getStructData(data: anytype, mem: *[]u8) void {
|
||||||
|
const fields = std.meta.fields(@TypeOf(data));
|
||||||
|
inline for(fields) |field| {
|
||||||
|
appendValue(@field(data, field.name), mem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn appendValue(data: anytype, mem: *[]u8) void {
|
||||||
|
const data_type = @TypeOf(data);
|
||||||
|
switch(data_type) {
|
||||||
|
[]const u8 => {
|
||||||
|
std.mem.bytesAsValue(u32, mem.*[0..4]).* = data.len;
|
||||||
|
std.mem.copyForwards(u8, mem.*[4..], data);
|
||||||
|
mem.* = mem.*[4 + data.len ..];
|
||||||
|
},
|
||||||
|
i8, u8, i16, u16, i32, u32,
|
||||||
|
i64, u64, i128, u128, i256, u256,
|
||||||
|
f32, f64 => {
|
||||||
|
std.mem.bytesAsValue(data_type, mem.*[0..@sizeOf(data_type)]).* = data;
|
||||||
|
mem.* = mem.*[@sizeOf(data_type)..];
|
||||||
},
|
},
|
||||||
else => blk: {
|
else => blk: {
|
||||||
if(@typeInfo(field.type) == .@"struct") {
|
if(@typeInfo(data_type) == .@"struct") {
|
||||||
offset_mem = getStructData(@field(data, field.name), offset_mem);
|
getStructData(data, mem);
|
||||||
break :blk;
|
break :blk;
|
||||||
} else if(@typeInfo(field.type) == .@"union") {
|
} else if(@typeInfo(data_type) == .@"union") {
|
||||||
offset_mem = getUnionData(@field(data, field.name), offset_mem);
|
getUnionData(data, mem);
|
||||||
|
break :blk;
|
||||||
|
} else if(@typeInfo(data_type) == .@"optional") {
|
||||||
|
mem.*[0] = @intFromBool(data == null);
|
||||||
|
mem.* = mem.*[1..];
|
||||||
|
if(data != null) {
|
||||||
|
appendValue(data.?, mem);
|
||||||
|
}
|
||||||
|
break :blk;
|
||||||
|
} else if(@typeInfo(data_type) == .@"enum") {
|
||||||
|
std.mem.bytesAsValue(data_type, mem.*[0..@sizeOf(data_type)]).* = data;
|
||||||
|
mem.* = mem.*[@sizeOf(data_type)..];
|
||||||
break :blk;
|
break :blk;
|
||||||
}
|
}
|
||||||
@compileLog(field.type);
|
@compileLog(data_type);
|
||||||
@compileError("Unsupported type in StructSerializer");
|
@compileError("failed to append type!");
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return offset_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn StructSerializer(struct_type: type) fn(std.mem.Allocator, struct_type) std.mem.Allocator.Error![]u8 {
|
pub fn StructSerializer(struct_type: type) fn(std.mem.Allocator, struct_type) std.mem.Allocator.Error![]u8 {
|
||||||
return struct {
|
return struct {
|
||||||
pub fn serialize(allocator: std.mem.Allocator, data: struct_type) ![]u8 {
|
pub fn serialize(allocator: std.mem.Allocator, data: struct_type) ![]u8 {
|
||||||
const size: usize = getStructSize(data);
|
const size: usize = switch(@typeInfo(@TypeOf(data))) {
|
||||||
|
.@"struct" => getStructSize(data),
|
||||||
|
else => @compileError("A table schema has to be a struct!"),
|
||||||
|
};
|
||||||
const mem = try allocator.alloc(u8, size);
|
const mem = try allocator.alloc(u8, size);
|
||||||
_ = getStructData(data, mem);
|
var offset_mem = mem;
|
||||||
|
_ = getStructData(data, &offset_mem);
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
}.serialize;
|
}.serialize;
|
||||||
|
|
@ -265,7 +258,9 @@ pub fn UnionDeserializer(union_type: type) fn(allocator: std.mem.Allocator, *[]c
|
||||||
@field(ret.*, field.name) = str;
|
@field(ret.*, field.name) = str;
|
||||||
offset_mem = offset_mem[4+len ..];
|
offset_mem = offset_mem[4+len ..];
|
||||||
},
|
},
|
||||||
u32, u64, i32, i64, f32 => {
|
i8, u8, i16, u16, i32, u32,
|
||||||
|
i64, u64, i128, u128, i256, u256,
|
||||||
|
f32, f64 => {
|
||||||
@field(ret.*, field.name) = std.mem.bytesAsValue(field.type, offset_mem[0..@sizeOf(field.type)]).*;
|
@field(ret.*, field.name) = std.mem.bytesAsValue(field.type, offset_mem[0..@sizeOf(field.type)]).*;
|
||||||
offset_mem = offset_mem[@sizeOf(field.type)..];
|
offset_mem = offset_mem[@sizeOf(field.type)..];
|
||||||
},
|
},
|
||||||
|
|
@ -304,7 +299,10 @@ pub fn StructDeserializer(struct_type: type) fn(allocator: std.mem.Allocator, *[
|
||||||
@field(ret.*, field.name) = str;
|
@field(ret.*, field.name) = str;
|
||||||
offset_mem = offset_mem[4+len ..];
|
offset_mem = offset_mem[4+len ..];
|
||||||
},
|
},
|
||||||
u32, u64, i32, i64, f32 => {
|
i8, u8, i16, u16, i32, u32,
|
||||||
|
i64, u64, i128, u128, i256, u256,
|
||||||
|
f32, f64 => {
|
||||||
|
std.log.debug("field_type: {} (offset_mem.len: {})", .{field.type, offset_mem.len});
|
||||||
@field(ret.*, field.name) = std.mem.bytesAsValue(field.type, offset_mem[0..@sizeOf(field.type)]).*;
|
@field(ret.*, field.name) = std.mem.bytesAsValue(field.type, offset_mem[0..@sizeOf(field.type)]).*;
|
||||||
offset_mem = offset_mem[@sizeOf(field.type)..];
|
offset_mem = offset_mem[@sizeOf(field.type)..];
|
||||||
},
|
},
|
||||||
|
|
@ -322,11 +320,190 @@ pub fn StructDeserializer(struct_type: type) fn(allocator: std.mem.Allocator, *[
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.* = offset_mem;
|
data.* = offset_mem;
|
||||||
|
std.log.debug("StructDeserializer Ended!", .{});
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}.deserialize;
|
}.deserialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const BoundVariant = enum(u8)
|
||||||
|
{
|
||||||
|
Inclusive = 0,
|
||||||
|
Exclusive = 1,
|
||||||
|
Unbounded = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
noinline fn lineInfo() usize {
|
||||||
|
return @returnAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Iter(struct_type: type) type {
|
||||||
|
return struct {
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
handle: spacetime.RowIter,
|
||||||
|
buffer: [0x20_000]u8 = undefined,
|
||||||
|
contents: ?[]u8 = null,
|
||||||
|
last_ret: SpacetimeValue = .OK,
|
||||||
|
|
||||||
|
pub fn next(self: *@This()) spacetime.ReducerError!?*struct_type {
|
||||||
|
std.log.debug("line: {} (handle: {})", .{358, self.handle});
|
||||||
|
var buffer_len: usize = undefined;
|
||||||
|
//while(true)
|
||||||
|
//{
|
||||||
|
var ret: spacetime.SpacetimeValue = self.last_ret;
|
||||||
|
if(self.contents == null or self.contents.?.len == 0) {
|
||||||
|
std.log.debug("line: {} (contents: {any})", .{364, self.contents});
|
||||||
|
if(self.handle._inner == spacetime.RowIter.INVALID._inner) {
|
||||||
|
std.log.debug("line: {}", .{366});
|
||||||
|
|
||||||
|
self.contents = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
std.log.debug("line: {}", .{371});
|
||||||
|
|
||||||
|
buffer_len = self.buffer.len;
|
||||||
|
std.log.debug("line: {}", .{374});
|
||||||
|
ret = try spacetime.retMap(spacetime.row_iter_bsatn_advance(self.handle, @constCast(@ptrCast(&self.buffer)), &buffer_len));
|
||||||
|
std.log.debug("ret: {}", .{ret});
|
||||||
|
std.log.debug("self.buffer[0..buffer_len]: {any} {any} {any}", .{(&self.buffer).ptr, self.buffer.len, buffer_len});
|
||||||
|
self.contents = self.buffer[0..buffer_len];
|
||||||
|
std.log.debug("line: {}", .{379});
|
||||||
|
|
||||||
|
if(ret == .EXHAUSTED) {
|
||||||
|
std.log.debug("line: {}", .{382});
|
||||||
|
self.handle = spacetime.RowIter.INVALID;
|
||||||
|
}
|
||||||
|
std.log.debug("line: {}", .{385});
|
||||||
|
}
|
||||||
|
|
||||||
|
std.log.debug("{}", .{struct_type});
|
||||||
|
return StructDeserializer(struct_type)(self.allocator, &(self.contents.?));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn one_or_null(self: *@This()) ?*struct_type {
|
||||||
|
defer self.close();
|
||||||
|
return self.next() catch null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(self: *@This()) void {
|
||||||
|
_ = spacetime.row_iter_bsatn_close(self.handle);
|
||||||
|
self.handle = spacetime.RowIter.INVALID;
|
||||||
|
self.contents = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Column2ORM(comptime table_name: []const u8, comptime column_name: [:0]const u8) type {
|
||||||
|
const table = blk: {
|
||||||
|
for(spacetime.tables) |table| {
|
||||||
|
if(std.mem.eql(u8, table_name, table.name.?)) {
|
||||||
|
break :blk table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@compileError("Table " ++ table_name ++ " does not exist!");
|
||||||
|
};
|
||||||
|
const struct_type = table.schema;
|
||||||
|
const column_type = utils.getMemberDefaultType(struct_type, column_name);
|
||||||
|
|
||||||
|
const wrapped_type = @Type(.{
|
||||||
|
.@"struct" = std.builtin.Type.Struct{
|
||||||
|
.backing_integer = null,
|
||||||
|
.decls = &.{},
|
||||||
|
.fields = &.{
|
||||||
|
std.builtin.Type.StructField{
|
||||||
|
.alignment = @alignOf(column_type),
|
||||||
|
.default_value = null,
|
||||||
|
.is_comptime = false,
|
||||||
|
.name = column_name,
|
||||||
|
.type = column_type,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.is_tuple = false,
|
||||||
|
.layout = .auto,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return struct {
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
pub fn filter(self: @This(), val: wrapped_type) !Iter(struct_type) {
|
||||||
|
const temp_name: []const u8 = table_name ++ "_" ++ column_name ++ "_idx_btree";
|
||||||
|
var id = spacetime.IndexId{ ._inner = std.math.maxInt(u32)};
|
||||||
|
const err = try spacetime.retMap(spacetime.index_id_from_name(temp_name.ptr, temp_name.len, &id));
|
||||||
|
std.log.debug("index_id_from_name({}): {x}", .{err, id._inner});
|
||||||
|
|
||||||
|
const nVal: struct{ bounds: BoundVariant, val: wrapped_type } = .{
|
||||||
|
.bounds = .Inclusive,
|
||||||
|
.val = val,
|
||||||
|
};
|
||||||
|
|
||||||
|
const size: usize = getStructSize(nVal);
|
||||||
|
const mem = try self.allocator.alloc(u8, size);
|
||||||
|
var offset_mem = mem;
|
||||||
|
defer self.allocator.free(mem);
|
||||||
|
getStructData(nVal, &offset_mem);
|
||||||
|
|
||||||
|
const data = mem[0..size];
|
||||||
|
const rstart: []u8 = data[0..];
|
||||||
|
const rend: []u8 = data[0..];
|
||||||
|
|
||||||
|
var rowIter: spacetime.RowIter = undefined;
|
||||||
|
|
||||||
|
_ = try spacetime.retMap(spacetime.datastore_index_scan_range_bsatn(
|
||||||
|
id,
|
||||||
|
data.ptr, 0,
|
||||||
|
spacetime.ColId{ ._inner = 0},
|
||||||
|
rstart.ptr, rstart.len,
|
||||||
|
rend.ptr, rend.len,
|
||||||
|
&rowIter
|
||||||
|
));
|
||||||
|
|
||||||
|
return Iter(struct_type){
|
||||||
|
.allocator = self.allocator,
|
||||||
|
.handle = rowIter,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find(self: @This(), val: wrapped_type) !?*struct_type {
|
||||||
|
var iter = try self.filter(val);
|
||||||
|
return iter.one_or_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete(self: @This(), val: wrapped_type) !void {
|
||||||
|
const temp_name: []const u8 = table_name ++ "_" ++ column_name ++ "_idx_btree";
|
||||||
|
var id = spacetime.IndexId{ ._inner = std.math.maxInt(u32)};
|
||||||
|
_ = spacetime.index_id_from_name(temp_name.ptr, temp_name.len, &id);
|
||||||
|
|
||||||
|
const nVal: struct{ bounds: BoundVariant, val: wrapped_type } = .{
|
||||||
|
.bounds = .Inclusive,
|
||||||
|
.val = val,
|
||||||
|
};
|
||||||
|
|
||||||
|
const size: usize = getStructSize(nVal);
|
||||||
|
const mem = try self.allocator.alloc(u8, size);
|
||||||
|
var offset_mem = mem;
|
||||||
|
defer self.allocator.free(mem);
|
||||||
|
getStructData(nVal, &offset_mem);
|
||||||
|
|
||||||
|
const data = mem[0..size];
|
||||||
|
const rstart: []u8 = data[0..];
|
||||||
|
const rend: []u8 = data[0..];
|
||||||
|
|
||||||
|
var deleted_fields: u32 = undefined;
|
||||||
|
|
||||||
|
_ = spacetime.datastore_delete_by_index_scan_range_bsatn(
|
||||||
|
id,
|
||||||
|
data.ptr, 0,
|
||||||
|
spacetime.ColId{ ._inner = 0},
|
||||||
|
rstart.ptr, rstart.len,
|
||||||
|
rend.ptr, rend.len,
|
||||||
|
&deleted_fields
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn Table2ORM(comptime table_name: []const u8) type {
|
pub fn Table2ORM(comptime table_name: []const u8) type {
|
||||||
const table = blk: {
|
const table = blk: {
|
||||||
for(spacetime.tables) |table| {
|
for(spacetime.tables) |table| {
|
||||||
|
|
@ -340,71 +517,31 @@ pub fn Table2ORM(comptime table_name: []const u8) type {
|
||||||
return struct {
|
return struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
pub const Iter = struct {
|
pub fn insert(self: @This(), data: struct_type) !void {
|
||||||
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()) !?*struct_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(struct_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: struct_type) void {
|
|
||||||
var id: TableId = undefined;
|
var id: TableId = undefined;
|
||||||
_ = spacetime.table_id_from_name(table_name.ptr, table_name.len, &id);
|
_ = spacetime.table_id_from_name(table_name.ptr, table_name.len, &id);
|
||||||
const raw_data = StructSerializer(struct_type)(self.allocator, data) catch return;
|
const raw_data = try StructSerializer(struct_type)(self.allocator, data);
|
||||||
defer self.allocator.free(raw_data);
|
defer self.allocator.free(raw_data);
|
||||||
var raw_data_len: usize = raw_data.len;
|
var raw_data_len: usize = raw_data.len;
|
||||||
_ = spacetime.datastore_insert_bsatn(id, raw_data.ptr, &raw_data_len);
|
_ = spacetime.datastore_insert_bsatn(id, raw_data.ptr, &raw_data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(self: @This()) Iter {
|
pub fn iter(self: @This()) Iter(struct_type) {
|
||||||
var id: TableId = undefined;
|
var id: TableId = undefined;
|
||||||
_ = spacetime.table_id_from_name(table_name.ptr, table_name.len, &id);
|
_ = spacetime.table_id_from_name(table_name.ptr, table_name.len, &id);
|
||||||
var rowIter: spacetime.RowIter = undefined;
|
var rowIter: spacetime.RowIter = undefined;
|
||||||
_ = spacetime.datastore_table_scan_bsatn(id, &rowIter);
|
_ = spacetime.datastore_table_scan_bsatn(id, &rowIter);
|
||||||
return Iter{
|
return Iter(struct_type){
|
||||||
.allocator = self.allocator,
|
.allocator = self.allocator,
|
||||||
.handle = rowIter,
|
.handle = rowIter,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn col(self: @This(), comptime column_name: [:0]const u8) Column2ORM(table_name, column_name) {
|
||||||
|
return .{
|
||||||
|
.allocator = self.allocator,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,9 +556,9 @@ pub const Local = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ReducerContext = struct {
|
pub const ReducerContext = struct {
|
||||||
indentity: u256,
|
sender: spacetime.Identity,
|
||||||
timestamp: u64,
|
timestamp: spacetime.Timestamp,
|
||||||
connection_id: u128,
|
connection_id: spacetime.ConnectionId,
|
||||||
db: Local,
|
db: Local,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue