zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 66e5205047576768f075ec8f016f6fe21ce71bd0 (tree)
parent 78c6d39cd49225bdfd2de4da7b1730ba26a41ba4
Author: Jakub Konka <kubkon@jakubkonka.com>
Date:   Tue, 23 Jun 2020 21:54:36 +0200

Refactor PreopenList.find()

This commit generalizes `std.fs.wasi.PreopenList.find(...)` allowing
search by `std.fs.wasi.PreopenType` union type rather than by dir
name. In the future releases of WASI, it is expected to have more
preopen types (or capabilities) than just directories. This commit
aligns itself with that vision.

This is a potentially breaking change. However, since `std.fs.wasi.PreopenList`
wasn't made part of any Zig release yet, I think we should be OK
to introduce those changes without pointing to any deprecations.

Diffstat:
Mdoc/langref.html.in | 2+-
Mlib/std/fs/wasi.zig | 77++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mlib/std/testing.zig | 2+-
3 files changed, 44 insertions(+), 37 deletions(-)

diff --git a/doc/langref.html.in b/doc/langref.html.in @@ -9738,7 +9738,7 @@ pub fn main() !void { } {#code_end#} <pre><code>$ wasmtime --dir=. preopens.wasm -0: { .fd = 3, .Dir = '.' } +0: Preopen{ .fd = 3, .type = PreopenType{ .Dir = '.' } } </code></pre> {#header_close#} {#header_close#} diff --git a/lib/std/fs/wasi.zig b/lib/std/fs/wasi.zig @@ -5,13 +5,39 @@ const Allocator = mem.Allocator; usingnamespace std.os.wasi; -/// Type of WASI preopen. +/// Type-tag of WASI preopen. /// /// WASI currently offers only `Dir` as a valid preopen resource. -pub const PreopenType = enum { +pub const PreopenTypeTag = enum { Dir, }; +/// Type of WASI preopen. +/// +/// WASI currently offers only `Dir` as a valid preopen resource. +pub const PreopenType = union(PreopenTypeTag) { + /// Preopened directory type. + Dir: []const u8, + + const Self = @This(); + + pub fn eql(self: Self, other: PreopenType) bool { + if (!mem.eql(u8, @tagName(self), @tagName(other))) return false; + + switch (self) { + PreopenTypeTag.Dir => |this_path| return mem.eql(u8, this_path, other.Dir), + } + } + + pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void { + try out_stream.print("PreopenType{{ ", .{}); + switch (self) { + PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}), + } + return out_stream.print(" }}", .{}); + } +}; + /// WASI preopen struct. This struct consists of a WASI file descriptor /// and type of WASI preopen. It can be obtained directly from the WASI /// runtime using `PreopenList.populate()` method. @@ -20,29 +46,15 @@ pub const Preopen = struct { fd: fd_t, /// Type of the preopen. - @"type": union(PreopenType) { - /// Path to a preopened directory. - Dir: []const u8, - }, + @"type": PreopenType, - const Self = @This(); - - /// Construct new `Preopen` instance of type `PreopenType.Dir` from - /// WASI file descriptor and WASI path. - pub fn newDir(fd: fd_t, path: []const u8) Self { - return Self{ + /// Construct new `Preopen` instance. + pub fn new(fd: fd_t, preopen_type: PreopenType) Preopen { + return Preopen{ .fd = fd, - .@"type" = .{ .Dir = path }, + .@"type" = preopen_type, }; } - - pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void { - try out_stream.print("{{ .fd = {}, ", .{self.fd}); - switch (self.@"type") { - PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}), - } - return out_stream.print(" }}", .{}); - } }; /// Dynamically-sized array list of WASI preopens. This struct is a @@ -113,24 +125,18 @@ pub const PreopenList = struct { ESUCCESS => {}, else => |err| return os.unexpectedErrno(err), } - const preopen = Preopen.newDir(fd, path_buf); + const preopen = Preopen.new(fd, PreopenType{ .Dir = path_buf }); try self.buffer.append(preopen); fd += 1; } } - /// Find preopen by path. If the preopen exists, return it. + /// Find preopen by type. If the preopen exists, return it. /// Otherwise, return `null`. - /// - /// TODO make the function more generic by searching by `PreopenType` union. This will - /// be needed in the future when WASI extends its capabilities to resources - /// other than preopened directories. - pub fn find(self: Self, path: []const u8) ?*const Preopen { - for (self.buffer.items) |preopen| { - switch (preopen.@"type") { - PreopenType.Dir => |preopen_path| { - if (mem.eql(u8, path, preopen_path)) return &preopen; - }, + pub fn find(self: Self, preopen_type: PreopenType) ?*const Preopen { + for (self.buffer.items) |*preopen| { + if (preopen.@"type".eql(preopen_type)) { + return preopen; } } return null; @@ -156,7 +162,8 @@ test "extracting WASI preopens" { try preopens.populate(); std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len); - const preopen = preopens.find(".") orelse unreachable; - std.testing.expect(std.mem.eql(u8, ".", preopen.@"type".Dir)); + const preopen = preopens.find(PreopenType{ .Dir = "." }) orelse unreachable; + std.debug.print("\n{}\n", .{preopen}); + std.testing.expect(!preopen.@"type".eql(PreopenType{ .Dir = "." })); std.testing.expectEqual(@as(usize, 3), preopen.fd); } diff --git a/lib/std/testing.zig b/lib/std/testing.zig @@ -215,7 +215,7 @@ fn getCwdOrWasiPreopen() std.fs.Dir { defer preopens.deinit(); preopens.populate() catch @panic("unable to make tmp dir for testing: unable to populate preopens"); - const preopen = preopens.find(".") orelse + const preopen = preopens.find(std.fs.wasi.PreopenType{ .Dir = "." }) orelse @panic("unable to make tmp dir for testing: didn't find '.' in the preopens"); return std.fs.Dir{ .fd = preopen.fd };