╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭────────────────────────────────────────────╮ │ 5 │ │ 6 const event_id_size: usize = 32; │ │ 7 │ │ 8 -pub const EventData = union(enum) { │ │ 8 +pub const EventKind = enum { │ │ 9 + issue, │ │10 +}; │ │11 + │ │12 +pub const EventData = union(EventKind) {│ │13 issue: struct { │ │14 title: []const u8, │ │15 description: []const u8, │ ╰────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │125 // create a new transaction in the database that runs the above-defined Ctx function │ │126 const history = try DB.ArrayList(.read_write).init(db.rootCursor()); │ │127 try history.appendContext(.{ .slot = try history.getSlot(-1) }, Ctx{ .repo_events = repo_events });│ │128 +} │ │129 + │ │130 +pub fn read( │ │131 + comptime DB: type, │ │132 + comptime hash_kind: hash.HashKind, │ │133 + allocator: std.mem.Allocator, │ │134 + map: DB.HashMap(.read_only), │ │135 + kind: EventKind, │ │136 +) !EventData { │ │137 + return switch (kind) { │ │138 + .issue => .{ │ │139 + .issue = .{ │ │140 + .title = try readBytes(DB, hash_kind, allocator, map, "title"), │ │141 + .description = try readBytes(DB, hash_kind, allocator, map, "description"), │ │142 + .tags = try readBytes(DB, hash_kind, allocator, map, "tags"), │ │143 + }, │ │144 + }, │ │145 + }; │ │146 +} │ │147 + │ │148 +fn readBytes( │ │149 + comptime DB: type, │ │150 + comptime hash_kind: hash.HashKind, │ │151 + allocator: std.mem.Allocator, │ │152 + map: DB.HashMap(.read_only), │ │153 + field_name: []const u8, │ │154 +) ![]const u8 { │ │155 + const cursor = try map.getCursor(hash.hashInt(hash_kind, field_name)) orelse return error.NotFound;│ │156 + return try cursor.readBytesAlloc(allocator, null); │ │157 } │ │158 │ │159 fn upsert( │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │199 } │ │200 }, │ │201 .int => |int_info| switch (int_info.signedness) { │ │169 - .unsigned => try upsertUint(DB, hash_kind, map, key, value), │ │170 - .signed => try upsertInt(DB, hash_kind, map, key, value), │ │202 + .unsigned => { │ │203 + if (try map.getCursor(key)) |value_cursor| { │ │204 + if (try value_cursor.readUint() == value) { │ │205 + return; │ │206 + } │ │207 + } │ │208 + │ │209 + try map.put(key, .{ .uint = value }); │ │210 + }, │ │211 + .signed => { │ │212 + if (try map.getCursor(key)) |value_cursor| { │ │213 + if (try value_cursor.readInt() == value) { │ │214 + return; │ │215 + } │ │216 + } │ │217 + │ │218 + try map.put(key, .{ .int = value }); │ │219 + }, │ │220 }, │ │221 else => @compileError("unsupported upsert field type: " ++ @typeName(Field)),│ │222 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────╮ │243 try writer.finish(); │ │244 } │ │245 │ │197 -fn upsertUint( │ │198 - comptime DB: type, │ │199 - comptime hash_kind: hash.HashKind, │ │200 - map: DB.HashMap(.read_write), │ │201 - key: hash.HashInt(hash_kind), │ │202 - value: u64, │ │203 -) !void { │ │204 - if (try map.getCursor(key)) |value_cursor| { │ │205 - if (try value_cursor.readUint() == value) {│ │206 - return; │ │207 - } │ │208 - } │ │209 - │ │210 - try map.put(key, .{ .uint = value }); │ │211 -} │ │212 - │ │213 -fn upsertInt( │ │214 - comptime DB: type, │ │215 - comptime hash_kind: hash.HashKind, │ │216 - map: DB.HashMap(.read_write), │ │217 - key: hash.HashInt(hash_kind), │ │218 - value: i64, │ │219 -) !void { │ │220 - if (try map.getCursor(key)) |value_cursor| { │ │221 - if (try value_cursor.readInt() == value) { │ │222 - return; │ │223 - } │ │224 - } │ │225 - │ │226 - try map.put(key, .{ .int = value }); │ │227 -} │ │228 - │ │246 fn bytesEqual( │ │247 comptime DB: type, │ │248 cursor: *DB.Cursor(.read_only), │ ╰────────────────────────────────────────────────────────╯ ╭ changed ─────────╮ │src/test/event.zig│ ╰──────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │184 │ │185 // get the issue out of the map that was edited │ │186 const first_issue_cursor = try event_id_to_issue.getCursor(hash.hashInt(repo_opts.hash, &first_event_id)) orelse return error.NotFound; │ │187 - const first_issue = try Repo.DB.HashMap(.read_only).init(first_issue_cursor); │ │187 + const first_issue_map = try Repo.DB.HashMap(.read_only).init(first_issue_cursor); │ │188 + const first_issue = try evt.read(Repo.DB, repo_opts.hash, arena.allocator(), first_issue_map, .issue); │ │189 │ │190 // make sure the issue's description was correctly edited │ │190 - const first_issue_description_cursor = try first_issue.getCursor(hash.hashInt(repo_opts.hash, "description")) orelse return error.NotFound;│ │191 - const first_issue_description_value = try first_issue_description_cursor.readBytesAlloc(allocator, null); │ │192 - defer allocator.free(first_issue_description_value); │ │193 - try std.testing.expectEqualStrings(events_to_consume[1].data.issue.description, first_issue_description_value); │ │191 + try std.testing.expectEqualStrings(events_to_consume[1].data.issue.description, first_issue.issue.description); │ │192 │ │193 // make sure the issue's tags were correctly edited │ │196 - const tags_cursor = try first_issue.getCursor(hash.hashInt(repo_opts.hash, "tags")) orelse return error.NotFound; │ │197 - const tags_value = try tags_cursor.readBytesAlloc(allocator, null); │ │198 - defer allocator.free(tags_value); │ │199 - try std.testing.expectEqualStrings(events_to_consume[1].data.issue.tags, tags_value); │ │194 + try std.testing.expectEqualStrings(events_to_consume[1].data.issue.tags, first_issue.issue.tags); │ │195 } │ │196 } │ │197 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯