diff --git a/Cargo.lock b/Cargo.lock index 77c2c87..fb80a3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,18 +187,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -824,6 +824,31 @@ dependencies = [ "mize", ] +[[package]] +name = "mize-part-auth" +version = "0.1.0" +dependencies = [ + "log", + "mize", +] + +[[package]] +name = "mize-part-cli" +version = "0.1.0" +dependencies = [ + "clap", + "log", + "mize", +] + +[[package]] +name = "mize-part-dev" +version = "0.1.0" +dependencies = [ + "log", + "mize", +] + [[package]] name = "mize_macros" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 6997f34..547ea99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "macros", "apps/os", "apps/obsidian-plugin", + "parts/*", ] default-members = [ "apps/obsidian-plugin", diff --git a/apps/os/src/cli.rs b/apps/os/src/cli.rs index 9beca8e..030c8d2 100644 --- a/apps/os/src/cli.rs +++ b/apps/os/src/cli.rs @@ -1,5 +1,4 @@ use clap::ArgMatches; -use marts::CliPart; use core::result::Result::Err; use core::unimplemented; use mize::flume::bounded; @@ -19,6 +18,8 @@ use mize::item::{IntoItemData, ItemData}; use mize::platform::os::config_from_cli_args; use mize::platform::os::fsstore::FileStore; +use crate::generated; + pub fn get(sub_matches: &ArgMatches, instance: &mut Mize) -> MizeResult<()> { let id = sub_matches @@ -81,7 +82,7 @@ pub fn run(sub_matches: &ArgMatches, mize: &mut Mize) -> MizeResult<()> { let mut ext_cmdline = vec![runnable.to_owned()]; ext_cmdline.append(&mut ext_args); - let mut cli = mize.get_part_native::("cli")?; + let mut cli = generated::CliPart::get("cli")?; cli.run(ext_cmdline)?; } } diff --git a/apps/os/src/generated.rs b/apps/os/src/generated.rs new file mode 100644 index 0000000..f36c1e0 --- /dev/null +++ b/apps/os/src/generated.rs @@ -0,0 +1,70 @@ +use mize::prelude::*; + + +pub struct CliPart { + id: MizeId +} + +impl MizePart for CliPart { + fn id(&self) -> MizeId { + self.id.clone() + } +} + +impl CliPart { + pub fn get(name: &str) -> MizeResult { + let mut mize = get_global_mize()?; + let part = mize.get_part(name)?; + Ok(CliPart { id: part.id() }) + } + pub fn run(&self, cmdline: Vec) -> MizeResult<()> { + let cmdline = cmdline.into_item_data(); + let mut args = ItemData::new(); + args.set_path("0", cmdline)?; + dyn_call(self.id.clone(), "run", args)?; + Ok(()) + } + pub fn set_command(&self, name: &str) -> MizeResult<()> { + let name = name.into_item_data(); + let mut args = ItemData::new(); + args.set_path("0", name)?; + dyn_call(self.id.clone(), "set_command", args)?; + Ok(()) + } + pub fn subcommand MizeResult<()> + Send + Sync + 'static>(&self, subcmd: Command, action: T) -> MizeResult<()> { + let mut subcmd_arg = ItemData::new(); + subcmd_arg.set_path("_native", subcmd.native_id)?; + let mut action_arg = ItemData::from_native(action)?; + let mut args = ItemData::new(); + args.set_path("0", subcmd_arg)?; + args.set_path("1", action_arg)?; + dyn_call(self.id.clone(), "subcommand", args)?; + Ok(()) + } +} + +// the clap::Command native stuff +pub struct Command { + native_id: u32 +} + +pub struct ArgMatches { + native_id: u32 +} + +pub struct Action { + native_id: u32 +} + +impl Command { + pub fn new(name: &str) -> MizeResult { + let name = name.into_item_data(); + let mut args = ItemData::new(); + args.set_path("0", name)?; + let mut mize = get_global_mize()?; + let id = mize.id_new_dots("cli.Command")?; + let data = dyn_call(id.clone(), "new", args)?; + let native_id: u32 = data.get_path("_native")?.native_take()?; + Ok(Command { native_id }) + } +} diff --git a/apps/os/src/main.rs b/apps/os/src/main.rs index a59e95b..f19df6e 100644 --- a/apps/os/src/main.rs +++ b/apps/os/src/main.rs @@ -19,6 +19,8 @@ use std::sync::Arc; use tracing::{debug, error, info, trace, warn}; mod cli; +// the generated module by hand. as we need the mize-bin to run generate +mod generated; static APPNAME: &str = "mize"; @@ -61,6 +63,7 @@ fn tried_main() -> MizeResult<()> { let mut mize = Mize::with_config(config_from_cli_args(&cli_matches)?)?; // compiled in parts (which for now is all) + /* compile_in_parts! { mize, "cli": marts::cli, @@ -70,7 +73,8 @@ fn tried_main() -> MizeResult<()> { "ppc.server": marts::ppc::server::part_ppc_server, "c2vi": marts::part_c2vi, "sci.timetrack": marts::sci::timetrack::part_timetrack, - }; + }; + */ // match subcommand diff --git a/core/src/api.rs b/core/src/api.rs new file mode 100644 index 0000000..5e46c8f --- /dev/null +++ b/core/src/api.rs @@ -0,0 +1,6 @@ +use crate::prelude::*; + +pub fn dyn_call(part_id: MizeId, method: &str, args: ItemData) -> MizeResult { + let mut mize = get_global_mize()?; + mize.dyn_call(part_id, method, args) +} diff --git a/core/src/config.rs b/core/src/config.rs index 7ab3241..681dc36 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -2,7 +2,7 @@ use std::any::Any; use crate::MizeResult; -use crate::c_api::get_global_mize; +use crate::get_global_mize; use crate::id::MizeId; use crate::item::{IntoItemData, ItemData}; use crate::Mize; @@ -86,14 +86,14 @@ pub mod c_api { unsafe { let c_str = CStr::from_ptr(name); let string = c_str.to_string_lossy(); - super::opt(string.as_str()) + super::opt(&string) } } pub extern "C" fn method(name: *const c_char, c_fun: CFun) { unsafe { let c_str = CStr::from_ptr(name); let string = c_str.to_string_lossy(); - super::method(string.as_str(), move |args| { + super::method(&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); @@ -105,7 +105,7 @@ pub mod c_api { unsafe { let c_str = CStr::from_ptr(name); let string = c_str.to_string_lossy(); - super::effect(string.as_str(), move |args| { + 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); @@ -117,7 +117,7 @@ pub mod c_api { unsafe { let c_str = CStr::from_ptr(name); let string = c_str.to_string_lossy(); - super::thread(string.as_str(), move |args| { + 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); diff --git a/core/src/id.rs b/core/src/id.rs index 4324036..396360b 100644 --- a/core/src/id.rs +++ b/core/src/id.rs @@ -4,7 +4,7 @@ use interner::{ }; use std::hash::Hash; -use crate::{c_api::get_global_mize, error::MizeResult}; +use crate::{get_global_mize, error::MizeResult}; use crate::{instance::Mize, mize_err}; #[derive(Debug, Clone, Hash, Eq, PartialEq)] diff --git a/core/src/instance/connection.rs b/core/src/instance/connection.rs new file mode 100644 index 0000000..2c7d4e7 --- /dev/null +++ b/core/src/instance/connection.rs @@ -0,0 +1,57 @@ +use flume::{Receiver, Sender}; +use tracing::{debug, error, info, trace, warn}; + +use crate::error::{IntoMizeResult, MizeError, MizeResult}; +use crate::id::Namespace; +use crate::mize_err; +use crate::proto::MizeMessage; + +use super::Mize; +use crate::item::{get_raw_from_cbor, Item, ItemData}; + +// only created with Instance::new_connection() +#[derive(Clone, Debug)] +pub struct Connection { + pub tx: Sender, + pub id: u64, + pub ns: Option, +} + +pub trait ConnListener: Send + Sync { + fn listen(self, instance: Mize) -> MizeResult<()>; +} + +impl Connection { + pub fn send(&self, msg: MizeMessage) -> MizeResult<()> { + Ok(self.tx.send(msg)?) + } +} + +pub fn value_raw_con_by_id(item: &mut Item) -> MizeResult { + if item.id().nth_part(3)? == "peer" { + return value_raw_from_peer(item); + } else { + return Err(mize_err!("id with path: '{}' is not supported", item.id())); + } +} + +pub fn value_raw_from_peer(item: &mut Item) -> MizeResult { + let id = item.id(); + + let conn_id_str = id.nth_part(2)?; + let conn_id: u64 = conn_id_str.parse()?; + let tmp_path = id.path(); + let mut new_id_str = tmp_path.iter(); + let skipped = new_id_str.skip(4); + let new_id = item.instance.new_id(skipped.cloned().collect::>())?; + + let connection = item.instance.get_connection(conn_id)?; + + let msg = MizeMessage::new_get(new_id.clone(), connection.id); + + connection.tx.send(msg)?; + + let data = item.instance.give_msg_wait(new_id)?; + + return Ok(data); +} diff --git a/core/src/instance/mod.rs b/core/src/instance/mod.rs index 8849043..14338d7 100644 --- a/core/src/instance/mod.rs +++ b/core/src/instance/mod.rs @@ -11,7 +11,7 @@ use std::sync::{Arc, Mutex}; use std::{thread, vec}; use tracing::{debug, info, trace}; -use crate::c_api::set_global_mize; +use crate::set_global_mize; use crate::config::{ConfigOpt, ConfigOptId}; use crate::error::{MizeError, MizeResult}; use crate::id::{IntoMizeId, MizeId, Namespace}; @@ -259,7 +259,7 @@ impl Mize { set_global_mize(self.clone())?; // platform specific init code - crate::platform::instance_init(self)?; + crate::platform::init(self)?; // end of platform specific init code diff --git a/core/src/instance/msg_thread.rs b/core/src/instance/msg_thread.rs new file mode 100644 index 0000000..86b4fba --- /dev/null +++ b/core/src/instance/msg_thread.rs @@ -0,0 +1,2 @@ +// Message thread handling for the Mize instance. +// This module is reserved for future message threading functionality. diff --git a/core/src/instance/store.rs b/core/src/instance/store.rs new file mode 100644 index 0000000..f17c837 --- /dev/null +++ b/core/src/instance/store.rs @@ -0,0 +1,71 @@ +use dyn_clone::DynClone; +use std::fmt::Debug; +use std::iter::Map; +use std::option::Iter; + +use crate::error::MizeResult; +use crate::id::MizeId; +use crate::instance::Mize; +use crate::item::get_raw_from_cbor; +use crate::item::{Item, ItemData}; +use crate::memstore::MemStore; + +dyn_clone::clone_trait_object!(Store); + +pub trait Store: DynClone + Send + Sync + Debug { + // should have the ability to be multi threaded, if the underlying implementation supports + // multithreaded IO operations + // for now all refs to a store hold a Mutex but this mutex is part of where the MizeStore trait + // is implemented, so that there can be a multithreaded implementation + //fn get(self, id: MizeId) -> MizeResult> where Self: Sized; + + fn set(&self, id: MizeId, data: ItemData) -> MizeResult<()>; + + // in the future should implement transactions, .... + + // funcs to do with links, backlinks + fn get_links(&self, item: Item) -> MizeResult>; + + fn get_backlinks(&self, item: Item) -> MizeResult>; + + fn new_id(&self) -> MizeResult; + + fn get_value_raw(&self, id: MizeId) -> MizeResult>; + + fn get_value_data_full(&self, id: MizeId) -> MizeResult; + + fn id_iter(&self) -> MizeResult; + + fn next_id(&self, prev_id: &str) -> MizeResult>; + + fn first_id(&self) -> MizeResult; +} + +pub struct IdIter { + cur_id: String, + store: Box, +} + +impl IdIter { + pub fn new(store: Box) -> MizeResult { + Ok(IdIter { + cur_id: store.first_id()?, + store, + }) + } +} + +impl Iterator for IdIter { + type Item = MizeResult; + + fn next(&mut self) -> Option { + match self.store.next_id(&self.cur_id) { + Err(err) => Some(Err(err)), + Ok(Some(new_id)) => { + self.cur_id = new_id.clone(); + Some(Ok(new_id)) + } + Ok(None) => None, + } + } +} diff --git a/core/src/instance/subscription.rs b/core/src/instance/subscription.rs new file mode 100644 index 0000000..ddb7577 --- /dev/null +++ b/core/src/instance/subscription.rs @@ -0,0 +1,68 @@ +use core::fmt; +use flume::Sender; +use std::rc::Rc; +use std::sync::Arc; +use tracing::trace; + +use crate::error::MizeResult; +use crate::id::MizeId; +use crate::instance::connection::Connection; +use crate::item::Item; +use crate::proto::MizeMessage; + +use super::Mize; + +#[derive(Clone, Debug)] +pub struct Update { + pub instance: Arc, + pub id: MizeId, +} + +impl Update { + pub fn new_item(&self) -> MizeResult { + self.instance.get(self.id.clone()) + } +} + +pub enum Subscription { + Connection(Connection), + Closure(Box MizeResult<()> + Send>), + Channel(Sender), +} + +impl Subscription { + pub fn from_conn(conn: Connection) -> Subscription { + Subscription::Connection(conn) + } + pub fn from_closure(closure: Box MizeResult<()> + Send>) -> Subscription { + Subscription::Closure(closure) + } + pub fn from_sender(tx: Sender) -> Subscription { + Subscription::Channel(tx) + } + + pub fn handle(&mut self, update: Update) -> MizeResult<()> { + trace!("handleing update"); + match &self { + Subscription::Connection(conn) => { + let msg = MizeMessage::new_update( + update.id.clone(), + update.new_item()?.as_data_full()?, + conn.id, + ); + conn.send(msg)?; + } + Subscription::Closure(closure) => closure(update)?, + Subscription::Channel(tx) => { + tx.send(update); + } + } + Ok(()) + } +} + +impl fmt::Debug for Subscription { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "...Subscription...") + } +} diff --git a/core/src/instance/tests.rs b/core/src/instance/tests.rs new file mode 100644 index 0000000..827ca4b --- /dev/null +++ b/core/src/instance/tests.rs @@ -0,0 +1,252 @@ +use crate::item::IntoItemData; + +use super::*; + +#[test] +fn test_sort_keys() -> MizeResult<()> { + let mut data = ItemData::from_toml( + r#" + [hi] + test = 4 + + [config] + zzz = "hiiii" + hi = "hello from config/hi" + + [config.test] + inner = "inner" + "#, + )?; + + let data_sorted = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + test = { inner = "inner" } + zzz = "hiiii" + + [hi] + test = 4 + "#, + )?; + + data.sort_keys()?; + + assert_eq!(data.to_json()?, data_sorted.to_json()?); + + Ok(()) +} + +#[test] +fn test_get_module_hash() -> MizeResult<()> { + let mut instance = Mize::empty()?; + + use crate::platform::os::get_part_hash; + let selector_toml = r#" + mize_version = "0.0.0" + system = "x86_64-unknown-linux-gnu" + toolchain_version = "rustc 1.78.0 (9b00956e5 2024-04-29)" + "#; + + instance.set_blocking("0/config/selector", ItemData::from_toml(&selector_toml)?)?; + + let (hash, selector) = get_part_hash(&mut instance, "String", ItemData::new())?; + + println!("hash: {}", hash); + println!("selector: {}", selector); + + assert_eq!(hash, "e96edf60216688314efc263c1aa8d6ce".to_owned()); + + Ok(()) +} + +#[test] +fn test_set_store_path() -> MizeResult<()> { + let instance = Mize::empty()?; + + let store_path = "/home/me/.mize".to_owned(); + + let config = instance.get("0/config")?.as_data_full()?; + + println!("data at 0/config: {}", config); + + instance.set_blocking("0/config/store_path", store_path.clone().into_item_data())?; + + let store_path_new = instance.get("0/config/store_path")?.value_string()?; + + assert_eq!(store_path_new, store_path); + + Ok(()) +} + +#[test] +fn test_set_sub_path() -> MizeResult<()> { + let instance = Mize::empty()?; + + let data = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "inner" + "#, + )?; + + let data_two = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "new inner" + "#, + )?; + + let item = instance.new_item()?; + instance.set_blocking(item.id(), data.clone())?; + + assert_eq!(item.as_data_full()?, data); + + // try to set a sub path of item + instance.set_blocking( + vec![item.id().store_part(), "config", "test", "inner"], + "new inner".into_item_data(), + )?; + + // the contents of item should then be like data_two + println!( + "item with id '{}': {}", + item.id(), + instance.get(vec![item.id().store_part()])?.as_data_full()? + ); + assert_eq!( + instance + .get(vec![item.id().store_part(), "config", "test", "inner"])? + .as_data_full()?, + ItemData::from_string("new inner") + ); + assert_eq!(item.as_data_full()?, data_two); + + Ok(()) +} + +#[test] +fn test_itemdata_set_path() -> MizeResult<()> { + let mut data = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "inner" + "#, + )?; + + let data_two = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "new inner" + "#, + )?; + + data.set_path( + vec!["config", "test", "inner"], + ItemData::from_string("new inner"), + )?; + + assert_eq!(data, data_two); + + Ok(()) +} + +#[test] +fn test_itemdata_merge() -> MizeResult<()> { + let mut data = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "inner" + "#, + )?; + + let data_two = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "new inner" + "#, + )?; + + assert_eq!( + data.get_path(vec!["config", "test", "inner"])?, + ItemData::from_string("inner") + ); + + data.merge(data_two.clone()); + + assert_eq!(data, data_two); + + assert_eq!( + data.get_path(vec!["config", "test", "inner"])?, + ItemData::from_string("new inner") + ); + + Ok(()) +} + +#[test] +fn test_item_merge() -> MizeResult<()> { + let instance = Mize::empty()?; + + let mut item = instance.new_item()?; + + // here the item should contain "empty" data + assert_eq!(item.as_data_full()?, ItemData::new()); + + let data = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "inner" + "#, + )?; + + let data_two = ItemData::from_toml( + r#" + [config] + hi = "hello from config/hi" + + [config.test] + inner = "new inner" + "#, + )?; + + item.merge(data.clone())?; + + // now it should contain data + assert_eq!(item.as_data_full()?, data); + + let mut sub_item = instance.get(vec![item.id().store_part(), "config", "test", "inner"])?; + + // the sub item should have the string "inner" + assert_eq!(sub_item.as_data_full()?, ItemData::from_string("inner")); + + sub_item.merge(ItemData::from_string("new inner")); + + assert_eq!(sub_item.as_data_full()?, ItemData::from_string("new inner")); + + // also the item should be updated + assert_eq!(item.as_data_full()?, data_two); + + Ok(()) +} diff --git a/core/src/instance/updater.rs b/core/src/instance/updater.rs new file mode 100644 index 0000000..64e08ee --- /dev/null +++ b/core/src/instance/updater.rs @@ -0,0 +1,236 @@ +use flume::Receiver; +use std::borrow::BorrowMut; +use std::sync::Arc; +use tracing::{error, trace, warn}; + +use crate::error::{MizeError, MizeResult, MizeResultTrait}; +use crate::id::MizeId; +use crate::mize_err; +use crate::proto::{MessageCmd, MizeMessage}; +use crate::{instance::Mize, item::ItemData}; + +use super::connection::{self, Connection}; +use super::subscription::{Subscription, Update}; + +#[derive(Debug)] +pub enum Operation { + Set(MizeId, ItemData, Option), // bool: is_from_update_msg + Msg(MizeMessage), +} + +// console_log macro +// that can be copied into other files for debugging purposes +#[cfg(feature = "wasm-target")] +use wasm_bindgen::prelude::*; + +#[cfg(feature = "wasm-target")] +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn log(s: &str); +} + +#[cfg(feature = "wasm-target")] +macro_rules! console_log { + // Note that this is using the `log` function imported above during + // `bare_bones` + ($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())}) +} + +#[cfg(not(feature = "wasm-target"))] +macro_rules! console_log { + // Note that this is using the `log` function imported above during + // `bare_bones` + ($($t:tt)*) => {}; +} +//end of console_log macro + +pub async fn updater_thread_async(operation_rx: Receiver, instance: Mize) -> () { + let mut count = 0; + console_log!("inside an updater thread"); + + loop { + let mut operation = match operation_rx.recv_async().await { + Ok(val) => val, + Err(e) => { + instance.report_err(e.into()); + continue; + } + }; + + let op_str = match operation { + Operation::Set(_, _, _) => "SET", + Operation::Msg(_) => "MSG", + }; + + trace!("OPERATION {} - {}", count, op_str); + console_log!("OPERATION {} - {}", count, op_str); + + let result = handle_operation(&mut operation, &instance); + + trace!("OPERATION {} DONE", count); + count += 1; + + if let Err(err) = result { + error!("OPERATION {} FAILED: {:?}", count, operation); + err.log(); + } + } +} + +pub fn updater_thread(operation_rx: Receiver, instance: &Mize) -> MizeResult<()> { + let mut count = 0; + + loop { + let mut operation = operation_rx.recv()?; + let op_str = match operation { + Operation::Set(_, _, _) => "SET", + Operation::Msg(_) => "MSG", + }; + + trace!("OPERATION {} - {}", count, op_str); + + let result = handle_operation(&mut operation, instance); + + trace!("OPERATION {} DONE", count); + count += 1; + + if let Err(err) = result { + error!("OPERATION FAILED: {:?}", operation); + err.log(); + } + } + Ok(()) +} + +pub fn handle_operation(operation: &mut Operation, instance: &Mize) -> MizeResult<()> { + match operation { + Operation::Set(id, value, maybe_conn) => { + let item_data: ItemData = value.to_owned(); + let mut item = instance.get(id.clone())?; + item.merge(item_data)?; + + //check subs and handle them + let mut subs_inner = instance.subs.lock()?; + if let Some(vec) = subs_inner.get_mut(&id) { + let update = Update { + instance: Arc::new(instance.to_owned()), + id: id.clone(), + }; + for sub in vec.iter_mut() { + // don't handle sub of type connection, in case the update comes from this + // connection + if let Some(conn) = maybe_conn { + if let Subscription::Connection(conn2) = sub { + if conn.id == conn2.id { + continue; + } + } + } + + sub.handle(update.clone()); + } + } + } + Operation::Msg(msg) => handle_msg(msg, instance)?, + } + Ok(()) +} + +fn handle_msg(msg: &mut MizeMessage, instance: &Mize) -> MizeResult<()> { + match msg.cmd()? { + MessageCmd::Get => { + let id = msg.id(instance)?; + let mut connection = instance.get_connection(msg.conn_id)?.clone(); + let item = instance.get(id.clone())?; + let msg = MizeMessage::new_give(id, item.as_data_full()?, msg.conn_id); + connection.send(msg)?; + } + + MessageCmd::GetSub => { + let id = msg.id(instance)?; + let mut connection = instance.get_connection(msg.conn_id)?.clone(); + let item = instance.get(id.clone())?; + let msg = MizeMessage::new_give(id.clone(), item.as_data_full()?, msg.conn_id); + connection.send(msg)?; + let sub = Subscription::from_conn(connection.clone()); + instance.sub(id, sub)?; + } + + MessageCmd::Sub => { + let id = msg.id(instance)?; + let mut connection = instance.get_connection(msg.conn_id)?.clone(); + let sub = Subscription::from_conn(connection.clone()); + instance.sub(id, sub)?; + } + + MessageCmd::Update => { + let data = msg.data()?; + let id = msg.id(instance)?; + let connection = instance.get_connection(msg.conn_id)?; + instance + .op_tx + .send(Operation::Set(id.clone(), data, Some(connection))); + } + + // this should check, if the update is valid + // but for now, we do just always accept it + MessageCmd::UpdateRequest => { + let data = msg.data()?; + let id = msg.id(instance)?; + let connection = instance.get_connection(msg.conn_id)?; + instance + .op_tx + .send(Operation::Set(id.clone(), data, Some(connection))); + } + + MessageCmd::Give => { + let id = msg.id(instance)?; + let data = msg.data()?; + let give_msg_wait_inner = instance.give_msg_wait.lock()?; + if let Some(vec) = give_msg_wait_inner.get(&id) { + for tx in vec { + tx.send(data.clone()); + } + } else { + warn!( + "got give msg for id '{}', that has no one waiting for it", + id + ); + } + } + + MessageCmd::Create => { + println!("instance.store: {:?}", instance.clone().store); + let item = instance.new_item()?; + let reply_msg = MizeMessage::new_create_reply(item.id(), msg.conn_id); + let mut connection = instance.get_connection(msg.conn_id)?; + connection.send(reply_msg)?; + } + + MessageCmd::CreateReply => { + let create_msg_wait_inner = instance.create_msg_wait.lock()?; + if let Some(sender) = create_msg_wait_inner.as_ref() { + sender.send(msg.id(&mut instance.clone())?)?; + } + return Ok(()); + } + MessageCmd::Custom(type_val) => { + let listeners = instance.listeners.lock()?; + let type_str = type_val.value_string()?; + let msg = msg.clone(); + let mut mize = instance.clone(); + println!("type_str: {}", type_str); + println!("listeners: {:?}", listeners.keys()); + if let Some(listener) = listeners.get(&type_str) { + let listener = listener.clone(); + drop(listeners); + listener(msg, &mut mize)?; + } + } + _ => { + return Err(mize_err!("got a message, that is not handeled")); + } + } + Ok(()) +} diff --git a/core/src/item.rs b/core/src/item.rs index 1974c32..4851ab0 100644 --- a/core/src/item.rs +++ b/core/src/item.rs @@ -1,4 +1,4 @@ -use crate::c_api::get_global_mize; +use crate::get_global_mize; use crate::config::{ConfigOpt}; use ciborium::into_writer; use colored::Colorize; diff --git a/core/src/lib.rs b/core/src/lib.rs index a60b8c6..facd1d4 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,4 +1,5 @@ #![allow(warnings)] +#![feature(str_as_str)] use std::cell::RefCell; use std::fmt::format; @@ -16,18 +17,22 @@ macro_rules! out { } pub fn write_to_mize_stdout(args: std::fmt::Arguments) -> MizeResult<()> { - println!("{}", format_args!(args)); + println!("{}", args); Ok(()) } pub mod prelude { pub use super::*; pub use instance::Mize; + pub use id::*; pub use error::MizeError; pub use crate::mize_err; pub use error::MizeResult; pub use item::{Item, ItemData, IntoItemData}; pub use config::*; + pub use api::*; + pub use super::include_native; + pub use mize_macros::*; } pub use flume; @@ -43,6 +48,7 @@ pub mod memstore; pub mod proto; pub mod types; pub mod c_api; +pub mod api; pub use async_trait::async_trait; pub use ciborium; @@ -57,10 +63,6 @@ use std::path::PathBuf; use std::sync::{Arc, Mutex, OnceLock}; -use crate::error::MizeResult; -use crate::instance::Mize; -use crate::mize_err; - /// Global Mize instance storage. /// This is set once when the Mize instance is created and can be accessed from anywhere. pub static GLOBAL_MIZE: OnceLock>> = OnceLock::new(); @@ -79,10 +81,10 @@ pub fn get_global_mize() -> MizeResult { /// Set the global Mize instance. pub fn set_global_mize(mize: Mize) -> MizeResult<()> { - let arc = Arc::new(Mutex::new(mize)); + let arc = Arc::new(Mutex::new(mize.clone())); if let Err(_) = GLOBAL_MIZE.set(arc) { let a = GLOBAL_MIZE.get().unwrap(); - let mut b = a.lock(); + let mut b = a.lock().map_err(|_| mize_err!("Failed to lock global Mize"))?; *b = mize; } Ok(()) @@ -194,7 +196,7 @@ macro_rules! include_native { $crate::config::opt($name) $( .method(stringify!($method), |args| { - let this = $crate::c_api::get_global_mize()? + let this = $crate::prelude::get_global_mize()? .get_config($name)? .native_mut::<$type_path>()?; let result = this.$method(); diff --git a/core/src/platform/os/fsstore.rs b/core/src/platform/os/fsstore.rs index dc50e37..b852a86 100644 --- a/core/src/platform/os/fsstore.rs +++ b/core/src/platform/os/fsstore.rs @@ -6,8 +6,8 @@ use std::path::{Path, PathBuf}; use sysinfo::{Pid, ProcessRefreshKind, RefreshKind, System}; use tracing::debug; -use crate::core::id::MizeId; -use crate::core::item::{Item, ItemData}; +use crate::id::MizeId; +use crate::item::{Item, ItemData}; use crate::error::{IntoMizeResult, MizeError, MizeResult}; use crate::instance::store::IdIter; use crate::instance::{self, Mize}; @@ -170,7 +170,7 @@ impl Store for FileStore { let data: ItemData = cbor_value.into_item_data(); let tmp = id.path(); - let mut path_iter = tmp.into_iter(); + let mut path_iter = tmp.iter(); path_iter.next(); let new_path: Vec = path_iter.map(|v| v.to_owned()).collect(); //println!("data: {}", data); diff --git a/core/src/proto/mod.rs b/core/src/proto/mod.rs index 35d8204..c1fd99b 100644 --- a/core/src/proto/mod.rs +++ b/core/src/proto/mod.rs @@ -82,7 +82,7 @@ impl MizeMessage { pub fn new_get(id: MizeId, conn_id: u64) -> MizeMessage { let id_path = id .path() - .into_iter() + .iter() .map(|string| CborValue::Text(string.to_owned())) .collect(); @@ -99,7 +99,7 @@ impl MizeMessage { pub fn new_get_sub(id: MizeId, conn_id: u64) -> MizeMessage { let id_path = id .path() - .into_iter() + .iter() .map(|string| CborValue::Text(string.to_owned())) .collect(); @@ -116,7 +116,7 @@ impl MizeMessage { pub fn new_sub(id: MizeId, conn_id: u64) -> MizeMessage { let id_path = id .path() - .into_iter() + .iter() .map(|string| CborValue::Text(string.to_owned())) .collect(); @@ -143,7 +143,7 @@ impl MizeMessage { pub fn new_create_reply(id: MizeId, conn_id: u64) -> MizeMessage { let id_path = id .path() - .into_iter() + .iter() .map(|string| CborValue::Text(string.to_owned())) .collect(); @@ -160,7 +160,7 @@ impl MizeMessage { pub fn new_give(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage { let id_path = id .path() - .into_iter() + .iter() .map(|string| CborValue::Text(string.to_owned())) .collect(); @@ -178,7 +178,7 @@ impl MizeMessage { pub fn new_update_request(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage { let id_path = id .path() - .into_iter() + .iter() .map(|string| CborValue::Text(string.to_owned())) .collect(); @@ -196,7 +196,7 @@ impl MizeMessage { pub fn new_update(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage { let id_path = id .path() - .into_iter() + .iter() .map(|string| CborValue::Text(string.to_owned())) .collect(); diff --git a/macros/src/lib.rs b/macros/src/lib.rs index ee6002b..0b2cf54 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{Data, DeriveInput, Fields, parse_macro_input}; +use syn; diff --git a/parts/auth/Cargo.toml b/parts/auth/Cargo.toml new file mode 100644 index 0000000..3cccaf9 --- /dev/null +++ b/parts/auth/Cargo.toml @@ -0,0 +1,21 @@ +cargo-features = ["profile-rustflags"] + +[package] +name = "mize-part-auth" +version = "0.1.0" +edition = "2024" + +[lib] +name = "mize_part_auth" +crate-type = [ "cdylib", "rlib" ] + +[dependencies] +mize = { workspace = true } +log = "0.4.34" + + +[profile.dev] +rustflags = ["-C", "prefer-dynamic", "-C", "link-args=-Wl,--export-dynamic"] + +[profile.release] +rustflags = ["-C", "prefer-dynamic"] diff --git a/parts/auth/src/lib.rs b/parts/auth/src/lib.rs new file mode 100644 index 0000000..74bfa92 --- /dev/null +++ b/parts/auth/src/lib.rs @@ -0,0 +1,6 @@ + +pub mod auth { + pub mod client; + pub use client::*; +} +pub use auth::*; diff --git a/parts/cli/Cargo.toml b/parts/cli/Cargo.toml index d07930c..3b86646 100644 --- a/parts/cli/Cargo.toml +++ b/parts/cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" [lib] name = "mize_part_cli" -crate-type = [ "dylib", "rlib" ] +crate-type = [ "cdylib", "rlib" ] [dependencies] clap = { version = "4.6.7", features = [ "string" ] } diff --git a/parts/cli/src/lib.rs b/parts/cli/src/lib.rs index be0b6e1..ae786e4 100644 --- a/parts/cli/src/lib.rs +++ b/parts/cli/src/lib.rs @@ -1,6 +1,5 @@ use clap::{ArgMatches, Command}; use mize::item::ItemData; -use mize_macros::{include_native, part_impl}; use std::collections::HashMap; use mize::prelude::*; diff --git a/parts/mize.dev/Cargo.toml b/parts/mize.dev/Cargo.toml new file mode 100644 index 0000000..1f6d24e --- /dev/null +++ b/parts/mize.dev/Cargo.toml @@ -0,0 +1,21 @@ +cargo-features = ["profile-rustflags"] + +[package] +name = "mize-part-dev" +version = "0.1.0" +edition = "2024" + +[lib] +name = "mize_part_dev" +crate-type = [ "cdylib", "rlib" ] + +[dependencies] +log = "0.4.34" +mize = { workspace = true } + + +[profile.dev] +rustflags = ["-C", "prefer-dynamic", "-C", "link-args=-Wl,--export-dynamic"] + +[profile.release] +rustflags = ["-C", "prefer-dynamic"]