Fixes for stage1 compiler

This commit is contained in:
jaina heartles 2022-11-10 01:53:09 -08:00
parent 181e57a631
commit 7d13b2546b
9 changed files with 68 additions and 41 deletions

View file

@ -276,7 +276,10 @@ fn ApiConn(comptime DbConn: type) type {
username, username,
password, password,
self.community.id, self.community.id,
.{ .invite_id = if (maybe_invite) |inv| inv.id else null, .email = opt.email }, .{
.invite_id = if (maybe_invite) |inv| @as(?Uuid, inv.id) else null,
.email = opt.email,
},
self.arena.allocator(), self.arena.allocator(),
); );

View file

@ -94,7 +94,8 @@ pub const Actor = struct {
created_at: DateTime, created_at: DateTime,
}; };
pub fn get(db: anytype, id: Uuid, alloc: std.mem.Allocator) !Actor { pub const GetError = error{ NotFound, DatabaseFailure };
pub fn get(db: anytype, id: Uuid, alloc: std.mem.Allocator) GetError!Actor {
return db.queryRow( return db.queryRow(
Actor, Actor,
\\SELECT \\SELECT

View file

@ -83,11 +83,12 @@ pub fn create(db: anytype, origin: []const u8, options: CreateOptions, alloc: st
else => return error.DatabaseFailure, else => return error.DatabaseFailure,
} }
const name = options.name orelse host;
db.insert("community", .{ db.insert("community", .{
.id = id, .id = id,
.owner_id = null, .owner_id = null,
.host = host, .host = host,
.name = options.name orelse host, .name = name,
.scheme = scheme, .scheme = scheme,
.kind = options.kind, .kind = options.kind,
.created_at = DateTime.now(), .created_at = DateTime.now(),
@ -262,14 +263,20 @@ pub fn query(db: anytype, args: QueryArgs, alloc: std.mem.Allocator) !QueryResul
_ = try builder.array.appendSlice("\nLIMIT $7"); _ = try builder.array.appendSlice("\nLIMIT $7");
const query_args = .{ const query_args = blk: {
args.owner_id, const ord_val =
args.like, if (args.prev) |prev| @as(?QueryArgs.OrderVal, prev.order_val) else null;
args.created_before, const id =
args.created_after, if (args.prev) |prev| @as(?Uuid, prev.id) else null;
if (args.prev) |prev| prev.order_val else null, break :blk .{
if (args.prev) |prev| prev.id else null, args.owner_id,
max_items, args.like,
args.created_before,
args.created_after,
ord_val,
id,
max_items,
};
}; };
try builder.array.append(0); try builder.array.append(0);

View file

@ -71,7 +71,7 @@ pub fn create(db: anytype, created_by: Uuid, community_id: ?Uuid, options: Invit
.max_uses = options.max_uses, .max_uses = options.max_uses,
.created_at = created_at, .created_at = created_at,
.expires_at = if (options.lifespan) |lifespan| .expires_at = if (options.lifespan) |lifespan|
created_at.add(lifespan) @as(?DateTime, created_at.add(lifespan))
else else
null, null,

View file

@ -32,7 +32,7 @@ pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request(@TypeOf(reader)
// discard \r\n // discard \r\n
switch (try reader.readByte()) { switch (try reader.readByte()) {
'\r' => if (try reader.readByte() != '\n') return error.BadRequest, '\r' => if ((try reader.readByte()) != '\n') return error.BadRequest,
'\n' => {}, '\n' => {},
else => return error.BadRequest, else => return error.BadRequest,
} }

View file

@ -30,7 +30,7 @@ pub fn handshake(alloc: std.mem.Allocator, req: *http.Request, res: *http.Respon
if (std.ascii.indexOfIgnoreCase(connection, "Upgrade") == null) return error.BadHandshake; if (std.ascii.indexOfIgnoreCase(connection, "Upgrade") == null) return error.BadHandshake;
const key_hdr = req.headers.get("Sec-WebSocket-Key") orelse return error.BadHandshake; const key_hdr = req.headers.get("Sec-WebSocket-Key") orelse return error.BadHandshake;
if (try std.base64.standard.Decoder.calcSizeForSlice(key_hdr) != 16) return error.BadHandshake; if ((try std.base64.standard.Decoder.calcSizeForSlice(key_hdr)) != 16) return error.BadHandshake;
var key: [16]u8 = undefined; var key: [16]u8 = undefined;
std.base64.standard.Decoder.decode(&key, key_hdr) catch return error.BadHandshake; std.base64.standard.Decoder.decode(&key, key_hdr) catch return error.BadHandshake;
@ -164,15 +164,15 @@ fn writeFrame(writer: anytype, header: FrameInfo, buf: []const u8) !void {
const initial_len: u7 = if (header.len < 126) const initial_len: u7 = if (header.len < 126)
@intCast(u7, header.len) @intCast(u7, header.len)
else if (std.math.cast(u16, header.len)) |_| else if (std.math.cast(u16, header.len)) |_|
126 @as(u7, 126)
else else
127; @as(u7, 127);
var hdr_buf = [2]u8{ 0, 0 }; var hdr_buf = [2]u8{ 0, 0 };
hdr_buf[0] |= if (header.is_final) 0b1000_0000 else 0; hdr_buf[0] |= if (header.is_final) @as(u8, 0b1000_0000) else 0;
hdr_buf[0] |= @as(u8, header.rsv) << 4; hdr_buf[0] |= @as(u8, header.rsv) << 4;
hdr_buf[0] |= @enumToInt(header.opcode); hdr_buf[0] |= @enumToInt(header.opcode);
hdr_buf[1] |= if (header.masking_key) |_| 0b1000_0000 else 0; hdr_buf[1] |= if (header.masking_key) |_| @as(u8, 0b1000_0000) else 0;
hdr_buf[1] |= initial_len; hdr_buf[1] |= initial_len;
try writer.writeAll(&hdr_buf); try writer.writeAll(&hdr_buf);
if (initial_len == 126) if (initial_len == 126)

View file

@ -151,31 +151,37 @@ fn formatQueryParams(
return formatRecursive("", params, writer); return formatRecursive("", params, writer);
} }
fn formatField(comptime name: []const u8, val: anytype, writer: anytype) !void {
// TODO: percent-encode this
_ = try switch (@TypeOf(val)) {
[]const u8 => blk: {
break :blk std.fmt.format(writer, "{s}={s}&", .{ name, val });
},
else => |U| blk: {
if (comptime std.meta.trait.isContainer(U) and std.meta.trait.hasFn("format")(U)) {
break :blk std.fmt.format(writer, "{s}={}&", .{ name, val });
}
break :blk switch (@typeInfo(U)) {
.Enum => std.fmt.format(writer, "{s}={s}&", .{ name, @tagName(val) }),
.Struct => formatRecursive(name ++ ".", val, writer),
else => std.fmt.format(writer, "{s}={}&", .{ name, val }),
};
},
};
}
fn formatRecursive(comptime prefix: []const u8, params: anytype, writer: anytype) !void { fn formatRecursive(comptime prefix: []const u8, params: anytype, writer: anytype) !void {
inline for (std.meta.fields(@TypeOf(params))) |field| { inline for (std.meta.fields(@TypeOf(params))) |field| {
const val = @field(params, field.name); const val = @field(params, field.name);
const is_optional = comptime std.meta.trait.is(.Optional)(field.field_type); const name = prefix ++ field.name;
const present = if (comptime is_optional) val != null else true; if (comptime std.meta.trait.is(.Optional)(field.field_type)) {
if (present) { if (val) |v| {
const unwrapped = if (is_optional) val.? else val; try formatField(name, v, writer);
// TODO: percent-encode this }
_ = try switch (@TypeOf(unwrapped)) { } else {
[]const u8 => blk: { try formatField(name, val, writer);
break :blk std.fmt.format(writer, "{s}{s}={s}&", .{ prefix, field.name, unwrapped });
},
else => |U| blk: {
if (comptime std.meta.trait.isContainer(U) and std.meta.trait.hasFn("format")(U)) {
break :blk std.fmt.format(writer, "{s}{s}={}&", .{ prefix, field.name, unwrapped });
}
break :blk switch (@typeInfo(U)) {
.Enum => std.fmt.format(writer, "{s}{s}={s}&", .{ prefix, field.name, @tagName(unwrapped) }),
.Struct => formatRecursive(field.name ++ ".", unwrapped, writer),
else => std.fmt.format(writer, "{s}{s}={}&", .{ prefix, field.name, unwrapped }),
};
},
};
} }
} }
} }

View file

@ -186,10 +186,19 @@ pub const Db = struct {
var arena = std.heap.ArenaAllocator.init(alloc orelse return error.AllocatorRequired); var arena = std.heap.ArenaAllocator.init(alloc orelse return error.AllocatorRequired);
defer arena.deinit(); defer arena.deinit();
const params = try arena.allocator().alloc(?[*:0]const u8, args.len); const params = try arena.allocator().alloc(?[*:0]const u8, args.len);
// TODO: The following is a fix for the stage1 compiler. remove this
//inline for (args) |arg, i| { //inline for (args) |arg, i| {
inline for (std.meta.fields(@TypeOf(args))) |field, i| { inline for (std.meta.fields(@TypeOf(args))) |field, i| {
const arg = @field(args, field.name); const arg = @field(args, field.name);
params[i] = if (try common.prepareParamText(&arena, arg)) |slice|
// The stage1 compiler has issues with runtime branches that in any
// way involve compile time values
const maybe_slice = if (@import("builtin").zig_backend == .stage1)
common.prepareParamText(&arena, arg) catch unreachable
else
try common.prepareParamText(&arena, arg);
params[i] = if (maybe_slice) |slice|
slice.ptr slice.ptr
else else
null; null;

View file

@ -118,6 +118,7 @@ pub const Db = struct {
}; };
if (@TypeOf(args) != void) { if (@TypeOf(args) != void) {
// TODO: Fix for stage1 compiler
//inline for (args) |arg, i| { //inline for (args) |arg, i| {
inline for (std.meta.fields(@TypeOf(args))) |field, i| { inline for (std.meta.fields(@TypeOf(args))) |field, i| {
const arg = @field(args, field.name); const arg = @field(args, field.name);