╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1676 // │ │1677 // reading from xitdb │ │1678 // │ │1679 + │ │1680 +// read just `Fields`, a subset of `T.Record`, from the record with event id │ │1681 +// `id`, or null when there is none │ │1682 +pub fn readRecordSubset( │ │1683 + comptime T: type, │ │1684 + comptime Fields: type, │ │1685 + comptime DB: type, │ │1686 + comptime hash_kind: hash.HashKind, │ │1687 + haxy_moment: DB.HashMap(.read_only), │ │1688 + arena: *std.heap.ArenaAllocator, │ │1689 + id: []const u8, │ │1690 +) !?Fields { │ │1691 + comptime assertFieldSubset(Fields, T.Record); │ │1692 + const records_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, T.record_map_key)) orelse return null;│ │1693 + const records = try DB.HashMap(.read_only).init(records_cursor); │ │1694 + const record_cursor = try records.getCursor(hash.hashInt(hash_kind, id)) orelse return null; │ │1695 + return try read(Fields, DB, hash_kind, arena, try DB.HashMap(.read_only).init(record_cursor)); │ │1696 +} │ │1697 │ │1698 +fn assertFieldSubset(comptime Sub: type, comptime Full: type) void { │ │1699 + for (@typeInfo(Sub).@"struct".fields) |field| { │ │1700 + if (!@hasField(Full, field.name)) @compileError(@typeName(Full) ++ " has no field " ++ field.name); │ │1701 + const FullField = @FieldType(Full, field.name); │ │1702 + if (@typeInfo(field.type) == .@"struct") { │ │1703 + assertFieldSubset(field.type, FullField); │ │1704 + } else if (field.type != FullField) { │ │1705 + @compileError(@typeName(Full) ++ "." ++ field.name ++ " is a " ++ @typeName(FullField)); │ │1706 + } │ │1707 + } │ │1708 +} │ │1709 + │ │1710 pub fn read( │ │1711 comptime T: type, │ │1712 comptime DB: type, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯