ppc login works in mme main

This commit is contained in:
Sebastian Moser
2026-11-01 14:49:38 +01:00
parent 66b8713e3a
commit 6eedb1826a
68 changed files with 4123 additions and 1467 deletions

View File

@@ -59,13 +59,13 @@ impl ConfigOptId {
opt.fun = Some(fun);
self.clone()
}
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(self, name: &str, fun: F) -> ConfigOptId {
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(self, name: &str, signature: &str, fun: F) -> ConfigOptId {
let mize = get_global_mize().unwrap();
let mut cur_part = self.id.clone();
let id = cur_part.join(name).unwrap();
// in generate mode: record method metadata, skip normal registration
if mize.is_generate_mode().unwrap_or(false) {
mize.record_method(name, id.clone(), "method").ok();
mize.record_method(name, id.clone(), "method", signature).ok();
return self.clone();
}
let mut opts = mize.config_opts.lock().unwrap();
@@ -118,13 +118,13 @@ pub fn opt(name: &str) -> crate::config::ConfigOptId {
ConfigOptId { id }
}
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(name: &str, fun: F) -> ConfigOptId {
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(name: &str, signature: &str, fun: F) -> ConfigOptId {
let mize = get_global_mize().unwrap();
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
let id = cur_part.join(name).unwrap();
// in generate mode: record method metadata, skip normal registration
if mize.is_generate_mode().unwrap_or(false) {
mize.record_method(name, id.clone(), "method").ok();
mize.record_method(name, id.clone(), "method", signature).ok();
return ConfigOptId { id };
}
let mut opts = mize.config_opts.lock().unwrap();
@@ -146,7 +146,7 @@ pub fn effect<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(n
let id = cur_part.join(name).unwrap();
// in generate mode: record effect metadata, skip normal registration
if mize.is_generate_mode().unwrap_or(false) {
mize.record_method(name, id.clone(), "effect").ok();
mize.record_method(name, id.clone(), "effect", "").ok();
return ConfigOptId { id };
}
let mut opts = mize.config_opts.lock().unwrap();
@@ -168,7 +168,7 @@ pub fn thread<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(n
let id = cur_part.join(name).unwrap();
// in generate mode: record thread metadata, skip normal registration
if mize.is_generate_mode().unwrap_or(false) {
mize.record_method(name, id.clone(), "thread").ok();
mize.record_method(name, id.clone(), "thread", "").ok();
return ConfigOptId { id };
}
let mut opts = mize.config_opts.lock().unwrap();
@@ -199,11 +199,15 @@ pub mod c_api {
super::opt(&string)
}
}
pub extern "C" fn method(name: *const c_char, c_fun: CFun) -> ConfigOptId {
pub extern "C" fn method(name: *const c_char, signature: *const c_char, c_fun: CFun) -> ConfigOptId {
unsafe {
let c_str = CStr::from_ptr(name);
let string = c_str.to_string_lossy();
super::method(&string, move |args| {
let name_str = CStr::from_ptr(name).to_string_lossy();
let sig_str = if signature.is_null() {
String::new()
} else {
CStr::from_ptr(signature).to_string_lossy().into_owned()
};
super::method(&name_str, &sig_str, move |args| {
let raw_ptr = Box::into_raw(Box::new(args));
let ret_ptr = c_fun(raw_ptr);
let data = *Box::from_raw(ret_ptr);

View File

@@ -9,7 +9,7 @@ use std::fmt::Debug;
use std::fmt::Display;
use std::io;
use std::string::FromUtf8Error;
use tracing::{debug, error, info, trace, warn};
use crate::prelude::*;
//use crate::proto::MizeMessage;

View File

@@ -9,7 +9,6 @@ use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, RwLock};
use std::{thread, vec};
use tracing::{debug, info, trace};
use crate::set_global_mize;
use crate::config::{ConfigOpt, ConfigOptId, MizeFun};
@@ -24,6 +23,7 @@ use crate::memstore::MemStore;
use crate::mize_err;
use crate::proto::MizeMessage;
use crate::error::IntoMizeResult;
use crate::prelude::*;
use self::connection::{ConnListener, Connection};
use self::updater::handle_operation;
@@ -47,7 +47,7 @@ mod tests;
static MSG_CHANNEL_SIZE: usize = 200;
static BUILD_TIME_CONFIG: &str = include_str!(std::env!("MIZE_BUILD_CONFIG"));
static BUILD_TIME_CONFIG: &str = std::env!("MIZE_BUILD_CONFIG");
/// The Instance type is the heart of the mize system
#[derive(Clone)]
@@ -121,6 +121,35 @@ pub struct MethodMetadata {
pub name: String,
pub id: MizeId,
pub kind: String, // "method", "effect", "thread"
/// Raw signature string, e.g. `"String -> ()"` or `"Command, Func -> ()"`.
pub signature: String,
/// Parsed argument type names (left of `->`).
pub arg_types: Vec<String>,
/// Parsed return type name (right of `->`). Empty means unspecified / ItemData.
pub return_type: String,
}
/// Parse a method signature like `"String -> ()"` or `"Command, Func -> ()"`.
/// Returns `(arg_types, return_type)` where `return_type` is empty if no `->` was given.
pub fn parse_method_signature(signature: &str) -> (Vec<String>, String) {
let signature = signature.trim();
if signature.is_empty() {
return (Vec::new(), String::new());
}
let (args_part, ret_part) = match signature.split_once("->") {
Some((a, r)) => (a.trim(), r.trim().to_string()),
None => (signature, String::new()),
};
let arg_types = if args_part.is_empty() {
Vec::new()
} else {
args_part
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect()
};
(arg_types, ret_part)
}
#[derive(Clone, Debug)]
@@ -129,6 +158,10 @@ pub struct NativeMetadata {
pub type_name: String,
pub associated: Vec<String>,
pub methods: Vec<String>,
/// Signature strings parallel to `associated`.
pub associated_sigs: Vec<String>,
/// Signature strings parallel to `methods`.
pub method_sigs: Vec<String>,
}
pub struct InstanceRef {
@@ -146,8 +179,8 @@ impl PartRef {
}
impl MizePart for PartRef {
fn id(&self) -> MizeId {
self.id.clone()
fn id(&self) -> MizeResult<MizeId> {
Ok(self.id.clone())
}
}
@@ -160,11 +193,15 @@ pub struct InstanceAsync {
}
pub trait MizePart {
fn id(&self) -> MizeId;
fn id(&self) -> MizeResult<MizeId>;
}
impl Mize {
pub fn empty() -> MizeResult<Mize> {
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build()?;
let guard = runtime.enter();
std::mem::forget(guard);
let id_pool = Arc::new(Mutex::new(VecStringPool::default()));
let namespace_pool_raw = StringPool::default();
let connections = Arc::new(Mutex::new(Vec::new()));
@@ -206,9 +243,7 @@ impl Mize {
part_metadata: Arc::new(Mutex::new(HashMap::new())),
#[cfg(feature = "async")]
runtime: Arc::new(Mutex::new(
Runtime::new().mres_msg("Could not create async runtime")?,
)),
runtime: Arc::new(Mutex::new(runtime)),
};
#[cfg(feature = "target-os")]
@@ -244,7 +279,7 @@ impl Mize {
console_log!("before loading build time config");
// load the config from build time
let config = ItemData::from_toml(BUILD_TIME_CONFIG)?;
let config = ItemData::from_json(BUILD_TIME_CONFIG.to_owned())?;
instance.set_blocking("0", config);
#[cfg(feature = "target-wasm ")]
@@ -546,7 +581,7 @@ impl Mize {
}
/// Record a method/effect/thread declaration while in generate mode.
pub fn record_method(&self, name: &str, id: MizeId, kind: &str) -> MizeResult<()> {
pub fn record_method(&self, name: &str, id: MizeId, kind: &str, signature: &str) -> MizeResult<()> {
let cur_part = self.cur_eval_part.lock()?.clone()
.ok_or_else(|| mize_err!("no cur_eval_part set"))?;
let mut metadata_map = self.part_metadata.lock()?;
@@ -554,10 +589,14 @@ impl Mize {
part_name: cur_part.dot(),
..Default::default()
});
let (arg_types, return_type) = parse_method_signature(signature);
let m = MethodMetadata {
name: name.to_string(),
id,
kind: kind.to_string(),
signature: signature.to_string(),
arg_types,
return_type,
};
match kind {
"effect" => metadata.effects.push(m),
@@ -568,7 +607,15 @@ impl Mize {
}
/// Record a native type inclusion while in generate mode.
pub fn record_native(&self, name: &str, type_name: &str, associated: Vec<String>, methods: Vec<String>) -> MizeResult<()> {
pub fn record_native(
&self,
name: &str,
type_name: &str,
associated: Vec<String>,
methods: Vec<String>,
associated_sigs: Vec<String>,
method_sigs: Vec<String>,
) -> MizeResult<()> {
let cur_part = self.cur_eval_part.lock()?.clone()
.ok_or_else(|| mize_err!("no cur_eval_part set"))?;
let mut metadata_map = self.part_metadata.lock()?;
@@ -581,6 +628,8 @@ impl Mize {
type_name: type_name.to_string(),
associated,
methods,
associated_sigs,
method_sigs,
});
Ok(())
}
@@ -805,12 +854,15 @@ impl Mize {
) -> MizeResult<()> {
let mut threads_inner = self.threads.lock()?;
let mut next_thread_id = self.next_thread_id.lock()?;
let tokio_handle = tokio::runtime::Handle::current();
let my_thread_id_no_mutex_guard = *next_thread_id;
let _thread_mutex = self.threads.clone();
let name_to_move = name.to_owned();
let to_spawn = move || -> () {
debug!("spawning thread: {}", name_to_move);
let guard = tokio_handle.enter();
std::mem::forget(guard);
let _my_thread_id = my_thread_id_no_mutex_guard;
let res = func();
@@ -883,8 +935,8 @@ impl Mize {
let mut next_thread_id = self.next_thread_id.lock()?;
threads_inner.push((*next_thread_id, name.to_owned(), None));
let runtime_inner = self.runtime.lock().unwrap();
runtime_inner.spawn(func);
let runtime = tokio::runtime::Handle::current();
runtime.spawn(func);
*next_thread_id += 1;
@@ -893,9 +945,7 @@ impl Mize {
#[cfg(feature = "async")]
pub fn async_get_handle(&self) -> Handle {
let runtime_inner = self.runtime.lock().unwrap();
let handle = runtime_inner.handle().to_owned();
handle
tokio::runtime::Handle::current()
}
#[cfg(feature = "async")]
@@ -916,16 +966,13 @@ impl Mize {
.expect("mutex lock failed in spawn_async_blocking");
threads_inner.push((*next_thread_id, name.to_owned(), None));
let runtime_inner = self.runtime.lock().unwrap();
let handle = runtime_inner.handle().to_owned();
let runtime = tokio::runtime::Handle::current();
*next_thread_id += 1;
drop(runtime_inner);
drop(threads_inner);
drop(next_thread_id);
handle.enter();
let result = handle.block_on(func);
let result = runtime.block_on(func);
return result;
}
@@ -958,24 +1005,29 @@ impl Mize {
let mut opt = config_opts
.get_mut(&id)
.ok_or_else(|| mize_err!("Config opt for {name} not in config_opts"))?;
.ok_or_else(|| mize_err!("Config opt for {id} not in config_opts"))?;
if let Some(val) = opt.val.clone() {
return Ok(val);
}
// in case it is not cached run the fun if it exists
if let Some(fun) = &opt.fun {
if opt.fun.is_some() {
let fun = opt.fun.take().unwrap();
drop(config_opts);
let res = fun()?;
let mut config_opts = self.config_opts.lock().unwrap();
let mut opt = config_opts.get_mut(&id).unwrap();
opt.fun = Some(fun);
opt.val = Some(res.clone());
return Ok(res);
}
Err(mize_err!("ConfigOpt {name} has no fun and no cached value"))
Err(mize_err!("ConfigOpt {id} has no fun and no cached value"))
}
pub fn dyn_call(&mut self, part_id: MizeId, method: &str, args: ItemData) -> MizeResult<ItemData> {
debug!("dyn call {}.{} with args: {}", part_id, method, args);
debug!("dyn call {}/{} with args: {}", part_id, method, args);
let mut fun_values = self.fun_values.lock()?;
let id = part_id.clone().join(method)?;
@@ -985,7 +1037,9 @@ impl Mize {
let calling_part = self.clone().cur_eval_part()?;
self.clone().set_cur_eval_part(Some(part_id));
println!("before call");
let res = fun(args);
println!("after call");
self.clone().set_cur_eval_part(calling_part);
let mut fun_values = self.fun_values.lock()?;
fun_values.insert(id, fun);

View File

@@ -2,13 +2,13 @@ use core::fmt;
use flume::Sender;
use std::rc::Rc;
use std::sync::Arc;
use tracing::trace;
use crate::error::MizeResult;
use crate::id::MizeId;
use crate::instance::connection::Connection;
use crate::item::Item;
use crate::proto::MizeMessage;
use crate::prelude::*;
use super::Mize;

View File

@@ -1,11 +1,11 @@
use flume::Receiver;
use std::borrow::BorrowMut;
use std::sync::Arc;
use tracing::{error, trace, warn};
use crate::error::{MizeError, MizeResult, MizeResultTrait};
use crate::id::MizeId;
use crate::mize_err;
use crate::prelude::*;
use crate::proto::{MessageCmd, MizeMessage};
use crate::{instance::Mize, item::ItemData};

View File

@@ -1,8 +1,9 @@
use crate::{config, get_global_mize};
use crate::config::{ConfigOpt, FromItemData, MizeFun};
use ciborium::into_writer;
use ciborium::from_reader;
use colored::Colorize;
use serde_json::from_reader;
use serde::de::DeserializeOwned;
use core::fmt;
use serde::Deserialize;
use serde::Serialize;
@@ -13,7 +14,8 @@ use std::sync::MutexGuard;
use std::{boxed, io};
use std::fmt::Display;
use std::i128;
use tracing::{debug, instrument, trace, warn};
use crate::tracing::instrument;
use crate::prelude::*;
use crate::error::{IntoMizeResult, MizeError, MizeErrorWhichImplementsError, MizeResult};
use crate::id::MizeId;
@@ -256,7 +258,12 @@ impl ItemData {
let fun_num = self.get_path("_fun_num")?.value_u32()?;
let fun_id = mize.clone().id_new_dots("mize.fun")?.join(format!("{fun_num}").as_str())?;
let fun = fun_values.remove(&fun_id).ok_or(mize_err!("fun with id {fun_id} not in fun_values"))?;
drop(fun_values);
let res = fun(args)?;
let mut fun_values = mize.fun_values.lock()?;
fun_values.insert(fun_id, fun);
return Ok(res);
}
@@ -406,6 +413,13 @@ impl ItemData {
return None;
}
pub fn deserialize<T: Serialize + DeserializeOwned>(&self) -> MizeResult<T> {
let mut buffer = Vec::new();
into_writer(&self, &mut buffer)?;
let cbor_val: T = from_reader(buffer.as_slice())?;
Ok(cbor_val)
}
/// Get an immutable reference to the native value stored in this ItemData.
///
/// If the ItemData has a `_native` field (stored via `from_native()`), returns a guard
@@ -467,6 +481,7 @@ impl ItemData {
///
/// Otherwise, constructs the value via `T::from_itemdata(self)`, stores it in the
/// registry, and returns a guard to it.
/// i hate rust. (as you can't have a generic FromItemData impl and then more specific ones.)
pub fn native_from<T: FromItemData + Any + Send + Sync + 'static>(&self) -> MizeResult<NativeRefGuard<T>> {
// Fast path: the registry already holds a T for this ItemData
if let Some(id) = self.try_get_native_id() {

View File

@@ -9,7 +9,7 @@ use std::fmt::format;
macro_rules! out {
($($arg:tt)*) => {
// format_args! handles string interpolation safely at compile time
if let Err(e) = $crate::write_to_mize_stdout(format_args!($($arg)*)) {
if let Err(e) = $crate::write_to_mize_stdout(format_args!("{}\n", format_args!($($arg)*))) {
// Choose your error handling behavior here (panic, print to stderr, or ignore)
eprintln!("out! macro failed to write!!");
}
@@ -17,7 +17,7 @@ macro_rules! out {
}
pub fn write_to_mize_stdout(args: std::fmt::Arguments) -> MizeResult<()> {
println!("{}", args);
print!("{}", args);
Ok(())
}
@@ -84,8 +84,11 @@ pub mod prelude {
pub use config::*;
pub use api::*;
pub use mize_macros::*;
pub use crate::tracing::{trace, warn, debug, info, error};
}
pub use flume;
use tokio::runtime::Builder;
use tokio::runtime::Runtime;
pub use tracing;
@@ -108,13 +111,15 @@ pub use error::MizeError;
pub use error::MizeResult;
pub use instance::Mize;
pub use instance::{
MizePart, PartMetadata, OptMetadata, MethodMetadata, NativeMetadata,
MizePart, PartMetadata, OptMetadata, MethodMetadata, NativeMetadata, parse_method_signature,
};
pub use mize_macros::*;
use std::path::PathBuf;
use std::sync::{Arc, Mutex, OnceLock};
use crate::platform::os;
/// Global Mize instance storage.
/// This is set once when the Mize instance is created and can be accessed from anywhere.
pub static GLOBAL_MIZE: OnceLock<Arc<Mutex<Mize>>> = OnceLock::new();
@@ -144,9 +149,32 @@ pub fn set_global_mize(mize: Mize) -> MizeResult<()> {
/// C API function to set the global Mize instance from a dynamically loaded part.
/// This is a hack to allow Rust parts loaded as .so files to access the global Mize instance.
// i hate rust.
#[unsafe(no_mangle)]
pub extern "C" fn mize_rust_hack_set_global(mize: Arc<Mutex<Mize>>) {
pub extern "C" fn mize_rust_hack_set_global(mize: Arc<Mutex<Mize>>, dispatch_ptr: *const std::ffi::c_void) {
// and also set the tokio runtime
//let mize_locked = mize.lock().unwrap();
//let rt = mize_locked.runtime.lock().unwrap();
//rt.enter();
//drop(rt);
//drop(mize_locked);
let rt = Builder::new_multi_thread().enable_all().build().unwrap();
let guard = rt.enter();
std::mem::forget(guard);
use crate::tracing::Dispatch;
let _ = GLOBAL_MIZE.set(mize);
//and also init tracing
unsafe {
/// i hate rust.
let dispatch = &*(dispatch_ptr as *const Dispatch);
if let Err(e) = tracing::dispatcher::set_global_default(dispatch.clone()) {
println!("failed to set tracing dispatcher: {e}");
}
tracing::callsite::rebuild_interest_cache();
}
}
/// Resolve an executable name to its full path in the nixpkgs store.

View File

@@ -4,7 +4,7 @@ use std::collections::binary_heap::Iter;
use std::collections::HashMap;
use std::iter::Map;
use std::sync::{Arc, Mutex};
use tracing::{instrument, trace};
use crate::tracing::instrument;
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::id::MizeId;
@@ -13,6 +13,7 @@ use crate::instance::Mize;
use crate::item::get_raw_from_cbor;
use crate::item::{Item, ItemData};
use crate::mize_err;
use crate::prelude::*;
#[derive(Clone, Debug)]
pub struct MemStore {

View File

@@ -4,7 +4,6 @@ use std::fs::OpenOptions;
use std::io::Write;
use std::path::{Path, PathBuf};
use sysinfo::{Pid, ProcessRefreshKind, RefreshKind, System};
use tracing::debug;
use crate::id::MizeId;
use crate::item::{Item, ItemData};
@@ -15,6 +14,9 @@ use crate::item::get_raw_from_cbor;
use crate::item::IntoItemData;
use crate::memstore::MemStore;
use crate::{instance::store::Store, mize_err};
use crate::prelude::*;
#[cfg(target_family = "unix")]
use tokio::net::UnixStream;
#[derive(Clone, Debug)]
@@ -72,6 +74,7 @@ impl FileStore {
}
}
#[cfg(target_family = "unix")]
async fn try_connect_to_sock(store_path: String) -> MizeResult<()> {
match UnixStream::connect(PathBuf::from(store_path).join("sock")).await {
Err(_) => Err(mize_err!("")),
@@ -79,6 +82,21 @@ async fn try_connect_to_sock(store_path: String) -> MizeResult<()> {
}
}
#[cfg(target_family = "windows")]
async fn try_connect_to_sock(store_path: String) -> MizeResult<()> {
use tokio::net::windows::named_pipe::{ClientOptions};
let pipe_name = format!(
"\\.\\pipe\\mize_{}",
store_path.replace('\\', "_").replace('/', "_").replace(':', "_")
);
// ClientOptions::new().open() is synchronous, not async
// So we just try to open and immediately close it
match ClientOptions::new().open(&pipe_name) {
Err(_) => Err(mize_err!("")),
Ok(_) => Ok(()),
}
}
impl Store for FileStore {
fn new_id(&self) -> MizeResult<String> {
let mut next_id: u64 =
@@ -191,6 +209,7 @@ impl Store for FileStore {
}
}
#[cfg(target_family = "unix")]
fn valid_pid_file(path: &Path) -> MizeResult<Option<u32>> {
let pid_file_path = path.join("pid");

View File

@@ -12,8 +12,7 @@ use std::sync::Arc;
use std::sync::Mutex;
use tokio::sync::mpsc;
use tracing::level_filters::LevelFilter;
use tracing::Event;
use tracing::{debug, error, info, trace, warn};
use tracing::{Dispatch, Event};
use tracing::{field::Visit, Id, Subscriber};
use tracing::{span_enabled, Instrument, Level};
use tracing_core::Field;
@@ -29,10 +28,65 @@ use crate::id::MizeId;
use crate::item::ItemData;
use crate::MizeError;
use crate::MizeResult;
use crate::prelude::*;
static DEFAULT_LOG_LEVEL: LevelFilter = LevelFilter::WARN;
pub fn init_logger(cli_matches: &ArgMatches) {
/*
#[macro_export]
macro_rules! trace {
($($arg:tt)*) => {
// format_args! handles string interpolation safely at compile time
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::yellow("TRACE"), format_args!($($arg)*))) {
// Choose your error handling behavior here (panic, print to stderr, or ignore)
eprintln!("out! macro failed to write!!");
}
};
}
#[macro_export]
macro_rules! debug {
($($arg:tt)*) => {
// format_args! handles string interpolation safely at compile time
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::green("DEBUG"), format_args!($($arg)*))) {
// Choose your error handling behavior here (panic, print to stderr, or ignore)
eprintln!("out! macro failed to write!!");
}
};
}
#[macro_export]
macro_rules! info {
($($arg:tt)*) => {
// format_args! handles string interpolation safely at compile time
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::blue("INFO"), format_args!($($arg)*))) {
// Choose your error handling behavior here (panic, print to stderr, or ignore)
eprintln!("out! macro failed to write!!");
}
};
}
#[macro_export]
macro_rules! warn {
($($arg:tt)*) => {
// format_args! handles string interpolation safely at compile time
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::truecolor("WARN", 245, 164, 66), format_args!($($arg)*))) {
// Choose your error handling behavior here (panic, print to stderr, or ignore)
eprintln!("out! macro failed to write!!");
}
};
}
#[macro_export]
macro_rules! error {
($($arg:tt)*) => {
// format_args! handles string interpolation safely at compile time
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::red("ERROR"), format_args!($($arg)*))) {
// Choose your error handling behavior here (panic, print to stderr, or ignore)
eprintln!("out! macro failed to write!!");
}
};
}
*/
pub fn init_logger(cli_matches: Option<&ArgMatches>) {
trace!("init_logger called");
// to save log messages, before the logger is setup
let mut log_messages: Vec<(Level, String)> = Vec::new();
@@ -96,67 +150,69 @@ pub fn init_logger(cli_matches: &ArgMatches) {
log_messages.append(&mut val_mize_log.1);
// check -vvvvv flags
let v_flag_count = cli_matches.get_count("verbose");
if v_flag_count > 0 {
let default_log_level_as_num = match DEFAULT_LOG_LEVEL {
LevelFilter::OFF => 0,
LevelFilter::ERROR => 1,
LevelFilter::WARN => 2,
LevelFilter::INFO => 3,
LevelFilter::DEBUG => 4,
LevelFilter::TRACE => 5,
};
let new_log_level_num = default_log_level_as_num + v_flag_count;
log_level = match new_log_level_num {
0 => LevelFilter::OFF,
1 => LevelFilter::ERROR,
2 => LevelFilter::WARN,
3 => LevelFilter::INFO,
4 => LevelFilter::DEBUG,
5 => LevelFilter::TRACE,
_ => {
log_messages.push((
Level::TRACE,
format!(
"the number of verbose (-v) flags passed ({}) exeeds the maximumg log_level",
v_flag_count
),
));
LevelFilter::TRACE
}
};
log_messages.push((
Level::TRACE,
format!("set log level from the verbose flags to {}", log_level),
));
}
if let Some(cli_matches) = cli_matches {
let v_flag_count = cli_matches.get_count("verbose");
if v_flag_count > 0 {
let default_log_level_as_num = match DEFAULT_LOG_LEVEL {
LevelFilter::OFF => 0,
LevelFilter::ERROR => 1,
LevelFilter::WARN => 2,
LevelFilter::INFO => 3,
LevelFilter::DEBUG => 4,
LevelFilter::TRACE => 5,
};
let new_log_level_num = default_log_level_as_num + v_flag_count;
log_level = match new_log_level_num {
0 => LevelFilter::OFF,
1 => LevelFilter::ERROR,
2 => LevelFilter::WARN,
3 => LevelFilter::INFO,
4 => LevelFilter::DEBUG,
5 => LevelFilter::TRACE,
_ => {
log_messages.push((
Level::TRACE,
format!(
"the number of verbose (-v) flags passed ({}) exeeds the maximumg log_level",
v_flag_count
),
));
LevelFilter::TRACE
}
};
log_messages.push((
Level::TRACE,
format!("set log level from the verbose flags to {}", log_level),
));
}
// check --log-level arg
if let Some(log_level_arg_string) = cli_matches.get_one::<String>("log-level") {
let log_level_from_arg = match log_level_arg_string.to_owned().to_lowercase().as_str() {
"none" => LevelFilter::OFF,
"trace" => LevelFilter::TRACE,
"debug" => LevelFilter::DEBUG,
"info" => LevelFilter::INFO,
"warn" => LevelFilter::WARN,
"error" => LevelFilter::ERROR,
_ => {
log_messages.push((Level::WARN, format!(
"The argument to --log-level \"{}\" is not a valid log-level. loglevel stays at: {}"
, log_level_arg_string
, log_level
)));
log_level
}
};
log_level = log_level_from_arg;
log_messages.push((
Level::TRACE,
format!(
"set log level from the --log-level arg to {}",
log_level_from_arg
),
));
// check --log-level arg
if let Some(log_level_arg_string) = cli_matches.get_one::<String>("log-level") {
let log_level_from_arg = match log_level_arg_string.to_owned().to_lowercase().as_str() {
"none" => LevelFilter::OFF,
"trace" => LevelFilter::TRACE,
"debug" => LevelFilter::DEBUG,
"info" => LevelFilter::INFO,
"warn" => LevelFilter::WARN,
"error" => LevelFilter::ERROR,
_ => {
log_messages.push((Level::WARN, format!(
"The argument to --log-level \"{}\" is not a valid log-level. loglevel stays at: {}"
, log_level_arg_string
, log_level
)));
log_level
}
};
log_level = log_level_from_arg;
log_messages.push((
Level::TRACE,
format!(
"set log level from the --log-level arg to {}",
log_level_from_arg
),
));
}
}
// actually set the log_level on the builder
@@ -181,13 +237,18 @@ pub fn init_logger(cli_matches: &ArgMatches) {
}
Ok(())
});
builder
let subscriber = builder
//.with_env_filter(my_env_filter)
.without_time()
.event_format(MyFormatter)
.fmt_fields(field_formatter)
.with_max_level(log_level)
.init();
.finish();
let dispatch = Dispatch::new(subscriber);
if let Err(e) = tracing::dispatcher::set_global_default(dispatch) {
println!("faild to set_global_default(dispatch): {e}");
}
// write out all log messages from log_messages
for (level, msg) in log_messages {

View File

@@ -1,5 +1,6 @@
use clap::ArgMatches;
use colored::Colorize;
use tracing::Dispatch;
use core::fmt;
use flate2::bufread::GzDecoder;
use sha2::{Digest, Sha256};
@@ -12,7 +13,6 @@ use std::path::PathBuf;
use std::time::UNIX_EPOCH;
use tar::Archive;
use tracing::Event;
use tracing::{debug, info, trace, warn};
use tracing::field::Visit;
use tracing::Level;
use tracing_core::Field;
@@ -25,12 +25,8 @@ use tracing_subscriber::registry::LookupSpan;
use std::sync::Arc;
use std::sync::Mutex;
use crate::GLOBAL_MIZE;
use crate::config::ConfigOpt;
use crate::error::{IntoMizeResult, MizeResult};
use crate::instance::Mize;
use crate::item::{data_from_string, IntoItemData, ItemData};
use crate::mize_err;
use crate::prelude::*;
use crate::item::data_from_string;
use self::fsstore::FileStore;
@@ -40,8 +36,14 @@ pub mod logging;
#[cfg(target_family = "unix")]
mod unix_socket;
#[cfg(target_family = "windows")]
mod windows_socket;
#[cfg(target_family = "unix")]
use crate::platform::os::unix_socket::UnixListener;
#[cfg(target_family = "windows")]
use crate::platform::os::windows_socket::WindowsListener as UnixListener;
//mod web;
pub fn os_instance_init(mize: &mut Mize) -> MizeResult<()> {
@@ -133,7 +135,10 @@ pub fn os_instance_init(mize: &mut Mize) -> MizeResult<()> {
#[cfg(target_family = "windows")]
{
error!("CONNECTING... would connect, but that is not implemented on windows yet");
info!("CONNECTING");
use crate::platform::os::windows_socket;
windows_socket::connect(mize, store_path.into())?;
return Ok(());
}
} else {
// else open it ourselves
@@ -149,7 +154,7 @@ pub fn os_instance_init(mize: &mut Mize) -> MizeResult<()> {
#[cfg(target_family = "windows")]
{
warn!("would add a Listener on a local socket, but that is not yet implemented for windows");
mize.add_conn_listener(UnixListener::new(path)?)?;
}
}
@@ -273,31 +278,33 @@ pub fn fetch_part(mize: &mut Mize, part_name: &str) -> MizeResult<String> {
fn get_part_path(mize: &mut Mize, part_name: &str, _path: Option<String>) -> MizeResult<String> {
let part_symbol_name = part_name.replace(".", "_");
// check if $name.src is set
if let Ok(itm) = mize.get_config(format!("{part_name}.src").as_str()) {
let part_src = itm.value_string().map_err(|e| e.msg(format!("opt {part_name}.src was not a string")))?;
// will only work for rust for now
let part_path = format!("{part_src}/target/debug/libmize_part_{part_name}.so");
let part_path = format!("{part_src}/target/debug/libmize_part_{part_symbol_name}.so");
return Ok(part_path);
}
// check if $name.out is set
if let Ok(itm) = mize.get_config(format!("{part_name}.out").as_str()) {
let part_out = itm.value_string().map_err(|e| e.msg(format!("opt {part_name}.out was not a string")))?;
let part_path = format!("{part_out}/lib/libmize_part_{part_name}.so");
let part_path = format!("{part_out}/lib/libmize_part_{part_symbol_name}.so");
return Ok(part_path);
}
// check if we find the part inside mize.src
if let Ok(itm) = mize.get_config("mize.src") {
let mize_src = itm.value_string().map_err(|e| e.msg("opt mize.src was not a string"))?;
let part_path = format!("{mize_src}/target/debug/libmize_part_{part_name}.so");
let part_path = format!("{mize_src}/target/debug/libmize_part_{part_symbol_name}.so");
return Ok(part_path);
}
// fetch the part from https://mize.works
let out_path = fetch_part(mize, part_name)?;
return Ok(format!("{out_path}/lib/libmize_part_{part_name}.so"));
return Ok(format!("{out_path}/lib/libmize_part_{part_symbol_name}.so"));
//Err(mize_err!("part {part_name} not found"))
}
@@ -308,16 +315,33 @@ pub fn load_part(mize: &mut Mize, part_name: &str, path: Option<String>) -> Mize
let lib = unsafe { libloading::Library::new(part_path)? };
unsafe {
if let Ok(rust_hack_func) = lib.get::<libloading::Symbol<unsafe extern "C" fn(Arc<Mutex<Mize>>)>>("mize_rust_hack_set_global".as_bytes()) {
rust_hack_func(GLOBAL_MIZE.get().unwrap().clone())
if let Ok(rust_hack_func) = lib.get::<libloading::Symbol<unsafe extern "C" fn(Arc<Mutex<Mize>>, *const std::ffi::c_void)>>("mize_rust_hack_set_global".as_bytes()) {
tracing::dispatcher::get_default(|dispatch| {
rust_hack_func(GLOBAL_MIZE.get().unwrap().clone(), dispatch as *const Dispatch as *const std::ffi::c_void);
});
};
}
let part_symbol_name = part_name.replace(".", "_");
let func: libloading::Symbol<
unsafe extern "C" fn() -> MizeResult<()>,
> = unsafe { lib.get(format!("part_{}", part_name).as_bytes())? };
> = unsafe { lib.get(format!("part_{}", part_symbol_name).as_bytes())? };
mize.clone().set_cur_eval_part(Some(mize.clone().id_new_dots(part_name)?))?;
let part_id = mize.clone().id_new_dots(part_name)?;
{
let mut opts = mize.config_opts.lock()?;
opts.entry(part_id.clone()).or_insert_with(|| ConfigOpt {
name: part_name.to_owned(),
val: Some(ItemData::new()),
fun: None,
deps: Vec::new(),
});
}
mize.clone().set_cur_eval_part(Some(part_id))?;
unsafe { func()? };
mize.clone().set_cur_eval_part(None)?;

View File

@@ -5,12 +5,12 @@ use std::path::{Path, PathBuf};
use tokio::io::{AsyncReadExt, AsyncWriteExt, Interest};
use tokio::net::unix::{OwnedReadHalf, OwnedWriteHalf};
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, Mize};
use crate::proto::{self, MizeMessage};
use crate::prelude::*;
pub struct UnixListener {
sock_path: PathBuf,

View File

@@ -0,0 +1,224 @@
// This module is only compiled on Windows
// It provides the same functionality as unix_socket.rs but using Windows named pipes
use ciborium::Value as CborValue;
use flume::{unbounded, Receiver, Sender};
use std::path::PathBuf;
use std::sync::Arc;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
use tokio::sync::Mutex;
use tracing::{debug, info, warn};
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::instance::connection::{ConnListener, Connection};
use crate::instance::{self, Mize};
use crate::proto::{self, MizeMessage};
pub struct WindowsListener {
pipe_name: String,
}
impl WindowsListener {
pub fn new(store_path: PathBuf) -> MizeResult<WindowsListener> {
// On Windows, we use a named pipe with a specific format
// The format is \.\pipe\<name> for local pipes
// We'll use the store path hash or name to create a unique pipe name
let pipe_name = format!(
"\\.\\pipe\\mize_{}",
store_path.to_string_lossy().replace('\\', "_").replace('/', "_").replace(':', "_")
);
Ok(WindowsListener { pipe_name })
}
}
pub fn connect(instance: &mut Mize, store_path: PathBuf) -> MizeResult<()> {
let conn_id = instance.spawn_async_blocking(
"windows_connection",
connect_async(instance.clone(), store_path),
)?;
let ns_of_peer_str = instance
.get(format!(
"inst/con_by_id/{}/peer/self/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()
);
instance.connection_set_namespace(conn_id, ns_of_peer.clone());
instance.set_namespace(ns_of_peer);
Ok(())
}
async fn connect_async(mut instance: Mize, store_path: PathBuf) -> MizeResult<u64> {
let pipe_name = format!(
"\\.\\pipe\\mize_{}",
store_path.to_string_lossy().replace('\\', "_").replace('/', "_").replace(':', "_")
);
// Create the client synchronously
let client = ClientOptions::new().open(&pipe_name)?;
// Wrap the client in an Arc<Mutex> so it can be shared between incoming and outgoing tasks
let shared_client = Arc::new(Mutex::new(client));
let (send_tx, send_rx) = unbounded::<MizeMessage>();
let conn_id = instance.new_connection(send_tx)?;
let cloned_instance = instance.clone();
let incoming_client = shared_client.clone();
instance.spawn_background("incomming", move || {
let result = windows_incomming(incoming_client, cloned_instance, conn_id);
if let Err(err) = result {
warn!("Connection closing because of EOF: {:?}", err);
}
Ok(())
});
let outgoing_cloned_instance = instance.clone();
let outgoing_client = shared_client.clone();
instance.spawn_background("outgoing", move || {
let result = windows_outgoing(outgoing_client, send_rx, outgoing_cloned_instance, conn_id);
if let Err(err) = result {
warn!("Connection closing because of EOF: {:?}", err);
}
Ok(())
});
Ok(conn_id)
}
impl ConnListener for WindowsListener {
fn listen(self, mut instance: Mize) -> MizeResult<()> {
instance.spawn_async("windows listen async", windows_listen(self, instance.clone()));
Ok(())
}
}
async fn windows_listen(listener: WindowsListener, mut instance: Mize) -> MizeResult<()> {
// Create the first server instance
let mut server = ServerOptions::new()
.first_pipe_instance(true)
.create(&listener.pipe_name)?;
loop {
// Wait for a client to connect
server.connect().await.mres_msg("Error while accepting Windows named pipe connection")?;
info!("new connection");
let (send_tx, send_rx) = unbounded::<MizeMessage>();
let conn_id = instance.new_connection(send_tx)?;
// Take ownership of the current server (which is now connected)
let connected_server = server;
// Create a new server for the next connection
server = ServerOptions::new().create(&listener.pipe_name)?;
// Wrap the connected server in an Arc<Mutex> so it can be shared
let shared_server = Arc::new(Mutex::new(connected_server));
let cloned_instance = instance.clone();
let incoming_server = shared_server.clone();
instance.spawn_background("incomming", move || {
let result = windows_incomming(incoming_server, cloned_instance, conn_id);
if let Err(err) = result {
warn!("Connection closing because of EOF: {:?}", err);
}
Ok(())
});
let outgoing_cloned_instance = instance.clone();
let outgoing_server = shared_server.clone();
instance.spawn_background("outgoing", move || {
let result = windows_outgoing(outgoing_server, send_rx, outgoing_cloned_instance, conn_id);
if let Err(err) = result {
warn!("Connection closing because of EOF: {:?}", err);
}
Ok(())
});
}
}
fn windows_outgoing<W>(shared_pipe: Arc<Mutex<W>>, send_rx: Receiver<MizeMessage>, mut instance: Mize, conn_id: u64) -> MizeResult<()>
where
W: AsyncWriteExt + Unpin,
{
for msg in send_rx {
debug!("windows outgoing got msg: {}", msg);
let adapter = MyCiboriumWriter {
inner: &mut *shared_pipe.blocking_lock(),
instance: &mut instance,
};
let value = msg.value();
ciborium::into_writer(&value, adapter)?
}
Ok(())
}
pub fn windows_incomming<R>(shared_pipe: Arc<Mutex<R>>, mut instance: Mize, conn_id: u64) -> MizeResult<()>
where
R: AsyncReadExt + Unpin,
{
loop {
let adapter = MyCiboriumReader {
inner: &mut *shared_pipe.blocking_lock(),
instance: &mut instance,
};
let value: CborValue = ciborium::from_reader(adapter)?;
if let CborValue::Integer(_) = value {
break;
}
let msg = MizeMessage::new(value, conn_id);
debug!("windows incomming got msg: {}", msg);
instance.got_msg(msg);
}
Ok(())
}
struct MyCiboriumWriter<'a, W> {
inner: &'a mut W,
instance: &'a mut Mize,
}
impl<'a, W> ciborium_io::Write for MyCiboriumWriter<'a, W>
where
W: AsyncWriteExt + Unpin,
{
type Error = MizeError;
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
let runtime = self.instance.runtime.lock()?;
let _ = runtime.block_on(self.inner.write_all(data))?;
Ok(())
}
fn flush(&mut self) -> Result<(), Self::Error> {
let handle = self.instance.async_get_handle();
let _ = handle.block_on(self.inner.flush());
Ok(())
}
}
struct MyCiboriumReader<'a, R> {
inner: &'a mut R,
instance: &'a mut Mize,
}
impl<'a, R> ciborium_io::Read for MyCiboriumReader<'a, R>
where
R: AsyncReadExt + Unpin,
{
type Error = MizeError;
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
let handle = self.instance.async_get_handle();
let _ = handle.block_on(self.inner.read_exact(data))?;
Ok(())
}
}