Skip to content

Commit

Permalink
Implement PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
NGnius committed May 3, 2021
1 parent 05a1109 commit aa8faeb
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
Cargo.lock
/.idea
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "libfj"]
path = libfj
url = https://github.com/NGnius/libfj
8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
[package]
name = "clibfj"
name = "libfj-c"
version = "0.1.0"
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
libc = "0.2.93"
libfj = { path = "libfj", features = ["simple"] }

[lib]
name = "libfj"
crate-type = ["rlib", "cdylib"]
1 change: 1 addition & 0 deletions libfj
Submodule libfj added at 9211fe
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod robocraft_bindings;

#[cfg(test)]
mod tests {
#[test]
Expand Down
29 changes: 29 additions & 0 deletions src/libfj.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef LIBFJ
#define LIBFJ

typedef struct FactoryRobotListInfo_struct{
uint32_t item_id;
char* item_name;
char* item_description;
char* thumbnail; // url
char* added_by;
char* added_by_display_name;
char* added_date; // ISO date
char* expiry_date; // ISO date
uint32_t cpu;
uint32_t total_robot_ranking;
uint32_t rent_count;
uint32_t buy_count;
uint32_t buyable; // bool
char* removed_date;
char* ban_date;
uint32_t featured; // bool
char* banner_message;
float combat_rating;
float cosmetic_rating;
char* cube_amounts; // JSON as str
} FactoryRobotListInfo;

void get_factory_front_page(uint32_t size, FactoryRobotListInfo* array_ptr);

#endif
126 changes: 126 additions & 0 deletions src/robocraft_bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use libc;
use std::ffi::CString;
use std::os::raw::c_char;
use libfj::robocraft_simple as robocraft;
use libfj::robocraft::FactoryRobotListInfo;

#[repr(C)]
pub struct FactoryRobotListInfoC {
pub item_id: u32,
pub item_name: *mut c_char,
pub item_description: *mut c_char,
pub thumbnail: *mut c_char, // url
pub added_by: *mut c_char,
pub added_by_display_name: *mut c_char,
pub added_date: *mut c_char, // ISO date
pub expiry_date: *mut c_char, // ISO date
pub cpu: u32,
pub total_robot_ranking: u32,
pub rent_count: u32,
pub buy_count: u32,
pub buyable: bool, // bool
pub removed_date: *mut c_char,
pub ban_date: *mut c_char,
pub featured: bool, // bool
pub banner_message: *mut c_char,
pub combat_rating: f32,
pub cosmetic_rating: f32,
pub cube_amounts: *mut c_char, // JSON as str
}

impl FactoryRobotListInfoC {
fn mock_error(msg: &str, url: &str) -> Self {
let mut err = Self::default();
err.item_name = unsafe {allocate_cstring(msg)};
err.thumbnail = unsafe {allocate_cstring(url)};
err.added_by_display_name = unsafe {allocate_cstring("ERROR")};
err.added_by = unsafe {allocate_cstring("ERROR")};
err.item_id = u32::MAX;
err
}
}

impl Default for FactoryRobotListInfoC {
fn default() -> Self {
FactoryRobotListInfoC {
item_id: 0,
item_name: unsafe {allocate_cstring("")},
item_description: unsafe {allocate_cstring("")},
thumbnail: unsafe {allocate_cstring("")},
added_by: unsafe {allocate_cstring("")},
added_by_display_name: unsafe {allocate_cstring("")},
added_date: unsafe {allocate_cstring("")},
expiry_date: unsafe {allocate_cstring("")},
cpu: 0,
total_robot_ranking: 0,
rent_count: 0,
buy_count: 0,
buyable: false,
removed_date: unsafe {allocate_cstring("")},
ban_date: unsafe {allocate_cstring("")},
featured: false,
banner_message: unsafe {allocate_cstring("")},
combat_rating: 0.0,
cosmetic_rating: 0.0,
cube_amounts: unsafe {allocate_cstring("")},
}
}
}

impl From<FactoryRobotListInfo> for FactoryRobotListInfoC {
fn from(frli: FactoryRobotListInfo) -> Self {
let def = "".to_string();
FactoryRobotListInfoC {
item_id: frli.item_id as u32,
item_name: unsafe {allocate_cstring(&frli.item_name)},
item_description: unsafe {allocate_cstring(&frli.item_description)},
thumbnail: unsafe {allocate_cstring(&frli.thumbnail)},
added_by: unsafe {allocate_cstring(&frli.added_by)},
added_by_display_name: unsafe {allocate_cstring(&frli.added_by_display_name)},
added_date: unsafe {allocate_cstring(&frli.added_date)},
expiry_date: unsafe {allocate_cstring(&frli.expiry_date)},
cpu: frli.cpu as u32,
total_robot_ranking: frli.total_robot_ranking as u32,
rent_count: frli.rent_count as u32,
buy_count: frli.buy_count as u32,
buyable: frli.buyable,
removed_date: unsafe {allocate_cstring(&frli.removed_date.unwrap_or(def.clone()))},
ban_date: unsafe {allocate_cstring(&frli.ban_date.unwrap_or(def.clone()))},
featured: frli.featured,
banner_message: unsafe {allocate_cstring(&frli.banner_message.unwrap_or(def.clone()))},
combat_rating: frli.combat_rating,
cosmetic_rating: frli.cosmetic_rating,
cube_amounts: unsafe {allocate_cstring(&frli.cube_amounts)},
}
}
}

#[no_mangle]
pub unsafe extern "C" fn get_factory_front_page(items: libc::c_uint, array_ptr: *mut FactoryRobotListInfoC) {
if items == 0 {return;} // nothing to populate, so it's useless to do work
let factory_api = robocraft::FactoryAPI::new();
let result = factory_api.list();
if let Ok(info) = result {
let max = if info.response.roboshop_items.len() < (items as usize) { info.response.roboshop_items.len() } else {items as usize};
let c_result = std::slice::from_raw_parts_mut(array_ptr, items as usize);
// copy results to output array
for i in 0..max {
c_result[i] = info.response.roboshop_items[i].clone().into();
}
} else if let Err(e) = result {
println!("{}", e);
// place error info into first array item
let c_result = std::slice::from_raw_parts_mut(array_ptr, items as usize);
c_result[0] = FactoryRobotListInfoC::mock_error(
&format!("{}", &e),
""
);
}
}

unsafe fn allocate_cstring(input: &str) -> *mut c_char {
let input_c = CString::new(input).expect("Rust &str -> CString conversion failed");
let space = libc::malloc(libc::strlen(input_c.as_ptr()) + 1) as *mut c_char;
libc::strcpy(space, input_c.as_ptr());
return space;
}

0 comments on commit aa8faeb

Please sign in to comment.