#![feature(try_trait)]
use rand::prelude::*;
use std::collections::{BTreeMap, HashMap};
use std::env;
use std::ffi::c_void;
use wasmer_runtime::{func, imports, Ctx, ImportObject, Memory};
pub mod abi;
pub mod error;
pub mod resource;
pub mod scheme;
#[derive(Debug)]
pub struct ExitCode {
pub code: i32,
}
pub struct Process {
pub name: String,
pub args: Vec<String>,
pub called_functions: Box<HashMap<String, u32>>,
pub envvars: BTreeMap<String, String>,
pub resources: Box<HashMap<u32, Box<dyn resource::Resource>>>,
}
impl Process {
pub fn new(host_name: String, args: Vec<String>) -> Self {
let mut envvars = BTreeMap::new();
for (key, value) in env::vars() {
envvars.insert(key, value);
}
Process {
name: host_name,
args: args,
called_functions: Box::new(HashMap::new()),
envvars: envvars,
resources: Box::new(HashMap::new()),
}
}
pub fn log_call(&mut self, func_name: String) {
let func_log = &mut self.called_functions.as_mut();
if func_log.contains_key(&func_name) {
func_log.insert(func_name.clone(), {
let amt = func_log[&func_name] + 1;
amt
});
} else {
func_log.insert(func_name, 1);
}
}
pub fn get_memory_and_environment(ctx: &mut Ctx, mem_index: u32) -> (&Memory, &mut Process) {
unsafe { ctx.memory_and_data_mut(mem_index) }
}
pub fn get_fd(&self) -> u32 {
let mut rng = thread_rng();
let mut result = rng.next_u32();
while self.resources.contains_key(&result) {
result = rng.next_u32();
}
result
}
}
pub fn import_object(name: String, args: Vec<String>) -> ImportObject {
let env_generator = move || {
let my_name = name.clone();
fn destructor(data: *mut c_void) {
unsafe {
drop(Box::from_raw(data as *mut Process));
}
}
let custom_abi_env = Box::new(Process::new(my_name, args.clone()));
(
Box::into_raw(custom_abi_env) as *mut c_void,
destructor as fn(*mut c_void),
)
};
imports! {
env_generator,
"cwa" => {
"env_get" => func!(abi::env::get),
"io_get_stderr" => func!(abi::io::stderr),
"io_get_stdout" => func!(abi::io::stdout),
"io_get_stdin" => func!(abi::io::stdin),
"log_write" => func!(abi::log::write),
"random_i32" => func!(abi::random::rand_i32),
"random_u32" => func!(abi::random::rand_u32),
"random_i64" => func!(abi::random::rand_i64),
"random_u64" => func!(abi::random::rand_u64),
"resource_open" => func!(abi::resource::open),
"resource_close" => func!(abi::resource::close),
"resource_read" => func!(abi::resource::read),
"resource_write" => func!(abi::resource::write),
"resource_flush" => func!(abi::resource::flush),
"runtime_name" => func!(abi::runtime::name),
"runtime_exit" => func!(abi::runtime::exit),
"runtime_spec_major" => func!(abi::runtime::spec_major),
"runtime_spec_minor" => func!(abi::runtime::spec_minor),
"runtime_msleep" => func!(abi::runtime::sleep),
"startup_arg_len" => func!(abi::startup::arg_len),
"startup_arg_at" => func!(abi::startup::arg_at),
"time_now" => func!(abi::time::now),
},
"env" => {
"env_get" => func!(abi::env::get),
"io_get_stderr" => func!(abi::io::stderr),
"io_get_stdout" => func!(abi::io::stdout),
"io_get_stdin" => func!(abi::io::stdin),
"log_write" => func!(abi::log::write),
"random_i32" => func!(abi::random::rand_i32),
"random_u32" => func!(abi::random::rand_u32),
"random_i64" => func!(abi::random::rand_i64),
"random_u64" => func!(abi::random::rand_u64),
"resource_open" => func!(abi::resource::open),
"resource_close" => func!(abi::resource::close),
"resource_read" => func!(abi::resource::read),
"resource_write" => func!(abi::resource::write),
"resource_flush" => func!(abi::resource::flush),
"runtime_name" => func!(abi::runtime::name),
"runtime_exit" => func!(abi::runtime::exit),
"runtime_spec_major" => func!(abi::runtime::spec_major),
"runtime_spec_minor" => func!(abi::runtime::spec_minor),
"runtime_msleep" => func!(abi::runtime::sleep),
"startup_arg_len" => func!(abi::startup::arg_len),
"startup_arg_at" => func!(abi::startup::arg_at),
"time_now" => func!(abi::time::now),
},
}
}