basically fully restored
This commit is contained in:
33
Cargo.lock
generated
33
Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -4,6 +4,7 @@ members = [
|
||||
"macros",
|
||||
"apps/os",
|
||||
"apps/obsidian-plugin",
|
||||
"parts/*",
|
||||
]
|
||||
default-members = [
|
||||
"apps/obsidian-plugin",
|
||||
|
||||
@@ -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::<CliPart>("cli")?;
|
||||
let mut cli = generated::CliPart::get("cli")?;
|
||||
cli.run(ext_cmdline)?;
|
||||
}
|
||||
}
|
||||
|
||||
70
apps/os/src/generated.rs
Normal file
70
apps/os/src/generated.rs
Normal file
@@ -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<CliPart> {
|
||||
let mut mize = get_global_mize()?;
|
||||
let part = mize.get_part(name)?;
|
||||
Ok(CliPart { id: part.id() })
|
||||
}
|
||||
pub fn run(&self, cmdline: Vec<String>) -> 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<T: Fn(ArgMatches) -> 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<Command> {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
6
core/src/api.rs
Normal file
6
core/src/api.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn dyn_call(part_id: MizeId, method: &str, args: ItemData) -> MizeResult<ItemData> {
|
||||
let mut mize = get_global_mize()?;
|
||||
mize.dyn_call(part_id, method, args)
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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)]
|
||||
|
||||
57
core/src/instance/connection.rs
Normal file
57
core/src/instance/connection.rs
Normal file
@@ -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<MizeMessage>,
|
||||
pub id: u64,
|
||||
pub ns: Option<Namespace>,
|
||||
}
|
||||
|
||||
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<ItemData> {
|
||||
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<ItemData> {
|
||||
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::<Vec<String>>())?;
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
2
core/src/instance/msg_thread.rs
Normal file
2
core/src/instance/msg_thread.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
// Message thread handling for the Mize instance.
|
||||
// This module is reserved for future message threading functionality.
|
||||
71
core/src/instance/store.rs
Normal file
71
core/src/instance/store.rs
Normal file
@@ -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<Item<Self>> 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<Vec<MizeId>>;
|
||||
|
||||
fn get_backlinks(&self, item: Item) -> MizeResult<Vec<MizeId>>;
|
||||
|
||||
fn new_id(&self) -> MizeResult<String>;
|
||||
|
||||
fn get_value_raw(&self, id: MizeId) -> MizeResult<Vec<u8>>;
|
||||
|
||||
fn get_value_data_full(&self, id: MizeId) -> MizeResult<ItemData>;
|
||||
|
||||
fn id_iter(&self) -> MizeResult<IdIter>;
|
||||
|
||||
fn next_id(&self, prev_id: &str) -> MizeResult<Option<String>>;
|
||||
|
||||
fn first_id(&self) -> MizeResult<String>;
|
||||
}
|
||||
|
||||
pub struct IdIter {
|
||||
cur_id: String,
|
||||
store: Box<dyn Store>,
|
||||
}
|
||||
|
||||
impl IdIter {
|
||||
pub fn new(store: Box<dyn Store>) -> MizeResult<IdIter> {
|
||||
Ok(IdIter {
|
||||
cur_id: store.first_id()?,
|
||||
store,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for IdIter {
|
||||
type Item = MizeResult<String>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
68
core/src/instance/subscription.rs
Normal file
68
core/src/instance/subscription.rs
Normal file
@@ -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<Mize>,
|
||||
pub id: MizeId,
|
||||
}
|
||||
|
||||
impl Update {
|
||||
pub fn new_item(&self) -> MizeResult<Item> {
|
||||
self.instance.get(self.id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Subscription {
|
||||
Connection(Connection),
|
||||
Closure(Box<dyn Fn(Update) -> MizeResult<()> + Send>),
|
||||
Channel(Sender<Update>),
|
||||
}
|
||||
|
||||
impl Subscription {
|
||||
pub fn from_conn(conn: Connection) -> Subscription {
|
||||
Subscription::Connection(conn)
|
||||
}
|
||||
pub fn from_closure(closure: Box<dyn Fn(Update) -> MizeResult<()> + Send>) -> Subscription {
|
||||
Subscription::Closure(closure)
|
||||
}
|
||||
pub fn from_sender(tx: Sender<Update>) -> 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...")
|
||||
}
|
||||
}
|
||||
252
core/src/instance/tests.rs
Normal file
252
core/src/instance/tests.rs
Normal file
@@ -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(())
|
||||
}
|
||||
236
core/src/instance/updater.rs
Normal file
236
core/src/instance/updater.rs
Normal file
@@ -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<Connection>), // 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<Operation>, 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<Operation>, 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(())
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Arc<Mutex<Mize>>> = OnceLock::new();
|
||||
@@ -79,10 +81,10 @@ pub fn get_global_mize() -> MizeResult<Mize> {
|
||||
|
||||
/// 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();
|
||||
|
||||
@@ -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<String> = path_iter.map(|v| v.to_owned()).collect();
|
||||
//println!("data: {}", data);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{Data, DeriveInput, Fields, parse_macro_input};
|
||||
use syn;
|
||||
|
||||
|
||||
|
||||
|
||||
21
parts/auth/Cargo.toml
Normal file
21
parts/auth/Cargo.toml
Normal file
@@ -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"]
|
||||
6
parts/auth/src/lib.rs
Normal file
6
parts/auth/src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
pub mod auth {
|
||||
pub mod client;
|
||||
pub use client::*;
|
||||
}
|
||||
pub use auth::*;
|
||||
@@ -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" ] }
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
|
||||
21
parts/mize.dev/Cargo.toml
Normal file
21
parts/mize.dev/Cargo.toml
Normal file
@@ -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"]
|
||||
Reference in New Issue
Block a user