| ... | @@ -5,13 +5,39 @@ const Allocator = mem.Allocator; | ... | @@ -5,13 +5,39 @@ const Allocator = mem.Allocator; |
| 5 | | 5 | |
| 6 | usingnamespace std.os.wasi; | 6 | usingnamespace std.os.wasi; |
| 7 | | 7 | |
| 8 | /// Type of WASI preopen. | 8 | /// Type-tag of WASI preopen. |
| 9 | /// | 9 | /// |
| 10 | /// WASI currently offers only `Dir` as a valid preopen resource. | 10 | /// WASI currently offers only `Dir` as a valid preopen resource. |
| 11 | pub const PreopenType = enum { | 11 | pub const PreopenTypeTag = enum { |
| 12 | Dir, | 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 | /// WASI preopen struct. This struct consists of a WASI file descriptor | 41 | /// WASI preopen struct. This struct consists of a WASI file descriptor |
| 16 | /// and type of WASI preopen. It can be obtained directly from the WASI | 42 | /// and type of WASI preopen. It can be obtained directly from the WASI |
| 17 | /// runtime using `PreopenList.populate()` method. | 43 | /// runtime using `PreopenList.populate()` method. |
| ... | @@ -20,29 +46,15 @@ pub const Preopen = struct { | ... | @@ -20,29 +46,15 @@ pub const Preopen = struct { |
| 20 | fd: fd_t, | 46 | fd: fd_t, |
| 21 | | 47 | |
| 22 | /// Type of the preopen. | 48 | /// Type of the preopen. |
| 23 | @"type": union(PreopenType) { | 49 | @"type": PreopenType, |
| 24 | /// Path to a preopened directory. | | |
| 25 | Dir: []const u8, | | |
| 26 | }, | | |
| 27 | | 50 | |
| 28 | const Self = @This(); | 51 | /// Construct new `Preopen` instance. |
| 29 | | 52 | pub fn new(fd: fd_t, preopen_type: PreopenType) Preopen { |
| 30 | /// Construct new `Preopen` instance of type `PreopenType.Dir` from | 53 | return Preopen{ |
| 31 | /// WASI file descriptor and WASI path. | | |
| 32 | pub fn newDir(fd: fd_t, path: []const u8) Self { | | |
| 33 | return Self{ | | |
| 34 | .fd = fd, | 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 | /// Dynamically-sized array list of WASI preopens. This struct is a | 60 | /// Dynamically-sized array list of WASI preopens. This struct is a |
| ... | @@ -113,24 +125,18 @@ pub const PreopenList = struct { | ... | @@ -113,24 +125,18 @@ pub const PreopenList = struct { |
| 113 | ESUCCESS => {}, | 125 | ESUCCESS => {}, |
| 114 | else => |err| return os.unexpectedErrno(err), | 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 | try self.buffer.append(preopen); | 129 | try self.buffer.append(preopen); |
| 118 | fd += 1; | 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 | /// Otherwise, return `null`. | 135 | /// Otherwise, return `null`. |
| 124 | /// | 136 | pub fn find(self: Self, preopen_type: PreopenType) ?*const Preopen { |
| 125 | /// TODO make the function more generic by searching by `PreopenType` union. This will | 137 | for (self.buffer.items) |*preopen| { |
| 126 | /// be needed in the future when WASI extends its capabilities to resources | 138 | if (preopen.@"type".eql(preopen_type)) { |
| 127 | /// other than preopened directories. | 139 | return preopen; |
| 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 | }, | | |
| 134 | } | 140 | } |
| 135 | } | 141 | } |
| 136 | return null; | 142 | return null; |
| ... | @@ -156,7 +162,7 @@ test "extracting WASI preopens" { | ... | @@ -156,7 +162,7 @@ test "extracting WASI preopens" { |
| 156 | try preopens.populate(); | 162 | try preopens.populate(); |
| 157 | | 163 | |
| 158 | std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len); | 164 | std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len); |
| 159 | const preopen = preopens.find(".") orelse unreachable; | 165 | const preopen = preopens.find(PreopenType{ .Dir = "." }) orelse unreachable; |
| 160 | std.testing.expect(std.mem.eql(u8, ".", preopen.@"type".Dir)); | 166 | std.testing.expect(preopen.@"type".eql(PreopenType{ .Dir = "." })); |
| 161 | std.testing.expectEqual(@as(usize, 3), preopen.fd); | 167 | std.testing.expectEqual(@as(usize, 3), preopen.fd); |
| 162 | } | 168 | } |