Stub out account creation
This commit is contained in:
parent
cf8871bbcd
commit
2a6154b5ec
1 changed files with 105 additions and 44 deletions
149
src/db.zig
149
src/db.zig
|
@ -1,59 +1,120 @@
|
|||
const std = @import("std");
|
||||
const root = @import("root");
|
||||
const Uuid = root.util.Uuid;
|
||||
const util = @import("./util.zig");
|
||||
const Uuid = util.Uuid;
|
||||
const ciutf8 = util.ciutf8;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
pub const Actor = struct {
|
||||
pub const Account = struct {
|
||||
id: Uuid,
|
||||
display_name: ?[]const u8 = null,
|
||||
handle: []const u8,
|
||||
host: []const u8,
|
||||
bio: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub const Note = struct {
|
||||
id: Uuid,
|
||||
author: Uuid,
|
||||
content: []const u8 = "",
|
||||
};
|
||||
const IdSource = struct {
|
||||
data: *anyopaque,
|
||||
nextFn: fn (*anyopaque) Uuid,
|
||||
|
||||
pub fn CreateInfo(comptime T: type) type {
|
||||
if (@typeInfo(T) != .Struct) @compileError("type is not struct");
|
||||
if (!std.meta.trait.hasField("id")(T)) @compileError("type does not have id field");
|
||||
if (@typeInfo(T).Struct.is_tuple) @compileError("type cannot be tuple");
|
||||
pub fn init(pointer: anytype, comptime nextFn: fn (ptr: @TypeOf(pointer)) Uuid) IdSource {
|
||||
const Ptr = @TypeOf(pointer);
|
||||
assert(@typeInfo(Ptr) == .Pointer); // Must be a pointer
|
||||
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;
|
||||
var i = 0;
|
||||
|
||||
for (std.meta.fields(T)) |field| {
|
||||
if (std.mem.eql(u8, field.name, "id")) continue;
|
||||
fields[i] = field;
|
||||
i += 1;
|
||||
return .{
|
||||
.data = pointer,
|
||||
.nextFn = gen.next,
|
||||
};
|
||||
}
|
||||
|
||||
return @Type(.{
|
||||
.Struct = .{
|
||||
.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,
|
||||
fn next(self: *IdSource) Uuid {
|
||||
return self.nextFn(self.data);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn getActorById(id: Uuid) !?Actor {
|
||||
if (Uuid.eql(id, actor.id)) return actor;
|
||||
const ConstId = struct {
|
||||
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 {
|
||||
return Uuid.randV4(root.util.getRandom());
|
||||
pub const MemoryDb = struct {
|
||||
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"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue