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 }