atproto pds in zig pds.zat.dev
pds atproto
Something went wrong. Try again.
Zig
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788const std = @import("std");const zat = @import("zat");
pub const Error = error{ InvalidAtUri, InvalidCollection, InvalidRepoPath, InvalidRecordKey, MissingCollection, MissingRecordKey,};
pub const RecordRef = struct { uri: zat.AtUri, cid: ?[]const u8 = null,
pub fn parse(uri: []const u8, cid: ?[]const u8) Error!RecordRef { const parsed = zat.AtUri.parse(uri) orelse return Error.InvalidAtUri; if (!parsed.hasCollection()) return Error.MissingCollection; if (!parsed.hasRkey()) return Error.MissingRecordKey; return .{ .uri = parsed, .cid = cid }; }};
pub const RepoPath = struct { raw: []const u8, slash: usize,
pub fn parse(path: []const u8) Error!RepoPath { const slash = std.mem.indexOfScalar(u8, path, '/') orelse return Error.InvalidRepoPath; if (std.mem.indexOfScalarPos(u8, path, slash + 1, '/') != null) return Error.InvalidRepoPath; if (zat.Nsid.parse(path[0..slash]) == null) return Error.InvalidCollection; if (zat.Rkey.parse(path[slash + 1 ..]) == null) return Error.InvalidRecordKey; return .{ .raw = path, .slash = slash }; }
pub fn collection(self: RepoPath) []const u8 { return self.raw[0..self.slash]; }
pub fn rkey(self: RepoPath) []const u8 { return self.raw[self.slash + 1 ..]; }};
pub const WriteAction = enum { create, update, delete,};
pub const WriteOp = struct { action: WriteAction, path: RepoPath, cid: ?[]const u8 = null, prev: ?[]const u8 = null,
pub fn create(path: []const u8, cid: []const u8) Error!WriteOp { return .{ .action = .create, .path = try RepoPath.parse(path), .cid = cid }; }
pub fn update(path: []const u8, cid: []const u8, prev: []const u8) Error!WriteOp { return .{ .action = .update, .path = try RepoPath.parse(path), .cid = cid, .prev = prev }; }
pub fn delete(path: []const u8, prev: []const u8) Error!WriteOp { return .{ .action = .delete, .path = try RepoPath.parse(path), .prev = prev }; }};
test "parses repo paths" { const path = try RepoPath.parse("app.bsky.feed.post/3jxtb5w2hkt2m"); try std.testing.expectEqualStrings("app.bsky.feed.post", path.collection()); try std.testing.expectEqualStrings("3jxtb5w2hkt2m", path.rkey());}
test "requires full record refs" { const ref = try RecordRef.parse("at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3jxtb5w2hkt2m", "bafyreiblah"); try std.testing.expectEqualStrings("app.bsky.feed.post", ref.uri.collection().?); try std.testing.expectError(Error.MissingRecordKey, RecordRef.parse("at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post", null));}
test "models sync write ops" { const op = try WriteOp.update("app.bsky.feed.post/3jxtb5w2hkt2m", "new", "old"); try std.testing.expectEqual(.update, op.action); try std.testing.expectEqualStrings("old", op.prev.?);}