Basic Reducer functionality

This commit is contained in:
ookami125 2025-03-09 05:35:17 -04:00
parent 46a832ce42
commit cb2145b882
6 changed files with 628 additions and 445 deletions

View file

@ -9,11 +9,11 @@ pub fn build(b: *std.Build) void {
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
//const target = b.resolveTargetQuery(.{
// .cpu_arch = .wasm32,
// .os_tag = .freestanding,
//});
const target = b.standardTargetOptions(.{});
const target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.os_tag = .freestanding,
});
//const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not

3
publish-local.sh Executable file
View file

@ -0,0 +1,3 @@
spacetime logout
spacetime login --server-issued-login local
spacetime publish -y --server local --bin-path=zig-out/bin/stdb-zig-helloworld.wasm

View file

@ -1,426 +1,102 @@
const std = @import("std");
const spacetime = @import("spacetime.zig");
//extern "spacetime_10.0"
pub fn console_log(
level: u8,
target_ptr: [*c]const u8,
target_len: usize,
filename_ptr: [*c]const u8,
filename_len: usize,
line_number: u32,
message_ptr: [*c]const u8,
message_len: usize,
) void {
_ = level;
_ = target_ptr;
_ = target_len;
_ = filename_ptr;
_ = filename_len;
_ = line_number;
_ = message_ptr;
_ = message_len;
const reducers = spacetime.parse_reducers(@This());
pub fn print(fmt: []const u8) void {
spacetime.console_log(2, null, 0, null, 0, 0, fmt.ptr, fmt.len);
}
const BytesSink = extern struct { inner: u32 };
const BytesSource = extern struct { inner: u32 };
//extern "spacetime_10.0"
pub fn bytes_sink_write(sink: BytesSink, buffer_ptr: [*c]const u8, buffer_len_ptr: *usize) u16 {
_ = sink;
_ = buffer_ptr;
_ = buffer_len_ptr;
return 0;
const moduleDef: spacetime.RawModuleDefV9 = .{
.typespace = .{
.types = &[_]spacetime.AlgebraicType{
.{
.Product = .{
.elements = &[_]spacetime.ProductTypeElement{
.{
.name = "name",
.algebraic_type = .String,
}
}
const NO_SUCH_BYTES = 8;
const NO_SPACE = 9;
fn write_to_sink(sink: BytesSink, _buf: []const u8) void {
var buf: []const u8 = _buf;
while(true) {
const len: *usize = &buf.len;
switch(bytes_sink_write(sink, buf.ptr, len)) {
0 => {
// Set `buf` to remainder and bail if it's empty.
buf = buf[len.*..];
if(buf.len == 0) {
break;
}
},
NO_SUCH_BYTES => @panic("invalid sink passed"),
NO_SPACE => @panic("no space left at sink"),
else => unreachable,
}
}
}
//pub const ReducerFn = fn(ReducerContext, []u8) ReducerResult;
pub const SumTypeVariant = struct {
name: ?*[]u8,
algebraic_type: AlgebraicType,
};
pub const SumType = struct {
variants: []SumTypeVariant,
};
pub const ArrayType = struct {
/// The base type every element of the array has.
elem_ty: []AlgebraicType,
};
pub const AlgebraicType = union(enum) {
Ref: AlgebraicTypeRef,
Sum: SumType,
Product: ProductType,
Array: ArrayType,
String: []u8,
Bool: bool,
I8: i8,
U8: u8,
I16: i16,
U16: u16,
I32: i32,
U32: u32,
I64: i64,
U64: u64,
I128: i128,
U128: u128,
I256: i256,
U256: u256,
F32: f32,
F64: f64,
};
pub const Typespace = struct {
types: []AlgebraicType,
};
pub const RawIdentifier = *[*c]u8;
pub const AlgebraicTypeRef = struct {
inner: u32,
};
pub const RawIndexAlgorithm = union {
BTree: []u16,
Hash: []u16,
Direct: u16,
};
pub const RawIndexDefV9 = struct {
name: ?[]u8,
accessor_name: ?[]u8,
algorithm: RawIndexAlgorithm,
};
pub const RawUniqueConstraintDataV9 = union {
Columns: u16,
};
pub const RawConstraintDataV9 = union {
unique: RawUniqueConstraintDataV9,
};
pub const RawConstraintDefV9 = struct {
name: ?[]u8,
data: RawConstraintDataV9
};
pub const RawSequenceDefV9 = struct {
Name: ?[]u8,
Column: u16,
Start: ?i128,
MinValue: ?i128,
MaxValue: ?i128,
Increment: i128
};
pub const RawScheduleDefV9 = struct {
Name: ?[]u8,
ReducerName: []u8,
ScheduledAtColumn: u16
};
pub const TableType = enum {
System,
User,
};
pub const TableAccess = enum {
Public,
Private,
};
pub const RawTableDefV9 = struct {
name: RawIdentifier,
product_type_ref: AlgebraicTypeRef,
primary_key: []u16,
indexes: []RawIndexDefV9,
constraints: []RawConstraintDefV9,
sequences: []RawSequenceDefV9,
schedule: ?RawScheduleDefV9,
table_type: TableType,
table_access: TableAccess,
};
pub const ProductTypeElement = struct {
name: ?*[]u8,
algebraic_type: AlgebraicType,
};
pub const ProductType = struct {
elements: []ProductTypeElement,
};
pub const Lifecycle = enum {
Init,
OnConnect,
OnDisconnect,
};
pub const RawReducerDefV9 = struct{
name: RawIdentifier,
params: ProductType,
lifecycle: ?Lifecycle,
};
pub const RawScopedTypeNameV9 = struct {
scope: [][]u8,
name: []u8,
};
pub const RawTypeDefV9 = struct {
name: RawScopedTypeNameV9,
ty: AlgebraicTypeRef,
custom_ordering: bool,
};
pub const RawMiscModuleExportV9 = enum {};
pub const RawSql = *[*c]u8;
pub const RawRowLevelSecurityDefV9 = struct {
sql: RawSql,
};
pub const RawModuleDefV9 = struct {
typespace: Typespace,
tables: []RawTableDefV9,
reducers: []RawReducerDefV9,
types: []RawTypeDefV9,
misc_exports: []RawMiscModuleExportV9,
row_level_security: []RawRowLevelSecurityDefV9,
};
// V9(
// RawModuleDefV9 {
// typespace: Typespace [
// Product(
// ProductType {
// "name": String,
// },
// ),
// ],
// tables: [
// RawTableDefV9 {
// name: "person",
// product_type_ref: AlgebraicTypeRef(
// 0,
// ),
// primary_key: [],
// indexes: [],
// constraints: [],
// sequences: [],
// schedule: None,
// table_type: User,
// table_access: Private,
// },
// ],
// reducers: [
// RawReducerDefV9 {
// name: "add",
// params: ProductType {
// "name": String,
// },
// lifecycle: None,
// },
// RawReducerDefV9 {
// name: "identity_connected",
// params: ProductType {},
// lifecycle: Some(
// OnConnect,
// ),
// },
// RawReducerDefV9 {
// name: "identity_disconnected",
// params: ProductType {},
// lifecycle: Some(
// OnDisconnect,
// ),
// },
// RawReducerDefV9 {
// name: "init",
// params: ProductType {},
// lifecycle: Some(
// Init,
// ),
// },
// RawReducerDefV9 {
// name: "say_hello",
// params: ProductType {},
// lifecycle: None,
// },
// ],
// types: [
// RawTypeDefV9 {
// name: "Person",
// ty: AlgebraicTypeRef(
// 0,
// ),
// custom_ordering: true,
// },
// ],
// misc_exports: [],
// row_level_security: [],
// },
// )
const bytes = [_]u8{
1, //VP9
1, 0, 0, 0, //Typespace.types.len
2, //Typespace.types[0].tag(Product)
1, 0, 0, 0, //Typespace.types[0].tag(Product).elements.len
0, // optional?
4, 0, 0, 0, //Typespace.types[0].tag(Product).elements[0].name.len
110, 97, 109, 101, //Typespace.types[0].tag(Product).elements[0].name[0..4] "name"
4, //Typespace.types[0].tag(Product).elements[0].algebraic_type(String)
1, 0, 0, 0, //Typespace.types[0].tag(Product).elements[0].algebraic_type(String).len
6, 0, 0, 0, //tables[0].name.len
112, 101, 114, 115, 111, 110, //tables[0].name "person"
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1,
1,
1,
5, 0, 0, 0,
3, 0, 0, 0,
97, 100, 100,
1, 0, 0, 0,
0,
4, 0, 0, 0,
110, 97, 109, 101,
4,
1,
18, 0, 0, 0,
105, 100, 101, 110, 116, 105, 116, 121, 95, 99, 111, 110, 110, 101, 99, 116, 101, 100,
0, 0, 0, 0,
0,
1,
21, 0, 0, 0,
105, 100, 101, 110, 116, 105, 116, 121, 95, 100, 105, 115, 99, 111, 110, 110, 101, 99, 116, 101, 100,
0, 0, 0, 0,
0,
2,
4, 0, 0, 0,
105, 110, 105, 116,
0, 0, 0, 0,
0,
0,
9, 0, 0, 0,
115, 97, 121, 95, 104, 101, 108, 108, 111,
0, 0, 0, 0,
1,
1,
0, 0, 0, 0,
0, 0, 0,
6, 0, 0, 0,
80, 101, 114, 115, 111, 110,
0, 0, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0,
0
};
pub fn print(comptime fmt: []const u8) void {
console_log(0, null, 0, null, 0, 0, fmt.ptr, fmt.len);
}
pub fn module_write(val: anytype) void {
switch(@TypeOf(val)) {
RawModuleDefV9 => {
std.debug.print("{{ 1 }},\n", .{});
module_write(val.typespace);
},
Typespace => {
std.debug.print("{any},\n", .{std.mem.toBytes(@as(u32, @intCast(val.types.len)))});
for(val.types) |_type| {
module_write(_type);
},
.tables = &[_]spacetime.RawTableDefV9{
.{
.name = "person",
.product_type_ref = .{ .inner = 0, },
.primary_key = &[_]u16{},
.indexes = &[_]spacetime.RawIndexDefV9{},
.constraints = &[_]spacetime.RawConstraintDefV9{},
.sequences = &[_]spacetime.RawSequenceDefV9{},
.schedule = null,
.table_type = .User,
.table_access = .Private,
}
},
AlgebraicType => {
switch(val) {
AlgebraicType.String => |string| {
std.debug.print("{any},\n", .{string});
.reducers = reducers,
//&[_]spacetime.RawReducerDefV9{
//.{
// .name = "add",
// .params = .{
// .elements = &[_]spacetime.ProductTypeElement{
// .{
// .name = "name",
// .algebraic_type = .String,
// }
// }
// },
// .lifecycle = null,
//},
//.{
// .name = "identity_connected",
// .params = .{ .elements = &[_]spacetime.ProductTypeElement{} },
// .lifecycle = .OnConnect,
//},
//.{
// .name = "identity_disconnected",
// .params = .{ .elements = &[_]spacetime.ProductTypeElement{} },
// .lifecycle = .OnDisconnect,
//},
//.{
// .name = "init",
// .params = .{ .elements = &[_]spacetime.ProductTypeElement{} },
// .lifecycle = .Init,
//},
//.{
// .name = "say_hello",
// .params = .{ .elements = &[_]spacetime.ProductTypeElement{} },
// .lifecycle = null,
//}
//},
.types = &[_]spacetime.RawTypeDefV9{
.{
.name = .{
.scope = &[_][]u8{},
.name = "Person"
},
AlgebraicType.Product => |product| {
module_write(product);
},
else => std.debug.print("{any},\n", .{val}),
.ty = .{ .inner = 0, },
.custom_ordering = true,
}
},
ProductType => {
std.debug.print("{any},\n", .{std.mem.toBytes(@as(u32, @intCast(val.elements.len)))});
for(val.elements) |element| {
module_write(element);
}
.misc_exports = &[_]spacetime.RawMiscModuleExportV9{},
.row_level_security = &[_]spacetime.RawRowLevelSecurityDefV9{},
};
},
ProductTypeElement => {
if(val.name == null) {
std.debug.print("{{ 1 }},\n", .{});
} else {
std.debug.print("{{ 0 }},\n", .{});
std.debug.print("{any},\n", .{val.name});
}
module_write(val.algebraic_type);
},
else => |v| @compileLog(v, val),
}
}
export fn __describe_module__(description: spacetime.BytesSink) void {
const allocator = std.heap.wasm_allocator;
print("Hello from Zig!");
test {
const moduleDef: RawModuleDefV9 = std.mem.zeroes(RawModuleDefV9);
module_write(moduleDef);
}
var moduleDefBytes = std.ArrayList(u8).init(allocator);
defer moduleDefBytes.deinit();
export fn __describe_module__(description: BytesSink) void {
console_log(0, null, 0, null, 0, 0, "Hello from Zig!", 15);
spacetime.serialize_module(&moduleDefBytes, moduleDef) catch {
print("Allocator Error: Cannot continue!");
@panic("Allocator Error: Cannot continue!");
};
const moduleDef: RawModuleDefV9 = std.mem.zeroes(RawModuleDefV9);
//moduleDef.
// We need this explicit cast here to make `ToBytes` understand the types correctly.
//RawModuleDef versioned = new RawModuleDef.V9(moduleDef);
//var moduleBytes = IStructuralReadWrite.ToBytes(new RawModuleDef.BSATN(), versioned);
//description.Write(moduleBytes);
module_write(moduleDef);
write_to_sink(description, &bytes);
spacetime.write_to_sink(description, moduleDefBytes.items);
}
export fn __call_reducer__(
@ -432,41 +108,59 @@ export fn __call_reducer__(
conn_id_0: u64,
conn_id_1: u64,
timestamp: u64,
args: BytesSource,
err: BytesSink,
args: spacetime.BytesSource,
err: spacetime.BytesSink,
) i16 {
_ = id;
_ = sender_0;
_ = sender_1;
_ = sender_2;
_ = sender_3;
_ = conn_id_0;
_ = conn_id_1;
_ = timestamp;
_ = args;
_ = err;
const allocator = std.heap.wasm_allocator;
print(std.fmt.allocPrint(allocator, "id: {}", .{id}) catch "id: err");
print(std.fmt.allocPrint(allocator, "sender_0: {}", .{sender_0}) catch "sender_0: err");
print(std.fmt.allocPrint(allocator, "sender_1: {}", .{sender_1}) catch "sender_1: err");
print(std.fmt.allocPrint(allocator, "sender_2: {}", .{sender_2}) catch "sender_2: err");
print(std.fmt.allocPrint(allocator, "sender_3: {}", .{sender_3}) catch "sender_3: err");
print(std.fmt.allocPrint(allocator, "conn_id_0: {}", .{conn_id_0}) catch "conn_id_0: err");
print(std.fmt.allocPrint(allocator, "conn_id_1: {}", .{conn_id_1}) catch "conn_id_1: err");
print(std.fmt.allocPrint(allocator, "timestamp: {}", .{timestamp}) catch "timestamp: err");
print(std.fmt.allocPrint(allocator, "args: {}", .{args}) catch "args: err");
print(std.fmt.allocPrint(allocator, "err: {}", .{err}) catch "err: err");
return 0;
}
const ReducerContext = anyopaque;
pub const Person = struct{
name: []u8,
};
var module: RawModuleDefV9 = .{};
const ReducerFn = fn(*ReducerContext) void;
comptime {
for(@typeInfo(@This()).@"struct".decls) |decl| {
const field = @field(@This(), decl.name);
if(@typeInfo(@TypeOf(field)) != .@"fn") continue;
if(@TypeOf(field) != ReducerFn) continue;
@compileLog(.{field});
}
}
pub fn init(_ctx: *ReducerContext) void {
pub fn Init(_ctx: *spacetime.ReducerContext) void {
// Called when the module is initially published
_ = _ctx;
console_log(0, null, 0, null, 0, 0, "Hello, init!", 12);
print("Hello, Init!");
}
pub fn OnConnect(_ctx: *spacetime.ReducerContext) void {
// Called everytime a new client connects
_ = _ctx;
print("Hello, OnConnect!");
}
pub fn OnDisconnect(_ctx: *spacetime.ReducerContext) void {
// Called everytime a client disconnects
_ = _ctx;
print("Hello, OnDisconnect!");
}
pub fn add(_ctx: *spacetime.ReducerContext, name: []u8) void {
_ = _ctx;
_ = name;
//ctx.db.person().insert(Person { name });
}
//#[spacetimedb::reducer]
pub fn say_hello(_ctx: *spacetime.ReducerContext) void {
//for person in ctx.db.person().iter() {
// log::info!("Hello, {}!", person.name);
//}
//log::info!("Hello, World!");
_ = _ctx;
print("Hello, World!");
}

108
src/spacetime.zig Normal file
View file

@ -0,0 +1,108 @@
const std = @import("std");
pub const types = @import("spacetime/types.zig");
pub const serializer = @import("spacetime/serializer.zig");
pub const SumTypeVariant = types.SumTypeVariant;
pub const SumType = types.SumType;
pub const ArrayType = types.ArrayType;
pub const AlgebraicType = types.AlgebraicType;
pub const Typespace = types.Typespace;
pub const RawIdentifier = types.RawIdentifier;
pub const AlgebraicTypeRef = types.AlgebraicTypeRef;
pub const RawIndexAlgorithm = types.RawIndexAlgorithm;
pub const RawIndexDefV9 = types.RawIndexDefV9;
pub const RawUniqueConstraintDataV9 = types.RawUniqueConstraintDataV9;
pub const RawConstraintDataV9 = types.RawConstraintDataV9;
pub const RawConstraintDefV9 = types.RawConstraintDefV9;
pub const RawSequenceDefV9 = types.RawSequenceDefV9;
pub const RawScheduleDefV9 = types.RawScheduleDefV9;
pub const TableType = types.TableType;
pub const TableAccess = types.TableAccess;
pub const RawTableDefV9 = types.RawTableDefV9;
pub const ProductTypeElement = types.ProductTypeElement;
pub const ProductType = types.ProductType;
pub const Lifecycle = types.Lifecycle;
pub const ReducerContext = types.ReducerContext;
pub const ReducerFn = types.ReducerFn;
pub const RawReducerDefV9 = types.RawReducerDefV9;
pub const RawScopedTypeNameV9 = types.RawScopedTypeNameV9;
pub const RawTypeDefV9 = types.RawTypeDefV9;
pub const RawMiscModuleExportV9 = types.RawMiscModuleExportV9;
pub const RawSql = types.RawSql;
pub const RawRowLevelSecurityDefV9 = types.RawRowLevelSecurityDefV9;
pub const RawModuleDefV9 = types.RawModuleDefV9;
pub const serialize_module = serializer.serialize_module;
pub extern "spacetime_10.0" fn console_log(
level: u8,
target_ptr: [*c]const u8,
target_len: usize,
filename_ptr: [*c]const u8,
filename_len: usize,
line_number: u32,
message_ptr: [*c]const u8,
message_len: usize,
) void;
pub const BytesSink = 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;
const NO_SUCH_BYTES = 8;
const NO_SPACE = 9;
pub fn write_to_sink(sink: BytesSink, _buf: []const u8) void {
var buf: []const u8 = _buf;
while(true) {
const len: *usize = &buf.len;
switch(bytes_sink_write(sink, buf.ptr, len)) {
0 => {
// Set `buf` to remainder and bail if it's empty.
buf = buf[len.*..];
if(buf.len == 0) {
break;
}
},
NO_SUCH_BYTES => @panic("invalid sink passed"),
NO_SPACE => @panic("no space left at sink"),
else => unreachable,
}
}
}
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;
}

View file

@ -0,0 +1,211 @@
const std = @import("std");
pub const types = @import("types.zig");
pub const SumTypeVariant = types.SumTypeVariant;
pub const SumType = types.SumType;
pub const ArrayType = types.ArrayType;
pub const AlgebraicType = types.AlgebraicType;
pub const Typespace = types.Typespace;
pub const RawIdentifier = types.RawIdentifier;
pub const AlgebraicTypeRef = types.AlgebraicTypeRef;
pub const RawIndexAlgorithm = types.RawIndexAlgorithm;
pub const RawIndexDefV9 = types.RawIndexDefV9;
pub const RawUniqueConstraintDataV9 = types.RawUniqueConstraintDataV9;
pub const RawConstraintDataV9 = types.RawConstraintDataV9;
pub const RawConstraintDefV9 = types.RawConstraintDefV9;
pub const RawSequenceDefV9 = types.RawSequenceDefV9;
pub const RawScheduleDefV9 = types.RawScheduleDefV9;
pub const TableType = types.TableType;
pub const TableAccess = types.TableAccess;
pub const RawTableDefV9 = types.RawTableDefV9;
pub const ProductTypeElement = types.ProductTypeElement;
pub const ProductType = types.ProductType;
pub const Lifecycle = types.Lifecycle;
pub const ReducerContext = types.ReducerContext;
pub const ReducerFn = types.ReducerFn;
pub const RawReducerDefV9 = types.RawReducerDefV9;
pub const RawScopedTypeNameV9 = types.RawScopedTypeNameV9;
pub const RawTypeDefV9 = types.RawTypeDefV9;
pub const RawMiscModuleExportV9 = types.RawMiscModuleExportV9;
pub const RawSql = types.RawSql;
pub const RawRowLevelSecurityDefV9 = types.RawRowLevelSecurityDefV9;
pub const RawModuleDefV9 = types.RawModuleDefV9;
fn serialize_raw_table_def_v9(array: *std.ArrayList(u8), val: RawTableDefV9) !void {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.name.len))));
try array.appendSlice(val.name);
try serialize_algebraic_type_ref(array, val.product_type_ref);
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.primary_key.len))));
try array.appendSlice(std.mem.sliceAsBytes(val.primary_key));
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.indexes.len))));
for(val.indexes) |index| {
try serialize_raw_index_def_v9(array, index);
}
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.constraints.len))));
for(val.constraints) |constraint| {
try serialize_raw_constraint_def_v9(array, constraint);
}
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.sequences.len))));
for(val.sequences) |sequence| {
try serialize_raw_sequence_def_v9(array, sequence);
}
try array.appendSlice(&[_]u8{ @intFromBool(val.schedule == null) });
if(val.schedule) |schedule| {
try serialize_raw_schedule_def_v9(array, schedule);
}
try serialize_table_type(array, val.table_type);
try serialize_table_access(array, val.table_access);
}
fn serialize_raw_reducer_def_v9(array: *std.ArrayList(u8), val: RawReducerDefV9) !void {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.name.len))));
try array.appendSlice(val.name);
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.params.elements.len))));
for(val.params.elements) |element| {
try serialize_product_type_element(array, element);
}
try array.appendSlice(&[_]u8{ @intFromBool(val.lifecycle == null) });
if(val.lifecycle) |lifecycle| {
try serialize_lifecycle(array, lifecycle);
}
}
fn serialize_lifecycle(array: *std.ArrayList(u8), val: Lifecycle) !void {
try array.appendSlice(&[_]u8{@intFromEnum(val)});
}
fn serialize_algebraic_type_ref(array: *std.ArrayList(u8), val: AlgebraicTypeRef) !void {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.inner))));
}
fn serialize_raw_type_def_v9(array: *std.ArrayList(u8), val: RawTypeDefV9) !void {
try serialize_raw_scoped_type_name_v9(array, val.name);
try serialize_algebraic_type_ref(array, val.ty);
try serialize_bool(array, val.custom_ordering);
}
fn serialize_raw_scoped_type_name_v9(array: *std.ArrayList(u8), val: RawScopedTypeNameV9) !void {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.scope.len))));
for(val.scope) |sub_scope| {
try serialize_raw_identifier(array, sub_scope);
}
try serialize_raw_identifier(array, val.name);
}
fn serialize_raw_identifier(array: *std.ArrayList(u8), val: RawIdentifier) !void {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.len))));
try array.appendSlice(val);
}
fn serialize_bool(array: *std.ArrayList(u8), val: bool) !void {
try array.appendSlice(&[_]u8{@intFromBool(val)});
}
fn serialize_raw_misc_module_export_v9(array: *std.ArrayList(u8), val: RawMiscModuleExportV9) !void {
_ = array;
_ = val;
unreachable;
}
fn serialize_raw_row_level_security_def_v9(array: *std.ArrayList(u8), val: RawRowLevelSecurityDefV9) !void {
_ = array;
_ = val;
unreachable;
}
fn serialize_raw_index_def_v9(array: *std.ArrayList(u8), val: RawIndexDefV9) !void {
_ = array;
_ = val;
unreachable;
}
fn serialize_raw_constraint_def_v9(array: *std.ArrayList(u8), val: RawConstraintDefV9) !void {
_ = array;
_ = val;
unreachable;
}
fn serialize_raw_sequence_def_v9(array: *std.ArrayList(u8), val: RawSequenceDefV9) !void {
_ = array;
_ = val;
unreachable;
}
fn serialize_raw_schedule_def_v9(array: *std.ArrayList(u8), val: RawScheduleDefV9) !void {
_ = array;
_ = val;
unreachable;
}
fn serialize_table_type(array: *std.ArrayList(u8), val: TableType) !void {
try array.appendSlice(&[_]u8{@intFromEnum(val)});
}
fn serialize_table_access(array: *std.ArrayList(u8), val: TableAccess) !void {
try array.appendSlice(&[_]u8{@intFromEnum(val)});
}
fn serialize_product_type_element(array: *std.ArrayList(u8), val: ProductTypeElement) !void {
try array.appendSlice(&[_]u8{ @intFromBool(val.name == null) });
if(val.name) |name| {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(name.len))));
try array.appendSlice(name);
}
try serialize_algebraic_type(array, val.algebraic_type);
}
fn serialize_product_type(array: *std.ArrayList(u8), val: ProductType) std.mem.Allocator.Error!void {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.elements.len))));
for(val.elements) |element| {
try serialize_product_type_element(array, element);
}
}
fn serialize_algebraic_type(array: *std.ArrayList(u8), val: AlgebraicType) !void {
switch(val) {
AlgebraicType.Product => |product| {
try array.appendSlice(&[_]u8{@intFromEnum(val)});
try serialize_product_type(array, product);
},
else => try array.appendSlice(&[_]u8{@intFromEnum(val)}),
}
}
fn serialize_typespace(array: *std.ArrayList(u8), val: Typespace) !void {
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.types.len))));
for(val.types) |_type| {
try serialize_algebraic_type(array, _type);
}
}
pub fn serialize_module(array: *std.ArrayList(u8), val: RawModuleDefV9) !void {
try array.appendSlice(&[_]u8{1});
try serialize_typespace(array, val.typespace);
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.tables.len))));
for(val.tables) |table| {
try serialize_raw_table_def_v9(array, table);
}
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.reducers.len))));
for(val.reducers) |reducer| {
try serialize_raw_reducer_def_v9(array, reducer);
}
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.types.len))));
for(val.types) |_type| {
try serialize_raw_type_def_v9(array, _type);
}
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.misc_exports.len))));
for(val.misc_exports) |misc_export| {
try serialize_raw_misc_module_export_v9(array, misc_export);
}
try array.appendSlice(&std.mem.toBytes(@as(u32, @intCast(val.row_level_security.len))));
for(val.row_level_security) |rls| {
try serialize_raw_row_level_security_def_v9(array, rls);
}
}

167
src/spacetime/types.zig Normal file
View file

@ -0,0 +1,167 @@
pub const Str = []const u8;
pub const SumTypeVariant = struct {
name: ?Str,
algebraic_type: AlgebraicType,
};
pub const SumType = struct {
variants: []const SumTypeVariant,
};
pub const ArrayType = struct {
/// The base type every element of the array has.
elem_ty: []const AlgebraicType,
};
pub const AlgebraicType = union(enum) {
Ref: AlgebraicTypeRef,
Sum: SumType,
Product: ProductType,
Array: ArrayType,
String: void,
Bool: void,
I8: void,
U8: void,
I16: void,
U16: void,
I32: void,
U32: void,
I64: void,
U64: void,
I128: void,
U128: void,
I256: void,
U256: void,
F32: void,
F64: void,
};
pub const Typespace = struct {
types: []const AlgebraicType,
};
pub const RawIdentifier = Str;
pub const AlgebraicTypeRef = struct {
inner: u32,
};
pub const RawIndexAlgorithm = union {
BTree: []const u16,
Hash: []const u16,
Direct: u16,
};
pub const RawIndexDefV9 = struct {
name: ?Str,
accessor_name: ?Str,
algorithm: RawIndexAlgorithm,
};
pub const RawUniqueConstraintDataV9 = union {
Columns: u16,
};
pub const RawConstraintDataV9 = union {
unique: RawUniqueConstraintDataV9,
};
pub const RawConstraintDefV9 = struct {
name: ?Str,
data: RawConstraintDataV9
};
pub const RawSequenceDefV9 = struct {
Name: ?Str,
Column: u16,
Start: ?i128,
MinValue: ?i128,
MaxValue: ?i128,
Increment: i128
};
pub const RawScheduleDefV9 = struct {
Name: ?Str,
ReducerName: Str,
ScheduledAtColumn: u16
};
pub const TableType = enum {
System,
User,
};
pub const TableAccess = enum {
Public,
Private,
};
pub const RawTableDefV9 = struct {
name: RawIdentifier,
product_type_ref: AlgebraicTypeRef,
primary_key: []const u16,
indexes: []const RawIndexDefV9,
constraints: []const RawConstraintDefV9,
sequences: []const RawSequenceDefV9,
schedule: ?RawScheduleDefV9,
table_type: TableType,
table_access: TableAccess,
};
pub const ProductTypeElement = struct {
name: ?Str,
algebraic_type: AlgebraicType,
};
pub const ProductType = struct {
elements: []const ProductTypeElement,
};
pub const Lifecycle = enum {
Init,
OnConnect,
OnDisconnect,
};
pub const ReducerContext = struct {
indentity: u256,
};
pub const ReducerFn = fn(*ReducerContext) void;
pub const RawReducerDefV9 = struct {
name: RawIdentifier,
params: ProductType,
lifecycle: ?Lifecycle,
};
pub const RawScopedTypeNameV9 = struct {
scope: []RawIdentifier,
name: RawIdentifier,
};
pub const RawTypeDefV9 = struct {
name: RawScopedTypeNameV9,
ty: AlgebraicTypeRef,
custom_ordering: bool,
};
pub const RawMiscModuleExportV9 = enum {
RESERVED,
};
pub const RawSql = []u8;
pub const RawRowLevelSecurityDefV9 = struct {
sql: RawSql,
};
pub const RawModuleDefV9 = struct {
typespace: Typespace,
tables: []const RawTableDefV9,
reducers: []const RawReducerDefV9,
types: []const RawTypeDefV9,
misc_exports: []const RawMiscModuleExportV9,
row_level_security: []const RawRowLevelSecurityDefV9,
};