struct State <'a> {
ident: i32,
runnable: &'a dyn runnable::Runnable
}
struct DefaultRunnable {}
impl runnable::Runnable for DefaultRunnable {
fn run(&self, _input: Vec<u8>) -> Option<Vec<u8>> {
return None;
}
}
static mut STATE: State = State {
ident: 0,
runnable: &DefaultRunnable{},
};
pub mod runnable {
use std::mem;
use std::slice;
extern {
fn return_result(result_pointer: *const u8, result_size: i32, ident: i32);
}
pub trait Runnable {
fn run(&self, input: Vec<u8>) -> Option<Vec<u8>>;
}
pub fn set(runnable: &'static dyn Runnable) {
unsafe {
super::STATE.runnable = runnable;
}
}
#[no_mangle]
pub extern fn allocate(size: i32) -> *const u8 {
let mut buffer = Vec::with_capacity(size as usize);
let buffer_slice = buffer.as_mut_slice();
let pointer = buffer_slice.as_mut_ptr();
mem::forget(buffer_slice);
pointer as *const u8
}
#[no_mangle]
pub extern fn deallocate(pointer: *const u8, size: i32) {
unsafe {
let _ = slice::from_raw_parts(pointer, size as usize);
}
}
#[no_mangle]
pub extern fn run_e(pointer: *const u8, size: i32, ident: i32) {
unsafe { super::STATE.ident = ident };
let in_slice: &[u8] = unsafe {
slice::from_raw_parts(pointer, size as usize)
};
let in_bytes = Vec::from(in_slice);
let result: Vec<u8> = unsafe { match super::STATE.runnable.run(in_bytes) {
Some(val) => val,
None => Vec::from("run returned no data"),
} };
let result_slice = result.as_slice();
let result_size = result_slice.len();
unsafe {
return_result(result_slice.as_ptr() as *const u8, result_size as i32, ident);
}
}
}
pub mod http {
use std::slice;
static METHOD_GET: i32 = 1;
extern {
fn fetch_url(method: i32, url_pointer: *const u8, url_size: i32, body_pointer: *const u8, body_size: i32, dest_pointer: *const u8, dest_max_size: i32, ident: i32) -> i32;
}
pub fn get(url: &str) -> Vec<u8> {
let mut dest_pointer: *const u8;
let mut dest_size: i32;
let mut capacity: i32 = 256000;
loop {
let cap = &mut capacity;
let mut dest_bytes = Vec::with_capacity(*cap as usize);
let dest_slice = dest_bytes.as_mut_slice();
dest_pointer = dest_slice.as_mut_ptr() as *const u8;
dest_size = unsafe { fetch_url(METHOD_GET, url.as_ptr(), url.len() as i32, 0 as *const u8, 0 as i32, dest_pointer, *cap, super::STATE.ident) };
if dest_size < 0 {
return Vec::from(format!("request_failed:{}", dest_size))
} else if dest_size > *cap {
super::log::info(format!("increasing capacity, need {}", dest_size).as_str());
*cap = dest_size;
} else {
break;
}
}
let result: &[u8] = unsafe {
slice::from_raw_parts(dest_pointer, dest_size as usize)
};
return Vec::from(result)
}
}
pub mod cache {
use std::slice;
extern {
fn cache_set(key_pointer: *const u8, key_size: i32, value_pointer: *const u8, value_size: i32, ttl: i32, ident: i32) -> i32;
fn cache_get(key_pointer: *const u8, key_size: i32, dest_pointer: *const u8, dest_max_size: i32, ident: i32) -> i32;
}
pub fn set(key: &str, val: Vec<u8>, ttl: i32) {
let val_slice = val.as_slice();
let val_ptr = val_slice.as_ptr();
unsafe {
cache_set(key.as_ptr(), key.len() as i32, val_ptr, val.len() as i32, ttl, super::STATE.ident);
}
}
pub fn get(key: &str) -> Option<Vec<u8>> {
let mut dest_pointer: *const u8;
let mut result_size: i32;
let mut capacity: i32 = 1024;
loop {
let cap = &mut capacity;
let mut dest_bytes = Vec::with_capacity(*cap as usize);
let dest_slice = dest_bytes.as_mut_slice();
dest_pointer = dest_slice.as_mut_ptr() as *const u8;
result_size = unsafe { cache_get(key.as_ptr(), key.len() as i32, dest_pointer, *cap, super::STATE.ident) };
if result_size < 0 {
return None;
} else if result_size > *cap {
super::log::info(format!("increasing capacity, need {}", result_size).as_str());
*cap = result_size;
} else {
break;
}
}
let result: &[u8] = unsafe {
slice::from_raw_parts(dest_pointer, result_size as usize)
};
Some(Vec::from(result))
}
}
pub mod req {
use std::slice;
use super::util;
extern {
fn request_get_field(field_type: i32, key_pointer: *const u8, key_size: i32, dest_pointer: *const u8, dest_max_size: i32, ident: i32) -> i32;
}
static FIELD_TYPE_META: i32 = 0 as i32;
static FIELD_TYPE_BODY: i32 = 1 as i32;
static FIELD_TYPE_HEADER: i32 = 2 as i32;
static FIELD_TYPE_PARAMS: i32 = 3 as i32;
static FIELD_TYPE_STATE: i32 = 4 as i32;
pub fn method() -> String {
match get_field(FIELD_TYPE_META, "method") {
Some(bytes) => return util::to_string(bytes),
None => return String::from("")
}
}
pub fn url() -> String {
match get_field(FIELD_TYPE_META, "url") {
Some(bytes) => return util::to_string(bytes),
None => return String::from("")
}
}
pub fn id() -> String {
match get_field(FIELD_TYPE_META, "id") {
Some(bytes) => return util::to_string(bytes),
None => return String::from("")
}
}
pub fn body_raw() -> Vec<u8> {
match get_field(FIELD_TYPE_META, "body") {
Some(bytes) => return bytes,
None => return util::to_vec(String::from(""))
}
}
pub fn body_field(key: &str) -> String {
match get_field(FIELD_TYPE_BODY, key) {
Some(bytes) => return util::to_string(bytes),
None => return String::from("")
}
}
pub fn header(key: &str) -> String {
match get_field(FIELD_TYPE_HEADER, key) {
Some(bytes) => return util::to_string(bytes),
None => return String::from("")
}
}
pub fn url_param(key: &str) -> String {
match get_field(FIELD_TYPE_PARAMS, key) {
Some(bytes) => return util::to_string(bytes),
None => return String::from("")
}
}
pub fn state(key: &str) -> String {
match get_field(FIELD_TYPE_STATE, key) {
Some(bytes) => return util::to_string(bytes),
None => return String::from("")
}
}
fn get_field(field_type: i32, key: &str) -> Option<Vec<u8>> {
let mut dest_pointer: *const u8;
let mut result_size: i32;
let mut capacity: i32 = 1024;
loop {
let cap = &mut capacity;
let mut dest_bytes = Vec::with_capacity(*cap as usize);
let dest_slice = dest_bytes.as_mut_slice();
dest_pointer = dest_slice.as_mut_ptr() as *const u8;
result_size = unsafe { request_get_field(field_type, key.as_ptr(), key.len() as i32, dest_pointer, *cap, super::STATE.ident) };
if result_size < 0 {
return None;
} else if result_size > *cap {
super::log::info(format!("increasing capacity, need {}", result_size).as_str());
*cap = result_size;
} else {
break;
}
}
let result: &[u8] = unsafe {
slice::from_raw_parts(dest_pointer, result_size as usize)
};
Some(Vec::from(result))
}
}
pub mod log {
extern {
fn log_msg(pointer: *const u8, result_size: i32, level: i32, ident: i32);
}
pub fn info(msg: &str) {
log_at_level(msg, 3)
}
pub fn warn(msg: &str) {
log_at_level(msg, 2)
}
pub fn error(msg: &str) {
log_at_level(msg, 1)
}
fn log_at_level(msg: &str, level: i32) {
let msg_vec = Vec::from(msg);
let msg_slice = msg_vec.as_slice();
let pointer = msg_slice.as_ptr();
unsafe { log_msg(pointer, msg_slice.len() as i32, level, super::STATE.ident) };
}
}
pub mod util {
pub fn to_string(input: Vec<u8>) -> String {
String::from_utf8(input).unwrap()
}
pub fn to_vec(input: String) -> Vec<u8> {
input.as_bytes().to_vec()
}
pub fn str_to_vec(input: &str) -> Vec<u8> {
String::from(input).as_bytes().to_vec()
}
}