╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────╮ │ 6 const obj = xit.object; │ │ 7 const rf = xit.ref; │ │ 8 │ │ 9 -pub const user = @import("event/user.zig"); │ │ 9 +pub const User = @import("event/User.zig"); │ │10 +pub const Repo = @import("event/Repo.zig"); │ │11 +pub const Issue = @import("event/Issue.zig");│ │12 │ │13 pub const event_id_size: usize = 32; │ │14 │ ╰─────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │16 user, │ │17 repo, │ │18 issue, │ │17 -}; │ │18 - │ │19 -pub const EventData = union(EventKind) { │ │20 - user: User, │ │21 - repo: Repo, │ │22 - issue: Issue, │ │23 - │ │24 - pub const User = struct { │ │25 - name: []const u8, │ │26 - email: []const u8, │ │27 - password_hash: []const u8, │ │28 - }; │ │29 - │ │30 - pub const Repo = struct { │ │31 - user_id: []const u8, │ │32 - name: []const u8, │ │33 - enable_issue: bool, │ │34 - }; │ │35 - │ │36 - pub const Issue = struct { │ │37 - title: []const u8, │ │38 - description: []const u8, │ │39 - tags: []const u8, │ │40 - }; │ │41 - │ │42 - pub fn read( │ │43 - comptime DB: type, │ │44 - comptime hash_kind: hash.HashKind, │ │45 - allocator: std.mem.Allocator, │ │46 - map: DB.HashMap(.read_only), │ │47 - kind: EventKind, │ │48 - ) !EventData { │ │49 - return switch (kind) { │ │50 - .user => .{ │ │51 - .user = .{ │ │52 - .name = try readBytes(DB, hash_kind, allocator, map, "name"), │ │53 - .email = try readBytes(DB, hash_kind, allocator, map, "email"), │ │54 - .password_hash = try readBytes(DB, hash_kind, allocator, map, "password_hash"), │ │55 - }, │ │56 - }, │ │57 - .repo => .{ │ │58 - .repo = .{ │ │59 - .user_id = try readBytes(DB, hash_kind, allocator, map, "user_id"), │ │60 - .name = try readBytes(DB, hash_kind, allocator, map, "name"), │ │61 - .enable_issue = try readBool(DB, hash_kind, map, "enable_issue"), │ │62 - }, │ │63 - }, │ │64 - .issue => .{ │ │65 - .issue = .{ │ │66 - .title = try readBytes(DB, hash_kind, allocator, map, "title"), │ │67 - .description = try readBytes(DB, hash_kind, allocator, map, "description"), │ │68 - .tags = try readBytes(DB, hash_kind, allocator, map, "tags"), │ │69 - }, │ │70 - }, │ │71 - }; │ │72 - } │ │73 - │ │74 - fn readBytes( │ │75 - comptime DB: type, │ │76 - comptime hash_kind: hash.HashKind, │ │77 - allocator: std.mem.Allocator, │ │78 - map: DB.HashMap(.read_only), │ │79 - field_name: []const u8, │ │80 - ) ![]const u8 { │ │81 - const cursor = try map.getCursor(hash.hashInt(hash_kind, field_name)) orelse return error.NotFound;│ │82 - return try cursor.readBytesAlloc(allocator, null); │ │83 - } │ │84 - │ │85 - fn readBool( │ │86 - comptime DB: type, │ │87 - comptime hash_kind: hash.HashKind, │ │88 - map: DB.HashMap(.read_only), │ │89 - field_name: []const u8, │ │90 - ) !bool { │ │91 - const cursor = try map.getCursor(hash.hashInt(hash_kind, field_name)) orelse return error.NotFound;│ │92 - var buffer: [5]u8 = undefined; │ │93 - const bytes = try cursor.readBytesObject(&buffer); │ │94 - const format_tag = bytes.format_tag orelse return error.InvalidFormatTag; │ │95 - if (!std.mem.eql(u8, &format_tag, "bl")) return error.InvalidFormatTag; │ │96 - if (std.mem.eql(u8, bytes.value, "true")) return true; │ │97 - if (std.mem.eql(u8, bytes.value, "false")) return false; │ │98 - return error.InvalidBool; │ │99 - } │ │19 }; │ │20 │ │21 pub const Event = struct { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 22 id: [event_id_size * 2]u8, │ │104 - data: MaybeEventData, │ │105 - │ │106 - pub const MaybeEventData = union(EventKind) { │ │107 - user: ?EventData.User, │ │108 - repo: ?EventData.Repo, │ │109 - issue: ?EventData.Issue, │ │ 23 + data: union(EventKind) { │ │ 24 + user: ?User, │ │ 25 + repo: ?Repo, │ │ 26 + issue: ?Issue, │ │ 27 + }, │ │ 28 │ │111 - fn fromJson( │ │112 - allocator: std.mem.Allocator, │ │113 - kind: EventKind, │ │114 - value_maybe: ?std.json.Value, │ │115 - ) !MaybeEventData { │ │116 - return switch (kind) { │ │117 - .user => .{ │ │118 - .user = if (value_maybe) |value| try std.json.parseFromValueLeaky(EventData.User, allocator, value, .{}) else null, │ │119 - }, │ │120 - .repo => .{ │ │121 - .repo = if (value_maybe) |value| try std.json.parseFromValueLeaky(EventData.Repo, allocator, value, .{}) else null, │ │122 - }, │ │123 - .issue => .{ │ │124 - .issue = if (value_maybe) |value| try std.json.parseFromValueLeaky(EventData.Issue, allocator, value, .{}) else null,│ │125 - }, │ │126 - }; │ │127 - } │ │128 - }; │ │129 - │ │ 29 pub fn jsonStringify(self: Event, jw: anytype) !void { │ │ 30 try jw.beginObject(); │ │ 31 try jw.objectField("id"); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │ 39 try jw.endObject(); │ │ 40 } │ │ 41 │ │143 - fn fromString(allocator: std.mem.Allocator, message: []const u8) !Event { │ │ 42 + fn fromString(arena: *std.heap.ArenaAllocator, message: []const u8) !Event {│ │ 43 const JsonEvent = struct { │ │ 44 id: [event_id_size * 2]u8, │ │ 45 kind: EventKind, │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 46 data: ?std.json.Value = null, │ │ 47 }; │ │149 - const json_event = try std.json.parseFromSliceLeaky(JsonEvent, allocator, message, .{}); │ │ 48 + const json_event = try std.json.parseFromSliceLeaky(JsonEvent, arena.allocator(), message, .{}); │ │ 49 return .{ │ │ 50 .id = json_event.id, │ │152 - .data = try MaybeEventData.fromJson(allocator, json_event.kind, json_event.data), │ │ 51 + .data = switch (json_event.kind) { │ │ 52 + .user => .{ │ │ 53 + .user = if (json_event.data) |value| try std.json.parseFromValueLeaky(User, arena.allocator(), value, .{}) else null, │ │ 54 + }, │ │ 55 + .repo => .{ │ │ 56 + .repo = if (json_event.data) |value| try std.json.parseFromValueLeaky(Repo, arena.allocator(), value, .{}) else null, │ │ 57 + }, │ │ 58 + .issue => .{ │ │ 59 + .issue = if (json_event.data) |value| try std.json.parseFromValueLeaky(Issue, arena.allocator(), value, .{}) else null,│ │ 60 + }, │ │ 61 + }, │ │ 62 }; │ │ 63 } │ │ 64 + │ │ 65 + pub fn randomId(random: std.Random) [event_id_size]u8 { │ │ 66 + var id_bytes: [event_id_size]u8 = undefined; │ │ 67 + random.bytes(&id_bytes); │ │ 68 + return id_bytes; │ │ 69 + } │ │ 70 }; │ │156 - │ │157 -pub fn randomId(random: std.Random) [event_id_size]u8 { │ │158 - var id_bytes: [event_id_size]u8 = undefined; │ │159 - random.bytes(&id_bytes); │ │160 - return id_bytes; │ │161 -} │ │ 71 │ │ 72 pub fn consume( │ │ 73 comptime repo_opts: rp.RepoOpts(.xit), │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │285 try commit_object.object_reader.seekTo(commit_object.content.commit.message_position); │ │286 const message = try commit_object.object_reader.interface.allocRemaining(arena.allocator(), .unlimited);│ │287 │ │379 - const event = try Event.fromString(arena.allocator(), message); │ │288 + const event = try Event.fromString(&arena, message); │ │289 │ │290 // get the id of the current event as bytes │ │291 var current_event_id: [event_id_size]u8 = undefined; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │300 │ │301 if (user_data_maybe) |user_data| { │ │302 const user_cursor = try event_id_to_user.putCursor(user_key); │ │394 - const user_map = try DB.HashMap(.read_write).init(user_cursor); │ │395 - try upsert(DB, repo_opts.hash, user_map, EventData.User, user_data); │ │303 + const user = try DB.HashMap(.read_write).init(user_cursor); │ │304 + try upsert(DB, repo_opts.hash, user, User, user_data); │ │305 } else { │ │306 if (!try event_id_to_user.remove(user_key)) return error.EventNotFound;│ │307 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │318 │ │319 if (repo_data_maybe) |repo_data| { │ │320 const repo_cursor = try event_id_to_repo.putCursor(repo_key); │ │412 - const repo_map = try DB.HashMap(.read_write).init(repo_cursor); │ │413 - try upsert(DB, repo_opts.hash, repo_map, EventData.Repo, repo_data); │ │321 + const repo = try DB.HashMap(.read_write).init(repo_cursor); │ │322 + try upsert(DB, repo_opts.hash, repo, Repo, repo_data); │ │323 │ │324 const user_id_to_repos_cursor = try haxy_moment.putCursor(hash.hashInt(repo_opts.hash, "user-id->repos"));│ │325 const user_id_to_repos = try DB.HashMap(.read_write).init(user_id_to_repos_cursor); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │329 try user_repos.put(repo_key, .{ .bytes = &current_event_id }); │ │330 } else { │ │331 if (try event_id_to_repo.getCursor(repo_key)) |existing_repo_cursor| { │ │423 - const existing_repo_map = try DB.HashMap(.read_only).init(existing_repo_cursor); │ │424 - const existing_repo = try EventData.read(DB, repo_opts.hash, arena.allocator(), existing_repo_map, .repo);│ │425 - const data = existing_repo.repo; │ │332 + const existing_repo = try DB.HashMap(.read_only).init(existing_repo_cursor); │ │333 + const existing_repo_data = try Repo.read(DB, repo_opts.hash, &arena, existing_repo); │ │334 │ │335 const user_id_to_repos_cursor = try haxy_moment.putCursor(hash.hashInt(repo_opts.hash, "user-id->repos"));│ │336 const user_id_to_repos = try DB.HashMap(.read_write).init(user_id_to_repos_cursor); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │337 │ │430 - const user_key = hash.hashInt(repo_opts.hash, data.user_id); │ │338 + const user_key = hash.hashInt(repo_opts.hash, existing_repo_data.user_id); │ │339 const user_repos_cursor = try user_id_to_repos.putCursor(user_key); │ │340 const user_repos = try DB.CountedHashSet(.read_write).init(user_repos_cursor);│ │341 _ = try user_repos.remove(repo_key); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯