1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
//! Unstable non-standard Wasmer-specific API that contains more WASI
//! API.
use super::super::{
externals::wasm_extern_t, module::wasm_module_t, types::wasm_name_t, wasi::wasi_env_t,
};
/// Unstable non-standard type wrapping `wasm_extern_t` with the
/// addition of two `wasm_name_t` respectively for the module name and
/// the name of the extern (very likely to be an import). This
/// non-standard type is used by the unstable non-standard
/// `wasi_get_unordered_imports` function.
///
/// The `module`, `name` and `extern` fields are all owned by this type.
#[allow(non_camel_case_types)]
#[derive(Clone)]
pub struct wasmer_named_extern_t {
module: wasm_name_t,
name: wasm_name_t,
r#extern: Box<wasm_extern_t>,
}
wasm_declare_boxed_vec!(named_extern, wasmer);
/// So. Let's explain a dirty hack. `cbindgen` reads the code and
/// collects symbols. What symbols do we need? None of the one
/// declared in `wasm.h`, but for non-standard API, we need to collect
/// all of them. The problem is that `wasmer_named_extern_t` is the only
/// non-standard type where extra symbols are generated by a macro
/// (`wasm_declare_boxed_vec!`). If we want those macro-generated
/// symbols to be collected by `cbindgen`, we need to _expand_ the
/// crate (i.e. running something like `rustc -- -Zunstable-options
/// --pretty=expanded`). Expanding code is unstable and available only
/// on nightly compiler. We _don't want_ to use a nightly compiler
/// only for that. So how can we help `cbindgen` to _see_ those
/// symbols?
///
/// First solution: We write the C code directly in a file, which is
/// then included in the generated header file with the `cbindgen`
/// API. Problem, it's super easy to get it outdated, and it makes the
/// build process more complex.
///
/// Second solution: We write those symbols in a custom module, that
/// is just here for `cbindgen`, never used by our Rust code
/// (otherwise it's duplicated code), with no particular
/// implementation.
///
/// And that's why we have the following `cbindgen_hack`
/// module.
///
/// But this module must not be compiled by `rustc`. How to force
/// `rustc` to ignore a module? With conditional compilation. Because
/// `cbindgen` does not support conditional compilation, it will
/// always _ignore_ the `#[cfg]` attribute, and will always read the
/// content of the module.
///
/// Sorry.
#[doc(hidden)]
#[cfg(__cbindgen_hack__ = "yes")]
mod __cbindgen_hack__ {
use super::*;
#[repr(C)]
pub struct wasmer_named_extern_vec_t {
pub size: usize,
pub data: *mut *mut wasmer_named_extern_t,
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_named_extern_vec_new(
out: *mut wasmer_named_extern_vec_t,
length: usize,
init: *const *mut wasmer_named_extern_t,
) {
unimplemented!()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_named_extern_vec_new_uninitialized(
out: *mut wasmer_named_extern_vec_t,
length: usize,
) {
unimplemented!()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_named_extern_vec_copy(
out_ptr: &mut wasmer_named_extern_vec_t,
in_ptr: &wasmer_named_extern_vec_t,
) {
unimplemented!()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_named_extern_vec_delete(
ptr: Option<&mut wasmer_named_extern_vec_t>,
) {
unimplemented!()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_named_extern_vec_new_empty(
out: *mut wasmer_named_extern_vec_t,
) {
unimplemented!()
}
}
/// Non-standard function to get the module name of a
/// `wasmer_named_extern_t`.
///
/// The returned value isn't owned by the caller.
#[no_mangle]
pub extern "C" fn wasmer_named_extern_module(
named_extern: Option<&wasmer_named_extern_t>,
) -> Option<&wasm_name_t> {
Some(&named_extern?.module)
}
/// Non-standard function to get the name of a `wasmer_named_extern_t`.
///
/// The returned value isn't owned by the caller.
#[no_mangle]
pub extern "C" fn wasmer_named_extern_name(
named_extern: Option<&wasmer_named_extern_t>,
) -> Option<&wasm_name_t> {
Some(&named_extern?.name)
}
/// Non-standard function to get the wrapped extern of a
/// `wasmer_named_extern_t`.
///
/// The returned value isn't owned by the caller.
#[no_mangle]
pub extern "C" fn wasmer_named_extern_unwrap(
named_extern: Option<&wasmer_named_extern_t>,
) -> Option<&wasm_extern_t> {
Some(named_extern?.r#extern.as_ref())
}
/// Non-standard function to get the imports needed for the WASI
/// implementation with no particular order. Each import has its
/// associated module name and name, so that it can be re-order later
/// based on the `wasm_module_t` requirements.
#[no_mangle]
pub unsafe extern "C" fn wasi_get_unordered_imports(
wasi_env: Option<&mut wasi_env_t>,
module: Option<&wasm_module_t>,
imports: &mut wasmer_named_extern_vec_t,
) -> bool {
wasi_get_unordered_imports_inner(wasi_env, module, imports).is_some()
}
unsafe fn wasi_get_unordered_imports_inner(
wasi_env: Option<&mut wasi_env_t>,
module: Option<&wasm_module_t>,
imports: &mut wasmer_named_extern_vec_t,
) -> Option<()> {
let wasi_env = wasi_env?;
let store = &mut wasi_env.store;
let mut store_mut = store.store_mut();
let module = module?;
let import_object = c_try!(wasi_env.inner.import_object(&mut store_mut, &module.inner));
imports.set_buffer(
import_object
.into_iter()
.map(move |((module, name), extern_)| {
let module = module.into();
let name = name.into();
Some(Box::new(wasmer_named_extern_t {
module,
name,
r#extern: Box::new(wasm_extern_t::new(store.clone(), extern_)),
}))
})
.collect::<Vec<_>>(),
);
Some(())
}