Skip to content

Commit e8f09a7

Browse files
committed
wasi: implementation of wasi from wasmer api
1 parent 6d8f97f commit e8f09a7

File tree

1 file changed

+139
-8
lines changed

1 file changed

+139
-8
lines changed

src/wasi.zig

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1-
pub const wasm = @import("./wasm.zig");
1+
const std = @import("std");
2+
const wasm = @import("./wasm.zig");
23

4+
/// Custom error set for WASI operations
5+
pub const WasiError = error{
6+
ConfigInit,
7+
PreopenDirFailed,
8+
MapDirFailed,
9+
EnvInit,
10+
ReadStdoutFailed,
11+
ReadStderrFailed,
12+
InitializeInstanceFailed,
13+
GetImportsFailed,
14+
StartFunctionNotFound,
15+
};
16+
17+
/// Opaque type representing WASI configuration
318
pub const WasiConfig = opaque {
4-
/// Options to inherit when inherriting configs
5-
/// By default all is `true` as you often want to
6-
/// inherit everything rather than something specifically.
19+
/// Options to inherit when inheriting configs
720
const InheritOptions = struct {
821
argv: bool = true,
922
env: bool = true,
@@ -12,16 +25,20 @@ pub const WasiConfig = opaque {
1225
std_err: bool = true,
1326
};
1427

28+
/// Initialize a new WASI configuration
1529
pub fn init() !*WasiConfig {
16-
return wasi_config_new() orelse error.ConfigInit;
30+
return wasi_config_new() orelse WasiError.ConfigInit;
1731
}
1832

33+
/// Clean up WASI configuration
34+
/// The `wasi_env_new` function takes the ownership of the wasm_config_t
35+
/// https://github.com/wasmerio/wasmer/issues/2468
1936
pub fn deinit(self: *WasiConfig) void {
20-
wasi_config_delete(self);
37+
_ = self;
38+
@compileError("not implemented in wasmer");
2139
}
2240

23-
/// Allows to inherit the native environment into the current config.
24-
/// Inherits everything by default.
41+
/// Inherit native environment settings
2542
pub fn inherit(self: *WasiConfig, options: InheritOptions) void {
2643
if (options.argv) self.inheritArgv();
2744
if (options.env) self.inheritEnv();
@@ -50,11 +67,125 @@ pub const WasiConfig = opaque {
5067
wasi_config_inherit_stderr(self);
5168
}
5269

70+
/// Set a command-line argument
71+
pub fn setArg(self: *WasiConfig, arg: []const u8) void {
72+
wasi_config_arg(self, arg.ptr);
73+
}
74+
75+
/// Set an environment variable
76+
pub fn setEnv(self: *WasiConfig, key: []const u8, value: []const u8) void {
77+
wasi_config_env(self, key.ptr, value.ptr);
78+
}
79+
80+
/// Pre-open a directory
81+
pub fn preopenDir(self: *WasiConfig, dir: []const u8) !void {
82+
if (!wasi_config_preopen_dir(self, dir.ptr)) {
83+
return WasiError.PreopenDirFailed;
84+
}
85+
}
86+
87+
/// Map a directory
88+
pub fn mapDir(self: *WasiConfig, alias: []const u8, dir: []const u8) !void {
89+
if (!wasi_config_mapdir(self, alias.ptr, dir.ptr)) {
90+
return WasiError.MapDirFailed;
91+
}
92+
}
93+
94+
/// Capture stdout
95+
pub fn captureStdout(self: *WasiConfig) void {
96+
wasi_config_capture_stdout(self);
97+
}
98+
99+
/// Capture stderr
100+
pub fn captureStderr(self: *WasiConfig) void {
101+
wasi_config_capture_stderr(self);
102+
}
103+
104+
// External C function declarations
53105
extern "c" fn wasi_config_new() ?*WasiConfig;
54106
extern "c" fn wasi_config_delete(?*WasiConfig) void;
55107
extern "c" fn wasi_config_inherit_argv(?*WasiConfig) void;
56108
extern "c" fn wasi_config_inherit_env(?*WasiConfig) void;
57109
extern "c" fn wasi_config_inherit_stdin(?*WasiConfig) void;
58110
extern "c" fn wasi_config_inherit_stdout(?*WasiConfig) void;
59111
extern "c" fn wasi_config_inherit_stderr(?*WasiConfig) void;
112+
extern "c" fn wasi_config_arg(?*WasiConfig, [*]const u8) void;
113+
extern "c" fn wasi_config_env(?*WasiConfig, [*]const u8, [*]const u8) void;
114+
extern "c" fn wasi_config_preopen_dir(?*WasiConfig, [*]const u8) bool;
115+
extern "c" fn wasi_config_mapdir(?*WasiConfig, [*]const u8, [*]const u8) bool;
116+
extern "c" fn wasi_config_capture_stdout(?*WasiConfig) void;
117+
extern "c" fn wasi_config_capture_stderr(?*WasiConfig) void;
60118
};
119+
120+
/// Opaque type representing WASI environment
121+
pub const WasiEnv = opaque {
122+
/// Initialize a new WASI environment
123+
pub fn init(store: *wasm.Store, config: *WasiConfig) !*WasiEnv {
124+
return wasi_env_new(store, config) orelse WasiError.EnvInit;
125+
}
126+
127+
/// Clean up WASI environment
128+
pub fn deinit(self: *WasiEnv) void {
129+
wasi_env_delete(self);
130+
}
131+
132+
/// Read from captured stdout
133+
pub fn readStdout(self: *WasiEnv, buffer: []u8) !usize {
134+
const result = wasi_env_read_stdout(self, buffer.ptr, buffer.len);
135+
return if (result >= 0) @as(usize, @intCast(result)) else WasiError.ReadStdoutFailed;
136+
}
137+
138+
/// Read from captured stderr
139+
pub fn readStderr(self: *WasiEnv, buffer: []u8) !usize {
140+
const result = wasi_env_read_stderr(self, buffer.ptr, buffer.len);
141+
return if (result >= 0) @as(usize, @intCast(result)) else WasiError.ReadStderrFailed;
142+
}
143+
144+
/// Initialize a WASI instance
145+
pub fn initializeInstance(self: *WasiEnv, store: *wasm.Store, instance: *wasm.Instance) !void {
146+
if (!wasi_env_initialize_instance(self, store, instance)) {
147+
return WasiError.InitializeInstanceFailed;
148+
}
149+
}
150+
151+
// External C function declarations
152+
extern "c" fn wasi_env_new(?*wasm.Store, ?*WasiConfig) ?*WasiEnv;
153+
extern "c" fn wasi_env_delete(?*WasiEnv) void;
154+
extern "c" fn wasi_env_read_stdout(?*WasiEnv, [*]u8, usize) isize;
155+
extern "c" fn wasi_env_read_stderr(?*WasiEnv, [*]u8, usize) isize;
156+
extern "c" fn wasi_env_initialize_instance(?*WasiEnv, ?*wasm.Store, ?*wasm.Instance) bool;
157+
};
158+
159+
/// Enum representing different WASI versions
160+
pub const WasiVersion = enum(c_int) {
161+
InvalidVersion = -1,
162+
Latest = 0,
163+
Snapshot0 = 1,
164+
Snapshot1 = 2,
165+
Wasix32v1 = 3,
166+
Wasix64v1 = 4,
167+
};
168+
169+
/// Get the WASI version of a module
170+
pub fn getWasiVersion(module: *wasm.Module) WasiVersion {
171+
return @enumFromInt(wasi_get_wasi_version(module));
172+
}
173+
174+
/// Get WASI imports for a module
175+
pub fn getImports(store: *wasm.Store, wasi_env: *WasiEnv, module: *wasm.Module) !wasm.ExternVec {
176+
var imports = wasm.ExternVec.empty();
177+
if (!wasi_get_imports(store, wasi_env, module, &imports)) {
178+
return WasiError.GetImportsFailed;
179+
}
180+
return imports;
181+
}
182+
183+
/// Get the start function of a WASI module
184+
pub fn getStartFunction(instance: *wasm.Instance) !*wasm.Func {
185+
return wasi_get_start_function(instance) orelse WasiError.StartFunctionNotFound;
186+
}
187+
188+
// External C function declarations
189+
extern "c" fn wasi_get_wasi_version(?*wasm.Module) c_int;
190+
extern "c" fn wasi_get_imports(?*wasm.Store, ?*WasiEnv, ?*wasm.Module, ?*wasm.ExternVec) bool;
191+
extern "c" fn wasi_get_start_function(?*wasm.Instance) ?*wasm.Func;

0 commit comments

Comments
 (0)