use crate::map::{IndexType, MapManager};
use tokio::runtime::{Runtime, Builder};
use std::os::raw::c_char;
use std::sync::{Once};
pub mod astar;
pub mod errors;
pub mod id;
pub mod map;
pub mod rmacro;
#[repr(C)] pub struct CPoint {
pub x: i32,
pub y: i32,
}
#[repr(C)]
pub struct CPointArray {
length: usize,
data: *const (i32,i32),
cap: usize,
}
static TOKIO_RUNTIME_INIT: Once = Once::new();
static mut TOKIO_RUNTIME: Option<Runtime> = None;
pub fn init_tokio_runtime(worker_threads: usize) {
TOKIO_RUNTIME_INIT.call_once(|| {
unsafe {
TOKIO_RUNTIME = Some(
Builder::new_multi_thread()
.worker_threads(worker_threads)
.build()
.unwrap()
);
}
});
}
pub fn get_tokio_runtime() -> &'static Runtime {
unsafe {
TOKIO_RUNTIME.as_ref().unwrap()
}
}
#[no_mangle]
pub extern "C" fn init_runtime(worker_threads: usize) {
init_tokio_runtime(worker_threads);
}
#[no_mangle]
pub extern "C" fn find_path(map_id:i64, start_point:&CPoint, end_point:&CPoint) -> CPointArray {
return get_tokio_runtime().block_on(async {
find(map_id, start_point, end_point).await
});
}
#[no_mangle]
pub extern "C" fn set_walkable(map_id:i64, point:&CPoint, walkable:i32) -> bool {
return get_tokio_runtime().block_on(async {
set_walkable_impl(map_id, point, walkable).await
});
}
#[no_mangle]
pub extern "C" fn load_map(c_string: *const c_char) -> i64 {
return get_tokio_runtime().block_on(async {
let map_file = unsafe { std::ffi::CStr::from_ptr(c_string) };
load_map_from_file(map_file.to_string_lossy().into_owned()).await
});
}
#[no_mangle]
pub extern "C" fn load_map_from_string(file_content: *const c_char) -> i64 {
return get_tokio_runtime().block_on(async {
let map_file_content = unsafe { std::ffi::CStr::from_ptr(file_content) };
load_map_from_file_content(map_file_content.to_string_lossy().into_owned()).await
});
}
#[no_mangle]
pub extern "C" fn free_path(path: CPointArray) {
free_array(path);
}
async fn load_map_from_file(map_file: String) -> i64 {
let map = MapManager::get_instance();
let map_id = match map.write() {
Ok(mut write_lock) => write_lock.new_astar().await,
Err(err) => {println!("{}", err); return 0}
};
return match map.read() {
Ok(read_lock) => {
match read_lock.load_from_file(&map_id, map_file.to_string()).await {
Ok(_) => map_id,
Err(err) => {println!("{}", err);0}
}
},
Err(err) => {println!("{}", err);0}
};
}
async fn load_map_from_file_content(file_content: String) -> i64 {
let map = MapManager::get_instance();
let map_id = match map.write() {
Ok(mut write_lock) => write_lock.new_astar().await,
Err(err) => {println!("{}", err); return 0}
};
return match map.read() {
Ok(read_lock) => {
match read_lock.load_from_string(&map_id, file_content).await {
Ok(_) => map_id,
Err(err) => {println!("{}", err);0}
}
},
Err(err) => {println!("{}", err);0}
};
}
async fn find(map_id:i64, start_point:&CPoint, end_point:&CPoint) -> CPointArray {
let map = MapManager::get_instance();
let result = match map.read() {
Ok(read_lock) => read_lock.find_path(&map_id,(start_point.x, start_point.y), (end_point.x, end_point.y)),
Err(err) => {println!("{}", err); return CPointArray{ data: &(0, 0), length: 0, cap: 0 }}
};
match result {
Ok(v) => convert_to_c_array(v),
Err(_e) => CPointArray{ data: &(0, 0), length: 0, cap: 0 },
}
}
async fn set_walkable_impl(map_id:i64, point:&CPoint, walkable:i32) -> bool {
let map = MapManager::get_instance();
return match map.write() {
Ok(write_lock) => write_lock.set_walkable(&map_id, (point.x, point.y), walkable),
Err(err) => {println!("{}", err); return false}
}.is_ok();
}
fn convert_to_c_array(mut vec: Vec<(IndexType, IndexType)>) -> CPointArray {
let ptr = vec.as_mut_ptr();
let len = vec.len();
let cap = vec.capacity();
std::mem::forget(vec);
CPointArray {
data: ptr,
length: len,
cap
}
}
fn free_array(vec:CPointArray) {
let xx:Vec<(IndexType, IndexType)> = unsafe { Vec::from_raw_parts(vec.data as *mut (IndexType, IndexType), vec.length, vec.cap) };
drop(xx);
}