243 lines
7.6 KiB
Rust
243 lines
7.6 KiB
Rust
use std::any::Any;
|
|
use std::fmt::Debug;
|
|
|
|
use crate::MizeResult;
|
|
|
|
use crate::get_global_mize;
|
|
use crate::id::MizeId;
|
|
use crate::item::{IntoItemData, ItemData};
|
|
use crate::Mize;
|
|
|
|
pub type ConfigFun = Box<dyn Fn() -> MizeResult<ItemData> + Send + Sync + 'static>;
|
|
pub type MizeFun = Box<dyn Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>;
|
|
|
|
pub struct ConfigOpt {
|
|
pub name: String,
|
|
pub val: Option<ItemData>,
|
|
pub fun: Option<ConfigFun>,
|
|
pub deps: Vec<String>,
|
|
}
|
|
|
|
pub trait FromItemData {
|
|
fn from_itemdata(data: ItemData) -> MizeResult<Self> where Self: Sized;
|
|
}
|
|
|
|
impl Debug for ConfigOpt {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "({}: {})", self.name, self.val.clone().unwrap_or(ItemData::new()))
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
#[repr(C)]
|
|
pub struct ConfigOptId {
|
|
pub id: MizeId,
|
|
}
|
|
|
|
impl ConfigOptId {
|
|
pub fn default_val(self, val: ItemData) -> Self {
|
|
let mize = get_global_mize().unwrap();
|
|
// in generate mode: record the default value as metadata, skip normal op
|
|
if mize.is_generate_mode().unwrap_or(false) {
|
|
mize.record_opt("_default_val", self.id.clone(), Some(val)).ok();
|
|
return self.clone();
|
|
}
|
|
let mut config_opts = mize.config_opts.lock().unwrap();
|
|
let opt = config_opts.get_mut(&self.id).unwrap();
|
|
opt.val = Some(val);
|
|
self.clone()
|
|
}
|
|
pub fn fun(self, fun: ConfigFun) -> Self {
|
|
let mize = get_global_mize().unwrap();
|
|
// in generate mode: record as an opt with a fun, skip normal op
|
|
if mize.is_generate_mode().unwrap_or(false) {
|
|
mize.record_opt("_fun", self.id.clone(), None).ok();
|
|
return self.clone();
|
|
}
|
|
let mut config_opts = mize.config_opts.lock().unwrap();
|
|
let opt = config_opts.get_mut(&self.id).unwrap();
|
|
opt.fun = Some(fun);
|
|
self.clone()
|
|
}
|
|
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(self, name: &str, signature: &str, fun: F) -> ConfigOptId {
|
|
let mize = get_global_mize().unwrap();
|
|
let mut cur_part = self.id.clone();
|
|
let id = cur_part.join(name).unwrap();
|
|
// in generate mode: record method metadata, skip normal registration
|
|
if mize.is_generate_mode().unwrap_or(false) {
|
|
mize.record_method(name, id.clone(), "method", signature).ok();
|
|
return self.clone();
|
|
}
|
|
let mut opts = mize.config_opts.lock().unwrap();
|
|
let opt = ConfigOpt {
|
|
name: id.dot(),
|
|
val: None,
|
|
fun: None,
|
|
deps: Vec::new(),
|
|
};
|
|
let mut fun_values = mize.fun_values.lock().unwrap();
|
|
fun_values.insert(id.clone(), Box::new(fun));
|
|
opts.insert(id.clone(), opt);
|
|
|
|
self.clone()
|
|
}
|
|
}
|
|
|
|
//pub trait ToItemDataHelper {
|
|
//fn into_item_data(self) -> ItemData;
|
|
//}
|
|
|
|
pub trait MizeAny {
|
|
fn as_raw_ptr(&self) -> *const ();
|
|
}
|
|
|
|
impl<T> MizeAny for T {
|
|
fn as_raw_ptr(&self) -> *const () {
|
|
self as *const Self as *const ()
|
|
}
|
|
}
|
|
|
|
|
|
pub fn opt(name: &str) -> crate::config::ConfigOptId {
|
|
let mize = get_global_mize().unwrap();
|
|
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
|
|
let id = cur_part.join(name).unwrap();
|
|
// in generate mode: record opt metadata, skip normal registration
|
|
if mize.is_generate_mode().unwrap_or(false) {
|
|
mize.record_opt(name, id.clone(), None).ok();
|
|
return ConfigOptId { id };
|
|
}
|
|
let mut opts = mize.config_opts.lock().unwrap();
|
|
let opt = ConfigOpt {
|
|
name: id.dot(),
|
|
val: None,
|
|
fun: None,
|
|
deps: Vec::new(),
|
|
};
|
|
opts.insert(id.clone(), opt);
|
|
ConfigOptId { id }
|
|
}
|
|
|
|
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(name: &str, signature: &str, fun: F) -> ConfigOptId {
|
|
let mize = get_global_mize().unwrap();
|
|
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
|
|
let id = cur_part.join(name).unwrap();
|
|
// in generate mode: record method metadata, skip normal registration
|
|
if mize.is_generate_mode().unwrap_or(false) {
|
|
mize.record_method(name, id.clone(), "method", signature).ok();
|
|
return ConfigOptId { id };
|
|
}
|
|
let mut opts = mize.config_opts.lock().unwrap();
|
|
let opt = ConfigOpt {
|
|
name: id.dot(),
|
|
val: None,
|
|
fun: None,
|
|
deps: Vec::new(),
|
|
};
|
|
let mut fun_values = mize.fun_values.lock().unwrap();
|
|
fun_values.insert(id.clone(), Box::new(fun));
|
|
opts.insert(id.clone(), opt);
|
|
ConfigOptId { id }
|
|
}
|
|
|
|
pub fn effect<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(name: &str, fun: F) -> ConfigOptId {
|
|
let mize = get_global_mize().unwrap();
|
|
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
|
|
let id = cur_part.join(name).unwrap();
|
|
// in generate mode: record effect metadata, skip normal registration
|
|
if mize.is_generate_mode().unwrap_or(false) {
|
|
mize.record_method(name, id.clone(), "effect", "").ok();
|
|
return ConfigOptId { id };
|
|
}
|
|
let mut opts = mize.config_opts.lock().unwrap();
|
|
let opt = ConfigOpt {
|
|
name: id.dot(),
|
|
val: None,
|
|
fun: None,
|
|
deps: Vec::new(),
|
|
};
|
|
let mut fun_values = mize.fun_values.lock().unwrap();
|
|
fun_values.insert(id.clone(), Box::new(fun));
|
|
opts.insert(id.clone(), opt);
|
|
ConfigOptId { id }
|
|
}
|
|
|
|
pub fn thread<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(name: &str, fun: F) -> ConfigOptId {
|
|
let mize = get_global_mize().unwrap();
|
|
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
|
|
let id = cur_part.join(name).unwrap();
|
|
// in generate mode: record thread metadata, skip normal registration
|
|
if mize.is_generate_mode().unwrap_or(false) {
|
|
mize.record_method(name, id.clone(), "thread", "").ok();
|
|
return ConfigOptId { id };
|
|
}
|
|
let mut opts = mize.config_opts.lock().unwrap();
|
|
let opt = ConfigOpt {
|
|
name: id.dot(),
|
|
val: None,
|
|
fun: None,
|
|
deps: Vec::new(),
|
|
};
|
|
let mut fun_values = mize.fun_values.lock().unwrap();
|
|
fun_values.insert(id.clone(), Box::new(fun));
|
|
opts.insert(id.clone(), opt);
|
|
ConfigOptId { id }
|
|
}
|
|
|
|
type CFun = unsafe extern "C" fn (*mut ItemData) -> *mut ItemData;
|
|
|
|
pub mod c_api {
|
|
use std::ffi::c_char;
|
|
|
|
use crate::config::{CFun, ConfigOptId};
|
|
use std::ffi::CStr;
|
|
|
|
pub extern "C" fn opt(name: *const c_char) -> ConfigOptId {
|
|
unsafe {
|
|
let c_str = CStr::from_ptr(name);
|
|
let string = c_str.to_string_lossy();
|
|
super::opt(&string)
|
|
}
|
|
}
|
|
pub extern "C" fn method(name: *const c_char, signature: *const c_char, c_fun: CFun) -> ConfigOptId {
|
|
unsafe {
|
|
let name_str = CStr::from_ptr(name).to_string_lossy();
|
|
let sig_str = if signature.is_null() {
|
|
String::new()
|
|
} else {
|
|
CStr::from_ptr(signature).to_string_lossy().into_owned()
|
|
};
|
|
super::method(&name_str, &sig_str, move |args| {
|
|
let raw_ptr = Box::into_raw(Box::new(args));
|
|
let ret_ptr = c_fun(raw_ptr);
|
|
let data = *Box::from_raw(ret_ptr);
|
|
Ok(data)
|
|
})
|
|
}
|
|
}
|
|
pub extern "C" fn effect(name: *const c_char, c_fun: CFun) -> ConfigOptId {
|
|
unsafe {
|
|
let c_str = CStr::from_ptr(name);
|
|
let string = c_str.to_string_lossy();
|
|
super::effect(&string, move |args| {
|
|
let raw_ptr = Box::into_raw(Box::new(args));
|
|
let ret_ptr = c_fun(raw_ptr);
|
|
let data = *Box::from_raw(ret_ptr);
|
|
Ok(data)
|
|
})
|
|
}
|
|
}
|
|
pub extern "C" fn thread(name: *const c_char, c_fun: CFun) -> ConfigOptId {
|
|
unsafe {
|
|
let c_str = CStr::from_ptr(name);
|
|
let string = c_str.to_string_lossy();
|
|
super::thread(&string, move |args| {
|
|
let raw_ptr = Box::into_raw(Box::new(args));
|
|
let ret_ptr = c_fun(raw_ptr);
|
|
let data = *Box::from_raw(ret_ptr);
|
|
Ok(data)
|
|
})
|
|
}
|
|
}
|
|
}
|