Commit e288148f60

Sage Hane <sage@sagehane.com>
2022-01-29 14:52:08
fs: Use `OpenMode` enum instead of read/write flags.
1 parent 88edde4
doc/docgen.zig
@@ -45,7 +45,7 @@ pub fn main() !void {
         }
     }
 
-    var in_file = try fs.cwd().openFile(in_file_name, .{ .read = true });
+    var in_file = try fs.cwd().openFile(in_file_name, .{ .mode = .read_only });
     defer in_file.close();
 
     var out_file = try fs.cwd().createFile(out_file_name, .{});
@@ -1866,7 +1866,7 @@ test "shell parsed" {
         // intentional space after "--build-option1 \"
         const shell_out =
             \\$ zig build test.zig \
-            \\ --build-option1 \ 
+            \\ --build-option1 \
             \\ --build-option2
             \\$ ./test
         ;
lib/std/fs/file.zig
@@ -69,12 +69,17 @@ pub const File = struct {
         Unexpected,
     } || os.OpenError || os.FlockError;
 
+    pub const OpenMode = enum {
+        read_only,
+        write_only,
+        read_write,
+    };
+
     pub const Lock = enum { None, Shared, Exclusive };
 
     /// TODO https://github.com/ziglang/zig/issues/3802
     pub const OpenFlags = struct {
-        read: bool = true,
-        write: bool = false,
+        mode: OpenMode = .read_only,
 
         /// Open the file with an advisory lock to coordinate with other processes
         /// accessing it at the same time. An exclusive lock will prevent other
@@ -118,6 +123,14 @@ pub const File = struct {
         /// Set this to allow the opened file to automatically become the
         /// controlling TTY for the current process.
         allow_ctty: bool = false,
+
+        pub fn isRead(self: OpenFlags) bool {
+            return self.mode != .write_only;
+        }
+
+        pub fn isWrite(self: OpenFlags) bool {
+            return self.mode != .read_only;
+        }
     };
 
     /// TODO https://github.com/ziglang/zig/issues/3802
lib/std/fs/test.zig
@@ -319,9 +319,9 @@ test "file operations on directories" {
             try testing.expectError(error.IsDir, tmp_dir.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize)));
         },
     }
-    // Note: The `.write = true` is necessary to ensure the error occurs on all platforms.
+    // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms.
     // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732
-    try testing.expectError(error.IsDir, tmp_dir.dir.openFile(test_dir_name, .{ .write = true }));
+    try testing.expectError(error.IsDir, tmp_dir.dir.openFile(test_dir_name, .{ .mode = .read_write }));
 
     switch (builtin.os.tag) {
         .wasi, .freebsd, .netbsd, .openbsd, .dragonfly => {},
lib/std/fs/watch.zig
@@ -678,7 +678,7 @@ fn testWriteWatchWriteDelete(allocator: Allocator) !void {
     };
 
     // overwrite line 2
-    const file = try std.fs.cwd().openFile(file_path, .{ .read = true, .write = true });
+    const file = try std.fs.cwd().openFile(file_path, .{ .mode = .read_write });
     {
         defer file.close();
         const write_contents = "lorem ipsum";
lib/std/fs.zig
@@ -938,10 +938,10 @@ pub const Dir = struct {
         const w = os.wasi;
         var fdflags: w.fdflags_t = 0x0;
         var base: w.rights_t = 0x0;
-        if (flags.read) {
+        if (flags.isRead()) {
             base |= w.RIGHT.FD_READ | w.RIGHT.FD_TELL | w.RIGHT.FD_SEEK | w.RIGHT.FD_FILESTAT_GET;
         }
-        if (flags.write) {
+        if (flags.isWrite()) {
             fdflags |= w.FDFLAG.APPEND;
             base |= w.RIGHT.FD_WRITE |
                 w.RIGHT.FD_TELL |
@@ -988,12 +988,11 @@ pub const Dir = struct {
         if (!flags.allow_ctty) {
             os_flags |= os.O.NOCTTY;
         }
-        os_flags |= if (flags.write and flags.read)
-            @as(u32, os.O.RDWR)
-        else if (flags.write)
-            @as(u32, os.O.WRONLY)
-        else
-            @as(u32, os.O.RDONLY);
+        os_flags |= switch (flags.mode) {
+            .read_only => @as(u32, os.O.RDONLY),
+            .write_only => @as(u32, os.O.WRONLY),
+            .read_write => @as(u32, os.O.RDWR),
+        };
         const fd = if (flags.intended_io_mode != .blocking)
             try std.event.Loop.instance.?.openatZ(self.fd, sub_path, os_flags, 0)
         else
@@ -1045,8 +1044,8 @@ pub const Dir = struct {
             .handle = try w.OpenFile(sub_path_w, .{
                 .dir = self.fd,
                 .access_mask = w.SYNCHRONIZE |
-                    (if (flags.read) @as(u32, w.GENERIC_READ) else 0) |
-                    (if (flags.write) @as(u32, w.GENERIC_WRITE) else 0),
+                    (if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) |
+                    (if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0),
                 .creation = w.FILE_OPEN,
                 .io_mode = flags.intended_io_mode,
             }),
@@ -2042,12 +2041,11 @@ pub const Dir = struct {
             const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path);
             return self.accessW(sub_path_w.span().ptr, flags);
         }
-        const os_mode = if (flags.write and flags.read)
-            @as(u32, os.R_OK | os.W_OK)
-        else if (flags.write)
-            @as(u32, os.W_OK)
-        else
-            @as(u32, os.F_OK);
+        const os_mode = switch (flags.mode) {
+            .read_only => @as(u32, os.F_OK),
+            .write_only => @as(u32, os.W_OK),
+            .read_write => @as(u32, os.R_OK | os.W_OK),
+        };
         const result = if (need_async_thread and flags.intended_io_mode != .blocking)
             std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode, 0)
         else
lib/std/Thread.zig
@@ -79,7 +79,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
             var buf: [32]u8 = undefined;
             const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()});
 
-            const file = try std.fs.cwd().openFile(path, .{ .write = true });
+            const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });
             defer file.close();
 
             try file.writer().writeAll(name);
src/Cache.zig
@@ -308,8 +308,7 @@ pub const Manifest = struct {
             // comparing the hashes on the files used for the cached item
             while (true) {
                 if (self.cache.manifest_dir.openFile(&manifest_file_path, .{
-                    .read = true,
-                    .write = true,
+                    .mode = .read_write,
                     .lock = .Exclusive,
                     .lock_nonblocking = self.want_shared_lock,
                 })) |manifest_file| {
@@ -410,7 +409,7 @@ pub const Manifest = struct {
                 cache_hash_file.path = try self.cache.gpa.dupe(u8, file_path);
             }
 
-            const this_file = fs.cwd().openFile(cache_hash_file.path.?, .{ .read = true }) catch |err| switch (err) {
+            const this_file = fs.cwd().openFile(cache_hash_file.path.?, .{ .mode = .read_only }) catch |err| switch (err) {
                 error.FileNotFound => {
                     try self.upgradeToExclusiveLock();
                     return false;
src/test.zig
@@ -958,14 +958,14 @@ pub const TestContext = struct {
 
             switch (update.case) {
                 .Header => |expected_output| {
-                    var file = try tmp.dir.openFile("test_case.h", .{ .read = true });
+                    var file = try tmp.dir.openFile("test_case.h", .{ .mode = .read_only });
                     defer file.close();
                     const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024);
 
                     try std.testing.expectEqualStrings(expected_output, out);
                 },
                 .CompareObjectFile => |expected_output| {
-                    var file = try tmp.dir.openFile(bin_name, .{ .read = true });
+                    var file = try tmp.dir.openFile(bin_name, .{ .mode = .read_only });
                     defer file.close();
                     const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024);