feat(runtime-c-api) Ability to generate ImportObject for a specific WASI version.

This patch introduces 2 new functions:

* `wasmer_wasi_generate_import_object_for_version` and
* `wasmer_wasi_get_version`.

It mimics the current API provided by `wasmer_wasi`, nothing fancy
here. It's just a regular port to C/C++.

Because `wasmer_wasi::get_wasi_version` returns an option, and in
order to simplify the C/C++ API, `wasmer_wasi_get_version` can return
`Version::Unknown` in case of an error. It's up to the user to check
the version is valid (i.e. not unknown).
This commit is contained in:
Ivan Enderlin 2019-12-02 15:59:20 +01:00
parent fdc3d5107a
commit ca4a1b41a6

View File

@ -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::<Result<Vec<_>, _>>()?;
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
}