atproto utils for zig zat.dev
atproto sdk zig

fix: replace deprecated std.io.fixedBufferStream with std.Io.Writer.fixed

deprecated in zig 0.15 — migrate all 11 callsites across cbor tests,
firehose client, and jetstream client to the new API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+67 -69
+52 -52
src/internal/repo/cbor.zig
··· 649 649 650 650 test "encode unsigned integers" { 651 651 var buf: [16]u8 = undefined; 652 - var stream = std.io.fixedBufferStream(&buf); 652 + var w: std.Io.Writer = .fixed(&buf); 653 653 const alloc = std.testing.allocator; 654 654 655 655 // 0 → single byte 656 - try encode(alloc, stream.writer(), .{ .unsigned = 0 }); 657 - try std.testing.expectEqualSlices(u8, &.{0x00}, stream.getWritten()); 656 + try encode(alloc, &w, .{ .unsigned = 0 }); 657 + try std.testing.expectEqualSlices(u8, &.{0x00}, w.buffered()); 658 658 659 - stream.reset(); 660 - try encode(alloc, stream.writer(), .{ .unsigned = 23 }); 661 - try std.testing.expectEqualSlices(u8, &.{0x17}, stream.getWritten()); 659 + w.end = 0; 660 + try encode(alloc, &w, .{ .unsigned = 23 }); 661 + try std.testing.expectEqualSlices(u8, &.{0x17}, w.buffered()); 662 662 663 663 // 24 → 2 bytes (shortest encoding) 664 - stream.reset(); 665 - try encode(alloc, stream.writer(), .{ .unsigned = 24 }); 666 - try std.testing.expectEqualSlices(u8, &.{ 0x18, 24 }, stream.getWritten()); 664 + w.end = 0; 665 + try encode(alloc, &w, .{ .unsigned = 24 }); 666 + try std.testing.expectEqualSlices(u8, &.{ 0x18, 24 }, w.buffered()); 667 667 668 668 // 1000 → 3 bytes 669 - stream.reset(); 670 - try encode(alloc, stream.writer(), .{ .unsigned = 1000 }); 671 - try std.testing.expectEqualSlices(u8, &.{ 0x19, 0x03, 0xe8 }, stream.getWritten()); 669 + w.end = 0; 670 + try encode(alloc, &w, .{ .unsigned = 1000 }); 671 + try std.testing.expectEqualSlices(u8, &.{ 0x19, 0x03, 0xe8 }, w.buffered()); 672 672 } 673 673 674 674 test "encode negative integers" { 675 675 var buf: [16]u8 = undefined; 676 - var stream = std.io.fixedBufferStream(&buf); 676 + var w: std.Io.Writer = .fixed(&buf); 677 677 const alloc = std.testing.allocator; 678 678 679 679 // -1 → major 1, additional 0 680 - try encode(alloc, stream.writer(), .{ .negative = -1 }); 681 - try std.testing.expectEqualSlices(u8, &.{0x20}, stream.getWritten()); 680 + try encode(alloc, &w, .{ .negative = -1 }); 681 + try std.testing.expectEqualSlices(u8, &.{0x20}, w.buffered()); 682 682 683 - stream.reset(); 684 - try encode(alloc, stream.writer(), .{ .negative = -10 }); 685 - try std.testing.expectEqualSlices(u8, &.{0x29}, stream.getWritten()); 683 + w.end = 0; 684 + try encode(alloc, &w, .{ .negative = -10 }); 685 + try std.testing.expectEqualSlices(u8, &.{0x29}, w.buffered()); 686 686 } 687 687 688 688 test "encode text strings" { 689 689 var buf: [64]u8 = undefined; 690 - var stream = std.io.fixedBufferStream(&buf); 690 + var w: std.Io.Writer = .fixed(&buf); 691 691 const alloc = std.testing.allocator; 692 692 693 - try encode(alloc, stream.writer(), .{ .text = "" }); 694 - try std.testing.expectEqualSlices(u8, &.{0x60}, stream.getWritten()); 693 + try encode(alloc, &w, .{ .text = "" }); 694 + try std.testing.expectEqualSlices(u8, &.{0x60}, w.buffered()); 695 695 696 - stream.reset(); 697 - try encode(alloc, stream.writer(), .{ .text = "hello" }); 698 - try std.testing.expectEqualSlices(u8, &.{ 0x65, 'h', 'e', 'l', 'l', 'o' }, stream.getWritten()); 696 + w.end = 0; 697 + try encode(alloc, &w, .{ .text = "hello" }); 698 + try std.testing.expectEqualSlices(u8, &.{ 0x65, 'h', 'e', 'l', 'l', 'o' }, w.buffered()); 699 699 } 700 700 701 701 test "encode byte strings" { 702 702 var buf: [64]u8 = undefined; 703 - var stream = std.io.fixedBufferStream(&buf); 703 + var w: std.Io.Writer = .fixed(&buf); 704 704 const alloc = std.testing.allocator; 705 705 706 - try encode(alloc, stream.writer(), .{ .bytes = &.{} }); 707 - try std.testing.expectEqualSlices(u8, &.{0x40}, stream.getWritten()); 706 + try encode(alloc, &w, .{ .bytes = &.{} }); 707 + try std.testing.expectEqualSlices(u8, &.{0x40}, w.buffered()); 708 708 709 - stream.reset(); 710 - try encode(alloc, stream.writer(), .{ .bytes = &.{ 1, 2, 3 } }); 711 - try std.testing.expectEqualSlices(u8, &.{ 0x43, 1, 2, 3 }, stream.getWritten()); 709 + w.end = 0; 710 + try encode(alloc, &w, .{ .bytes = &.{ 1, 2, 3 } }); 711 + try std.testing.expectEqualSlices(u8, &.{ 0x43, 1, 2, 3 }, w.buffered()); 712 712 } 713 713 714 714 test "encode booleans and null" { 715 715 var buf: [4]u8 = undefined; 716 - var stream = std.io.fixedBufferStream(&buf); 716 + var w: std.Io.Writer = .fixed(&buf); 717 717 const alloc = std.testing.allocator; 718 718 719 - try encode(alloc, stream.writer(), .{ .boolean = false }); 720 - try std.testing.expectEqualSlices(u8, &.{0xf4}, stream.getWritten()); 719 + try encode(alloc, &w, .{ .boolean = false }); 720 + try std.testing.expectEqualSlices(u8, &.{0xf4}, w.buffered()); 721 721 722 - stream.reset(); 723 - try encode(alloc, stream.writer(), .{ .boolean = true }); 724 - try std.testing.expectEqualSlices(u8, &.{0xf5}, stream.getWritten()); 722 + w.end = 0; 723 + try encode(alloc, &w, .{ .boolean = true }); 724 + try std.testing.expectEqualSlices(u8, &.{0xf5}, w.buffered()); 725 725 726 - stream.reset(); 727 - try encode(alloc, stream.writer(), .null); 728 - try std.testing.expectEqualSlices(u8, &.{0xf6}, stream.getWritten()); 726 + w.end = 0; 727 + try encode(alloc, &w, .null); 728 + try std.testing.expectEqualSlices(u8, &.{0xf6}, w.buffered()); 729 729 } 730 730 731 731 test "encode array" { 732 732 var buf: [64]u8 = undefined; 733 - var stream = std.io.fixedBufferStream(&buf); 733 + var w: std.Io.Writer = .fixed(&buf); 734 734 const alloc = std.testing.allocator; 735 735 736 736 // [1, 2, 3] 737 - try encode(alloc, stream.writer(), .{ .array = &.{ 737 + try encode(alloc, &w, .{ .array = &.{ 738 738 .{ .unsigned = 1 }, 739 739 .{ .unsigned = 2 }, 740 740 .{ .unsigned = 3 }, 741 741 } }); 742 - try std.testing.expectEqualSlices(u8, &.{ 0x83, 0x01, 0x02, 0x03 }, stream.getWritten()); 742 + try std.testing.expectEqualSlices(u8, &.{ 0x83, 0x01, 0x02, 0x03 }, w.buffered()); 743 743 } 744 744 745 745 test "encode map with DAG-CBOR key sorting" { 746 746 var buf: [128]u8 = undefined; 747 - var stream = std.io.fixedBufferStream(&buf); 747 + var w: std.Io.Writer = .fixed(&buf); 748 748 const alloc = std.testing.allocator; 749 749 750 750 // keys provided unsorted — encoder must sort by length, then lex 751 751 // "bb" (len 2), "a" (len 1), "cc" (len 2) → sorted: "a", "bb", "cc" 752 - try encode(alloc, stream.writer(), .{ .map = &.{ 752 + try encode(alloc, &w, .{ .map = &.{ 753 753 .{ .key = "bb", .value = .{ .unsigned = 2 } }, 754 754 .{ .key = "a", .value = .{ .unsigned = 1 } }, 755 755 .{ .key = "cc", .value = .{ .unsigned = 3 } }, ··· 761 761 0x62, 'b', 'b', 0x02, // "bb": 2 (same length, lex order) 762 762 0x62, 'c', 'c', 0x03, // "cc": 3 763 763 }; 764 - try std.testing.expectEqualSlices(u8, expected, stream.getWritten()); 764 + try std.testing.expectEqualSlices(u8, expected, w.buffered()); 765 765 } 766 766 767 767 test "round-trip encode → decode" { ··· 838 838 839 839 test "writeUvarint round-trip" { 840 840 var buf: [16]u8 = undefined; 841 - var stream = std.io.fixedBufferStream(&buf); 841 + var w: std.Io.Writer = .fixed(&buf); 842 842 843 843 const test_values = [_]u64{ 0, 1, 127, 128, 255, 256, 16384, 0xffffffff }; 844 844 for (test_values) |val| { 845 - stream.reset(); 846 - try writeUvarint(stream.writer(), val); 847 - const written = stream.getWritten(); 845 + w.end = 0; 846 + try writeUvarint(&w, val); 847 + const written = w.buffered(); 848 848 849 849 var pos: usize = 0; 850 850 const decoded = readUvarint(written, &pos).?; ··· 856 856 test "DAG-CBOR key sort is stable" { 857 857 // same-length keys must be lexicographically sorted 858 858 var buf: [128]u8 = undefined; 859 - var stream = std.io.fixedBufferStream(&buf); 859 + var w: std.Io.Writer = .fixed(&buf); 860 860 const alloc = std.testing.allocator; 861 861 862 - try encode(alloc, stream.writer(), .{ .map = &.{ 862 + try encode(alloc, &w, .{ .map = &.{ 863 863 .{ .key = "op", .value = .{ .unsigned = 1 } }, 864 864 .{ .key = "ab", .value = .{ .unsigned = 2 } }, 865 865 } }); 866 866 867 867 var arena = std.heap.ArenaAllocator.init(alloc); 868 868 defer arena.deinit(); 869 - const decoded = try decodeAll(arena.allocator(), stream.getWritten()); 869 + const decoded = try decodeAll(arena.allocator(), w.buffered()); 870 870 871 871 // "ab" should come before "op" (lex order, same length) 872 872 const entries = decoded.map;
+4 -5
src/internal/streaming/firehose.zig
··· 463 463 464 464 fn connectAndRead(self: *FirehoseClient, host: []const u8, handler: anytype) !void { 465 465 var path_buf: [256]u8 = undefined; 466 - var stream = std.io.fixedBufferStream(&path_buf); 467 - const writer = stream.writer(); 466 + var w: std.Io.Writer = .fixed(&path_buf); 468 467 469 - try writer.writeAll("/xrpc/com.atproto.sync.subscribeRepos"); 468 + try w.writeAll("/xrpc/com.atproto.sync.subscribeRepos"); 470 469 if (self.last_seq) |cursor| { 471 - try writer.print("?cursor={d}", .{cursor}); 470 + try w.print("?cursor={d}", .{cursor}); 472 471 } 473 - const path = stream.getWritten(); 472 + const path = w.buffered(); 474 473 475 474 log.info("connecting to wss://{s}{s}", .{ host, path }); 476 475
+11 -12
src/internal/streaming/jetstream.zig
··· 214 214 } 215 215 216 216 fn buildSubscribePath(self: *JetstreamClient, buf: *[2048]u8) ![]const u8 { 217 - var stream = std.io.fixedBufferStream(buf); 218 - const writer = stream.writer(); 217 + var w: std.Io.Writer = .fixed(buf); 219 218 220 - try writer.writeAll("/subscribe"); 219 + try w.writeAll("/subscribe"); 221 220 222 221 var has_param = false; 223 222 224 223 for (self.options.wanted_collections) |col| { 225 - try writer.writeByte(if (!has_param) '?' else '&'); 226 - try writer.writeAll("wantedCollections="); 227 - try writer.writeAll(col); 224 + try w.writeByte(if (!has_param) '?' else '&'); 225 + try w.writeAll("wantedCollections="); 226 + try w.writeAll(col); 228 227 has_param = true; 229 228 } 230 229 231 230 for (self.options.wanted_dids) |did| { 232 - try writer.writeByte(if (!has_param) '?' else '&'); 233 - try writer.writeAll("wantedDids="); 234 - try writer.writeAll(did); 231 + try w.writeByte(if (!has_param) '?' else '&'); 232 + try w.writeAll("wantedDids="); 233 + try w.writeAll(did); 235 234 has_param = true; 236 235 } 237 236 238 237 if (self.last_time_us) |cursor| { 239 - try writer.writeByte(if (!has_param) '?' else '&'); 240 - try writer.print("cursor={d}", .{cursor}); 238 + try w.writeByte(if (!has_param) '?' else '&'); 239 + try w.print("cursor={d}", .{cursor}); 241 240 } 242 241 243 - return stream.getWritten(); 242 + return w.buffered(); 244 243 } 245 244 }; 246 245