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 MizeResult + Send + Sync + 'static>; pub type MizeFun = Box MizeResult + Send + Sync + 'static>; pub struct ConfigOpt { pub name: String, pub val: Option, pub fun: Option, pub deps: Vec, } pub trait FromItemData { fn from_itemdata(data: ItemData) -> MizeResult 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 MizeResult + 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 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 MizeResult + 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 MizeResult + 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 MizeResult + 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) }) } } }