Stub out account creation

This commit is contained in:
jaina heartles 2022-05-15 14:21:34 -07:00
parent cf8871bbcd
commit 2a6154b5ec

View file

@ -1,59 +1,120 @@
const std = @import("std"); const std = @import("std");
const root = @import("root"); const util = @import("./util.zig");
const Uuid = root.util.Uuid; const Uuid = util.Uuid;
const ciutf8 = util.ciutf8;
const assert = std.debug.assert;
pub const Actor = struct { pub const Account = struct {
id: Uuid, id: Uuid,
display_name: ?[]const u8 = null,
handle: []const u8, handle: []const u8,
host: []const u8,
bio: ?[]const u8 = null,
}; };
pub const Note = struct { const IdSource = struct {
id: Uuid, data: *anyopaque,
author: Uuid, nextFn: fn (*anyopaque) Uuid,
content: []const u8 = "",
};
pub fn CreateInfo(comptime T: type) type { pub fn init(pointer: anytype, comptime nextFn: fn (ptr: @TypeOf(pointer)) Uuid) IdSource {
if (@typeInfo(T) != .Struct) @compileError("type is not struct"); const Ptr = @TypeOf(pointer);
if (!std.meta.trait.hasField("id")(T)) @compileError("type does not have id field"); assert(@typeInfo(Ptr) == .Pointer); // Must be a pointer
if (@typeInfo(T).Struct.is_tuple) @compileError("type cannot be tuple"); assert(@typeInfo(Ptr).Pointer.size == .One); // Must be a single-item pointer
assert(@typeInfo(@typeInfo(Ptr).Pointer.child) == .Struct); // Must point to a struct
const gen = struct {
fn next(ptr: *anyopaque) Uuid {
const alignment = @typeInfo(Ptr).Pointer.alignment;
const self = @ptrCast(Ptr, @alignCast(alignment, ptr));
return nextFn(self);
}
};
var fields: [std.meta.fields(T).len - 1]std.builtin.TypeInfo.StructField = undefined; return .{
var i = 0; .data = pointer,
.nextFn = gen.next,
for (std.meta.fields(T)) |field| { };
if (std.mem.eql(u8, field.name, "id")) continue;
fields[i] = field;
i += 1;
} }
return @Type(.{ fn next(self: *IdSource) Uuid {
.Struct = .{ return self.nextFn(self.data);
.layout = @typeInfo(T).Struct.layout, }
.fields = &fields,
.is_tuple = false,
.decls = &[_]std.builtin.TypeInfo.Declaration{},
},
});
}
const this_host = "localhost:8080";
const actor = Actor{
.id = Uuid.parse("f75f5160-12d3-42c2-a81d-ad2245b7a74b") catch unreachable,
.handle = "testacct",
.host = this_host,
}; };
pub fn getActorById(id: Uuid) !?Actor { const ConstId = struct {
if (Uuid.eql(id, actor.id)) return actor; val: Uuid = Uuid.Nil,
fn next(self: *ConstId) Uuid {
return self.val;
}
return null; fn source(self: *ConstId) IdSource {
} return IdSource.init(self, next);
}
};
pub fn createNote(_: CreateInfo(Note)) !Uuid { pub const MemoryDb = struct {
return Uuid.randV4(root.util.getRandom()); const Self = @This();
const Table = std.ArrayListUnmanaged;
allocator: std.mem.Allocator,
id_source: IdSource,
accounts: Table(Account),
pub fn init(allocator: std.mem.Allocator, id_source: IdSource) Self {
return .{
.allocator = allocator,
.id_source = id_source,
.accounts = Table(Account){},
};
}
pub fn deinit(self: *Self) void {
self.accounts.deinit(self.allocator);
}
pub fn createAccount(self: *Self, handle: []const u8) !Account {
const id = self.id_source.next();
for (self.accounts.items) |a| {
if (ciutf8.eql(handle, a.handle)) {
return error.DuplicateHandle;
}
if (Uuid.eql(id, a.id)) {
return error.DuplicateId;
}
}
const acc = .{
.id = id,
.handle = handle,
};
try self.accounts.append(self.allocator, acc);
return acc;
}
};
test "createAccount" {
var next_id = ConstId{};
var db = MemoryDb.init(std.testing.allocator, next_id.source());
defer db.deinit();
const admin_id = try Uuid.parse("00000000-ffff-0000-0000-000000000000");
const sally_id = try Uuid.parse("00000000-eeee-0000-0000-000000000000");
const other_id = try Uuid.parse("00000000-dddd-0000-0000-000000000000");
next_id.val = admin_id;
const admin = try db.createAccount("admin");
try std.testing.expectEqual(admin_id, admin.id);
try std.testing.expectEqualStrings("admin", admin.handle);
next_id.val = other_id;
try std.testing.expectError(error.DuplicateHandle, db.createAccount("admin"));
next_id.val = sally_id;
const sally = try db.createAccount("sally");
try std.testing.expectEqual(sally_id, sally.id);
try std.testing.expectEqualStrings("sally", sally.handle);
next_id.val = admin_id;
try std.testing.expectError(error.DuplicateId, db.createAccount("jaina"));
} }