lib/tracy/src/file.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const sys = @import("sys");
 3 
 4 pub const File = struct {
 5     file: std.Io.File = undefined,
 6     buffer: [8192]u8 = undefined,
 7     writer: std.Io.File.Writer = undefined,
 8     opened: bool = false,
 9 
10     pub fn open(self: *File, path: []const u8) !void {
11         if (self.opened) return error.TraceFileAlreadyOpen;
12         self.file = try sys.fs.cwd().createFile(sys.fs.debugIo(), path, .{ .truncate = true });
13         errdefer self.file.close(sys.fs.debugIo());
14         self.writer = self.file.writer(sys.fs.debugIo(), &self.buffer);
15         self.opened = true;
16     }
17 
18     pub fn interface(self: *File) ?*std.Io.Writer {
19         if (!self.opened) return null;
20         return &self.writer.interface;
21     }
22 
23     pub fn finish(self: *File) !void {
24         if (!self.opened) return;
25         defer {
26             self.file.close(sys.fs.debugIo());
27             self.opened = false;
28         }
29         try self.writer.flush();
30     }
31 
32     pub fn close(self: *File) void {
33         self.finish() catch {};
34     }
35 };
36 
37 test "trace file owns a buffered writer in place" {
38     const allocator = std.testing.allocator;
39     var tmp = std.testing.tmpDir(.{});
40     defer tmp.cleanup();
41 
42     const root = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], allocator);
43     defer allocator.free(root);
44     const path = try std.fs.path.join(allocator, &.{ root, "tracy.jsonl" });
45     defer allocator.free(path);
46 
47     var file: File = .{};
48     try file.open(path);
49     try file.interface().?.writeAll("one\n");
50     try file.finish();
51 
52     const contents = try sys.fs.cwd().readFileAlloc(sys.fs.debugIo(), path, allocator, .limited(128));
53     defer allocator.free(contents);
54     try std.testing.expectEqualStrings("one\n", contents);
55     try std.testing.expect(file.interface() == null);
56     file.close();
57 }
58 
59 test "trace file rejects double open" {
60     const allocator = std.testing.allocator;
61     var tmp = std.testing.tmpDir(.{});
62     defer tmp.cleanup();
63 
64     const root = try tmp.parent_dir.realPathFileAlloc(sys.fs.debugIo(), tmp.sub_path[0..], allocator);
65     defer allocator.free(root);
66     const path = try std.fs.path.join(allocator, &.{ root, "tracy.jsonl" });
67     defer allocator.free(path);
68 
69     var file: File = .{};
70     try file.open(path);
71     defer file.close();
72 
73     try std.testing.expectError(error.TraceFileAlreadyOpen, file.open(path));
74 }