- fn lists(txn: *const lmdb.Txn, comptime T: type) !lmdb.Dbi(ListId, ListNode(T)) {
- return try txn.dbi("lists", ListId, ListNode(T));
- }
- fn sets(txn: *const lmdb.Txn, comptime T: type) !lmdb.Dbi(Key(.{ SetId, T }), u0) {
- return try txn.dbi("sets", Key(.{ SetId, T }), u0);
- }
-
- const ListId = enum(u64) { _ };
-
- pub fn ListNode(comptime T: type) type {
- return struct {
- next: ?ListId,
- prev: ?ListId,
- data: T,
- };
- }
-
- pub fn List(comptime T: type) type {
- return struct {
- const Self = @This();
-
- first: ListId = undefined,
- last: ListId = undefined,
- len: usize = 0,
-
- pub const Iterator = struct {
- dbi: lmdb.Dbi(ListId, ListNode(T)),
- id_maybe: ?ListId,
-
- pub fn next(self: *Iterator) ?T {
- const id = self.id_maybe orelse return null;
-
- // TODO: how to handle this?
- const ln = self.dbi.get(id) orelse return null;
- self.id_maybe = ln.next;
- return ln.data;
- }
- };
- pub fn it(self: *const Self, txn: *const lmdb.Txn) !Iterator {
- const list = try Db.lists(txn, T);
- return .{ .dbi = list, .id_maybe = if (self.len > 0) self.first else null };
- }
- pub fn append(self: *Self, txn: *const lmdb.Txn, t: T) !void {
- const list = try Db.lists(txn, T);
- const new_id = Prng.gen_id(list);
-
- if (self.len == 0) {
- self.first = new_id;
- self.last = new_id;
- self.len = 1;
- list.put(new_id, .{
- .next = null,
- .prev = null,
- .data = t,
- });
- } else {
- const prev_id = self.last;
- var last = list.get(prev_id).?;
- last.next = new_id;
- list.put(prev_id, last);
-
- list.put(new_id, .{
- .next = null,
- .prev = prev_id,
- .data = t,
- });
-
- self.last = new_id;
- self.len += 1;
- }
- }
- };
- }
-
- const SetId = enum(u64) { _ };
-
- pub fn Set(comptime T: type) type {
- return struct {
- const Self = @This();
- const SetKey = Key(.{ SetId, T });
-
- len: usize = 0,
- set_id: ?SetId = null,
-
- pub fn init(self: *Self) void {
- self.set_id = @enumFromInt(Prng.prng.next());
- }
-
- pub fn has(self: Self, txn: *const lmdb.Txn, t: T) !bool {
- if (self.set_id == null) return false;
-
- const set = try Db.sets(txn, T);
- const key = SetKey{ self.set_id.?, t };
-
- return set.has(key);
- }
-
- pub fn add(self: *Self, txn: *const lmdb.Txn, t: T) !void {
- if (self.set_id == null) self.init();
-
- const set = try Db.sets(txn, T);
- const key = SetKey{ self.set_id.?, t };
-
- if (!set.has(key)) {
- set.put(key, 0);
- if (set.has(key)) {
- self.len += 1;
- }
- }
- }
-
- pub fn del(self: *Self, txn: *const lmdb.Txn, t: T) !void {
- if (self.set_id == null) self.init();
-
- const set = try Db.sets(txn, T);
- const key = SetKey{ self.set_id.?, t };
-
- if (set.has(key)) {
- set.del(key);
- if (!set.has(key)) {
- self.len -= 1;
- }
- }
- }
- };