some MizePart stuff and other stuff

This commit is contained in:
Sebastian Moser
2026-02-04 20:41:39 +01:00
parent fa103b3fa7
commit 7b6f177d14
29 changed files with 5585 additions and 816 deletions

8
parts/cli/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "cli"
version = "0.1.0"
edition = "2024"
[dependencies]
clap = { version = "4.5.57", features = ["cargo"] }
mize = { path = "../../parts/mize"}

72
parts/cli/src/lib.rs Normal file
View File

@@ -0,0 +1,72 @@
use clap::{ArgMatches, Command};
use std::any::Any;
use std::collections::HashMap;
use mize::{Mize, MizePart, MizeResult, instance::MizePartGuard};
struct CliPart {
mize: Mize,
cmd: Option<Command>,
actions: HashMap<String, fn(&ArgMatches) -> MizeResult<()>>,
}
pub fn new(mize: Mize) -> CliPart {
CliPart {
mize,
cmd: None,
actions: HashMap::new(),
}
}
impl MizePart for CliPart {
fn name(&self) -> &'static str {
"cli"
}
fn get_mize(&mut self) -> &mut Mize {
&mut self.mize
}
fn init(&mut self, _mize: &mut Mize) -> MizeResult<()> {
Ok(())
}
fn opts(&self, mize: &mut Mize) {
mize.new_opt("cli.name");
}
fn run(&mut self, _mize: &mut Mize) -> MizeResult<()> {
let matches = self.cmd.take().unwrap().get_matches();
let sub_cmd = matches.subcommand_name().unwrap();
let action = self.actions.get(sub_cmd).unwrap();
action(matches.subcommand_matches(sub_cmd).unwrap());
Ok(())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&self) -> &dyn std::any::Any {
self
}
fn into_any(self: Box<CliPart>) -> Box<dyn Any> {
self
}
}
impl CliPart {
pub fn subcommand(
&mut self,
cmd: Command,
action: fn(sub_matches: &ArgMatches) -> MizeResult<()>,
) -> &mut Command {
let cmd = self.cmd.take().unwrap().subcommand(cmd);
self.actions.insert(cmd.get_name().to_string(), action);
self.cmd = Some(cmd);
self.cmd.as_mut().unwrap()
}
pub fn get(mize: &mut Mize) -> MizePartGuard<CliPart> {
let mut dyn_guard = mize.get_part("cli").unwrap();
let part = dyn_guard.part.take().unwrap();
let cli_part = part.into_any().downcast::<CliPart>().unwrap();
MizePartGuard {
mize: dyn_guard.mize.clone(),
part: Some(*cli_part),
}
}
}

9
parts/js/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "js_part"
version = "0.1.0"
edition = "2024"
[dependencies]
deno_core = "0.383.0"
mize = { path = "../../parts/mize" }
tokio = { version = "1.49.0", features = ["full"] }

41
parts/js/src/lib.rs Normal file
View File

@@ -0,0 +1,41 @@
use deno_core::error::AnyError;
use mize::{Mize, MizePart, MizeResult};
use std::rc::Rc;
pub struct JsPart {
mize: Mize,
}
impl JsPart {
pub fn new(mize: Mize) -> Self {
JsPart { mize }
}
}
impl MizePart for JsPart {
fn name(&self) -> &'static str {
"js"
}
fn get_mize(&mut self) -> &mut Mize {
&mut self.mize
}
fn init(&mut self, mize: &mut Mize) -> MizeResult<()> {
println!("deno part init");
Ok(())
}
}
async fn run_js_file(file_path: &str) -> Result<(), AnyError> {
let main_module = deno_core::resolve_path(file_path, &std::env::current_dir()?)?;
let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions {
module_loader: Some(Rc::new(deno_core::FsModuleLoader)),
..Default::default()
});
let mod_id = js_runtime.load_main_es_module(&main_module).await?;
let result = js_runtime.mod_evaluate(mod_id);
js_runtime.run_event_loop(Default::default()).await?;
result.await
}

View File

@@ -1,10 +1,7 @@
use std::process::Command;
use std::env;
//use std::env;
fn main() {
// compile the string plugin
//let _out_dir = env::var_os("OUT_DIR").unwrap();
//let mut string_module = Command::new("bash");
//string_module.arg("-c");
//string_module.arg("echo hiiiiiiiiiiiiiiiii");
@@ -15,14 +12,14 @@ fn main() {
//let _res = string_module.spawn();
//let _child = Command::new("cargo")
//.arg("build")
//.arg("--lib")
//.arg("--manifest-path")
//.arg("/home/me/work/mize/modules/modules/Blob/Cargo.toml")
//.spawn()
//.expect("failed to start wasm build");
//.arg("build")
//.arg("--lib")
//.arg("--manifest-path")
//.arg("/home/me/work/mize/modules/modules/Blob/Cargo.toml")
//.spawn()
//.expect("failed to start wasm build");
//to outdir (), using the nightly feature --out-dir to have the result there. By default I get a libhearts.rlib
//to outdir (), using the nightly feature --out-dir to have the result there. By default I get a libhearts.rlib
println!("cargo:rustc-link-arg=-zstack-size=0x1000000");
//println!("cargo:rustc-link-arg=-zstack-size=0x1000000");
}

42
parts/mize/flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"crane": {
"locked": {
"lastModified": 1725125250,
"narHash": "sha256-CB20rDD5eHikF6mMTTJdwPP1qvyoiyyw1RDUzwIaIF8=",
"lastModified": 1769737823,
"narHash": "sha256-DrBaNpZ+sJ4stXm+0nBX7zqZT9t9P22zbk6m5YhQxS4=",
"owner": "ipetkov",
"repo": "crane",
"rev": "96fd12c7100e9e05fa1a0a5bd108525600ce282f",
"rev": "b2f45c3830aa96b7456a4c4bc327d04d7a43e1ba",
"type": "github"
},
"original": {
@@ -23,11 +23,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1748327829,
"narHash": "sha256-TJwbWCsyT9yJkBRTnqKE/YDTiXuEdYHb37WLK4TcAwE=",
"lastModified": 1770102568,
"narHash": "sha256-VYwA9FmakKJ3zLfAd7bdj9xIB9PzfISLoYh6eZl+EuQ=",
"owner": "nix-community",
"repo": "fenix",
"rev": "26fbcc33a5e94d6d0dc5f467eca8f7a746a54e6c",
"rev": "592daa37b5a3175c61541329b64d6c1972303bc1",
"type": "github"
},
"original": {
@@ -41,11 +41,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
@@ -57,11 +57,11 @@
"mize_modules": {
"flake": false,
"locked": {
"lastModified": 1725362504,
"narHash": "sha256-U0IQ+3SiyLb24BTDUvlnE30LdjjJWJ/P6dHPqxArJXk=",
"lastModified": 1739053120,
"narHash": "sha256-It6j1D3c3eO/O0ptHvZ3c9Ynei08DXX5n6DYonW3g+s=",
"owner": "c2vi",
"repo": "mize-modules",
"rev": "fa3b462cbe3e63fc9ecada6c4445d366e58a6f86",
"rev": "3bba470c849f7cbaf7eb7858c26aa1c64fd00b33",
"type": "github"
},
"original": {
@@ -72,11 +72,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1703637592,
"narHash": "sha256-8MXjxU0RfFfzl57Zy3OfXCITS0qWDNLzlBAdwxGZwfY=",
"lastModified": 1770115704,
"narHash": "sha256-KHFT9UWOF2yRPlAnSXQJh6uVcgNcWlFqqiAZ7OVlHNc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "cfc3698c31b1fb9cdcf10f36c9643460264d0ca8",
"rev": "e6eae2ee2110f3d31110d5c222cd395303343b08",
"type": "github"
},
"original": {
@@ -99,11 +99,11 @@
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1748295258,
"narHash": "sha256-ejRVtsT7fat4mGgDQpgIGKJP+vbr9r4Mo84jRb2bndk=",
"lastModified": 1770026591,
"narHash": "sha256-VZlloygYDmozJwbZZkCSNpiPhNdOW/AA0b6LmNBZ3xU=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "7fa66d67a72bcad236b50907e14f7464c47ecede",
"rev": "74eca73f3b0a41b80228b8e499c7547cc8b2effa",
"type": "github"
},
"original": {
@@ -120,11 +120,11 @@
]
},
"locked": {
"lastModified": 1725157860,
"narHash": "sha256-DhqyM7XJYKj+WAEaYwMtXaYX66tA+lOd31sd5QkxLDM=",
"lastModified": 1770088046,
"narHash": "sha256-4hfYDnUTvL1qSSZEA4CEThxfz+KlwSFQ30Z9jgDguO0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "1fd72e343c6890f695243a37b367a1e3b90a49ee",
"rev": "71f9daa4e05e49c434d08627e755495ae222bc34",
"type": "github"
},
"original": {

View File

@@ -0,0 +1,46 @@
use crate::MizeResult;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use crate::item::ItemData;
use crate::Mize;
type ConfigThunk = Box<dyn Fn() -> ItemData + Send + Sync>;
pub struct ConfigOpt {
pub name: String,
pub val: Option<ItemData>,
pub thunk: Option<ConfigThunk>,
}
#[derive(Clone)]
pub struct ConfigOptNameAndMize {
pub name: String,
pub mize: Mize,
}
impl ConfigOptNameAndMize {
pub fn default_val(self, val: ItemData) -> ConfigOptNameAndMize {
let mut config_opts = self.mize.config_opts.lock().unwrap();
let opt = config_opts.get_mut(&self.name).unwrap();
opt.val = Some(val);
self.clone()
}
pub fn fun(self, thunk: ConfigThunk) -> Self {
let mut config_opts = self.mize.config_opts.lock().unwrap();
let opt = config_opts.get_mut(&self.name).unwrap();
opt.thunk = Some(thunk);
self.clone()
}
}
pub fn gather_config(mize: &mut Mize) -> MizeResult<()> {
let mut config_opts = mize.config_opts.lock().unwrap();
let parts = mize.parts.lock().unwrap();
for part in parts.values() {
part.as_deref().unwrap().opts(&mut mize.clone());
}
Ok(())
}

View File

@@ -1,16 +1,15 @@
use colored::Colorize;
use core::result::Result;
use core::result::Result::Ok;
use std::collections::HashMap;
use std::fmt::format;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::format;
use std::string::FromUtf8Error;
use std::io;
use colored::Colorize;
use tracing::{trace, debug, info, warn, error};
use crate::proto::MizeMessage;
use std::string::FromUtf8Error;
use tracing::{debug, error, info, trace, warn};
//use crate::proto::MizeMessage;
#[macro_export]
macro_rules! mize_err {
@@ -26,7 +25,9 @@ pub trait MizeResultTrait<T> {
pub trait IntoMizeResult<T, S> {
fn mize_result(self) -> MizeResult<T>;
fn mize_result_msg(self, msg: S) -> MizeResult<T> where S: std::fmt::Display ;
fn mize_result_msg(self, msg: S) -> MizeResult<T>
where
S: std::fmt::Display;
}
#[derive(Debug, Clone)]
@@ -34,16 +35,18 @@ pub struct MizeError {
pub category: Vec<String>,
pub code: u32,
pub messages: Vec<String>,
pub caused_by_msg: Option<CausedByMessage>,
//pub caused_by_msg: Option<CausedByMessage>,
pub code_location: Option<MizeCodeLocation>,
pub backtrace: String,
}
/*
#[derive(Debug, Clone)]
pub struct CausedByMessage {
// peer: &Connection, // TODO: add later
msg: Box<MizeMessage>,
}
*/
#[derive(Debug, Clone)]
pub struct MizeCodeLocation {
@@ -54,16 +57,20 @@ pub struct MizeCodeLocation {
impl Display for MizeCodeLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "file: {} line: {} column: {}", self.file, self.line, self.column)
write!(
f,
"file: {} line: {} column: {}",
self.file, self.line, self.column
)
}
}
impl From<&std::panic::Location <'_>> for MizeCodeLocation {
impl From<&std::panic::Location<'_>> for MizeCodeLocation {
fn from(panic_location: &std::panic::Location) -> MizeCodeLocation {
let file = panic_location.file().to_string();
let line = panic_location.line();
let column = panic_location.column();
MizeCodeLocation {file, line, column}
MizeCodeLocation { file, line, column }
}
}
@@ -88,25 +95,28 @@ impl MizeError {
category: Vec::new(),
code: 0,
messages: Vec::new(),
caused_by_msg: None,
code_location: Some(caller_location.into()),
backtrace: format!("{}", std::backtrace::Backtrace::capture()),
}
};
}
pub fn msg<E>(mut self, msg: E) -> MizeError
where E: std::fmt::Display
pub fn msg<E>(mut self, msg: E) -> MizeError
where
E: std::fmt::Display,
{
self.messages.push(format!("{}", msg));
return self;
}
pub fn category<T>(mut self, category: T) -> MizeError where T: Into<String> {
pub fn category<T>(mut self, category: T) -> MizeError
where
T: Into<String>,
{
self.category.push(category.into());
return self;
}
fn send(self) -> MizeError{
fn send(self) -> MizeError {
self
}
@@ -134,15 +144,20 @@ impl MizeError {
return self.send().add_to_err_item().log();
}
pub fn critical(self){
pub fn critical(self) {
let mut msg_iter = self.messages.iter();
match msg_iter.next() {
None => {
error!("{} MizeError with code: {}", "CRITICAL".red(), self.code);
},
}
Some(msg) => {
error!("{} MizeError with code: {} - {}", "CRITICAL".red(), self.code, msg);
},
error!(
"{} MizeError with code: {} - {}",
"CRITICAL".red(),
self.code,
msg
);
}
}
for msg in msg_iter {
error!("{} {}", "MSG".red(), msg)
@@ -150,23 +165,16 @@ impl MizeError {
if let Some(location) = self.code_location {
error!("{} {}", "LOCATION".red(), location)
}
if let Some(caused_by_msg) = self.caused_by_msg {
error!("{} {:?}", "CAUSED_BY_MESSAGE".red(), caused_by_msg)
}
panic!();
}
pub fn location(mut self, location: MizeCodeLocation) -> MizeError {
self.code_location = Some(location);
self
}
}
/*
pub trait MizeResultExtension<T> {
fn extra_msg<E>(self, msg: E) -> Result<T, MizeError>
@@ -221,70 +229,90 @@ impl<T: Display> From<T> for MizeError {
fn from(value: T) -> Self {
let caller_location = std::panic::Location::caller();
MizeError::new()
.msg(format!("From {}: {}", std::any::type_name_of_val(&value), value))
.msg(format!(
"From {}: {}",
std::any::type_name_of_val(&value),
value
))
.location(caller_location.into())
}
}
impl <T> MizeResultTrait<T> for MizeResult<T> {
impl<T> MizeResultTrait<T> for MizeResult<T> {
fn critical(self) -> T {
match self {
Ok(val) => val,
Err(err) => {
err.critical();
unreachable!()
},
}
}
}
fn as_std(self) -> Result<T, MizeErrorWhichImplementsError> {
match self {
Ok(val) => Ok(val),
Err(err) => {
Err(MizeErrorWhichImplementsError { inner: err })
},
Err(err) => Err(MizeErrorWhichImplementsError { inner: err }),
}
}
}
impl<T, E, S> IntoMizeResult<T, S> for Result<T, E> where E: std::fmt::Display {
impl<T, E, S> IntoMizeResult<T, S> for Result<T, E>
where
E: std::fmt::Display,
{
#[track_caller]
fn mize_result(self) -> MizeResult<T> {
let caller_location = std::panic::Location::caller();
match self {
Ok(val) => MizeResult::Ok(val),
Err(err) => MizeResult::Err(MizeError::new()
.category("misc")
.msg(format!("From {}: {}", std::any::type_name_of_val(&err), err))),
Err(err) => MizeResult::Err(MizeError::new().category("misc").msg(format!(
"From {}: {}",
std::any::type_name_of_val(&err),
err
))),
}
}
#[track_caller]
fn mize_result_msg(self, msg: S) -> MizeResult<T> where S: std::fmt::Display {
fn mize_result_msg(self, msg: S) -> MizeResult<T>
where
S: std::fmt::Display,
{
let caller_location = std::panic::Location::caller();
match self {
Ok(val) => MizeResult::Ok(val),
Err(err) => MizeResult::Err(MizeError::new()
.category("misc")
.msg(format!("{}", msg))
.msg(format!("From {}: {}", std::any::type_name_of_val(&err), err))),
Err(err) => MizeResult::Err(
MizeError::new()
.category("misc")
.msg(format!("{}", msg))
.msg(format!(
"From {}: {}",
std::any::type_name_of_val(&err),
err
)),
),
}
}
}
fn get_error_by_code(code: u32, caller_location: &std::panic::Location) -> MizeError {
let err = MizeError {
category: Vec::new(),
code: 0,
messages: Vec::new(),
caused_by_msg: None,
code_location: Some(caller_location.into()),
backtrace: format!("{}", std::backtrace::Backtrace::capture()),
};
match code {
109 => err.set_code(109).category("decoding").msg("conversion from utf8 failed"),
108 => err.set_code(108).category("decoding").msg("serde deserialisation failed"),
109 => err
.set_code(109)
.category("decoding")
.msg("conversion from utf8 failed"),
108 => err
.set_code(108)
.category("decoding")
.msg("serde deserialisation failed"),
_ => err,
}
}
@@ -305,7 +333,7 @@ impl Display for MizeErrorWhichImplementsError {
write!(f, "[ {} ] {}", "BACKTRACE".yellow(), self.inner.backtrace);
for msg in &self.inner.messages {
write!(f,"[ {} ] {}", "MSG".yellow(), msg);
write!(f, "[ {} ] {}", "MSG".yellow(), msg);
}
Ok(())
}
@@ -318,5 +346,3 @@ impl From<MizeError> for MizeErrorWhichImplementsError {
}
impl std::error::Error for MizeErrorWhichImplementsError {}

View File

@@ -1,11 +1,17 @@
use core::fmt;
use std::{collections::binary_heap::Iter, fmt::write, hash::Hash};
use interner::{shared::{SharedPool, SharedString, SharedVecString}, Pooled};
use interner::{
shared::{SharedPool, SharedString, SharedVecString},
Pooled,
};
use std::collections::hash_map::RandomState;
use std::path::Path;
use std::{collections::binary_heap::Iter, fmt::write, hash::Hash};
use crate::{instance::{store::Store, Instance}, mize_err};
use crate::error::{MizeResult, MizeError, MizeResultTrait};
use crate::error::{MizeError, MizeResult, MizeResultTrait};
use crate::{
instance::{store::Store, Mize},
mize_err,
};
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct MizeId {
@@ -14,28 +20,30 @@ pub struct MizeId {
}
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Namespace ( pub SharedString );
pub struct Namespace(pub SharedString);
impl Namespace {
pub fn as_string(&self) -> SharedString {
self.0.clone()
}
pub fn as_real_string(&self) -> String {
let a = self.as_string();
let a = self.as_string();
let b = a.to_string();
return b;
}
}
pub trait IntoMizeId {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId>;
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId>;
}
impl MizeId {
pub fn store_part(&self) -> &str {
self.path.iter().nth(0)
.expect("an empty MizeId found, that should absolutely not be possible!!!!").as_str()
self.path
.iter()
.nth(0)
.expect("an empty MizeId found, that should absolutely not be possible!!!!")
.as_str()
}
pub fn nth_part(&self, n: usize) -> MizeResult<&str> {
@@ -74,34 +82,37 @@ impl fmt::Display for MizeId {
}
impl IntoMizeId for &str {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
instance.id_from_string(self.to_owned())
}
}
impl IntoMizeId for String {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
instance.id_from_string(self)
}
}
impl IntoMizeId for &String {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
instance.id_from_string(self.to_owned())
}
}
impl IntoMizeId for Vec<String> {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
instance.id_from_vec_string(self)
}
}
impl IntoMizeId for Vec<&String> {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
let owned = self.into_iter().map(|s| s.to_owned()).collect::<Vec<String>>();
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
let owned = self
.into_iter()
.map(|s| s.to_owned())
.collect::<Vec<String>>();
instance.id_from_vec_string(owned)
}
}
impl IntoMizeId for &[&str] {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
let mut vec: Vec<String> = Vec::new();
for i in self {
vec.push((*i).to_owned())
@@ -110,7 +121,7 @@ impl IntoMizeId for &[&str] {
}
}
impl IntoMizeId for Vec<&str> {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
let mut vec: Vec<String> = Vec::new();
for i in self {
vec.push((*i).to_owned())
@@ -119,7 +130,7 @@ impl IntoMizeId for Vec<&str> {
}
}
impl IntoMizeId for MizeId {
fn to_mize_id(self, instance: &Instance) -> MizeResult<MizeId> {
fn to_mize_id(self, instance: &Mize) -> MizeResult<MizeId> {
Ok(self)
}
}
@@ -127,33 +138,41 @@ impl IntoMizeId for MizeId {
// would only work with a global id_pool
// for now use Instance::new_id()
//impl<T: Into<String>> From<T> for MizeId {
//fn from(value: T) -> Self {
//let string = value.into();
//let path: Vec<String> = string.split("/").map(|v| v.to_owned()).collect();
//return MizeId { MIZE_ID_POOL.get(path) }
//}
//fn from(value: T) -> Self {
//let string = value.into();
//let path: Vec<String> = string.split("/").map(|v| v.to_owned()).collect();
//return MizeId { MIZE_ID_POOL.get(path) }
//}
//}
#[cfg(test)]
mod test {
use crate::instance::Instance;
use crate::instance::Mize;
use super::*;
#[test]
fn test_id() -> MizeResult<()> {
let instance = Instance::empty()?;
let instance = Mize::empty()?;
let id_one = instance.new_id("0/config/hi")?;
assert_eq!(instance.get_namespace()?, id_one.namespace());
assert_eq!("0", id_one.store_part());
assert_eq!(vec!["config".to_owned(), "hi".to_owned()], id_one.after_store_part());
assert_eq!(
vec!["config".to_owned(), "hi".to_owned()],
id_one.after_store_part()
);
let id_two = instance.new_id("test.ns:hello/config/hi")?;
assert_eq!(instance.namespace_from_string("test.ns".to_owned())?, id_two.namespace());
assert_eq!(
instance.namespace_from_string("test.ns".to_owned())?,
id_two.namespace()
);
assert_eq!("hello", id_two.store_part());
assert_eq!(vec!["config".to_owned(), "hi".to_owned()], id_one.after_store_part());
assert_eq!(
vec!["config".to_owned(), "hi".to_owned()],
id_one.after_store_part()
);
let id_three = instance.new_id("0/")?;
assert_eq!(instance.get_namespace()?, id_three.namespace());
@@ -161,7 +180,10 @@ mod test {
assert_eq!(Vec::<String>::new(), id_three.after_store_part());
let id_four = instance.new_id("test.ns:0/")?;
assert_eq!(instance.namespace_from_string("test.ns".to_owned())?, id_four.namespace());
assert_eq!(
instance.namespace_from_string("test.ns".to_owned())?,
id_four.namespace()
);
assert_eq!("0", id_four.store_part());
assert_eq!(Vec::<String>::new(), id_four.after_store_part());
@@ -172,9 +194,6 @@ mod test {
//TODO: add the parsing form mize:// urls....
Ok(())
}
}

View File

@@ -1,12 +1,12 @@
use flume::{Sender, Receiver};
use tracing::{trace, debug, info, warn, error};
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 crate::error::{MizeError, MizeResult, IntoMizeResult};
use super::Instance;
use super::Mize;
use crate::item::{get_raw_from_cbor, Item, ItemData};
// only created with Instance::new_connection()
@@ -17,8 +17,8 @@ pub struct Connection {
pub ns: Option<Namespace>,
}
pub trait ConnListener : Send + Sync {
fn listen(self, instance: Instance) -> MizeResult<()>;
pub trait ConnListener: Send + Sync {
fn listen(self, instance: Mize) -> MizeResult<()>;
}
impl Connection {
@@ -39,7 +39,7 @@ 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 conn_id: u64 = conn_id_str.parse()?;
let tmp_path = id.path();
let mut new_id_str = tmp_path.into_iter();
let skipped = new_id_str.skip(4);
@@ -55,5 +55,3 @@ pub fn value_raw_from_peer(item: &mut Item) -> MizeResult<ItemData> {
return Ok(data);
}

View File

@@ -1,46 +1,48 @@
use colored::Colorize;
use core::fmt;
use flume::{bounded, unbounded, Receiver, Sender};
use interner::shared::{StringPool, VecStringPool};
use std::any::Any;
use std::collections::HashMap;
use std::fs::create_dir;
use std::{thread, vec};
use flume::{bounded, Receiver, Sender, unbounded};
use std::fs::File;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::{thread, vec};
use tracing::{debug, error, info, trace, warn, Instrument};
use uuid::Uuid;
use std::fs::File;
use colored::Colorize;
use std::path::{Path, PathBuf};
use interner::shared::{VecStringPool, StringPool};
use crate::error::{MizeError, MizeResult, IntoMizeResult, MizeResultTrait};
use crate::instance::store::Store;
use crate::instance::updater::{ updater_thread, updater_thread_async };
use crate::config::ConfigOptNameAndMize;
use crate::config::{gather_config, ConfigOpt};
use crate::error::{IntoMizeResult, MizeError, MizeResult, MizeResultTrait};
use crate::id::{IntoMizeId, MizeId, Namespace};
use crate::instance::store::Store;
use crate::instance::subscription::Subscription;
use crate::instance::updater::Operation;
use crate::instance::updater::{updater_thread, updater_thread_async};
use crate::item::{Item, ItemData};
use crate::memstore::MemStore;
use crate::instance::updater::Operation;
use crate::{mize_err, Module};
use crate::proto::MizeMessage;
use crate::{mize_err, Module};
use self::connection::{ConnListener, Connection};
use self::updater::handle_operation;
#[cfg(feature = "async")]
use tokio::runtime::Runtime;
#[cfg(feature = "async")]
use tokio::runtime::Handle;
#[cfg(feature = "async")]
use tokio::runtime::Runtime;
use core::future::Future;
use std::thread::JoinHandle;
pub mod connection;
pub mod module;
pub mod msg_thread;
pub mod store;
pub mod subscription;
pub mod updater;
pub mod msg_thread;
pub mod module;
// console_log macro
// that can be copied into other files for debugging purposes
@@ -61,8 +63,17 @@ macro_rules! console_log {
($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())})
}
#[macro_export]
macro_rules! add_parts {
($mize:expr, $($part:expr),+) => {
$(
$mize.add_part(
Box::new($part)
);
)+
mize.init_parts();
};
}
#[cfg(test)]
mod tests;
@@ -73,16 +84,22 @@ static BUILD_TIME_CONFIG: &str = include_str!(std::env!("MIZE_BUILD_CONFIG"));
/// The Instance type is the heart of the mize system
#[derive(Clone)]
pub struct Instance {
// a bit a lot of Mutexes isn-it???
pub struct Mize {
// a bit a lot of Mutexes isn't it???
pub store: Arc<Mutex<Box<dyn Store>>>,
connections: Arc<Mutex<Vec<Connection>>>,
next_con_id: Arc<Mutex<u64>>,
subs: Arc<Mutex<HashMap<MizeId, Vec<Subscription>>>>,
pub modules: Arc<Mutex<HashMap<String, Box<dyn Module + Sync + Send >>>>,
pub modules: Arc<Mutex<HashMap<String, Box<dyn Module + Sync + Send>>>>,
pub id_pool: Arc<Mutex<VecStringPool>>,
pub namespace_pool: Arc<Mutex<StringPool>>,
pub(crate) parts: Arc<Mutex<HashMap<&'static str, Option<Box<dyn MizePart + Sync + Send>>>>>,
part_names: Arc<Mutex<Vec<&'static str>>>,
pub config_opts: Arc<Mutex<HashMap<String, ConfigOpt>>>,
// the namespace the instance operates in
pub namespace: Arc<Mutex<Namespace>>,
@@ -100,18 +117,84 @@ pub struct Instance {
}
pub struct InstanceRef {
inner: Arc<Mutex<Instance>>,
inner: Arc<Mutex<Mize>>,
}
pub struct InstanceAsync {
inner: Arc<Mutex<Instance>>,
inner: Arc<Mutex<Mize>>,
}
pub struct DynMizePartGuard {
pub mize: Mize,
pub part: Option<Box<dyn MizePart + Send + Sync>>,
}
impl Instance {
pub fn empty() -> MizeResult<Instance> {
pub struct MizePartGuard<T: MizePart + Send + Sync> {
pub mize: Mize,
pub part: Option<T>,
}
impl<T: MizePart + Send + Sync + Deref<Target = T>> Deref for MizePartGuard<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&*self.part.as_deref().unwrap()
}
}
impl<T: MizePart + Send + Sync + DerefMut<Target = T>> DerefMut for MizePartGuard<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.part.as_deref_mut().unwrap()
}
}
impl<T: MizePart + Send + Sync> Drop for MizePartGuard<T> {
fn drop(&mut self) {
let part = self.part.take().unwrap();
self.mize.give_back_part(Box::new(part));
}
}
impl Deref for DynMizePartGuard {
type Target = dyn MizePart + Send + Sync;
fn deref(&self) -> &Self::Target {
&*self.part.as_deref().unwrap()
}
}
impl DerefMut for DynMizePartGuard {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.part.as_deref_mut().unwrap()
}
}
impl Drop for DynMizePartGuard {
fn drop(&mut self) {
self.mize.give_back_part(self.part.take().unwrap());
}
}
pub trait MizePart: Any + Send + Sync {
fn name(&self) -> &'static str;
fn get_mize(&mut self) -> &mut Mize;
fn init(&mut self, mize: &mut Mize) -> MizeResult<()> {
Ok(())
}
fn run(&mut self, mize: &mut Mize) -> MizeResult<()> {
Ok(())
}
fn deps(&self) -> &'static [&'static str] {
&[]
}
fn opts(&self, mize: &mut Mize) {}
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&self) -> &dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
}
impl Mize {
pub fn empty() -> MizeResult<Mize> {
let id_pool = Arc::new(Mutex::new(VecStringPool::default()));
let namespace_pool_raw = StringPool::default();
let connections = Arc::new(Mutex::new(Vec::new()));
@@ -119,27 +202,38 @@ impl Instance {
let (op_tx, op_rx) = unbounded();
let give_msg_wait = Arc::new(Mutex::new(HashMap::new()));
let create_msg_wait = Arc::new(Mutex::new(None));
let namespace = Arc::new(Mutex::new(Namespace ( namespace_pool_raw.get("mize.default.namespace") )));
let self_namespace = Arc::new(Mutex::new(Namespace ( namespace_pool_raw.get("mize.default.namespace") )));
let namespace = Arc::new(Mutex::new(Namespace(
namespace_pool_raw.get("mize.default.namespace"),
)));
let self_namespace = Arc::new(Mutex::new(Namespace(
namespace_pool_raw.get("mize.default.namespace"),
)));
let mut instance = Instance {
let mut instance = Mize {
store: Arc::new(Mutex::new(Box::new(MemStore::new()))),
connections, subs, id_pool,
namespace, self_namespace, op_tx,
parts: Arc::new(Mutex::new(HashMap::new())),
part_names: Arc::new(Mutex::new(Vec::new())),
config_opts: Arc::new(Mutex::new(HashMap::new())),
connections,
subs,
id_pool,
namespace,
self_namespace,
op_tx,
namespace_pool: Arc::new(Mutex::new(namespace_pool_raw)),
modules: Arc::new(Mutex::new(HashMap::new())),
threads: Arc::new(Mutex::new(Vec::new())),
next_thread_id: Arc::new(Mutex::new(0)),
next_con_id: Arc::new(Mutex::new(1)),
give_msg_wait, create_msg_wait,
give_msg_wait,
create_msg_wait,
#[cfg(feature = "async")]
runtime: Arc::new(Mutex::new(Runtime::new().mize_result_msg("Could not create async runtime")?)),
runtime: Arc::new(Mutex::new(
Runtime::new().mize_result_msg("Could not create async runtime")?,
)),
};
#[cfg(feature = "os-target")]
{
let instance_clone = instance.clone();
@@ -152,7 +246,6 @@ impl Instance {
instance.spawn("updater_thread", closure_two)?;
}
// set up async update "threads" when using wasm
#[cfg(feature = "wasm-target")]
{
@@ -180,34 +273,55 @@ impl Instance {
#[cfg(feature = "wasm-target")]
console_log!("after loading build time config");
return Ok(instance);
}
pub fn new() -> MizeResult<Instance> {
pub fn new() -> MizeResult<Mize> {
trace!("[ {} ] Instance::new()", "CALL".yellow());
let mut instance = Instance::empty()?;
let mut instance = Mize::empty()?;
instance.init();
debug!("instance inited with config: {}", instance.get("0/config")?.as_data_full()?);
debug!(
"instance inited with config: {}",
instance.get("0/config")?.as_data_full()?
);
return Ok(instance);
}
pub fn get_part(&mut self, name: &str) -> MizeResult<DynMizePartGuard> {
match self.parts.lock().unwrap().get_mut(name) {
Some(part) => Ok(DynMizePartGuard {
part: Some(part.take().unwrap()),
mize: self.clone(),
}),
None => Err(mize_err!("Part not found or currently taken")),
}
}
pub fn add_part(&mut self, part: Box<dyn MizePart>) -> MizeResult<()> {
self.part_names.lock().unwrap().push(part.name());
self.parts.lock().unwrap().insert(part.name(), Some(part));
Ok(())
}
fn part_names(&mut self) -> Vec<&'static str> {
self.part_names.lock().unwrap().clone()
}
pub(crate) fn give_back_part(&mut self, part: Box<dyn MizePart + Send + Sync>) {
self.parts.lock().unwrap().insert(part.name(), Some(part));
}
pub fn init(&mut self) -> MizeResult<()> {
// gather options
gather_config(self)?;
// platform specific init code
crate::platform::any::instance_init(self)?;
// end of platform specific init code
// load the modules, ad specified in the load_modules config
match self.get("0/config/load_modules")?.value_string() {
Ok(modules_to_load) => {
@@ -216,23 +330,21 @@ impl Instance {
console_log!("loading module in Instance::init() ... {}", module);
self.load_module(module)?;
}
},
}
Err(err) => {
// no load_modules option is set
}
}
debug!("INSTANCE INIT DONE");
Ok(())
}
pub fn with_config(config: ItemData) -> MizeResult<Instance> {
pub fn with_config(config: ItemData) -> MizeResult<Mize> {
trace!("[ {} ] Instance::with_config()", "CALL".yellow());
trace!("config: {}", config);
let mut instance = Instance::empty()?;
let mut instance = Mize::empty()?;
instance.set_blocking("0", config);
@@ -254,7 +366,7 @@ impl Instance {
let id_of_new_store = new_store.new_id()?;
new_store.set(self.id_from_string(id_of_new_store)?, data.to_owned())?;
};
}
*old_store = new_store;
@@ -297,9 +409,16 @@ impl Instance {
self.op_tx.send(Operation::Set(id, value.into(), None));
Ok(())
}
pub fn set_blocking<I: IntoMizeId, V: Into<ItemData>>(&self, id: I, value: V) -> MizeResult<()> {
handle_operation(&mut Operation::Set(id.to_mize_id(self)?, value.into(), None), self)?;
pub fn set_blocking<I: IntoMizeId, V: Into<ItemData>>(
&self,
id: I,
value: V,
) -> MizeResult<()> {
handle_operation(
&mut Operation::Set(id.to_mize_id(self)?, value.into(), None),
self,
)?;
Ok(())
}
@@ -309,7 +428,7 @@ impl Instance {
match subs_inner.get_mut(&id) {
Some(vec) => {
vec.push(sub);
},
}
None => {
subs_inner.insert(id.clone(), vec![sub]);
}
@@ -330,26 +449,43 @@ impl Instance {
}
pub fn id_from_string(&self, string: String) -> MizeResult<MizeId> {
let vec_string: Vec<String> = string.split("/").map(|v| v.to_owned()).filter(|el| el.as_str() != "").collect();
let vec_string: Vec<String> = string
.split("/")
.map(|v| v.to_owned())
.filter(|el| el.as_str() != "")
.collect();
self.id_from_vec_string(vec_string)
}
pub fn id_from_vec_string(&self, mut vec_string: Vec<String>) -> MizeResult<MizeId> {
let id_pool_inner = self.id_pool.lock()?;
let namespace_inner = self.namespace.lock()?;
let first_el = vec_string.first_mut().ok_or(mize_err!("MizeId was empty"))?;
let first_el = vec_string
.first_mut()
.ok_or(mize_err!("MizeId was empty"))?;
let id = if first_el.contains(":") { // first el is a namespace + store_part
let id = if first_el.contains(":") {
// first el is a namespace + store_part
let new_first_el = first_el.clone();
let vec: Vec<&str> = new_first_el.split(":").collect();
let ns_part = vec.iter().nth(0).ok_or(mize_err!("should really not happen"))?;
let store_part = vec.iter().nth(1).ok_or(mize_err!("mizeid was like 'namespace:/hi', why are you doing that"))?;
let ns_part = vec
.iter()
.nth(0)
.ok_or(mize_err!("should really not happen"))?;
let store_part = vec.iter().nth(1).ok_or(mize_err!(
"mizeid was like 'namespace:/hi', why are you doing that"
))?;
*first_el = store_part.to_owned().to_owned();
MizeId { path: id_pool_inner.get(vec_string), namespace: self.namespace_from_string(ns_part.to_owned().to_owned())? }
MizeId {
path: id_pool_inner.get(vec_string),
namespace: self.namespace_from_string(ns_part.to_owned().to_owned())?,
}
} else {
MizeId { path: id_pool_inner.get(vec_string), namespace: namespace_inner.clone() }
MizeId {
path: id_pool_inner.get(vec_string),
namespace: namespace_inner.clone(),
}
};
trace!("new MizeId made: {:?}", id);
@@ -373,14 +509,17 @@ impl Instance {
pub fn get_module(&mut self, name: &str) -> MizeResult<Box<dyn Module + Send + Sync>> {
let inner = self.modules.lock()?;
let module = inner.get(name).ok_or(mize_err!("Couldn't get_module('{name}')"))?.clone_module();
let module = inner
.get(name)
.ok_or(mize_err!("Couldn't get_module('{name}')"))?
.clone_module();
Ok(module)
}
pub fn namespace_from_string(&self, ns_str: String) -> MizeResult<Namespace> {
let namespace_pool_inner = self.namespace_pool.lock()?;
let namespace = Namespace ( namespace_pool_inner.get(ns_str) );
let namespace = Namespace(namespace_pool_inner.get(ns_str));
Ok(namespace)
}
@@ -405,7 +544,7 @@ impl Instance {
Ok(self.get_namespace()? == self.get_self_namespace()?)
}
pub fn add_listener<T: ConnListener +'static>(&mut self, listener: T) -> MizeResult<()> {
pub fn add_listener<T: ConnListener + 'static>(&mut self, listener: T) -> MizeResult<()> {
let mut instance_clone = self.clone();
self.spawn("some_listener", move || listener.listen(instance_clone));
Ok(())
@@ -416,7 +555,11 @@ impl Instance {
let mut next_con_id = self.next_con_id.lock()?;
let old_next_con_id = *next_con_id;
let connection = Connection { id: next_con_id.to_owned(), tx, ns: None};
let connection = Connection {
id: next_con_id.to_owned(),
tx,
ns: None,
};
conn_inner.push(connection);
*next_con_id += 1;
Ok(old_next_con_id)
@@ -425,7 +568,12 @@ impl Instance {
pub fn new_connection_join_namespace(&self, tx: Sender<MizeMessage>) -> MizeResult<u64> {
let conn_id = self.new_connection(tx)?;
let ns_of_peer_str = self.get(format!("inst/con_by_id/{}/peer/0/config/namespace", conn_id))?.value_string()?;
let ns_of_peer_str = self
.get(format!(
"inst/con_by_id/{}/peer/0/config/namespace",
conn_id
))?
.value_string()?;
let ns_of_peer = self.namespace_from_string(ns_of_peer_str)?;
self.connection_set_namespace(conn_id, ns_of_peer.clone());
@@ -459,7 +607,10 @@ impl Instance {
}
}
return Err(mize_err!("Connection with id {} not known to instance", conn_id));
return Err(mize_err!(
"Connection with id {} not known to instance",
conn_id
));
Ok(())
}
@@ -472,7 +623,10 @@ impl Instance {
}
}
return Err(mize_err!("Connection with id {} not known to instance", conn_id));
return Err(mize_err!(
"Connection with id {} not known to instance",
conn_id
));
}
pub fn get_connection_by_ns(&self, ns: Namespace) -> MizeResult<Connection> {
@@ -484,11 +638,17 @@ impl Instance {
}
}
return Err(mize_err!("Connection with namespace {} not known to instance", ns.as_string()));
return Err(mize_err!(
"Connection with namespace {} not known to instance",
ns.as_string()
));
}
pub fn spawn(&mut self, name: &str, func: impl FnOnce() -> MizeResult<()> + Send + 'static) -> MizeResult<()> {
pub fn spawn(
&mut self,
name: &str,
func: impl FnOnce() -> MizeResult<()> + Send + 'static,
) -> MizeResult<()> {
let mut threads_inner = self.threads.lock()?;
let mut next_thread_id = self.next_thread_id.lock()?;
@@ -504,10 +664,14 @@ impl Instance {
func()?;
let mut threads_inner = thread_mutex.lock()?;
*threads_inner = threads_inner.clone().into_iter().filter(|el| match el {
(my_thread_id, _) => false,
(_, _) => true,
}).collect();
*threads_inner = threads_inner
.clone()
.into_iter()
.filter(|el| match el {
(my_thread_id, _) => false,
(_, _) => true,
})
.collect();
debug!("thread '{}' stopped", name_to_move);
Ok(())
};
@@ -528,7 +692,6 @@ impl Instance {
}
pub fn give_msg_wait(&self, id: MizeId) -> MizeResult<ItemData> {
let mut give_msg_wait_inner = self.give_msg_wait.lock()?;
let (tx, rx) = bounded::<ItemData>(1);
@@ -552,9 +715,12 @@ impl Instance {
return Ok(data);
}
#[cfg(feature = "async")]
pub fn spawn_async<F: Future<Output = impl Send + 'static> + Send + 'static>(&mut self, name: &str, func: F) -> MizeResult<()> {
pub fn spawn_async<F: Future<Output = impl Send + 'static> + Send + 'static>(
&mut self,
name: &str,
func: F,
) -> MizeResult<()> {
let mut threads_inner = self.threads.lock()?;
let mut next_thread_id = self.next_thread_id.lock()?;
@@ -567,7 +733,6 @@ impl Instance {
Ok(())
}
#[cfg(feature = "async")]
pub fn async_get_handle(&self) -> Handle {
let runtime_inner = self.runtime.lock().unwrap();
@@ -576,10 +741,21 @@ impl Instance {
}
#[cfg(feature = "async")]
pub fn spawn_async_blocking<F: Future<Output = impl Send + Sync + 'static> + Send + Sync + 'static>(&mut self, name: &str, func: F) -> F::Output {
let mut threads_inner = self.threads.lock().expect("mutex lock failed in spawn_async_blocking");
let mut next_thread_id = self.next_thread_id.lock().expect("mutex lock failed in spawn_async_blocking");
pub fn spawn_async_blocking<
F: Future<Output = impl Send + Sync + 'static> + Send + Sync + 'static,
>(
&mut self,
name: &str,
func: F,
) -> F::Output {
let mut threads_inner = self
.threads
.lock()
.expect("mutex lock failed in spawn_async_blocking");
let mut next_thread_id = self
.next_thread_id
.lock()
.expect("mutex lock failed in spawn_async_blocking");
threads_inner.push((*next_thread_id, name.to_owned()));
let runtime_inner = self.runtime.lock().unwrap();
@@ -592,7 +768,6 @@ impl Instance {
let result = handle.block_on(func);
return result;
}
@@ -603,15 +778,60 @@ impl Instance {
}
}
pub fn report_error(err: MizeError) {
err.log();
}
pub fn get_config(&mut self, name: &str) -> MizeResult<ItemData> {
let mut config_opts = self.config_opts.lock().unwrap();
let opt = config_opts
.get_mut(name)
.ok_or_else(|| mize_err!("Config opt for {name} not in config_opts"))?;
// get the cached value
if let Some(val) = opt.val.clone() {
return Ok(val);
}
// Evaluate the thunk
let thunk = opt
.thunk
.take()
.ok_or_else(|| mize_err!("ConfigOpt {name} does not have a thunk"))?;
let result = thunk();
// Cache the result
opt.val = Some(result.clone());
return Ok(result);
}
pub fn new_opt(&mut self, name: &str) -> ConfigOptNameAndMize {
let mut config_opts = self.config_opts.lock().unwrap();
let opt = ConfigOpt {
name: name.to_owned(),
val: None,
thunk: None,
};
config_opts.insert(name.to_string(), opt);
ConfigOptNameAndMize {
name: name.to_string(),
mize: self.clone(),
}
}
pub fn run(&mut self) -> MizeResult<()> {
let mut parts = self.parts.lock().unwrap();
for part in parts.values_mut() {
part.as_deref_mut().unwrap().run(&mut self.clone())?;
}
Ok(())
}
}
impl fmt::Debug for Instance {
impl fmt::Debug for Mize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Mize Instance with subs: {:?}", self.subs,)
}
}

View File

@@ -1,29 +1,25 @@
// https://users.rust-lang.org/t/casting-between-trait-object-types/97220/2
use std::ffi::OsString;
use crate::instance::Instance;
use crate::error::MizeResult;
use crate::instance::Mize;
pub trait Module: {
fn init(&mut self, instance: &Instance) -> MizeResult<()>;
pub trait Module {
fn init(&mut self, instance: &Mize) -> MizeResult<()>;
fn exit(&mut self, instance: &Instance) -> MizeResult<()>;
fn exit(&mut self, instance: &Mize) -> MizeResult<()>;
fn clone_module(&self) -> Box<dyn Module + Send + Sync>;
// extra traits, that can be implemented
// return None if not implemented
fn run_cli(&mut self, instance: &Instance, cmd_line: Vec<OsString>) -> Option<MizeResult<()>> {
fn run_cli(&mut self, instance: &Mize, cmd_line: Vec<OsString>) -> Option<MizeResult<()>> {
None
}
}
// console_log macro
// that can be copied into other files for debugging purposes
#[cfg(feature = "wasm-target")]
@@ -43,27 +39,22 @@ macro_rules! console_log {
($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())})
}
pub struct EmptyModule {
}
pub struct EmptyModule {}
impl Module for EmptyModule {
fn init(&mut self, instance: &Instance) -> MizeResult<()> {
fn init(&mut self, instance: &Mize) -> MizeResult<()> {
println!("empty module fn init");
#[cfg(feature = "wasm-target")]
console_log!("empty module fn init");
Ok(())
}
fn exit(&mut self, instance: &Instance) -> MizeResult<()> {
fn exit(&mut self, instance: &Mize) -> MizeResult<()> {
println!("empty module fn exit");
Ok(())
}
fn clone_module(&self) -> Box<dyn Module + Send + Sync> {
Box::new(EmptyModule { })
Box::new(EmptyModule {})
}
}

View File

@@ -1,19 +1,19 @@
use dyn_clone::DynClone;
use std::fmt::Debug;
use std::iter::Map;
use std::option::Iter;
use dyn_clone::DynClone;
use crate::error::MizeResult;
use crate::item::{Item, ItemData};
use crate::id::MizeId;
use crate::memstore::MemStore;
use crate::instance::Instance;
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
// 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
@@ -48,7 +48,10 @@ pub struct IdIter {
impl IdIter {
pub fn new(store: Box<dyn Store>) -> MizeResult<IdIter> {
Ok(IdIter { cur_id: store.first_id()?, store })
Ok(IdIter {
cur_id: store.first_id()?,
store,
})
}
}
@@ -57,17 +60,12 @@ impl Iterator for IdIter {
fn next(&mut self) -> Option<Self::Item> {
match self.store.next_id(&self.cur_id) {
Err(err) => {
Some(Err(err))
},
Err(err) => Some(Err(err)),
Ok(Some(new_id)) => {
self.cur_id = new_id.clone();
Some(Ok(new_id))
},
Ok(None) => {
None
},
}
Ok(None) => None,
}
}
}

View File

@@ -1,20 +1,20 @@
use core::fmt;
use std::rc::Rc;
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::error::MizeResult;
use crate::proto::MizeMessage;
use super::Instance;
use super::Mize;
#[derive(Clone, Debug)]
pub struct Update {
pub instance: Arc<Instance>,
pub instance: Arc<Mize>,
pub id: MizeId,
}
@@ -31,7 +31,7 @@ pub enum Subscription {
}
impl Subscription {
pub fn from_conn(conn: Connection) -> Subscription {
pub fn from_conn(conn: Connection) -> Subscription {
Subscription::Connection(conn)
}
pub fn from_closure(closure: Box<dyn Fn(Update) -> MizeResult<()> + Send>) -> Subscription {
@@ -45,12 +45,14 @@ impl Subscription {
trace!("handleing update");
match &self {
Subscription::Connection(conn) => {
let msg = MizeMessage::new_update(update.id.clone(), update.new_item()?.as_data_full()?, conn.id);
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::Closure(closure) => closure(update)?,
Subscription::Channel(tx) => {
tx.send(update);
}

View File

@@ -1,15 +1,13 @@
use tracing_subscriber::registry::Data;
use crate::item::IntoItemData;
use super::*;
#[test]
fn test_sort_keys() -> MizeResult<()> {
let mut data = ItemData::from_toml(r#"
let mut data = ItemData::from_toml(
r#"
[hi]
test = 4
@@ -19,9 +17,11 @@ fn test_sort_keys() -> MizeResult<()> {
[config.test]
inner = "inner"
"#)?;
"#,
)?;
let data_sorted = ItemData::from_toml(r#"
let data_sorted = ItemData::from_toml(
r#"
[config]
hi = "hello from config/hi"
test = { inner = "inner" }
@@ -29,19 +29,19 @@ fn test_sort_keys() -> MizeResult<()> {
[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 = Instance::empty()?;
let mut instance = Mize::empty()?;
use crate::platform::os::get_module_hash;
let selector_toml = r#"
@@ -64,7 +64,7 @@ fn test_get_module_hash() -> MizeResult<()> {
#[test]
fn test_set_store_path() -> MizeResult<()> {
let instance = Instance::empty()?;
let instance = Mize::empty()?;
let store_path = "/home/me/.mize".to_owned();
@@ -83,23 +83,27 @@ fn test_set_store_path() -> MizeResult<()> {
#[test]
fn test_set_sub_path() -> MizeResult<()> {
let instance = Instance::empty()?;
let instance = Mize::empty()?;
let data = ItemData::from_toml(r#"
let data = ItemData::from_toml(
r#"
[config]
hi = "hello from config/hi"
[config.test]
inner = "inner"
"#)?;
"#,
)?;
let data_two = ItemData::from_toml(r#"
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())?;
@@ -107,11 +111,23 @@ fn test_set_sub_path() -> MizeResult<()> {
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())?;
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"));
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(())
@@ -119,23 +135,30 @@ fn test_set_sub_path() -> MizeResult<()> {
#[test]
fn test_itemdata_set_path() -> MizeResult<()> {
let mut data = ItemData::from_toml(r#"
let mut data = ItemData::from_toml(
r#"
[config]
hi = "hello from config/hi"
[config.test]
inner = "inner"
"#)?;
"#,
)?;
let data_two = ItemData::from_toml(r#"
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"))?;
data.set_path(
vec!["config", "test", "inner"],
ItemData::from_string("new inner"),
)?;
assert_eq!(data, data_two);
@@ -144,57 +167,71 @@ fn test_itemdata_set_path() -> MizeResult<()> {
#[test]
fn test_itemdata_merge() -> MizeResult<()> {
let mut data = ItemData::from_toml(r#"
let mut data = ItemData::from_toml(
r#"
[config]
hi = "hello from config/hi"
[config.test]
inner = "inner"
"#)?;
"#,
)?;
let data_two = ItemData::from_toml(r#"
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"));
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"));
assert_eq!(
data.get_path(vec!["config", "test", "inner"])?,
ItemData::from_string("new inner")
);
Ok(())
}
#[test]
fn test_item_merge() -> MizeResult<()> {
let instance = Instance::empty()?;
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#"
let data = ItemData::from_toml(
r#"
[config]
hi = "hello from config/hi"
[config.test]
inner = "inner"
"#)?;
"#,
)?;
let data_two = ItemData::from_toml(r#"
let data_two = ItemData::from_toml(
r#"
[config]
hi = "hello from config/hi"
[config.test]
inner = "new inner"
"#)?;
"#,
)?;
item.merge(data.clone())?;
@@ -213,7 +250,6 @@ fn test_item_merge() -> MizeResult<()> {
// also the item should be updated
assert_eq!(item.as_data_full()?, data_two);
Ok(())
}
@@ -225,6 +261,3 @@ fn test_cant_set_non_existent_item() -> () {
instance.set_blocking("5", "hello world".into_item_data()).expect("correct panic");
}
*/

View File

@@ -1,28 +1,23 @@
use flume::Receiver;
use tracing::{error, trace, warn};
use std::borrow::BorrowMut;
use std::sync::Arc;
use tracing::{error, trace, warn};
use crate::mize_err;
use crate::{instance::Instance, item::ItemData};
use crate::error::{MizeError, MizeResult, MizeResultTrait};
use crate::id::MizeId;
use crate:: error::{MizeResult, MizeError, MizeResultTrait};
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")]
@@ -46,15 +41,11 @@ macro_rules! console_log {
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => ()
($($t:tt)*) => {};
}
//end of console_log macro
pub async fn updater_thread_async(operation_rx : Receiver<Operation>, instance: Instance) -> () {
pub async fn updater_thread_async(operation_rx: Receiver<Operation>, instance: Mize) -> () {
let mut count = 0;
console_log!("inside an updater thread");
@@ -84,11 +75,10 @@ pub async fn updater_thread_async(operation_rx : Receiver<Operation>, instance:
error!("OPERATION {} FAILED: {:?}", count, operation);
err.log();
}
}
}
pub fn updater_thread(operation_rx : Receiver<Operation>, instance: &Instance) -> MizeResult<()> {
pub fn updater_thread(operation_rx: Receiver<Operation>, instance: &Mize) -> MizeResult<()> {
let mut count = 0;
loop {
@@ -109,13 +99,11 @@ pub fn updater_thread(operation_rx : Receiver<Operation>, instance: &Instance) -
error!("OPERATION FAILED: {:?}", operation);
err.log();
}
}
Ok(())
}
pub fn handle_operation(operation: &mut Operation, instance: &Instance) -> MizeResult<()> {
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();
@@ -130,7 +118,6 @@ pub fn handle_operation(operation: &mut Operation, instance: &Instance) -> MizeR
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 {
@@ -144,15 +131,13 @@ pub fn handle_operation(operation: &mut Operation, instance: &Instance) -> MizeR
sub.handle(update.clone());
}
}
},
Operation::Msg(msg) => {
handle_msg(msg, instance)?
},
}
Operation::Msg(msg) => handle_msg(msg, instance)?,
}
Ok(())
}
fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
fn handle_msg(msg: &mut MizeMessage, instance: &Mize) -> MizeResult<()> {
match msg.cmd()? {
MessageCmd::Get => {
let id = msg.id(instance)?;
@@ -160,7 +145,7 @@ fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
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)?;
@@ -170,21 +155,23 @@ fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
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)));
},
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
@@ -192,8 +179,10 @@ fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
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)));
},
instance
.op_tx
.send(Operation::Set(id.clone(), data, Some(connection)));
}
MessageCmd::Give => {
let id = msg.id(instance)?;
@@ -204,9 +193,12 @@ fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
tx.send(data.clone());
}
} else {
warn!("got give msg for id '{}', that has no one waiting for it", id);
warn!(
"got give msg for id '{}', that has no one waiting for it",
id
);
}
},
}
MessageCmd::Create => {
println!("instance.store: {:?}", instance.clone().store);
@@ -225,10 +217,7 @@ fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
}
_ => {
return Err(mize_err!("got a message, that is not handeled"));
},
}
}
Ok(())
}

View File

@@ -1,44 +1,43 @@
use tracing::{debug, error, info, instrument, trace, warn, Instrument};
use colored::Colorize;
use core::fmt;
use serde::Deserialize;
use serde::Serialize;
use core::fmt;
use std::fmt::Debug;
use std::{i128, string};
use std::{collections::HashMap, path::PathBuf, io::Cursor, fmt::Display};
use std::fs::File;
use std::rc::Rc;
use colored::Colorize;
use std::io;
use std::rc::Rc;
use std::{collections::HashMap, fmt::Display, io::Cursor, path::PathBuf};
use std::{i128, string};
use tracing::{debug, error, info, instrument, trace, warn, Instrument};
use tracing::{span, Level};
use crate::error::{MizeError, MizeResult, IntoMizeResult};
use crate::instance::{connection, Instance};
use crate::instance::store::Store;
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::id::MizeId;
use crate::instance::connection::value_raw_con_by_id;
use crate::instance::store::Store;
use crate::instance::{connection, Mize};
use crate::mize_err;
use crate::proto::MizeMessage;
use ciborium::Value as CborValue;
use crate::instance::connection::value_raw_con_by_id;
// a item always has to do with a Instance, which takes care of how it is updated
#[derive(Debug, Clone)]
pub struct Item<'a> {
id: MizeId,
pub instance: &'a Instance
pub instance: &'a Mize,
}
// without an Instance it is not an item, but only the "data of an item"
// and this type for now is just an alias to CborValue
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ItemData ( pub CborValue );
pub struct ItemData(pub CborValue);
impl Item<'_> {
pub fn id(&self) -> MizeId {
self.id.clone()
}
pub fn new(id: MizeId, instance: &Instance) -> Item {
pub fn new(id: MizeId, instance: &Mize) -> Item {
Item { id, instance }
}
@@ -57,31 +56,43 @@ impl Item<'_> {
pub fn as_data_full(&self) -> MizeResult<ItemData> {
let id = self.id();
// the instance we are
if id.store_part() == "self" {
debug!("getting item '{}' from self", self.id());
match id.nth_part(1)? {
"con_by_id" => { return value_raw_con_by_id(&mut self.clone()); },
"namespace" => {
"con_by_id" => {
return value_raw_con_by_id(&mut self.clone());
}
"namespace" => {
let namespace_inner = self.instance.namespace.lock()?;
return Ok(ItemData::from_string(namespace_inner.as_real_string()));
},
}
"self_namespace" => {
let namespace_inner = self.instance.self_namespace.lock()?;
return Ok(ItemData::from_string(namespace_inner.as_real_string()));
},
}
"config" => {
let rest_path = id.path.into_iter().skip(2).map(|v| v.to_owned()).collect::<Vec<String>>().join("/");
let id_for_store = self.instance.new_id("0/config".to_owned() + "/" + rest_path.as_str())?;
let rest_path = id
.path
.into_iter()
.skip(2)
.map(|v| v.to_owned())
.collect::<Vec<String>>()
.join("/");
let id_for_store = self
.instance
.new_id("0/config".to_owned() + "/" + rest_path.as_str())?;
let store = self.instance.store.lock()?;
let data = store.get_value_data_full(id_for_store)?;
return Ok(data);
}
_ => {},
_ => {}
}
return Err(mize_err!("a /self path, but the next element in the path '{:?}' is not valid", id.nth_part(1)));
return Err(mize_err!(
"a /self path, but the next element in the path '{:?}' is not valid",
id.nth_part(1)
));
}
let self_namespace_inner = self.instance.self_namespace.lock()?;
@@ -91,27 +102,31 @@ impl Item<'_> {
if id.store_part() == "inst" {
match id.nth_part(1)? {
"con_by_id" => { return value_raw_con_by_id(&mut self.clone()); },
"namespace" => {
"con_by_id" => {
return value_raw_con_by_id(&mut self.clone());
}
"namespace" => {
let namespace_inner = self.instance.namespace.lock()?;
return Ok(ItemData::from_string(namespace_inner.as_real_string()));
},
"self_namespace" => {
}
"self_namespace" => {
let namespace_inner = self.instance.self_namespace.lock()?;
return Ok(ItemData::from_string(namespace_inner.as_real_string()));
},
_ => {},
}
_ => {}
}
}
let store_inner = self.instance.store.lock()?;
return store_inner.get_value_data_full(self.id());
} else {
let mut connection = self.instance.get_connection_by_ns(self.id().namespace())?;
debug!("getting item '{}' from connection '{}' from store", self.id(), connection.id);
debug!(
"getting item '{}' from connection '{}' from store",
self.id(),
connection.id
);
let msg = MizeMessage::new_get(self.id(), connection.id);
connection.send(msg);
@@ -121,8 +136,7 @@ impl Item<'_> {
}
#[instrument(name = "fn.ItemData::merge")]
pub fn merge<V: Into<ItemData> + Debug >(&mut self, mut value: V) -> MizeResult<()> {
pub fn merge<V: Into<ItemData> + Debug>(&mut self, mut value: V) -> MizeResult<()> {
let mut data = self.as_data_full()?;
//let mut data = data_full.get_path(id_path_without_store_part)?;
trace!("item::merge data: {:?}", data);
@@ -135,25 +149,28 @@ impl Item<'_> {
// handle the case of /self/*
if self.id().store_part() == "self" {
let rest_path = self.id().path.into_iter().skip(1).map(|v| v.to_owned()).collect::<Vec<String>>().join("/");
let id_for_store = self.instance.new_id("0".to_owned() + "/" + rest_path.as_str())?;
let rest_path = self
.id()
.path
.into_iter()
.skip(1)
.map(|v| v.to_owned())
.collect::<Vec<String>>()
.join("/");
let id_for_store = self
.instance
.new_id("0".to_owned() + "/" + rest_path.as_str())?;
let store_inner = self.instance.store.lock()?;
store_inner.set(id_for_store, data)?;
} else if self.instance.we_are_namespace()? {
let store_inner = self.instance.store.lock()?;
store_inner.set(self.id(), data)?;
} else {
let namespace = self.id().namespace();
let mut connection = self.instance.get_connection_by_ns(namespace)?;
let msg = MizeMessage::new_update_request(self.id(), data, connection.id);
connection.send(msg)?;
}
Ok(())
@@ -178,11 +195,12 @@ impl ItemData {
}
pub fn from_toml(toml_string: &str) -> MizeResult<ItemData> {
let toml_deserializer = toml::Deserializer::new(&toml_string);
let value = CborValue::deserialize(toml_deserializer)
.mize_result_msg(format!("Could not deserialize the toml string: {}", &toml_string))?;
let value = CborValue::deserialize(toml_deserializer).mize_result_msg(format!(
"Could not deserialize the toml string: {}",
&toml_string
))?;
return Ok(value.into_item_data());
}
@@ -197,14 +215,14 @@ impl ItemData {
pub fn from_string<S: Into<String>>(into_string: S) -> ItemData {
let string = into_string.into();
let data = CborValue::Text(string);
return ItemData (data);
return ItemData(data);
}
pub fn to_json(self) -> MizeResult<String> {
let mut result: Vec<u8> = Vec::new();
self.0.serialize(&mut serde_json::Serializer::new(&mut result))?;
self.0
.serialize(&mut serde_json::Serializer::new(&mut result))?;
Ok(String::from_utf8(result)?)
}
@@ -212,8 +230,10 @@ impl ItemData {
pub fn from_json(json_str: String) -> MizeResult<ItemData> {
let mut json_deserializer = serde_json::Deserializer::from_str(json_str.as_str());
let value = CborValue::deserialize(&mut json_deserializer)
.mize_result_msg(format!("could not deserialize the json string: {}", json_str))?;
let value = CborValue::deserialize(&mut json_deserializer).mize_result_msg(format!(
"could not deserialize the json string: {}",
json_str
))?;
return Ok(value.into_item_data());
}
@@ -227,7 +247,7 @@ impl ItemData {
}
pub fn from_cbor(cbor: CborValue) -> ItemData {
ItemData (cbor)
ItemData(cbor)
}
pub fn sort_keys(&mut self) -> MizeResult<()> {
@@ -247,7 +267,7 @@ impl ItemData {
return CborValue::Bool(true).into_item_data();
}
if let Ok(int) = value_str.parse::<i128>() {
return int.into_item_data()
return int.into_item_data();
}
return CborValue::Text(value_str).into_item_data();
}
@@ -262,12 +282,12 @@ impl ItemData {
pub fn get_path<P: IntoPath>(&self, path: P) -> MizeResult<ItemData> {
let path = path.into_path();
Ok(item_data_get_path(&self.0, path)?.to_owned().into_item_data())
Ok(item_data_get_path(&self.0, path)?
.to_owned()
.into_item_data())
}
}
impl Default for ItemData {
fn default() -> Self {
ItemData::new()
@@ -275,7 +295,6 @@ impl Default for ItemData {
}
pub fn data_from_string(data_string: String) -> MizeResult<ItemData> {
let mut data = ItemData::new();
// in case it's just a string
@@ -290,15 +309,25 @@ pub fn data_from_string(data_string: String) -> MizeResult<ItemData> {
continue;
}
let path = option.split("=").nth(0)
.ok_or(MizeError::new().msg(format!("Failed to parse Option: option '{}' has an empty path (thing before =)", option)))?;
let path = option
.split("=")
.nth(0)
.ok_or(MizeError::new().msg(format!(
"Failed to parse Option: option '{}' has an empty path (thing before =)",
option
)))?;
//trace!("data_from_string: path: {}", path);
let value = option.split("=").nth(1)
.ok_or(MizeError::new().msg(format!("Failed to parse Option: option '{}' has an empty value (thing after =)", option)))?;
let value = option
.split("=")
.nth(1)
.ok_or(MizeError::new().msg(format!(
"Failed to parse Option: option '{}' has an empty value (thing after =)",
option
)))?;
//trace!("data_from_string: value: {}", value);
let mut path_vec = Vec::new();
path_vec.extend(path.split("."));
@@ -333,18 +362,20 @@ pub fn item_data_get_path(data: &CborValue, path: Vec<String>) -> MizeResult<&Cb
}
}
}
},
}
val => {
return Err(MizeError::new()
.msg(format!("Failed to get path '{:?}' from ItemData, the data at '{}' is not a map", path, path_el))
.msg(format!(
"Failed to get path '{:?}' from ItemData, the data at '{}' is not a map",
path, path_el
))
.msg(format!("{:?} is: {:?}", path_el, val)));
},
}
};
item_data_get_path(sub_data, path_iter.collect())
}
pub fn item_data_sort_keys(data: &mut CborValue) -> MizeResult<()> {
// for a list, sort each item of the list
if data.is_array() {
for el in data.as_array_mut().unwrap().iter_mut() {
@@ -356,7 +387,7 @@ pub fn item_data_sort_keys(data: &mut CborValue) -> MizeResult<()> {
if data.is_map() {
let map: &mut Vec<(CborValue, CborValue)> = data.as_map_mut().unwrap();
//map.sort_by_key(|el| el.0);
map.sort_by(|a,b| {
map.sort_by(|a, b| {
match a.0.partial_cmp(&b.0) {
Some(val) => val,
None => {
@@ -375,7 +406,11 @@ pub fn item_data_sort_keys(data: &mut CborValue) -> MizeResult<()> {
Ok(())
}
pub fn item_data_set_path(data: &mut CborValue, path: Vec<String>, data_to_set: &CborValue) -> MizeResult<()> {
pub fn item_data_set_path(
data: &mut CborValue,
path: Vec<String>,
data_to_set: &CborValue,
) -> MizeResult<()> {
//trace!("[ {} ] item_data_set_path()", "CALL".yellow());
//trace!("[ {} ] data: {}", "ARG".yellow(), data.clone().into_item_data());
//trace!("[ {} ] path: {:?}", "ARG".yellow(), path);
@@ -395,11 +430,11 @@ pub fn item_data_set_path(data: &mut CborValue, path: Vec<String>, data_to_set:
// our base case
*data = data_to_set.to_owned();
return Ok(());
},
}
};
match data {
CborValue::Map(ref mut map) => {
for (key, val) in &mut * map {
for (key, val) in &mut *map {
if let CborValue::Text(key_str) = key {
if key_str == &path_el {
//trace!("item_data_set_path: setting key {key_str} in map with recursive call");
@@ -417,7 +452,7 @@ pub fn item_data_set_path(data: &mut CborValue, path: Vec<String>, data_to_set:
item_data_set_path(&mut inner_value, path_iter.collect(), data_to_set);
map.push((CborValue::Text(path_el.clone()), inner_value));
return Ok(());
},
}
CborValue::Null => {
//trace!("item_data_set_path: CborValue::Null case");
let mut inner_value = CborValue::Null;
@@ -427,18 +462,21 @@ pub fn item_data_set_path(data: &mut CborValue, path: Vec<String>, data_to_set:
*data = CborValue::Map(map_vec);
return Ok(());
},
}
val => {
return Err(MizeError::new()
.msg(format!("Failed to get path '{:?}' from ItemData, the data at '{}' is not a map", path, path_el))
.msg(format!(
"Failed to get path '{:?}' from ItemData, the data at '{}' is not a map",
path, path_el
))
.msg(format!("{:?} is: {:?}", path_el, val)));
},
}
};
return Err(MizeError::new().msg("unreachable"));
}
pub fn item_data_merge(merge_into: &mut CborValue, other: &CborValue){
pub fn item_data_merge(merge_into: &mut CborValue, other: &CborValue) {
// needs to be recursive
match (merge_into, other) {
@@ -447,25 +485,24 @@ pub fn item_data_merge(merge_into: &mut CborValue, other: &CborValue){
(CborValue::Map(ref mut merge_into_map), CborValue::Map(ref other_map)) => {
// go through other_map and merge those keys/values to merge_into
for (other_key, other_val) in other_map {
// so find that same vale in merge_into, if exists recursively merge, else just add to
// vec
let mut found_value = CborValue::Null;
let mut value_found = false;
let mut new_value_for_merge_into: Vec<(CborValue, CborValue)> = Vec::new(); // here we collect the
// new contents of the
// map, to assign later
// to merge_into_map
// new contents of the
// map, to assign later
// to merge_into_map
for (merge_into_key, merge_into_val) in merge_into_map.clone() {
if merge_into_key == *other_key {
value_found = true;
found_value = merge_into_val.to_owned();
// if we found it, also don't add it to new_value_for_merge_into
} else {
//if not found push to new_value_for_merge_into
new_value_for_merge_into.push((merge_into_key.to_owned(), merge_into_val.to_owned()));
new_value_for_merge_into
.push((merge_into_key.to_owned(), merge_into_val.to_owned()));
}
}
@@ -475,7 +512,6 @@ pub fn item_data_merge(merge_into: &mut CborValue, other: &CborValue){
// to asign push to new_value_for_merge_into, because the old was removed already
new_value_for_merge_into.push((other_key.to_owned(), found_value));
} else {
// if not found, just add the other_key/val to new_value_for_merge_into
new_value_for_merge_into.push((other_key.to_owned(), other_val.to_owned()));
@@ -488,8 +524,7 @@ pub fn item_data_merge(merge_into: &mut CborValue, other: &CborValue){
// if other is Null, don't asign
// this is gonna have repercussions.... because it's not clean behaviour
(merge_into, CborValue::Null) => {
}
(merge_into, CborValue::Null) => {}
// in any other case we just want to set merge_into to other
// also this is the base case
@@ -513,27 +548,30 @@ pub fn get_raw_from_cbor<'a>(value: &'a CborValue, path: Vec<&String>) -> MizeRe
CborValue::Bytes(vec) => {
trace!("[ {} ] ret value: {:?}", "RET".yellow(), &vec[..]);
return Ok(&vec[..]);
},
CborValue::Text(string) => {
}
CborValue::Text(string) => {
trace!("[ {} ] ret value: {:?}", "RET".yellow(), string.as_bytes());
return Ok(string.as_bytes());
},
}
other => {
return Err(mize_err!("path is empty and the value: '{:?}' is neither Bytes nor Text", other));
},
return Err(mize_err!(
"path is empty and the value: '{:?}' is neither Bytes nor Text",
other
));
}
};
},
}
};
match value {
CborValue::Bytes(vec) => {
trace!("[ {} ] ret value: {:?}", "RET".yellow(), &vec[..]);
return Ok(&vec[..]);
},
CborValue::Text(string) => {
}
CborValue::Text(string) => {
trace!("[ {} ] ret value: {:?}", "RET".yellow(), string.as_bytes());
return Ok(string.as_bytes());
},
}
CborValue::Map(map) => {
let mut inner_val: &CborValue = &CborValue::Null;
let mut inner_val_found = false;
@@ -547,12 +585,19 @@ pub fn get_raw_from_cbor<'a>(value: &'a CborValue, path: Vec<&String>) -> MizeRe
}
}
}
// if there is no value at that path
if inner_val_found == false {
return Err(MizeError::new()
// jesus christ, this is a pfusch...
.msg(format!("get_raw_from_cbor: Path '{}' not Found", path.clone().into_iter().map(|v| v.to_owned()).collect::<Vec<String>>().join("/"))))
.msg(format!(
"get_raw_from_cbor: Path '{}' not Found",
path.clone()
.into_iter()
.map(|v| v.to_owned())
.collect::<Vec<String>>()
.join("/")
)));
}
//path_iter.next();
@@ -560,9 +605,11 @@ pub fn get_raw_from_cbor<'a>(value: &'a CborValue, path: Vec<&String>) -> MizeRe
let ret_value = get_raw_from_cbor(inner_val, inner_path);
trace!("[ {} ] ret value: {:?}", "RET".yellow(), ret_value);
return ret_value;
},
_ => Err(MizeError::new()
.msg(format!("get_raw_from_cbor: value is not a map, text or bytes ... value: {:?}", value))),
}
_ => Err(MizeError::new().msg(format!(
"get_raw_from_cbor: value is not a map, text or bytes ... value: {:?}",
value
))),
}
}
@@ -613,7 +660,7 @@ impl IntoItemData for &String {
}
impl IntoItemData for CborValue {
fn into_item_data(self) -> ItemData {
ItemData ( self )
ItemData(self)
}
}
impl IntoItemData for ItemData {
@@ -630,8 +677,9 @@ impl IntoItemData for i128 {
impl fmt::Display for ItemData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ItemData: ");
let display_writer = DisplayWriter (f);
self.0.serialize(&mut serde_json::Serializer::pretty(display_writer))
let display_writer = DisplayWriter(f);
self.0
.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error)
}
}
@@ -641,13 +689,15 @@ struct DisplayWriter<'a, 'b>(&'a mut fmt::Formatter<'b>);
impl<'a, 'b> io::Write for DisplayWriter<'a, 'b> {
fn write(&mut self, bytes: &[u8]) -> std::result::Result<usize, std::io::Error> {
self.0.write_str(&String::from_utf8_lossy(bytes))
self.0
.write_str(&String::from_utf8_lossy(bytes))
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?;
Ok(bytes.len())
}
fn flush(&mut self) -> std::result::Result<(), std::io::Error> { todo!() }
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
todo!()
}
}
impl PartialEq for ItemData {
@@ -662,5 +712,3 @@ impl PartialEq for ItemData {
}
}
impl Eq for ItemData {}

View File

@@ -1,17 +1,17 @@
use ciborium::Value as CborValue;
use colored::Colorize;
use std::collections::binary_heap::Iter;
use std::collections::HashMap;
use std::iter::Map;
use std::sync::{Arc, Mutex};
use ciborium::Value as CborValue;
use tracing::{instrument, trace};
use colored::Colorize;
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::id::MizeId;
use crate::instance::store::{Store, IdIter};
use crate::error::{MizeError, MizeResult, IntoMizeResult};
use crate::item::{Item, ItemData};
use crate::instance::Instance;
use crate::instance::store::{IdIter, Store};
use crate::instance::Mize;
use crate::item::get_raw_from_cbor;
use crate::item::{Item, ItemData};
use crate::mize_err;
#[derive(Clone, Debug)]
@@ -37,13 +37,12 @@ impl Store for MemStore {
let path = id.after_store_part();
old_data.set_path(path, data)?;
inner.map.insert(id_to_u64(id)?, old_data);
} else {
// if no data exists for that store_part, just insert
inner.map.insert(id_to_u64(id)?, data);
}
return Ok(())
return Ok(());
}
fn get_links(&self, item: Item) -> MizeResult<Vec<MizeId>> {
let inner = self.inner.lock()?;
@@ -65,12 +64,17 @@ impl Store for MemStore {
#[instrument(name="fn.MemStore::get_value_raw" skip(self))]
fn get_value_raw(&self, id: MizeId) -> MizeResult<Vec<u8>> {
trace!("[ {} ] id: {:?}", "ARG".yellow(), id);
trace!("[ {} ] id: {:?}", "ARG".yellow(), id);
let inner = self.inner.lock()?;
let cbor_val = inner.map.get(&id_to_u64(id.clone())?)
.ok_or(MizeError::new()
.msg(format!("Item with store_part: {}, id: {} does not exist in MemStore", id_to_u64(id.clone())?, id)))?;
let cbor_val = inner
.map
.get(&id_to_u64(id.clone())?)
.ok_or(MizeError::new().msg(format!(
"Item with store_part: {}, id: {} does not exist in MemStore",
id_to_u64(id.clone())?,
id
)))?;
let path = id.path();
let mut id_iter = path.iter();
@@ -94,7 +98,6 @@ impl Store for MemStore {
return Ok(ret_data);
}
fn id_iter(&self) -> MizeResult<IdIter> {
IdIter::new(Box::new(self.to_owned()))
}
@@ -104,7 +107,6 @@ impl Store for MemStore {
let mut id = str_to_u64(prev_id_str)?;
loop {
id += 1;
if id > inner.next_id {
@@ -114,7 +116,6 @@ impl Store for MemStore {
if inner.map.contains_key(&id) {
println!("returning: {}", id);
return Ok(Some(format!("{}", id)));
} else {
// try id +1
continue;
@@ -129,8 +130,13 @@ impl Store for MemStore {
impl MemStore {
pub fn new() -> MemStore {
let inner = MemStoreInner { map: HashMap::new(), next_id: 0 };
return MemStore { inner: Arc::new(Mutex::new(inner)) };
let inner = MemStoreInner {
map: HashMap::new(),
next_id: 0,
};
return MemStore {
inner: Arc::new(Mutex::new(inner)),
};
}
}
@@ -139,10 +145,8 @@ fn id_to_u64(id: MizeId) -> MizeResult<u64> {
}
fn str_to_u64(id_str: &str) -> MizeResult<u64> {
id_str.parse()
.mize_result_msg(format!("Could not parse the store_part of mizeid {} into a u64 for the MemStore", id_str))
id_str.parse().mize_result_msg(format!(
"Could not parse the store_part of mizeid {} into a u64 for the MemStore",
id_str
))
}

View File

@@ -1,10 +1,15 @@
use core::fmt;
use std::io;
use serde::Serialize;
use std::io;
use ciborium::{value::Integer, Value as CborValue};
use crate::{error::{IntoMizeResult, MizeError, MizeResult}, id::MizeId, instance::{self, connection::Connection, Instance}, item::{IntoItemData, ItemData}};
use crate::{
error::{IntoMizeResult, MizeError, MizeResult},
id::MizeId,
instance::{self, connection::Connection, Mize},
item::{IntoItemData, ItemData},
};
#[derive(Clone)]
pub struct MizeMessage {
@@ -39,18 +44,22 @@ pub enum MessageCmd {
Sub,
}
impl MizeMessage {
pub fn new(value: CborValue, conn_id: u64) -> MizeMessage {
MizeMessage { value, conn_id }
}
pub fn new_get(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_GET.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_GET.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
@@ -58,9 +67,16 @@ impl MizeMessage {
}
pub fn new_get_sub(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_GET_SUB.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_GET_SUB.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
@@ -68,9 +84,16 @@ impl MizeMessage {
}
pub fn new_sub(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_SUB.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_SUB.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
@@ -78,16 +101,26 @@ impl MizeMessage {
}
pub fn new_create(conn_id: u64) -> MizeMessage {
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_CREATE.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_CREATE.into()),
);
let value = CborValue::Map(vec![cmd]);
MizeMessage::new(value, conn_id)
}
pub fn new_create_reply(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_CREATE_REPLY.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_CREATE_REPLY.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
@@ -95,9 +128,16 @@ impl MizeMessage {
}
pub fn new_give(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_GIVE.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_GIVE.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let data = (CborValue::Integer(MSG_DATA.into()), data.cbor().to_owned());
let value = CborValue::Map(vec![cmd, id, data]);
@@ -106,9 +146,16 @@ impl MizeMessage {
}
pub fn new_update_request(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_UPDATE_REQUEST.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_UPDATE_REQUEST.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let data = (CborValue::Integer(MSG_DATA.into()), data.cbor().to_owned());
let value = CborValue::Map(vec![cmd, id, data]);
@@ -117,9 +164,16 @@ impl MizeMessage {
}
pub fn new_update(id: MizeId, data: ItemData, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let id_path = id
.path()
.into_iter()
.map(|string| CborValue::Text(string.to_owned()))
.collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_UPDATE.into()));
let cmd = (
CborValue::Integer(MSG_CMD.into()),
CborValue::Integer(CMD_UPDATE.into()),
);
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let data = (CborValue::Integer(MSG_DATA.into()), data.cbor().to_owned());
let value = CborValue::Map(vec![cmd, id, data]);
@@ -137,7 +191,7 @@ impl MizeMessage {
CborValue::Map(val) => val,
_ => {
return Err(MizeError::new().msg("Message was not a map"));
},
}
};
//check if in this map there is a c, otherwise return err
@@ -172,20 +226,19 @@ impl MizeMessage {
8 => MessageCmd::Sub,
_ => {
return Err(MizeError::new().msg("error cmd of msg was not a valid command"));
},
}
};
return Ok(cmd);
}
pub fn id_str(&mut self) -> MizeResult<Vec<String>> {
// return err, if msg is not a map
let msg_as_map = match &self.value {
CborValue::Map(val) => val,
_ => {
return Err(MizeError::new().msg("Message was not a map"));
},
}
};
let vec_value = {
@@ -206,26 +259,25 @@ impl MizeMessage {
CborValue::Array(inner) => inner,
_ => {
return Err(MizeError::new().msg("Id is not a vector"));
},
}
}
};
let mut vec_string: Vec<String> = Vec::new();
for val in vec_value {
match val {
CborValue::Text(text) => {
vec_string.push(text.to_owned())
},
CborValue::Text(text) => vec_string.push(text.to_owned()),
_ => {
return Err(MizeError::new().msg("one in the vec of the id in a msg is not of type Text"));
},
return Err(MizeError::new()
.msg("one in the vec of the id in a msg is not of type Text"));
}
}
}
Ok(vec_string)
}
pub fn id(&mut self, instance: &Instance) -> MizeResult<MizeId> {
pub fn id(&mut self, instance: &Mize) -> MizeResult<MizeId> {
let id_str = self.id_str()?;
return instance.new_id(id_str);
}
@@ -236,7 +288,7 @@ impl MizeMessage {
CborValue::Map(val) => val,
_ => {
return Err(MizeError::new().msg("Message was not a map"));
},
}
};
let data = {
@@ -252,7 +304,7 @@ impl MizeMessage {
}
}
}
if ! found {
if !found {
return Err(MizeError::new().msg("error getting the data value form a msg"));
}
tmp_val
@@ -262,30 +314,30 @@ impl MizeMessage {
}
}
// thanks to: https://stackoverflow.com/a/61768916
struct DisplayWriter<'a, 'b>(&'a mut fmt::Formatter<'b>);
impl<'a, 'b> io::Write for DisplayWriter<'a, 'b> {
fn write(&mut self, bytes: &[u8]) -> std::result::Result<usize, std::io::Error> {
self.0.write_str(&String::from_utf8_lossy(bytes))
self.0
.write_str(&String::from_utf8_lossy(bytes))
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?;
Ok(bytes.len())
}
fn flush(&mut self) -> std::result::Result<(), std::io::Error> { todo!() }
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
todo!()
}
}
impl fmt::Display for MizeMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut err = false;
match self.to_owned().cmd() {
Ok(cmd) => {
writeln!(f, "MizeMessage with cmd: {:?}", cmd);
},
}
Err(e) => {
writeln!(f, "MizeMessage with unparsable cmd");
err = true;
@@ -296,7 +348,7 @@ impl fmt::Display for MizeMessage {
Ok(id) => {
let id_str = id.join("/");
writeln!(f, "\tid: {:?}", id_str);
},
}
Err(e) => {
writeln!(f, "\t msg has no id");
//err = true;
@@ -307,40 +359,44 @@ impl fmt::Display for MizeMessage {
Ok(data) => {
let value = data.cbor();
write!(f, "\tdata: ");
let display_writer = DisplayWriter (f);
if let Err(e) = value.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error) {
writeln!(f, "serialize err: {:?}", e);
err = true;
let display_writer = DisplayWriter(f);
if let Err(e) = value
.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error)
{
writeln!(f, "serialize err: {:?}", e);
err = true;
}
},
}
Err(e) => {
writeln!(f, "\t msg has no data");
//err = true;
},
}
}
if err {
write!(f, "Full msg: ");
let display_writer = DisplayWriter (f);
self.value.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error).mize_result_msg("serialize error")
.inspect_err(|e| { e.clone().log(); });
let display_writer = DisplayWriter(f);
self.value
.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error)
.mize_result_msg("serialize error")
.inspect_err(|e| {
e.clone().log();
});
}
Ok(())
}
}
impl fmt::Debug for MizeMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\nMizeMessage: ");
let display_writer = DisplayWriter (f);
let display_writer = DisplayWriter(f);
let value = self.to_owned().value();
value.serialize(&mut serde_json::Serializer::pretty(display_writer))
value
.serialize(&mut serde_json::Serializer::pretty(display_writer))
.map_err(|serde_err| std::fmt::Error)
}
}

View File

@@ -1,11 +1,10 @@
#![ allow( warnings ) ]
#![allow(warnings)]
static PROTO_VERSION: u8 = 1;
#[macro_export]
macro_rules! test_println {
($($arg:tt)*) => {
($($arg:tt)*) => {
#[cfg(test)]
print!("[[ {} ]] ", <&str as colored::Colorize>::blue("TEST"));
@@ -20,7 +19,7 @@ macro_rules! test_println {
#[macro_export]
macro_rules! test_print {
($($arg:tt)*) => {
($($arg:tt)*) => {
#[cfg(test)]
print!("[[ {} ]] ", <&str as colored::Colorize>::blue("TEST"));
@@ -32,20 +31,22 @@ macro_rules! test_print {
// the core part has the code that can run on any platform
mod core {
pub mod memstore;
pub mod config;
pub mod error;
pub mod id;
pub mod instance;
pub mod item;
pub mod id;
pub mod memstore;
pub mod proto;
pub mod error;
pub mod types;
}
pub use core::*;
pub use core::instance::module::Module;
pub use core::instance::Instance;
pub use core::error::MizeError;
pub use core::error::MizeResult;
pub use core::instance::module::Module;
pub use core::instance::Mize;
pub use core::instance::MizePart;
pub use core::*;
use std::path::PathBuf;
// platform specific stuff
@@ -67,7 +68,6 @@ pub mod platform {
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
pub use super::super::instance_init;
//////////// load_module
#[cfg(feature = "os-target")]
pub use super::os::load_module;
@@ -78,7 +78,6 @@ pub mod platform {
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
pub use super::super::load_module;
//////////// fetch_module
#[cfg(feature = "os-target")]
pub use super::os::fetch_module;
@@ -88,16 +87,19 @@ pub mod platform {
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
pub use super::super::fetch_module;
}
}
pub fn instance_init(instance: &mut core::instance::Mize) {}
pub fn instance_init(instance: &mut core::instance::Instance) {}
pub fn load_module(instance: &mut core::instance::Instance, name: &str, path: Option<String>) -> MizeResult<()> { Ok(()) }
pub fn fetch_module(instance: &mut core::instance::Instance, name: &str) -> MizeResult<String> { Ok("oh noooooooooooooo, something went really really wrong, if this ends up in the executable....".to_owned()) }
pub fn load_module(
instance: &mut core::instance::Mize,
name: &str,
path: Option<String>,
) -> MizeResult<()> {
Ok(())
}
pub fn fetch_module(instance: &mut core::instance::Mize, name: &str) -> MizeResult<String> {
Ok("oh noooooooooooooo, something went really really wrong, if this ends up in the executable....".to_owned())
}

View File

@@ -1,30 +1,28 @@
use clap::ArgMatches;
use core::result::Result::Err;
use core::unimplemented;
use flume::bounded;
use home::home_dir;
use mize::mize_err;
use std::ffi::OsString;
use std::io::Read;
use std::path::PathBuf;
use std::str::FromStr;
use clap::ArgMatches;
use home::home_dir;
use flume::bounded;
use mize::mize_err;
use std::io::Read;
use tracing::debug;
use mize::error::{IntoMizeResult, MizeError, MizeResult, MizeResultTrait};
use mize::instance::Instance;
use mize::platform::os::config_from_cli_args;
use mize::instance::subscription::Update;
use mize::platform::os::fsstore::FileStore;
use mize::instance::subscription::Subscription;
use mize::instance::subscription::Update;
use mize::instance::Mize;
use mize::item::{IntoItemData, ItemData};
use mize::platform::os::config_from_cli_args;
use mize::platform::os::fsstore::FileStore;
pub fn get(sub_matches: &ArgMatches) -> MizeResult<()> {
let instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
let instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
let id = sub_matches.get_one::<String>("id")
let id = sub_matches
.get_one::<String>("id")
.ok_or(MizeError::new().msg("No id Argument specified"))?;
let item = instance.get(id)?;
@@ -44,15 +42,12 @@ pub fn get(sub_matches: &ArgMatches) -> MizeResult<()> {
return Ok(());
}
pub fn call(sub_matches: &ArgMatches) -> MizeResult<()> {
Ok(())
}
pub fn create(sub_matches: &ArgMatches) -> MizeResult<()> {
let mut instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
let mut instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
let item = instance.new_item()?;
@@ -62,37 +57,32 @@ pub fn create(sub_matches: &ArgMatches) -> MizeResult<()> {
return Ok(());
}
pub fn is_running(sub_matches: &ArgMatches) -> MizeResult<()> {
println!("not implemented");
Err(mize_err!("not implemented"))
}
pub fn mount(sub_matches: &ArgMatches) -> MizeResult<()> {
Ok(())
}
pub fn run(sub_matches: &ArgMatches) -> MizeResult<()> {
let instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
let instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
instance.wait();
return Ok(());
}
pub fn set(sub_matches: &ArgMatches) -> MizeResult<()> {
let instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
let instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
let id = sub_matches.get_one::<String>("id")
let id = sub_matches
.get_one::<String>("id")
.ok_or(MizeError::new().msg("No id Argument specified"))?;
let value = sub_matches.get_one::<String>("value")
let value = sub_matches
.get_one::<String>("value")
.ok_or(MizeError::new().msg("No value Argument specified"))?;
instance.set_blocking(id, value.into_item_data())?;
@@ -100,12 +90,11 @@ pub fn set(sub_matches: &ArgMatches) -> MizeResult<()> {
Ok(())
}
pub fn show(sub_matches: &ArgMatches) -> MizeResult<()> {
let instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
let instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
let id = sub_matches.get_one::<String>("id")
let id = sub_matches
.get_one::<String>("id")
.ok_or(MizeError::new().msg("No id Argument specified"))?;
let item = instance.get(id)?;
@@ -124,14 +113,12 @@ pub fn show(sub_matches: &ArgMatches) -> MizeResult<()> {
Ok(())
}
pub fn stop(sub_matches: &ArgMatches) -> MizeResult<()> {
Ok(())
}
pub fn gui(sub_matches: &ArgMatches) -> MizeResult<()> {
let mut instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
let mut instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
instance.load_module("mme")?;
@@ -141,8 +128,7 @@ pub fn gui(sub_matches: &ArgMatches) -> MizeResult<()> {
}
pub fn format_cbor(sub_matches: &ArgMatches) -> MizeResult<()> {
let mut input: Vec<u8> = Vec::new();
let mut input: Vec<u8> = Vec::new();
let stdin = std::io::stdin();
let mut handle = stdin.lock();
//handle.read_to_end(&mut input);
@@ -155,20 +141,26 @@ pub fn format_cbor(sub_matches: &ArgMatches) -> MizeResult<()> {
Ok(())
}
pub fn run_from_module(cmd: &str, sub_matches: &ArgMatches) -> MizeResult<()> {
let default = OsString::default();
let mut sub_cmd_line: Vec<OsString> = sub_matches.get_many::<OsString>("").unwrap().map(|e| e.to_owned()).collect();
let mut sub_cmd_line: Vec<OsString> = sub_matches
.get_many::<OsString>("")
.unwrap()
.map(|e| e.to_owned())
.collect();
sub_cmd_line.insert(0, OsString::from_str(cmd)?);
let mut instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
let mut instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
debug!("loading module '{}'", cmd);
instance.load_module(cmd)?;
instance.get_module(cmd)?.run_cli(&instance, sub_cmd_line)
.ok_or(mize_err!("The Module '{cmd}' does not implement the run_cli() functionality"))??;
instance
.get_module(cmd)?
.run_cli(&instance, sub_cmd_line)
.ok_or(mize_err!(
"The Module '{cmd}' does not implement the run_cli() functionality"
))??;
Ok(())
}

View File

@@ -1,20 +1,20 @@
use std::fs;
use std::path::{Path, PathBuf};
use std::fs::OpenOptions;
use sysinfo::{System, Pid, ProcessRefreshKind, RefreshKind};
use std::io::Write;
use ciborium::Value as CborValue;
use std::fs;
use std::fs::OpenOptions;
use std::io::Write;
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::error::{IntoMizeResult, MizeError, MizeResult};
use crate::instance::store::IdIter;
use crate::instance::{self, Mize};
use crate::item::get_raw_from_cbor;
use crate::item::IntoItemData;
use crate::memstore::MemStore;
use crate::{core::instance::store::Store, mize_err};
use crate::error::{IntoMizeResult, MizeResult, MizeError};
use crate::core::item::{ItemData, Item};
use crate::core::id::MizeId;
use crate::item::get_raw_from_cbor;
use crate::instance::{self, Instance};
use tokio::net::UnixStream;
#[derive(Clone, Debug)]
@@ -24,7 +24,6 @@ pub struct FileStore {
impl FileStore {
pub fn new(path_str: &str) -> MizeResult<FileStore> {
let path = Path::new(path_str);
// create that path if it does not exist
@@ -50,19 +49,25 @@ impl FileStore {
fs::write(path.join("next_id"), "1");
}
Ok(FileStore { path: Path::new(&path).to_owned() })
Ok(FileStore {
path: Path::new(&path).to_owned(),
})
}
pub fn store_is_opened(store_path: String, instance: &mut Instance) -> MizeResult<bool> {
pub fn store_is_opened(store_path: String, instance: &mut Mize) -> MizeResult<bool> {
// this was the old method....
//let valid_pid_file = valid_pid_file(Path::new(&store_path))?.is_some();
let can_connect_to_sock = match instance.spawn_async_blocking("con_test_thread", try_connect_to_sock(store_path.clone())) {
let can_connect_to_sock = match instance
.spawn_async_blocking("con_test_thread", try_connect_to_sock(store_path.clone()))
{
Ok(_) => true,
Err(_) => false,
};
debug!("MiZe Store at {} opened: {}", store_path, can_connect_to_sock);
debug!(
"MiZe Store at {} opened: {}",
store_path, can_connect_to_sock
);
Ok(can_connect_to_sock)
}
}
@@ -76,11 +81,16 @@ async fn try_connect_to_sock(store_path: String) -> MizeResult<()> {
impl Store for FileStore {
fn new_id(&self) -> MizeResult<String> {
let mut next_id: u64 = String::from_utf8(fs::read(self.path.join("next_id"))
.mize_result_msg(format!("could not read next_id at '{}'", self.path.display()))?)?
let mut next_id: u64 =
String::from_utf8(fs::read(self.path.join("next_id")).mize_result_msg(format!(
"could not read next_id at '{}'",
self.path.display()
))?)?
.parse()
.mize_result_msg(format!("could not parse next_id at '{}' to u64", self.path.display()))?;
.mize_result_msg(format!(
"could not parse next_id at '{}' to u64",
self.path.display()
))?;
let id_string = format!("{}", next_id);
@@ -92,7 +102,11 @@ impl Store for FileStore {
}
fn set(&self, id: MizeId, data: ItemData) -> MizeResult<()> {
let path = self.path.join("store").join(id.namespace_str()).join(id.store_part());
let path = self
.path
.join("store")
.join(id.namespace_str())
.join(id.store_part());
fs::create_dir_all(self.path.join("store").join(id.namespace_str()))?;
let file = OpenOptions::new().write(true).create(true).open(path)?;
@@ -110,12 +124,18 @@ impl Store for FileStore {
}
fn get_value_raw(&self, id: MizeId) -> MizeResult<Vec<u8>> {
let path = self.path.join("store").join(id.namespace_str()).join(id.store_part());
let path = self
.path
.join("store")
.join(id.namespace_str())
.join(id.store_part());
let file = OpenOptions::new().read(true).create(true).open(path)?;
let cbor_val: CborValue = ciborium::from_reader(file)
.mize_result_msg(format!("could not read file '{}' from FileStore", self.path.join("store").join(id.store_part()).display()))?;
let cbor_val: CborValue = ciborium::from_reader(file).mize_result_msg(format!(
"could not read file '{}' from FileStore",
self.path.join("store").join(id.store_part()).display()
))?;
let path = id.path();
let mut id_iter = path.iter();
@@ -126,15 +146,27 @@ impl Store for FileStore {
}
fn get_value_data_full(&self, id: MizeId) -> MizeResult<ItemData> {
let file_path = self.path.join("store").join(id.namespace_str()).join(id.store_part());
if !file_path.exists() {
}
let file = OpenOptions::new().read(true).open(file_path.clone())
.map_err(|e| mize_err!("fsstoree: Unable to open '{}', err: {}", file_path.display(), e))?;
let file_path = self
.path
.join("store")
.join(id.namespace_str())
.join(id.store_part());
if !file_path.exists() {}
let file = OpenOptions::new()
.read(true)
.open(file_path.clone())
.map_err(|e| {
mize_err!(
"fsstoree: Unable to open '{}', err: {}",
file_path.display(),
e
)
})?;
let cbor_value: CborValue = ciborium::from_reader(file)
.mize_result_msg(format!("could not read file '{}' from FileStore", self.path.join("store").join(id.store_part()).display()))?;
let cbor_value: CborValue = ciborium::from_reader(file).mize_result_msg(format!(
"could not read file '{}' from FileStore",
self.path.join("store").join(id.store_part()).display()
))?;
let data: ItemData = cbor_value.into_item_data();
let tmp = id.path();
@@ -157,7 +189,6 @@ impl Store for FileStore {
}
fn valid_pid_file(path: &Path) -> MizeResult<Option<u32>> {
let pid_file_path = path.join("pid");
// if the pid file does not exist, there is no pid...
@@ -166,10 +197,15 @@ fn valid_pid_file(path: &Path) -> MizeResult<Option<u32>> {
}
// read pid file
let pid: u32 = String::from_utf8(fs::read(&pid_file_path)
.mize_result_msg(format!("Could not read contents of pid file at '{}'", pid_file_path.display()))?)?
.parse()
.mize_result_msg(format!("Could not parse contents of pid file at '{}' to u32", pid_file_path.display()))?;
let pid: u32 = String::from_utf8(fs::read(&pid_file_path).mize_result_msg(format!(
"Could not read contents of pid file at '{}'",
pid_file_path.display()
))?)?
.parse()
.mize_result_msg(format!(
"Could not parse contents of pid file at '{}' to u32",
pid_file_path.display()
))?;
if Path::new("/proc").join(format!("{}", pid)).exists() {
return Ok(Some(pid));
@@ -177,4 +213,3 @@ fn valid_pid_file(path: &Path) -> MizeResult<Option<u32>> {
return Ok(None);
}
}

View File

@@ -1,28 +1,27 @@
#![allow(warnings)]
#![ allow( warnings ) ]
use clap::builder::OsStr;
use clap::{crate_version, Arg, Command};
use clap::{ArgAction, ArgMatches};
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::exit;
use clap::builder::OsStr;
use clap::{ArgAction, ArgMatches};
use clap::{Arg, crate_version, Command};
use mize::error::{MizeError, MizeResult};
use mize::{instance, Instance};
use mize::item::ItemData;
use tokio::sync::{Mutex, mpsc};
use std::sync::Arc;
use std::io::Write;
use colored::Colorize;
use std::env;
use tracing_subscriber::fmt::Subscriber;
use tracing::Level;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::filter::EnvFilter;
use mize::error::{MizeError, MizeResult};
use mize::item::ItemData;
use mize::platform::os::logging::init_logger;
use mize::{instance, Mize};
use std::env;
use std::io::Write;
use std::sync::Arc;
use tokio::sync::{mpsc, Mutex};
use tracing::level_filters::LevelFilter;
use tracing::Level;
use tracing_subscriber::filter::EnvFilter;
use tracing_subscriber::fmt::Subscriber;
use tracing::{trace, debug, info, warn, error};
use tracing::{debug, error, info, trace, warn};
mod cli;
@@ -74,7 +73,8 @@ fn main() {
// some unknown command passed
Some((cmd, sub_matches)) => cli::run_from_module(cmd, sub_matches),
None => Err(MizeError::new().msg("No subcommand was passed. use --help to list availavle comamnds.")),
None => Err(MizeError::new()
.msg("No subcommand was passed. use --help to list availavle comamnds.")),
};
if let Err(err) = result {
@@ -83,105 +83,83 @@ fn main() {
}
}
fn cli_matches() -> clap::ArgMatches {
let main = Command::new(APPNAME)
.version(crate_version!())
.author("Sebastian Moser")
.about("The MiZe Command line tool")
.allow_external_subcommands(true)
.arg(Arg::new("verbose")
.long("verbose")
.short('v')
.action(ArgAction::Count)
.global(true)
.arg(
Arg::new("verbose")
.long("verbose")
.short('v')
.action(ArgAction::Count)
.global(true),
)
.arg(Arg::new("log-level")
.long("log-level")
.value_name("LOGLEVEL")
.help("set the log-level to one of OFF, ERROR, WARN, INFO, DEBUG, TRACE")
.global(true)
.arg(
Arg::new("log-level")
.long("log-level")
.value_name("LOGLEVEL")
.help("set the log-level to one of OFF, ERROR, WARN, INFO, DEBUG, TRACE")
.global(true),
)
.arg(Arg::new("silent")
.long("silent")
.action(ArgAction::SetTrue)
.help("set the log-level to OFF")
.global(true)
.arg(
Arg::new("silent")
.long("silent")
.action(ArgAction::SetTrue)
.help("set the log-level to OFF")
.global(true),
)
.arg(Arg::new("folder")
.short('f')
.long("folder")
.help("The folder the Instance stores all it's data and the socket for connections")
.global(true)
.arg(
Arg::new("folder")
.short('f')
.long("folder")
.help("The folder the Instance stores all it's data and the socket for connections")
.global(true),
)
.arg(Arg::new("config")
.short('c')
.long("config")
.help("overwrite config options")
.global(true)
.arg(
Arg::new("config")
.short('c')
.long("config")
.help("overwrite config options")
.global(true),
)
.arg(Arg::new("config-file")
.long("config-file")
.help("specify a config file")
.global(true)
.arg(
Arg::new("config-file")
.long("config-file")
.help("specify a config file")
.global(true),
)
.subcommand(
Command::new("run")
Command::new("run")
.aliases(["r"])
.about("Run a MiZe Instance")
)
.subcommand(Command::new("stop")
.about("Stop a MiZe Instance")
)
.about("Run a MiZe Instance"),
)
.subcommand(Command::new("stop").about("Stop a MiZe Instance"))
.subcommand(Command::new("mount").aliases(["m"]))
.subcommand(
Command::new("mount")
.aliases(["m"])
)
.subcommand(
Command::new("get")
Command::new("get")
.aliases(["g"])
.arg(Arg::new("id").help("The id or path to get"))
.arg(Arg::new("recurse")
.short('r')
.action(ArgAction::Count)
)
)
.arg(Arg::new("recurse").short('r').action(ArgAction::Count)),
)
.subcommand(
Command::new("set")
Command::new("set")
.aliases(["s"])
.arg(Arg::new("id").help("The id or path to set"))
.arg(Arg::new("value").help("The value to set the path to"))
)
.arg(Arg::new("value").help("The value to set the path to")),
)
.subcommand(
Command::new("show")
Command::new("show")
.aliases(["so"])
.arg(Arg::new("id").help("The id or path to sub to and show"))
)
.subcommand(
Command::new("call")
.aliases(["c"])
)
.subcommand(
Command::new("create")
.aliases(["cr"])
)
.subcommand(
Command::new("is-running")
.aliases(["isr"])
)
.subcommand(
Command::new("gui")
)
.subcommand(
Command::new("format-cbor")
)
.arg(Arg::new("id").help("The id or path to sub to and show")),
)
.subcommand(Command::new("call").aliases(["c"]))
.subcommand(Command::new("create").aliases(["cr"]))
.subcommand(Command::new("is-running").aliases(["isr"]))
.subcommand(Command::new("gui"))
.subcommand(Command::new("format-cbor"))
.arg_required_else_help(true);
return main.get_matches();
}

View File

@@ -1,25 +1,25 @@
use ciborium::Value as CborValue;
use clap::ArgMatches;
use flate2::bufread::GzDecoder;
use serde::Deserialize;
use sha2::{Digest, Sha256, Sha512};
use std::env::VarError;
use std::fs;
use tracing::{debug, error, info, trace, warn};
use clap::ArgMatches;
use std::path::{Path, PathBuf};
use std::time::UNIX_EPOCH;
use sha2::{Sha256, Sha512, Digest};
use flate2::bufread::GzDecoder;
use tar::Archive;
use std::fs::File;
use std::io::copy;
use std::path::{Path, PathBuf};
use std::time::UNIX_EPOCH;
use tar::Archive;
use tracing::{debug, error, info, trace, warn};
use crate::id::MizeId;
use crate::instance::store::Store;
use crate::instance::Instance;
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::id::MizeId;
use crate::instance::module::EmptyModule;
use crate::instance::store::Store;
use crate::instance::Mize;
use crate::item::{data_from_string, IntoItemData, ItemData};
use crate::memstore::MemStore;
use crate::{mize_err, Module};
use crate::instance::module::EmptyModule;
use self::fsstore::FileStore;
@@ -33,8 +33,7 @@ mod unix_socket;
use crate::platform::os::unix_socket::UnixListener;
//mod web;
pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
pub fn os_instance_init(instance: &mut Mize) -> MizeResult<()> {
// this is the code, that runs to initialize an Instance on a system with an os present.
////// load MIZE_CONFIG_FILE as the instance, which is item 0
@@ -43,16 +42,19 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
let config = config_from_file(config_file_path)?;
debug!("env var MIZE_CONFIG_FILE present");
instance.set_blocking("0", config)?;
trace!("config after MIZE_CONFIG_FILE env var: {}", instance.get("self/config")?);
trace!(
"config after MIZE_CONFIG_FILE env var: {}",
instance.get("self/config")?
);
}
Err(var_err) => match var_err {
VarError::NotPresent => {
debug!("env var MIZE_CONFIG_FILE NOT present");
},
}
VarError::NotUnicode(_) => {
warn!("env var MIZE_CONFIG_FILE is not Unicode, so not reading it")
},
}
}
},
};
////// load config from MIZE_CONFIG env var
@@ -61,44 +63,49 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
let config = data_from_string(config_string)?;
debug!("env var MIZE_CONFIG present");
instance.set_blocking("self/config", config)?;
trace!("config after MIZE_CONFIG env var: {}", instance.get("self/config")?);
trace!(
"config after MIZE_CONFIG env var: {}",
instance.get("self/config")?
);
}
Err(var_err) => match var_err {
VarError::NotPresent => {
debug!("env var MIZE_CONFIG NOT present")
},
}
VarError::NotUnicode(_) => {
warn!("env var MIZE_CONFIG is not Unicode, so not reading it")
},
}
}
},
};
////// if a config.store_path is set, upgrade to the filestore there
let mut test = instance.get("0")?.as_data_full()?;
let mut store_path = match instance.get("self/config/store_path")?.value_string() {
Ok(path) => {
path
},
Ok(path) => path,
Err(e) => {
// the default store_path: $HOME/.mize
let home_dir = if let Some(dir) = std::env::home_dir() {
dir
} else {
return Err(mize_err!("could not get home_dir and store_path is not set in the config"));
return Err(mize_err!(
"could not get home_dir and store_path is not set in the config"
));
};
let store_path_buff = home_dir.join(".mize");
let store_path = store_path_buff.display().to_string();
instance.set_blocking("self/config/store_path", store_path.clone().into_item_data())?;
instance.set_blocking(
"self/config/store_path",
store_path.clone().into_item_data(),
)?;
let store_path = instance.get("self/config/store_path")?.value_string()?;
println!("store_path: {}", store_path);
store_path
},
}
};
if FileStore::store_is_opened(store_path.to_owned(), instance)? {
@@ -117,7 +124,6 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
{
error!("CONNECTING... would connect, but that is not implemented on windows yet");
}
} else {
// else open it ourselves
let file_store = FileStore::new(store_path.as_str())?;
@@ -132,7 +138,7 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
#[cfg(target_family = "windows")]
{
warn!("would add a Listener on a local socket, but that is not yet implemented for windows");;
warn!("would add a Listener on a local socket, but that is not yet implemented for windows");
}
}
@@ -149,15 +155,24 @@ pub fn seconds_since_modification(path: &Path) -> MizeResult<u64> {
Ok(duration.as_secs())
}
pub fn get_module_hash(instance: &mut Instance, name: &str, mut options: ItemData) -> MizeResult<(String, String)> {
pub fn get_module_hash(
instance: &mut Mize,
name: &str,
mut options: ItemData,
) -> MizeResult<(String, String)> {
let mut selector_data = instance.get("self/config/selector")?.as_data_full()?;
// handle the case, when we want a module for not the system we are running on...
println!("get_module_hash: name: {}", name);
let mut name_parts = name.split(".");
if name_parts.next().ok_or(mize_err!("no 0th element in the modName"))? == "cross" {
let system = name_parts.next().ok_or(mize_err!("no 1th element in the modName"))?;
if name_parts
.next()
.ok_or(mize_err!("no 0th element in the modName"))?
== "cross"
{
let system = name_parts
.next()
.ok_or(mize_err!("no 1th element in the modName"))?;
let mod_name: String = name_parts.collect();
println!("get_module_hash: mod_name: {}", mod_name);
if mod_name == "" {
@@ -183,7 +198,8 @@ pub fn get_module_hash(instance: &mut Instance, name: &str, mut options: ItemDat
let result = hasher.finalize();
let mut hex: String = result.iter()
let mut hex: String = result
.iter()
.map(|b| format!("{:02x}", b).to_string())
.collect::<Vec<String>>()
.join("");
@@ -191,25 +207,46 @@ pub fn get_module_hash(instance: &mut Instance, name: &str, mut options: ItemDat
hex.truncate(32);
return Ok((hex, selector_str));
}
fn download_module(instance: &mut Instance, store_path: &str, module_url: &str, module_hash: &str, module_name: &str, module_selector: &str) -> MizeResult<()> {
fn download_module(
instance: &mut Mize,
store_path: &str,
module_url: &str,
module_hash: &str,
module_name: &str,
module_selector: &str,
) -> MizeResult<()> {
let tmp_file_path_gz = format!("{}/{}.tar.gz", store_path, module_hash);
let tmp_gz_file = if !PathBuf::from(tmp_file_path_gz.clone()).exists() {
let tmp_gz_file = if !PathBuf::from(tmp_file_path_gz.clone()).exists() {
let mut tmp_gz_file = File::create(&tmp_file_path_gz)?;
debug!("downloading module '{}' with hash: {}", module_name, module_hash);
debug!(
"downloading module '{}' with hash: {}",
module_name, module_hash
);
let response = http_req::request::get(format!("http://{}/mize/dist/{}-{}.tar.gz", module_url, module_hash, module_name), &mut tmp_gz_file)?;
let response = http_req::request::get(
format!(
"http://{}/mize/dist/{}-{}.tar.gz",
module_url, module_hash, module_name
),
&mut tmp_gz_file,
)?;
let code = response.status_code();
if code != 200.into() {
return Err(mize_err!("failed to get module '{}' with hash '{}' and selector: {}", module_name, module_hash, module_selector).msg(format!("the http request to fetch the module returned a status code of: {}", code)));
return Err(mize_err!(
"failed to get module '{}' with hash '{}' and selector: {}",
module_name,
module_hash,
module_selector
)
.msg(format!(
"the http request to fetch the module returned a status code of: {}",
code
)));
}
tmp_gz_file
@@ -233,10 +270,15 @@ fn download_module(instance: &mut Instance, store_path: &str, module_url: &str,
Ok(())
}
pub fn fetch_module(instance: &mut Instance, module_name: &str) -> MizeResult<String> {
pub fn fetch_module(instance: &mut Mize, module_name: &str) -> MizeResult<String> {
let module_name_with_slashes = module_name.replace(".", "/");
if let Ok(module_path) = instance.get(format!("self/config/module_dir/{}", module_name_with_slashes))?.value_string() {
if let Ok(module_path) = instance
.get(format!(
"self/config/module_dir/{}",
module_name_with_slashes
))?
.value_string()
{
// in case a dir is configured, which holds the modules output
return Ok(module_path);
} else {
@@ -245,29 +287,41 @@ pub fn fetch_module(instance: &mut Instance, module_name: &str) -> MizeResult<St
let store_path = instance.get("self/config/store_path")?.value_string()?;
let (module_hash, module_selector) = get_module_hash(instance, module_name, ItemData::new())?;
let (module_hash, module_selector) =
get_module_hash(instance, module_name, ItemData::new())?;
if !PathBuf::from(format!("{}/modules/{}", store_path, module_hash.as_str())).exists() {
// download module if it does not exist
download_module(instance, store_path.as_str(), module_url.as_str(), module_hash.as_str(), module_name, module_selector.as_str())?;
download_module(
instance,
store_path.as_str(),
module_url.as_str(),
module_hash.as_str(),
module_name,
module_selector.as_str(),
)?;
}
return Ok(format!("{}/modules/{}", store_path, module_hash.as_str()));
}
}
pub fn load_module(instance: &mut Instance, module_name: &str, path: Option<String>) -> MizeResult<()> {
let module_path = if path.is_some() {
pub fn load_module(instance: &mut Mize, module_name: &str, path: Option<String>) -> MizeResult<()> {
let module_path = if path.is_some() {
format!("{}/lib/libmize_module_{}.so", path.unwrap(), module_name)
} else {
format!("{}/lib/libmize_module_{}.so", fetch_module(instance, module_name)?, module_name)
} else {
format!(
"{}/lib/libmize_module_{}.so",
fetch_module(instance, module_name)?,
module_name
)
};
let lib = unsafe { libloading::Library::new(module_path)? };
let func: libloading::Symbol<unsafe extern "C" fn(&mut Box<dyn Module + Send + Sync>, Instance) -> ()> = unsafe { lib.get(format!("get_mize_module_{}", module_name).as_bytes())? };
let func: libloading::Symbol<
unsafe extern "C" fn(&mut Box<dyn Module + Send + Sync>, Mize) -> (),
> = unsafe { lib.get(format!("get_mize_module_{}", module_name).as_bytes())? };
let mut module: Box<dyn Module + Send + Sync> = Box::new(EmptyModule {});
@@ -289,7 +343,6 @@ pub fn load_module(instance: &mut Instance, module_name: &str, path: Option<Stri
}
pub fn config_from_cli_args(matches: &ArgMatches) -> MizeResult<ItemData> {
let mut config = ItemData::new();
if let Some(config_file_path) = matches.get_one::<String>("config-file") {
@@ -305,9 +358,7 @@ pub fn config_from_cli_args(matches: &ArgMatches) -> MizeResult<ItemData> {
return Ok(config);
}
pub fn config_from_file(file_path: String) -> MizeResult<ItemData> {
let toml_string = fs::read_to_string(&file_path)
.mize_result_msg(format!("Could not read file {} as mize config", &file_path))?;
@@ -315,7 +366,3 @@ pub fn config_from_file(file_path: String) -> MizeResult<ItemData> {
return Ok(item_data);
}

View File

@@ -1,15 +1,15 @@
use ciborium::Value as CborValue;
use flume::{unbounded, Receiver, Sender};
use std::fs;
use std::path::{Path, PathBuf};
use tokio::net::{UnixListener as TokioUnixListener, UnixStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt, Interest};
use tokio::net::unix::{OwnedReadHalf, OwnedWriteHalf};
use tokio::io::{Interest, AsyncReadExt, AsyncWriteExt};
use flume::{Receiver, Sender, unbounded};
use ciborium::Value as CborValue;
use tracing::{info, warn, debug};
use tokio::net::{UnixListener as TokioUnixListener, UnixStream};
use tracing::{debug, info, warn};
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::instance::connection::{ConnListener, Connection};
use crate::instance::{self, Instance};
use crate::error::{MizeError, MizeResult, IntoMizeResult};
use crate::instance::{self, Mize};
use crate::proto::{self, MizeMessage};
pub struct UnixListener {
@@ -18,19 +18,30 @@ pub struct UnixListener {
impl UnixListener {
pub fn new(store_path: PathBuf) -> MizeResult<UnixListener> {
Ok(UnixListener { sock_path: store_path.join("sock").to_owned() })
Ok(UnixListener {
sock_path: store_path.join("sock").to_owned(),
})
}
}
pub fn connect(instance: &mut Mize, store_path: PathBuf) -> MizeResult<()> {
let conn_id = instance.spawn_async_blocking(
"unix_connection",
connect_async(instance.clone(), store_path),
)?;
pub fn connect(instance: &mut Instance, store_path: PathBuf) -> MizeResult<()> {
let conn_id = instance.spawn_async_blocking("unix_connection", connect_async(instance.clone(), store_path) )?;
let ns_of_peer_str = instance.get(format!("inst/con_by_id/{}/peer/0/config/namespace", conn_id))?.value_string()?;
let ns_of_peer_str = instance
.get(format!(
"inst/con_by_id/{}/peer/0/config/namespace",
conn_id
))?
.value_string()?;
let ns_of_peer = instance.namespace_from_string(ns_of_peer_str)?;
info!("connect_async ... ns_of_peer: {}", ns_of_peer.clone().as_string());
info!(
"connect_async ... ns_of_peer: {}",
ns_of_peer.clone().as_string()
);
instance.connection_set_namespace(conn_id, ns_of_peer.clone());
instance.set_namespace(ns_of_peer);
@@ -38,15 +49,13 @@ pub fn connect(instance: &mut Instance, store_path: PathBuf) -> MizeResult<()> {
Ok(())
}
async fn connect_async(mut instance: Instance, store_path: PathBuf) -> MizeResult<u64> {
async fn connect_async(mut instance: Mize, store_path: PathBuf) -> MizeResult<u64> {
let mut stream = UnixStream::connect(store_path.join("sock")).await?;
let (unix_read, unix_write) = stream.into_split();
let (send_tx, send_rx) = unbounded::<MizeMessage>();
let conn_id = instance.new_connection(send_tx)?;
let conn_id = instance.new_connection(send_tx)?;
let cloned_instance = instance.clone();
instance.spawn("incomming", move || {
@@ -58,7 +67,6 @@ async fn connect_async(mut instance: Instance, store_path: PathBuf) -> MizeResul
Ok(())
});
let outgoing_cloned_instance = instance.clone();
instance.spawn("outgoing", move || {
let result = unix_outgoing(unix_write, send_rx, outgoing_cloned_instance, conn_id);
@@ -72,31 +80,32 @@ async fn connect_async(mut instance: Instance, store_path: PathBuf) -> MizeResul
return Ok(conn_id);
}
impl ConnListener for UnixListener {
fn listen(self, mut instance: Instance) -> MizeResult<()> {
fn listen(self, mut instance: Mize) -> MizeResult<()> {
instance.spawn_async("unix listen async", unix_listen(self, instance.clone()));
Ok(())
}
}
async fn unix_listen(listener: UnixListener, mut instance: Instance) -> MizeResult<()> {
async fn unix_listen(listener: UnixListener, mut instance: Mize) -> MizeResult<()> {
// remove the file at sock_path if it already exists
fs::remove_file(&listener.sock_path);
let listener = TokioUnixListener::bind(&listener.sock_path)
.mize_result_msg(format!("Could not bind to unix socket at '{}'", listener.sock_path.display()))?;
let listener = TokioUnixListener::bind(&listener.sock_path).mize_result_msg(format!(
"Could not bind to unix socket at '{}'",
listener.sock_path.display()
))?;
loop {
let (mut unix_sock, addr) = listener.accept().await
let (mut unix_sock, addr) = listener
.accept()
.await
.mize_result_msg("Error while accepting Unix sock connection")?;
info!("new connection");
let (send_tx, send_rx) = unbounded::<MizeMessage>();
let (unix_read, unix_write) = unix_sock.into_split();
let conn_id = instance.new_connection(send_tx)?;
let cloned_instance = instance.clone();
instance.spawn("incomming", move || {
@@ -120,21 +129,35 @@ async fn unix_listen(listener: UnixListener, mut instance: Instance) -> MizeResu
}
}
fn unix_outgoing(mut unix_write: OwnedWriteHalf, send_rx: Receiver<MizeMessage>, mut instance: Instance, conn_id: u64) -> MizeResult<()> {
fn unix_outgoing(
mut unix_write: OwnedWriteHalf,
send_rx: Receiver<MizeMessage>,
mut instance: Mize,
conn_id: u64,
) -> MizeResult<()> {
for msg in send_rx {
debug!("unix outgoing got msg: {}", msg);
let adapter = MyCiboriumWriter { inner: &mut unix_write, instance: &mut instance };
let adapter = MyCiboriumWriter {
inner: &mut unix_write,
instance: &mut instance,
};
let value = msg.value();
ciborium::into_writer(&value, adapter)?
}
Ok(())
}
fn unix_incomming(mut unix_read: OwnedReadHalf, mut instance: Instance, conn_id: u64) -> MizeResult<()> {
fn unix_incomming(
mut unix_read: OwnedReadHalf,
mut instance: Mize,
conn_id: u64,
) -> MizeResult<()> {
loop {
//println!("unix incoming loop...");
let adapter = MyCiboriumReader { inner: &mut unix_read, instance: &mut instance };
let adapter = MyCiboriumReader {
inner: &mut unix_read,
instance: &mut instance,
};
let value: CborValue = ciborium::from_reader(adapter)?;
if let CborValue::Integer(_) = value {
break;
@@ -146,10 +169,9 @@ fn unix_incomming(mut unix_read: OwnedReadHalf, mut instance: Instance, conn_id:
Ok(())
}
struct MyCiboriumWriter<'a> {
inner: &'a mut OwnedWriteHalf,
instance: &'a mut Instance,
instance: &'a mut Mize,
}
impl<'a> ciborium_io::Write for MyCiboriumWriter<'a> {
@@ -172,7 +194,7 @@ impl<'a> ciborium_io::Write for MyCiboriumWriter<'a> {
struct MyCiboriumReader<'a> {
inner: &'a mut OwnedReadHalf,
instance: &'a mut Instance,
instance: &'a mut Mize,
}
async fn test(test: &mut OwnedReadHalf, buf: &mut [u8]) {
@@ -204,9 +226,8 @@ impl<'a> ciborium_io::Read for MyCiboriumReader<'a> {
// if we read 0 bytes, that means the reader stream closed and we should terminate the
// connection
//if num_read == 0 {
//return Err(MizeError::new().msg("ReceiverStream closed"));
//return Err(MizeError::new().msg("ReceiverStream closed"));
//}
Ok(())
}
}