Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(rust): cargo fmt and refactor into two workspace with two crates #164

Merged
merged 9 commits into from
Nov 1, 2021
22 changes: 11 additions & 11 deletions api/rust/suborbital/Cargo.lock → Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[workspace]
members = [
"api/rust/*"
]
17 changes: 17 additions & 0 deletions api/rust/codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "suborbital-macro"
version = "0.1.0"
edition = "2021"
authors = ["cohix <connorjhicks@gmail.com>", "Florian Fromm <flrn.frmm@gmail.com>"]
description = "Macro for setting up a Runnable"
license = "Apache-2.0"
repository = "https://github.com/suborbital/reactr"
homepage = "https://suborbital.dev"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true

[dependencies]
syn = "1.0.80"
quote = "1.0.10"
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use syn::DeriveInput;
#[proc_macro_derive(Runnable)]
pub fn derive_runnable(token_stream: TokenStream) -> TokenStream {
let input = parse_macro_input!(token_stream as DeriveInput);

let runnable_name = input.ident;

let expanded = quote! {
Original file line number Diff line number Diff line change
@@ -12,4 +12,4 @@ homepage = "https://suborbital.dev"
crate-type = ["cdylib", "rlib"]

[dependencies]
codegen = { path = "./codegen" }
suborbital-macro = { path = "../codegen", version = "0.1.0" }
cohix marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 18 additions & 4 deletions api/rust/suborbital/src/cache.rs → api/rust/core/src/cache.rs
Original file line number Diff line number Diff line change
@@ -2,8 +2,15 @@ use crate::ffi;
use crate::runnable::HostErr;
use crate::STATE;

extern {
fn cache_set(key_pointer: *const u8, key_size: i32, value_pointer: *const u8, value_size: i32, ttl: i32, ident: i32) -> i32;
extern "C" {
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, ident: i32) -> i32;
}

@@ -12,7 +19,14 @@ pub fn set(key: &str, val: Vec<u8>, ttl: i32) {
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);
cache_set(
key.as_ptr(),
key.len() as i32,
val_ptr,
val.len() as i32,
ttl,
super::STATE.ident,
);
}
}

@@ -21,6 +35,6 @@ pub fn set(key: &str, val: Vec<u8>, ttl: i32) {
/// Then retreives the result from the host and returns it
pub fn get(key: &str) -> Result<Vec<u8>, HostErr> {
let result_size = unsafe { cache_get(key.as_ptr(), key.len() as i32, STATE.ident) };

ffi::result(result_size)
}
10 changes: 4 additions & 6 deletions api/rust/suborbital/src/db.rs → api/rust/core/src/db.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use crate::STATE;

use query::{QueryArg, QueryType};

extern {
extern "C" {
fn db_exec(query_type: i32, name_ptr: *const u8, name_size: i32, ident: i32) -> i32;
}

@@ -16,8 +16,7 @@ extern {
// the return value is the inserted auto-increment ID from the query result, if any,
// formatted as JSON with the key `lastInsertID`
pub fn insert(name: &str, args: Vec<QueryArg>) -> Result<Vec<u8>, runnable::HostErr> {
args.iter()
.for_each(|arg| ffi::add_var(&arg.name, &arg.value));
args.iter().for_each(|arg| ffi::add_var(&arg.name, &arg.value));

let result_size = unsafe { db_exec(QueryType::INSERT.into(), name.as_ptr(), name.len() as i32, STATE.ident) };

@@ -30,11 +29,10 @@ pub fn insert(name: &str, args: Vec<QueryArg>) -> Result<Vec<u8>, runnable::Host
//
// the return value is the query result formatted as JSON, with each column name as a top-level key
pub fn select(name: &str, args: Vec<QueryArg>) -> Result<Vec<u8>, runnable::HostErr> {
args.iter()
.for_each(|arg| ffi::add_var(&arg.name, &arg.value));
args.iter().for_each(|arg| ffi::add_var(&arg.name, &arg.value));

let result_size = unsafe { db_exec(QueryType::SELECT.into(), name.as_ptr(), name.len() as i32, STATE.ident) };

// retreive the result from the host and return it
ffi::result(result_size)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@

pub struct QueryArg {
pub name: String,
pub value: String
pub value: String,
}

impl QueryArg {
pub fn new(name: &str, value: &str) -> Self{
QueryArg{
pub fn new(name: &str, value: &str) -> Self {
QueryArg {
name: String::from(name),
value: String::from(value),
}
@@ -25,4 +24,4 @@ impl From<QueryType> for i32 {
QueryType::SELECT => 1,
}
}
}
}
26 changes: 14 additions & 12 deletions api/rust/suborbital/src/ffi.rs → api/rust/core/src/ffi.rs
Original file line number Diff line number Diff line change
@@ -4,18 +4,18 @@ use crate::runnable::HostErr;
use crate::util;
use crate::STATE;

extern {
extern "C" {
fn get_ffi_result(pointer: *const u8, ident: i32) -> i32;
fn add_ffi_var(name_ptr: *const u8, name_len: i32, val_ptr: *const u8, val_len: i32, ident: i32) -> i32;
}

pub (crate) fn result(size: i32) -> Result<Vec<u8>, HostErr> {
pub(crate) fn result(size: i32) -> Result<Vec<u8>, HostErr> {
let mut alloc_size = size;

// FFI functions return negative values when an error occurs
if size < 0 {
if size == -1 {
return Err(HostErr::new("unknown error returned from host"))
return Err(HostErr::new("unknown error returned from host"));
}

alloc_size = -size
@@ -25,29 +25,31 @@ pub (crate) fn result(size: i32) -> Result<Vec<u8>, HostErr> {
let mut result_mem = Vec::with_capacity(alloc_size as usize);
let result_ptr = result_mem.as_mut_slice().as_mut_ptr() as *const u8;

let code = unsafe {
get_ffi_result(result_ptr, STATE.ident)
};
let code = unsafe { get_ffi_result(result_ptr, STATE.ident) };

// check if it was successful, and then re-build the memory
if code != 0 {
return Err(HostErr::new("unknown error returned from host"));
}

let data: &[u8] = unsafe {
slice::from_raw_parts(result_ptr, alloc_size as usize)
};
let data: &[u8] = unsafe { slice::from_raw_parts(result_ptr, alloc_size as usize) };

if size < 0 {
let msg = Vec::from(data);
return Err(HostErr::new(util::to_string(msg).as_str()))
return Err(HostErr::new(util::to_string(msg).as_str()));
}

Ok(Vec::from(data))
}

pub(crate) fn add_var(name: &str, value: &str) {
unsafe {
add_ffi_var(name.as_ptr(), name.len() as i32, value.as_ptr(), value.len() as i32, STATE.ident);
add_ffi_var(
name.as_ptr(),
name.len() as i32,
value.as_ptr(),
value.len() as i32,
STATE.ident,
);
}
}
}
8 changes: 3 additions & 5 deletions api/rust/suborbital/src/file.rs → api/rust/core/src/file.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::STATE;
use crate::ffi;
use crate::STATE;

extern {
extern "C" {
fn get_static_file(name_ptr: *const u8, name_size: i32, ident: i32) -> i32;
}

@@ -13,8 +13,6 @@ pub fn get_static(name: &str) -> Option<Vec<u8>> {

match ffi::result(result_size) {
Ok(res) => Some(res),
Err(_) => {
None
}
Err(_) => None,
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
use crate::ffi;
use crate::runnable::HostErr;
use crate::STATE;
use crate::ffi;

extern {
fn graphql_query(endpoint_pointer: *const u8, endpoint_size: i32, query_pointer: *const u8, query_size: i32, ident: i32) -> i32;
extern "C" {
fn graphql_query(
endpoint_pointer: *const u8,
endpoint_size: i32,
query_pointer: *const u8,
query_size: i32,
ident: i32,
) -> i32;
}

/// Retreives the result from the host and returns it
pub fn query(endpoint: &str, query: &str) -> Result<Vec<u8>, HostErr> {
let endpoint_size = endpoint.len() as i32;
let query_size = query.len() as i32;

let result_size = unsafe {
graphql_query(endpoint.as_ptr(), endpoint_size, query.as_ptr(), query_size, STATE.ident)
let result_size = unsafe {
graphql_query(
endpoint.as_ptr(),
endpoint_size,
query.as_ptr(),
query_size,
STATE.ident,
)
};

ffi::result(result_size)
41 changes: 30 additions & 11 deletions api/rust/suborbital/src/http.rs → api/rust/core/src/http.rs
Original file line number Diff line number Diff line change
@@ -2,13 +2,20 @@ pub mod method;

use std::collections::BTreeMap;

use crate::runnable::HostErr;
use crate::ffi;
use crate::runnable::HostErr;
use crate::STATE;
use method::Method;

extern {
fn fetch_url(method: i32, url_pointer: *const u8, url_size: i32, body_pointer: *const u8, body_size: i32, ident: i32) -> i32;
extern "C" {
fn fetch_url(
method: i32,
url_pointer: *const u8,
url_size: i32,
body_pointer: *const u8,
body_size: i32,
ident: i32,
) -> i32;
}

pub fn get(url: &str, headers: Option<BTreeMap<&str, &str>>) -> Result<Vec<u8>, HostErr> {
@@ -33,12 +40,17 @@ pub fn delete(url: &str, headers: Option<BTreeMap<&str, &str>>) -> Result<Vec<u8
///
/// > Remark: The URL gets encoded with headers added on the end, seperated by ::
/// > eg. https://google.com/somepage::authorization:bearer qdouwrnvgoquwnrg::anotherheader:nicetomeetyou
fn do_request(method: i32, url: &str, body: Option<Vec<u8>>, headers: Option<BTreeMap<&str, &str>>) -> Result<Vec<u8>, HostErr> {
fn do_request(
method: i32,
url: &str,
body: Option<Vec<u8>>,
headers: Option<BTreeMap<&str, &str>>,
) -> Result<Vec<u8>, HostErr> {
cohix marked this conversation as resolved.
Show resolved Hide resolved
let header_string = render_header_string(headers);

let url_string = match header_string {
Some(h) => format!("{}::{}", url, h),
None => String::from(url)
None => String::from(url),
};

let body_pointer: *const u8;
@@ -49,20 +61,27 @@ fn do_request(method: i32, url: &str, body: Option<Vec<u8>>, headers: Option<BTr
let body_slice = b.as_slice();
body_pointer = body_slice.as_ptr();
body_size = b.len() as i32;
},
None => body_pointer = std::ptr::null::<u8>()
}
None => body_pointer = std::ptr::null::<u8>(),
}

let result_size = unsafe {
fetch_url(method, url_string.as_str().as_ptr(), url_string.len() as i32, body_pointer, body_size, STATE.ident)
fetch_url(
method,
url_string.as_str().as_ptr(),
url_string.len() as i32,
body_pointer,
body_size,
STATE.ident,
)
};

ffi::result(result_size)
}

fn render_header_string(headers: Option<BTreeMap<&str, &str>>) -> Option<String> {
let mut rendered: String = String::from("");

let header_map = headers?;

for key in header_map.keys() {
Original file line number Diff line number Diff line change
@@ -2,16 +2,16 @@ pub enum Method {
GET,
POST,
PATCH,
DELETE
DELETE,
}

impl From<Method> for i32 {
fn from(field_type: Method) -> Self {
fn from(field_type: Method) -> Self {
match field_type {
Method::GET => 0,
Method::POST => 1,
Method::PATCH => 2,
Method::DELETE => 3,
}
}
}
}
}
21 changes: 12 additions & 9 deletions api/rust/suborbital/src/lib.rs → api/rust/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
pub mod runnable;
pub mod db;
pub mod graphql;
pub mod http;
pub use suborbital_macro::*;

pub mod cache;
pub mod db;
pub mod ffi;
pub mod file;
pub mod graphql;
pub mod http;
pub mod log;
pub mod req;
pub mod resp;
pub mod runnable;
pub mod util;

/// This file represents the Rust "API" for Reactr Wasm runnables. The functions defined herein are used to exchange
/// data between the host (Reactr, written in Go) and the Runnable (a Wasm module, in this case written in Rust).
/// State struct to hold our dynamic Runnable
struct State <'a> {
ident: i32,
runnable: Option<&'a dyn runnable::Runnable>
struct State<'a> {
ident: i32,
runnable: Option<&'a dyn runnable::Runnable>,
}

/// The state that holds the user-provided Runnable and the current ident
static mut STATE: State = State {
ident: 0,
runnable: None
ident: 0,
runnable: None,
};

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::STATE;

extern {
extern "C" {
fn log_msg(pointer: *const u8, result_size: i32, level: i32, ident: i32);
}

59 changes: 31 additions & 28 deletions api/rust/suborbital/src/req.rs → api/rust/core/src/req.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,76 @@
pub mod field_type;

use crate::util;
use crate::ffi;
use crate::util;
use crate::STATE;
use field_type::FieldType;

extern {
extern "C" {
fn request_get_field(field_type: i32, key_pointer: *const u8, key_size: i32, ident: i32) -> i32;
fn request_set_field(field_type: i32, key_pointer: *const u8, key_size: i32, val_pointer: *const u8, val_size: i32, ident: i32) -> i32;
fn request_set_field(
field_type: i32,
key_pointer: *const u8,
key_size: i32,
val_pointer: *const u8,
val_size: i32,
ident: i32,
) -> i32;
}

pub fn method() -> String {
get_field(FieldType::Meta.into(), "method")
.map_or("".into(), util::to_string)
get_field(FieldType::Meta.into(), "method").map_or("".into(), util::to_string)
}

pub fn set_method(val: &str) -> Result<(), super::runnable::HostErr> {
set_field(FieldType::Meta.into(), "method", val)
}

pub fn url() -> String {
get_field(FieldType::Meta.into(), "url")
.map_or("".into(), util::to_string)
get_field(FieldType::Meta.into(), "url").map_or("".into(), util::to_string)
}

pub fn set_url(val: &str) -> Result<(), super::runnable::HostErr> {
set_field(FieldType::Meta.into(), "url", val)
}

pub fn id() -> String {
get_field(FieldType::Meta.into(), "id")
.map_or("".into(), util::to_string)
get_field(FieldType::Meta.into(), "id").map_or("".into(), util::to_string)
}

pub fn body_raw() -> Vec<u8> {
get_field(FieldType::Meta.into(), "body")
.unwrap_or_default()
get_field(FieldType::Meta.into(), "body").unwrap_or_default()
}

pub fn set_body(val: &str) -> Result<(), super::runnable::HostErr> {
set_field(FieldType::Body.into(), "body", val)
}

pub fn body_field(key: &str) -> String {
get_field(FieldType::Body.into(), key)
.map_or("".into(), util::to_string)
get_field(FieldType::Body.into(), key).map_or("".into(), util::to_string)
}

pub fn set_body_field(key: &str, val: &str) -> Result<(), super::runnable::HostErr> {
set_field(FieldType::Body.into(), key, val)
}

pub fn header(key: &str) -> String {
get_field(FieldType::Header.into(), key)
.map_or("".into(), util::to_string)
get_field(FieldType::Header.into(), key).map_or("".into(), util::to_string)
}

pub fn set_header(key: &str, val: &str) -> Result<(), super::runnable::HostErr> {
set_field(FieldType::Header.into(), key, val)
}

pub fn url_param(key: &str) -> String {
get_field(FieldType::Params.into(), key)
.map_or("".into(), util::to_string)
get_field(FieldType::Params.into(), key).map_or("".into(), util::to_string)
}

pub fn set_url_param(key: &str, val: &str) -> Result<(), super::runnable::HostErr> {
set_field(FieldType::Params.into(), key, val)
}

pub fn state(key: &str) -> Option<String> {
get_field(FieldType::State.into(), key)
.map(util::to_string)
get_field(FieldType::State.into(), key).map(util::to_string)
}

pub fn set_state(key: &str, val: &str) -> Result<(), super::runnable::HostErr> {
@@ -86,23 +85,27 @@ pub fn state_raw(key: &str) -> Option<Vec<u8>> {
///
/// Then retreives the result from the host and returns it
fn get_field(field_type: i32, key: &str) -> Option<Vec<u8>> {
let result_size = unsafe {
request_get_field(field_type, key.as_ptr(), key.len() as i32, STATE.ident)
};
let result_size = unsafe { request_get_field(field_type, key.as_ptr(), key.len() as i32, STATE.ident) };

ffi::result(result_size)
.map_or(None, Option::from)
ffi::result(result_size).map_or(None, Option::from)
}

fn set_field(field_type: i32, key: &str, val: &str) -> Result<(), super::runnable::HostErr> {
// make the request over FFI
let result_size = unsafe { request_set_field(field_type, key.as_ptr(), key.len() as i32, val.as_ptr(), val.len() as i32, super::STATE.ident) };
let result_size = unsafe {
request_set_field(
field_type,
key.as_ptr(),
key.len() as i32,
val.as_ptr(),
val.len() as i32,
super::STATE.ident,
)
};

// retreive the result from the host and return it
match ffi::result(result_size) {
Ok(_) => Ok(()),
Err(e) => {
Err(e)
}
Err(e) => Err(e),
}
}
Original file line number Diff line number Diff line change
@@ -3,17 +3,17 @@ pub enum FieldType {
Body,
Header,
Params,
State
State,
}

impl From<FieldType> for i32 {
fn from(field_type: FieldType) -> Self {
fn from(field_type: FieldType) -> Self {
match field_type {
FieldType::Meta => 0,
FieldType::Body => 1,
FieldType::Header => 2,
FieldType::Params => 3,
FieldType::State => 4,
}
}
}
}
12 changes: 9 additions & 3 deletions api/rust/suborbital/src/resp.rs → api/rust/core/src/resp.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
use crate::STATE;

extern {
extern "C" {
fn resp_set_header(key_pointer: *const u8, key_size: i32, val_pointer: *const u8, val_size: i32, ident: i32);
}

pub fn set_header(key: &str, val: &str) {
unsafe {
resp_set_header(key.as_ptr(), key.len() as i32, val.as_ptr(), val.len() as i32, STATE.ident)
unsafe {
resp_set_header(
key.as_ptr(),
key.len() as i32,
val.as_ptr(),
val.len() as i32,
STATE.ident,
)
};
}

Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
pub use codegen::Runnable;

use crate::STATE;
use std::mem;
use std::slice;

extern {
extern "C" {
fn return_result(result_pointer: *const u8, result_size: i32, ident: i32);
fn return_error(code: i32, result_pointer: *const u8, result_size: i32, ident: i32);
}
@@ -50,7 +48,7 @@ pub fn use_runnable(runnable: &'static dyn Runnable) {
/// We hand over the the pointer to the allocated memory.
/// Caller has to ensure that the memory gets freed again.
#[no_mangle]
pub unsafe extern fn allocate(size: i32) -> *const u8 {
pub unsafe extern "C" fn allocate(size: i32) -> *const u8 {
let mut buffer = Vec::with_capacity(size as usize);

let pointer = buffer.as_mut_ptr();
@@ -62,13 +60,13 @@ pub unsafe extern fn allocate(size: i32) -> *const u8 {

/// # Safety
#[no_mangle]
pub unsafe extern fn deallocate(pointer: *const u8, size: i32) {
pub unsafe extern "C" fn deallocate(pointer: *const u8, size: i32) {
let _ = slice::from_raw_parts(pointer, size as usize);
}

/// # Safety
#[no_mangle]
pub unsafe extern fn run_e(pointer: *mut u8, size: i32, ident: i32) {
pub unsafe extern "C" fn run_e(pointer: *mut u8, size: i32, ident: i32) {
STATE.ident = ident;

// rebuild the memory into something usable
@@ -84,7 +82,7 @@ pub unsafe extern fn run_e(pointer: *mut u8, size: i32, ident: i32) {
}
}

fn execute_runnable(runnable: Option<& dyn Runnable>, data: Vec<u8>) -> Result<Vec<u8>, RunErr> {
fn execute_runnable(runnable: Option<&dyn Runnable>, data: Vec<u8>) -> Result<Vec<u8>, RunErr> {
if let Some(runnable) = runnable {
return runnable.run(data);
}
File renamed without changes.
12 changes: 0 additions & 12 deletions api/rust/suborbital/codegen/Cargo.toml

This file was deleted.

2 changes: 2 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
hard_tabs=true
max_width=120