atproto pds in zig pds.zat.dev
pds atproto
25

Configure Feed

Select the types of activity you want to include in your feed.

repo: adopt Zat MST middle layer

authored by

zzstoatzz and committed by
Tangled
(Jun 1, 2026, 9:06 AM +0300) 8d1a8182 74781f1c

+37 -101
+2 -2
build.zig.zon
··· 5 5 .minimum_zig_version = "0.16.0", 6 6 .dependencies = .{ 7 7 .zat = .{ 8 - .url = "git+https://tangled.org/zat.dev/zat?ref=main#22bc51bd82f63d5464f0aa7386dd1a47e6bb0927", 9 - .hash = "zat-0.3.4-5PuC7ngGCQAsTo-8n0Hw14y7ii3kiyjI15AmhuANLnFz", 8 + .url = "git+https://tangled.org/zat.dev/zat#485f1d485a9b8e7b703e8627a6b6a8c3e3c36a0e", 9 + .hash = "zat-0.3.4-5PuC7ltTCQBUlFGCyduMbwKM929pVX-w7qxlwWtLZ9sV", 10 10 }, 11 11 .zqlite = .{ 12 12 .url = "git+https://github.com/karlseguin/zqlite.zig?ref=master#05a88d6758753e1c63fdd45b211dde2057094b0c",
+32 -27
src/atproto/repo.zig
··· 313 313 } 314 314 try verifyImportedRepoCar(request, allocator, account.did, body); 315 315 316 - const tree = zat.mst.Mst.loadFromBlocks(allocator, loaded.repo_car, loaded.commit.data_cid) catch { 316 + var tree = zat.mst.Mst.loadFromBlocks(allocator, loaded.repo_car, loaded.commit.data_cid) catch { 317 317 return http_api.xrpcError(request, .bad_request, "InvalidRequest", "repo CAR is missing MST blocks"); 318 318 }; 319 319 320 320 var imported_records: std.ArrayList(store.ImportedRecord) = .empty; 321 - collectImportedRecords(allocator, loaded.repo_car, tree.root, &imported_records) catch { 321 + collectImportedRecords(allocator, loaded.repo_car, &tree, &imported_records) catch { 322 322 return http_api.xrpcError(request, .bad_request, "InvalidRequest", "repo CAR contains records outside the atproto data model"); 323 323 }; 324 324 ··· 565 565 fn collectImportedRecords( 566 566 allocator: std.mem.Allocator, 567 567 repo_car: zat.car.Car, 568 - maybe_node: ?*zat.mst.Node, 568 + tree: *zat.mst.Mst, 569 569 out: *std.ArrayList(store.ImportedRecord), 570 570 ) anyerror!void { 571 - const node = maybe_node orelse return; 572 - try collectFromChild(allocator, repo_car, node.left, out); 573 - for (node.entries.items) |entry| { 574 - const block = zat.car.findBlock(repo_car, entry.value.raw) orelse return error.MissingRecordBlock; 575 - const record_value = try zat.cbor.decodeAll(allocator, block); 576 - var blobs: std.ArrayList([]const u8) = .empty; 577 - try collectBlobCids(allocator, record_value, &blobs); 578 - const slash = std.mem.indexOfScalar(u8, entry.key, '/') orelse return error.InvalidRepoPath; 579 - try out.append(allocator, .{ 580 - .collection = try allocator.dupe(u8, entry.key[0..slash]), 581 - .rkey = try allocator.dupe(u8, entry.key[slash + 1 ..]), 582 - .cid = try cidString(allocator, entry.value.raw), 583 - .blob_cids = try blobs.toOwnedSlice(allocator), 584 - }); 585 - try collectFromChild(allocator, repo_car, entry.right, out); 586 - } 571 + var ctx = ImportRecordWalkContext{ 572 + .allocator = allocator, 573 + .repo_car = repo_car, 574 + .out = out, 575 + }; 576 + try tree.walk(ctx.walker()); 587 577 } 588 578 589 - fn collectFromChild( 579 + const ImportRecordWalkContext = struct { 590 580 allocator: std.mem.Allocator, 591 581 repo_car: zat.car.Car, 592 - child: zat.mst.ChildRef, 593 582 out: *std.ArrayList(store.ImportedRecord), 594 - ) anyerror!void { 595 - switch (child) { 596 - .none => {}, 597 - .stub => return error.PartialTree, 598 - .node => |node| try collectImportedRecords(allocator, repo_car, node, out), 583 + 584 + fn walker(self: *ImportRecordWalkContext) zat.mst.Walker { 585 + return .{ 586 + .ctx = self, 587 + .entryFn = onEntry, 588 + }; 589 + } 590 + 591 + fn onEntry(ctx: *anyopaque, entry: zat.mst.WalkEntry) anyerror!void { 592 + const self: *ImportRecordWalkContext = @ptrCast(@alignCast(ctx)); 593 + const block = zat.car.findBlock(self.repo_car, entry.value.raw) orelse return error.MissingRecordBlock; 594 + const record_value = try zat.cbor.decodeAll(self.allocator, block); 595 + var blobs: std.ArrayList([]const u8) = .empty; 596 + try collectBlobCids(self.allocator, record_value, &blobs); 597 + const slash = std.mem.indexOfScalar(u8, entry.key, '/') orelse return error.InvalidRepoPath; 598 + try self.out.append(self.allocator, .{ 599 + .collection = try self.allocator.dupe(u8, entry.key[0..slash]), 600 + .rkey = try self.allocator.dupe(u8, entry.key[slash + 1 ..]), 601 + .cid = try cidString(self.allocator, entry.value.raw), 602 + .blob_cids = try blobs.toOwnedSlice(self.allocator), 603 + }); 599 604 } 600 - } 605 + }; 601 606 602 607 fn collectBlobCids(allocator: std.mem.Allocator, value: zat.cbor.Value, out: *std.ArrayList([]const u8)) !void { 603 608 switch (value) {
+3 -72
src/storage/store.zig
··· 1443 1443 1444 1444 const build_start = monotonicNs(); 1445 1445 const data_cid = try tree.rootCid(); 1446 - try writeMstBlocks(allocator, &tree, &mst_blocks); 1446 + try writeMstBlocks(&tree, &mst_blocks); 1447 1447 const commit = try signedCommitWithKeypair(allocator, account.did, rev, data_cid, if (current) |root| root.commit_cid_raw else null, &keypair); 1448 1448 addProfile(profile, .build_commit_ns, elapsedNs(build_start)); 1449 1449 ··· 2894 2894 return .{ .roots = &.{}, .blocks = try blocks.toOwnedSlice(allocator) }; 2895 2895 } 2896 2896 2897 - fn writeMstBlocks(allocator: std.mem.Allocator, tree: *zat.mst.Mst, out: *std.ArrayList(zat.car.Block)) !void { 2898 - if (tree.root) |root| { 2899 - try writeMstNodeBlocks(allocator, root, out); 2900 - return; 2901 - } 2902 - 2903 - const data = try encodeEmptyMstNode(allocator); 2904 - const cid = try zat.cbor.Cid.forDagCbor(allocator, data); 2905 - try out.append(allocator, .{ 2906 - .cid_raw = try allocator.dupe(u8, cid.raw), 2907 - .data = data, 2908 - }); 2909 - } 2910 - 2911 - fn writeMstNodeBlocks(allocator: std.mem.Allocator, node: *zat.mst.Node, out: *std.ArrayList(zat.car.Block)) !void { 2912 - switch (node.left) { 2913 - .node => |left| try writeMstNodeBlocks(allocator, left, out), 2914 - .stub, .none => {}, 2915 - } 2916 - for (node.entries.items) |entry| { 2917 - switch (entry.right) { 2918 - .node => |right| try writeMstNodeBlocks(allocator, right, out), 2919 - .stub, .none => {}, 2920 - } 2921 - } 2922 - 2923 - const data = try encodeMstNode(allocator, node); 2924 - const cid = try zat.cbor.Cid.forDagCbor(allocator, data); 2925 - try out.append(allocator, .{ 2926 - .cid_raw = try allocator.dupe(u8, cid.raw), 2927 - .data = data, 2928 - }); 2929 - } 2930 - 2931 - fn mstChildValue(allocator: std.mem.Allocator, child: zat.mst.ChildRef) anyerror!zat.cbor.Value { 2932 - return switch (child) { 2933 - .node => |node| blk: { 2934 - const data = try encodeMstNode(allocator, node); 2935 - const cid = try zat.cbor.Cid.forDagCbor(allocator, data); 2936 - break :blk .{ .cid = cid }; 2937 - }, 2938 - .stub => |cid| .{ .cid = cid }, 2939 - .none => .null, 2940 - }; 2941 - } 2942 - 2943 - fn encodeEmptyMstNode(allocator: std.mem.Allocator) ![]const u8 { 2944 - return zat.cbor.encodeAlloc(allocator, .{ .map = &.{ 2945 - .{ .key = "e", .value = .{ .array = &.{} } }, 2946 - .{ .key = "l", .value = .null }, 2947 - } }); 2948 - } 2949 - 2950 - fn encodeMstNode(allocator: std.mem.Allocator, node: *zat.mst.Node) anyerror![]const u8 { 2951 - var entry_values: std.ArrayList(zat.cbor.Value) = .empty; 2952 - var prev_key: []const u8 = ""; 2953 - for (node.entries.items) |entry| { 2954 - const prefix_len = zat.mst.commonPrefixLen(prev_key, entry.key); 2955 - const map_entries = try allocator.alloc(zat.cbor.Value.MapEntry, 4); 2956 - map_entries[0] = .{ .key = "k", .value = .{ .bytes = entry.key[prefix_len..] } }; 2957 - map_entries[1] = .{ .key = "p", .value = .{ .unsigned = prefix_len } }; 2958 - map_entries[2] = .{ .key = "t", .value = try mstChildValue(allocator, entry.right) }; 2959 - map_entries[3] = .{ .key = "v", .value = .{ .cid = entry.value } }; 2960 - try entry_values.append(allocator, .{ .map = map_entries }); 2961 - prev_key = entry.key; 2962 - } 2963 - 2964 - return zat.cbor.encodeAlloc(allocator, .{ .map = &.{ 2965 - .{ .key = "e", .value = .{ .array = entry_values.items } }, 2966 - .{ .key = "l", .value = try mstChildValue(allocator, node.left) }, 2967 - } }); 2897 + fn writeMstBlocks(tree: *zat.mst.Mst, out: *std.ArrayList(zat.car.Block)) !void { 2898 + try tree.collectBlocks(out); 2968 2899 } 2969 2900 2970 2901 const SignedCommit = struct {