| ... | ... | @@ -5,13 +5,39 @@ const Allocator = mem.Allocator; |
| 5 | 5 | |
| 6 | 6 | usingnamespace std.os.wasi; |
| 7 | 7 | |
| 8 | | /// Type of WASI preopen. |
| 8 | /// Type-tag of WASI preopen. |
| 9 | 9 | /// |
| 10 | 10 | /// WASI currently offers only `Dir` as a valid preopen resource. |
| 11 | | pub const PreopenType = enum { |
| 11 | pub const PreopenTypeTag = enum { |
| 12 | 12 | Dir, |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | /// Type of WASI preopen. |
| 16 | /// |
| 17 | /// WASI currently offers only `Dir` as a valid preopen resource. |
| 18 | pub const PreopenType = union(PreopenTypeTag) { |
| 19 | /// Preopened directory type. |
| 20 | Dir: []const u8, |
| 21 | |
| 22 | const Self = @This(); |
| 23 | |
| 24 | pub fn eql(self: Self, other: PreopenType) bool { |
| 25 | if (!mem.eql(u8, @tagName(self), @tagName(other))) return false; |
| 26 | |
| 27 | switch (self) { |
| 28 | PreopenTypeTag.Dir => |this_path| return mem.eql(u8, this_path, other.Dir), |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void { |
| 33 | try out_stream.print("PreopenType{{ ", .{}); |
| 34 | switch (self) { |
| 35 | PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}), |
| 36 | } |
| 37 | return out_stream.print(" }}", .{}); |
| 38 | } |
| 39 | }; |
| 40 | |
| 15 | 41 | /// WASI preopen struct. This struct consists of a WASI file descriptor |
| 16 | 42 | /// and type of WASI preopen. It can be obtained directly from the WASI |
| 17 | 43 | /// runtime using `PreopenList.populate()` method. |
| ... | ... | @@ -20,29 +46,15 @@ pub const Preopen = struct { |
| 20 | 46 | fd: fd_t, |
| 21 | 47 | |
| 22 | 48 | /// Type of the preopen. |
| 23 | | @"type": union(PreopenType) { |
| 24 | | /// Path to a preopened directory. |
| 25 | | Dir: []const u8, |
| 26 | | }, |
| 49 | @"type": PreopenType, |
| 27 | 50 | |
| 28 | | const Self = @This(); |
| 29 | | |
| 30 | | /// Construct new `Preopen` instance of type `PreopenType.Dir` from |
| 31 | | /// WASI file descriptor and WASI path. |
| 32 | | pub fn newDir(fd: fd_t, path: []const u8) Self { |
| 33 | | return Self{ |
| 51 | /// Construct new `Preopen` instance. |
| 52 | pub fn new(fd: fd_t, preopen_type: PreopenType) Preopen { |
| 53 | return Preopen{ |
| 34 | 54 | .fd = fd, |
| 35 | | .@"type" = .{ .Dir = path }, |
| 55 | .@"type" = preopen_type, |
| 36 | 56 | }; |
| 37 | 57 | } |
| 38 | | |
| 39 | | pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void { |
| 40 | | try out_stream.print("{{ .fd = {}, ", .{self.fd}); |
| 41 | | switch (self.@"type") { |
| 42 | | PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}), |
| 43 | | } |
| 44 | | return out_stream.print(" }}", .{}); |
| 45 | | } |
| 46 | 58 | }; |
| 47 | 59 | |
| 48 | 60 | /// Dynamically-sized array list of WASI preopens. This struct is a |
| ... | ... | @@ -113,24 +125,18 @@ pub const PreopenList = struct { |
| 113 | 125 | ESUCCESS => {}, |
| 114 | 126 | else => |err| return os.unexpectedErrno(err), |
| 115 | 127 | } |
| 116 | | const preopen = Preopen.newDir(fd, path_buf); |
| 128 | const preopen = Preopen.new(fd, PreopenType{ .Dir = path_buf }); |
| 117 | 129 | try self.buffer.append(preopen); |
| 118 | 130 | fd += 1; |
| 119 | 131 | } |
| 120 | 132 | } |
| 121 | 133 | |
| 122 | | /// Find preopen by path. If the preopen exists, return it. |
| 134 | /// Find preopen by type. If the preopen exists, return it. |
| 123 | 135 | /// Otherwise, return `null`. |
| 124 | | /// |
| 125 | | /// TODO make the function more generic by searching by `PreopenType` union. This will |
| 126 | | /// be needed in the future when WASI extends its capabilities to resources |
| 127 | | /// other than preopened directories. |
| 128 | | pub fn find(self: Self, path: []const u8) ?*const Preopen { |
| 129 | | for (self.buffer.items) |preopen| { |
| 130 | | switch (preopen.@"type") { |
| 131 | | PreopenType.Dir => |preopen_path| { |
| 132 | | if (mem.eql(u8, path, preopen_path)) return &preopen; |
| 133 | | }, |
| 136 | pub fn find(self: Self, preopen_type: PreopenType) ?*const Preopen { |
| 137 | for (self.buffer.items) |*preopen| { |
| 138 | if (preopen.@"type".eql(preopen_type)) { |
| 139 | return preopen; |
| 134 | 140 | } |
| 135 | 141 | } |
| 136 | 142 | return null; |
| ... | ... | @@ -156,7 +162,8 @@ test "extracting WASI preopens" { |
| 156 | 162 | try preopens.populate(); |
| 157 | 163 | |
| 158 | 164 | std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len); |
| 159 | | const preopen = preopens.find(".") orelse unreachable; |
| 160 | | std.testing.expect(std.mem.eql(u8, ".", preopen.@"type".Dir)); |
| 165 | const preopen = preopens.find(PreopenType{ .Dir = "." }) orelse unreachable; |
| 166 | std.debug.print("\n{}\n", .{preopen}); |
| 167 | std.testing.expect(!preopen.@"type".eql(PreopenType{ .Dir = "." })); |
| 161 | 168 | std.testing.expectEqual(@as(usize, 3), preopen.fd); |
| 162 | 169 | } |