diff --git a/lib/runtime-c-api/src/import/wasi.rs b/lib/runtime-c-api/src/import/wasi.rs index 3df3c7f70..ec362fdf2 100644 --- a/lib/runtime-c-api/src/import/wasi.rs +++ b/lib/runtime-c-api/src/import/wasi.rs @@ -1,6 +1,18 @@ use super::*; use crate::get_slice_checked; -use std::path::PathBuf; +use std::{path::PathBuf, ptr, str}; +use wasmer_wasi as wasi; + +#[derive(Debug)] +#[repr(u8)] +pub enum Version { + /// Version cannot be detected or is unknown. + Unknown, + /// `wasi_unstable`. + Snapshot0, + /// `wasi_snapshot_preview1`. + Snapshot1, +} /// Opens a directory that's visible to the WASI module as `alias` but /// is backed by the host file at `host_file_path` @@ -14,9 +26,9 @@ pub struct wasmer_wasi_map_dir_entry_t { impl wasmer_wasi_map_dir_entry_t { /// Converts the data into owned, Rust types - pub unsafe fn as_tuple(&self) -> Result<(String, PathBuf), std::str::Utf8Error> { + pub unsafe fn as_tuple(&self) -> Result<(String, PathBuf), str::Utf8Error> { let alias = self.alias.as_str()?.to_owned(); - let host_path = std::path::PathBuf::from(self.host_file_path.as_str()?); + let host_path = PathBuf::from(self.host_file_path.as_str()?); Ok((alias, host_path)) } @@ -44,21 +56,74 @@ pub unsafe extern "C" fn wasmer_wasi_generate_import_object( let mapped_dir_list = get_slice_checked(mapped_dirs, mapped_dirs_len as usize); wasmer_wasi_generate_import_object_inner( + Version::Snapshot1, arg_list, env_list, preopened_file_list, mapped_dir_list, ) - .unwrap_or(std::ptr::null_mut()) + .unwrap_or(ptr::null_mut()) +} + +/// Creates a WASI import object. +/// +/// This function is similar to `wasmer_wasi_generate_import_object` +/// except that the first argument describes the WASI version. +#[no_mangle] +pub unsafe extern "C" fn wasmer_wasi_generate_import_object_for_version( + version: Version, + args: *const wasmer_byte_array, + args_len: c_uint, + envs: *const wasmer_byte_array, + envs_len: c_uint, + preopened_files: *const wasmer_byte_array, + preopened_files_len: c_uint, + mapped_dirs: *const wasmer_wasi_map_dir_entry_t, + mapped_dirs_len: c_uint, +) -> *mut wasmer_import_object_t { + let arg_list = get_slice_checked(args, args_len as usize); + let env_list = get_slice_checked(envs, envs_len as usize); + let preopened_file_list = get_slice_checked(preopened_files, preopened_files_len as usize); + let mapped_dir_list = get_slice_checked(mapped_dirs, mapped_dirs_len as usize); + + wasmer_wasi_generate_import_object_inner( + version, + arg_list, + env_list, + preopened_file_list, + mapped_dir_list, + ) + .unwrap_or(ptr::null_mut()) +} + +/// Find the version of WASI used by the module. +/// +/// In case of error, the returned version is `Version::Unknown`. +#[no_mangle] +pub unsafe extern "C" fn wasmer_wasi_get_version(module: *const wasmer_module_t) -> Version { + if module.is_null() { + return Version::Unknown; + } + + let module = &*(module as *const Module); + + match wasi::get_wasi_version(module) { + Some(version) => match version { + wasi::WasiVersion::Snapshot0 => Version::Snapshot0, + wasi::WasiVersion::Snapshot1 => Version::Snapshot1, + }, + None => Version::Unknown, + } } /// Inner function that wraps error handling fn wasmer_wasi_generate_import_object_inner( + version: Version, arg_list: &[wasmer_byte_array], env_list: &[wasmer_byte_array], preopened_file_list: &[wasmer_byte_array], mapped_dir_list: &[wasmer_wasi_map_dir_entry_t], -) -> Result<*mut wasmer_import_object_t, std::str::Utf8Error> { +) -> Result<*mut wasmer_import_object_t, str::Utf8Error> { let arg_vec = arg_list.iter().map(|arg| unsafe { arg.as_vec() }).collect(); let env_vec = env_list .iter() @@ -73,7 +138,14 @@ fn wasmer_wasi_generate_import_object_inner( .map(|entry| unsafe { entry.as_tuple() }) .collect::, _>>()?; - let import_object = Box::new(wasmer_wasi::generate_import_object( + let version = match version { + Version::Snapshot0 => wasi::WasiVersion::Snapshot0, + Version::Snapshot1 => wasi::WasiVersion::Snapshot1, + _ => panic!(format!("Version {:?} is invalid.", version)), + }; + + let import_object = Box::new(wasi::generate_import_object_for_version( + version, arg_vec, env_vec, po_file_vec, @@ -90,12 +162,7 @@ fn wasmer_wasi_generate_import_object_inner( #[no_mangle] pub unsafe extern "C" fn wasmer_wasi_generate_default_import_object() -> *mut wasmer_import_object_t { - let import_object = Box::new(wasmer_wasi::generate_import_object( - vec![], - vec![], - vec![], - vec![], - )); + let import_object = Box::new(wasi::generate_import_object(vec![], vec![], vec![], vec![])); Box::into_raw(import_object) as *mut wasmer_import_object_t }