before yet another repo moving stuff around

This commit is contained in:
Sebastian Moser
2026-02-15 14:05:16 +01:00
parent 7b6f177d14
commit 691e695659
16 changed files with 363 additions and 108 deletions

10
Cargo.lock generated
View File

@@ -1769,6 +1769,7 @@ dependencies = [
name = "mize"
version = "0.0.1"
dependencies = [
"async-trait",
"axum",
"axum-extra",
"axum-macros",
@@ -1785,6 +1786,7 @@ dependencies = [
"http_req",
"interner",
"libloading",
"mize_macros",
"nix",
"serde",
"serde-wasm-bindgen",
@@ -1806,6 +1808,14 @@ dependencies = [
"wee_alloc",
]
[[package]]
name = "mize_macros"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "multipart"
version = "0.18.0"

View File

@@ -4,4 +4,4 @@ members = [
"parts/js",
"apps/ppc",
"parts/mize"
, "parts/cli"]
, "parts/cli", "parts/macro_mize"]

View File

@@ -1,17 +1,28 @@
use std::collections::HashMap;
use clap::crate_version;
use cli_part::Cli;
use config::Config;
use deno_part::JsPart;
use mize::{Mize, MizeError, MizePart, MizeResult, add_parts, mize_err};
use clap::crate_version;
use mize::{
DynMizePartGuard, Mize, MizeError, MizePart, MizePartGuard, MizeResult, add_parts, mize_err,
};
fn main() {
let mut mize = Mize::new();
add_parts!(&mut mize, Cli::new(&mut mize, "ppc"));
let cli = Cli::get(&mut mize);
cli.with_cmd(|cmd| cmd.version(crate_version!()).author("ppc").about("the ppc desktop program"));
cli.subcommand("test", |sub_matches| {
add_parts!(&mut mize, Cli);
let cli = mize.get_part_native::<Cli>("cli");
cli.with_cmd(|cmd| {
cmd.version(crate_version!())
.name("ppc")
.author("ppc")
.about("the ppc desktop program")
});
cli.subcommand(Command::new("test"), |sub_matches| {
println!("test ppc...");
Ok(())
});

3
parts/Cargo.toml Normal file
View File

@@ -0,0 +1,3 @@
[[lib]]
entry = standalone_parts.rs

View File

@@ -4,33 +4,17 @@ use std::collections::HashMap;
use mize::{Mize, MizePart, MizeResult, instance::MizePartGuard};
#[mize_part("cli")]
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();
@@ -38,14 +22,8 @@ impl MizePart for CliPart {
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
fn opts(&self, mize: &mut Mize) {
mize.new_opt("cli.name");
}
}
@@ -60,13 +38,4 @@ impl CliPart {
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),
}
}
}

View File

@@ -1,32 +1,143 @@
use deno_core::FsModuleLoader;
use deno_core::error::AnyError;
use mize::{Mize, MizePart, MizeResult};
use deno_core::{JsRuntime, ModuleSpecifier, PollEventLoopOptions, RuntimeOptions, extension, op2};
use mize::async_trait;
use mize::instance::MizePartCreate;
use mize::{Mize, MizePart, MizeResult, mize_part};
use std::path::Path;
use std::rc::Rc;
#[mize_part("js")]
pub struct JsPart {
mize: Mize,
}
impl JsPart {
pub fn new(mize: Mize) -> Self {
JsPart { mize }
}
mize: Mize,
js_runtime: JsRuntime,
}
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");
println!("js part init");
Ok(())
}
}
impl MizePartCreate for JsPart {
fn create(mize: &mut Mize) -> Box<dyn MizePart> {
let mut js_runtime = JsRuntime::new(RuntimeOptions {
module_loader: Some(Rc::new(FsModuleLoader)),
extensions: vec![mize_ext::init_ops()],
..Default::default()
});
let bootstrap_code = r#"
globalThis.mize = {
get_part: (name) => Deno.core.ops.op_mize_get_part(name),
get_config: (key) => Deno.core.ops.op_mize_get_config(key),
version: "1.0.0",
// Add more methods as needed
};
"#;
js_runtime.execute_script("[bootstrap]", bootstrap_code)?;
JsPart { mize, js_runtime }
}
}
impl JsPart {
pub fn part_from_js_file(
&mut self,
name: &'static str,
path: &str,
) -> Box<dyn MizePart + Send + Sync> {
Box::new(PartFromJsFileAdapter {
mize: self.mize.clone(),
name,
js_file: path,
})
}
}
#[mize_part]
struct PartFromJsFileAdapter {
mize: Mize,
name: &'static str,
js_file: &'static str,
}
#[async_trait]
impl MizePart for PartFromJsFileAdapter {
fn deps(&self) -> &'static [&'static str] {
&["js"]
}
fn name(&self) -> &'static str {
self.name
}
async fn async_init(&mut self, mize: &mut Mize) -> MizeResult<()> {
let js: JsPart = mize.get_part_native("js");
let path = self.js_file;
let js_code = format!(
r#"
import {{ opts, deps, create }} from "{path}";
const isPromise = (value) => {
return !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
};
// Call the async function
let create_result = create(mize);
if (isPromise(create_result)) {
create_result = await create_result;
}
const result = {
opts: opts(mize),
deps: deps(mize),
create: create_result,
};
result;
"#
);
// Execute the script
let result = js.runtime.execute_script("[main]", js_code)?;
// Resolve the promise and run event loop
let resolved_value = js.runtime.resolve_value(result).await?;
// Run the event loop to completion
js.runtime
.run_event_loop(PollEventLoopOptions::default())
.await?;
println!("Execution of part {} completed successfully", self.name());
Ok(())
}
async fn async_run(&mut self, mize: &mut Mize) -> MizeResult<()> {
let js: JsPart = mize.get_part_native("js");
let path = self.js_file;
let js_code = format!(
r#"
import {{ run }} from "{path}";
const result = run()
result;
"#
);
// Execute the script
let result = js.runtime.execute_script("[main]", js_code)?;
// Resolve the promise and run event loop
let resolved_value = js.runtime.resolve_value(result).await?;
// Run the event loop to completion
js.runtime
.run_event_loop(PollEventLoopOptions::default())
.await?;
println!("Running of part {} completed successfully", self.name());
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 {
@@ -39,3 +150,19 @@ async fn run_js_file(file_path: &str) -> Result<(), AnyError> {
js_runtime.run_event_loop(Default::default()).await?;
result.await
}
*/
// Define your custom ops for the "mize" object inside deno
#[op2(fast)]
fn op_mize_get_part(#[string] name: &str) {
println!("js wants the part {}", name);
}
#[op2]
#[string]
fn op_mize_get_config(#[string] key: &str) -> String {
format!("config_value_for_{}", key)
}
// Create an extension with your custom ops
extension!(mize_ext, ops = [op_mize_get_part, op_mize_get_config]);

View File

@@ -0,0 +1,11 @@
[package]
name = "mize_macros"
version = "0.1.0"
edition = "2024"
[lib]
proc-macro = true
[dependencies]
quote = "1.0.44"
syn = "2.0.114"

View File

@@ -0,0 +1,68 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, Fields, parse_macro_input};
#[proc_macro_attribute]
pub fn mize_part(attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
let struct_name = &input.ident;
// Parse name from attribute
let part_name = if !attr.is_empty() {
let lit: syn::LitStr = parse_macro_input!(attr);
lit.value()
} else {
struct_name.to_string().to_lowercase()
};
// Verify mize field exists
let has_mize = match &input.data {
Data::Struct(s) => match &s.fields {
Fields::Named(f) => f
.named
.iter()
.any(|field| field.ident.as_ref().map(|i| i == "mize").unwrap_or(false)),
_ => false,
},
_ => false,
};
if !has_mize {
return syn::Error::new_spanned(struct_name, "Struct must have a 'mize: Mize' field")
.to_compile_error()
.into();
}
let expanded = quote! {
#input
// impl the default new impl
impl mize::MizePartGenerated for #struct_name {
fn name_generated(&self) -> &'static str {
#part_name
}
fn get_mize_generated(&mut self) -> &mut Mize {
&mut self.mize
}
fn as_any_generated(&self) -> &dyn Any {
&self
}
fn as_any_mut_generated(&mut self) -> &dyn Any {
&mut self
}
fn into_any_generated(self: Box<Self>) -> Box<dyn Any> {
self
}
}
impl mize::MizePartCreateGenerated for #struct_name {
fn create_generated(mize: Mize) -> Self {
Self {
mize,
... Default::default(),
}
}
}
};
TokenStream::from(expanded)
}

View File

@@ -39,6 +39,7 @@ toml = { version = "0.8.13", features = ["parse"], optional = false }
dyn-clone = "1.0.17"
sha2 = "0.10.8"
flume = "0.11.1"
mize_macros = { path = "../macro_mize" }
# buildin modules
#mize_module_blob = { path = "./modules/modules/Blob" }
@@ -74,6 +75,7 @@ http_req = { git = "https://github.com/c2vi/http_req", optional = true, default-
axum = { version = "0.6.1", features = ["ws", "headers"], optional = true }
axum-extra = { version = "0.4.2", features = ["spa"], optional = true }
axum-macros = { version = "0.3.0", optional = true }
async-trait = "0.1.89"
#tokio-core = "0.1.18"
#tokio-io = "0.1.13"
@@ -94,4 +96,3 @@ wasm-bindgen-test = { version = "0.3.34" }
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

View File

@@ -35,7 +35,7 @@ let
];
wasmCrane = (crane.mkLib pkgs).overrideToolchain wasmToolchain;
osToolchain = fenix.packages.${system}.stable.toolchain;
osToolchain = fenix.packages.${system}.nightly.toolchain;
osCrane = (crane.mkLib pkgs).overrideToolchain osToolchain;
@@ -222,4 +222,3 @@ in {
rustPkgs = import nixpkgs { overlays = [rust-overlay.overlays.default]; system = "x86_64-linux"; };
};
}

View File

@@ -88,7 +88,7 @@ rec {
(crane.mkLib pkgs).overrideToolchain (fenix.packages.${buildSystem}.combine [
#fenix.packages.${buildSystem}.minimal.rustc
#fenix.packages.${buildSystem}.minimal.cargo
fenix.packages.${buildSystem}.stable.toolchain
fenix.packages.${buildSystem}.nightly.toolchain
fenix.packages.${buildSystem}.targets."${hostSystem.cpu.name}-pc-windows-gnu".stable.toolchain
])
@@ -271,8 +271,8 @@ rec {
nativeBuildInputs = attrs.nativeBuildInputs or [] ++ [
pkgs.pkg-config
(fenix.packages."x86_64-linux".combine [
fenix.packages."x86_64-linux".stable.toolchain
fenix.packages."x86_64-linux".targets.wasm32-unknown-unknown.stable.toolchain
fenix.packages."x86_64-linux".latest.toolchain
fenix.packages."x86_64-linux".targets.wasm32-unknown-unknown.latest.toolchain
])
# the shell script, to mk the dist folder, for a standard rust module
@@ -388,5 +388,3 @@ rec {
};
}

View File

@@ -1,3 +1,4 @@
use async_trait::async_trait;
use colored::Colorize;
use core::fmt;
use flume::{bounded, unbounded, Receiver, Sender};
@@ -44,37 +45,6 @@ pub mod store;
pub mod subscription;
pub mod updater;
// console_log macro
// that can be copied into other files for debugging purposes
#[cfg(feature = "wasm-target")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm-target")]
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[cfg(feature = "wasm-target")]
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())})
}
#[macro_export]
macro_rules! add_parts {
($mize:expr, $($part:expr),+) => {
$(
$mize.add_part(
Box::new($part)
);
)+
mize.init_parts();
};
}
#[cfg(test)]
mod tests;
@@ -129,7 +99,7 @@ pub struct DynMizePartGuard {
pub part: Option<Box<dyn MizePart + Send + Sync>>,
}
pub struct MizePartGuard<T: MizePart + Send + Sync> {
pub struct MizePartGuard<T: MizePart + Send + Sync + 'static> {
pub mize: Mize,
pub part: Option<T>,
}
@@ -175,9 +145,40 @@ impl Drop for DynMizePartGuard {
}
}
pub trait MizePart: Any + Send + Sync {
fn name(&self) -> &'static str;
fn get_mize(&mut self) -> &mut Mize;
pub trait MizePartCreateGenerated: Sized {
fn create_generated(mize: Mize) -> Self;
}
pub trait MizePartGenerated {
fn name_generated(&self) -> &'static str;
fn get_mize_generated(&mut self) -> &mut Mize;
fn as_any_generated(&self) -> &dyn Any;
fn as_any_mut_generated(&mut self) -> &mut dyn Any;
fn into_any_generated(self: Box<Self>) -> Box<dyn Any>;
}
pub trait MizePartCreate: MizePartCreateGenerated + MizePart + 'static {
fn create(mize: &mut Mize) -> Box<dyn MizePart> {
Box::new(Self::create_generated(mize.clone()))
}
}
#[async_trait]
pub trait MizePart: MizePartGenerated {
fn name(&self) -> &'static str {
self.name_generated()
}
fn get_mize(&mut self) -> &mut Mize {
self.get_mize_generated()
}
fn as_any(&self) -> &dyn Any {
self.as_any_generated()
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self.as_any_mut_generated()
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self.into_any_generated()
}
fn init(&mut self, mize: &mut Mize) -> MizeResult<()> {
Ok(())
}
@@ -187,10 +188,15 @@ pub trait MizePart: Any + Send + Sync {
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>;
fn opts(&self, mize: &mut Mize) {
()
}
async fn async_run(&mut self, mize: &mut Mize) -> MizeResult<()> {
Ok(())
}
async fn async_init(&mut self, mize: &mut Mize) -> MizeResult<()> {
Ok(())
}
}
impl Mize {
@@ -300,7 +306,7 @@ impl Mize {
None => Err(mize_err!("Part not found or currently taken")),
}
}
pub fn add_part(&mut self, part: Box<dyn MizePart>) -> MizeResult<()> {
pub fn add_part(&mut self, part: Box<dyn MizePart + Send + Sync>) -> MizeResult<()> {
self.part_names.lock().unwrap().push(part.name());
self.parts.lock().unwrap().insert(part.name(), Some(part));
Ok(())
@@ -828,6 +834,19 @@ impl Mize {
}
Ok(())
}
pub fn get_part_native<T: MizePart + Send + Sync + 'static>(
&mut self,
name: &str,
) -> MizeResult<MizePartGuard<T>> {
let mut dyn_guard = self.get_part(name)?;
let part = dyn_guard.part.take().unwrap();
let concrete_part = part.into_any().downcast::<T>().unwrap();
Ok(MizePartGuard {
mize: self.clone(),
part: Some(*concrete_part),
})
}
}
impl fmt::Debug for Mize {

View File

@@ -0,0 +1,31 @@
// console_log macro
// that can be copied into other files for debugging purposes
#[cfg(feature = "wasm-target")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm-target")]
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[cfg(feature = "wasm-target")]
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())})
}
#[macro_export]
macro_rules! add_parts {
($mize:expr, $($part:expr),+) => {
$(
let part = $part.create($mize.clone());
$mize.add_part(
part
);
)+
mize.init_parts();
};
}

View File

@@ -36,17 +36,23 @@ mod core {
pub mod id;
pub mod instance;
pub mod item;
pub mod macros;
pub mod memstore;
pub mod proto;
pub mod types;
}
pub use async_trait::async_trait;
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::instance::{
DynMizePartGuard, MizePart, MizePartCreate, MizePartCreateGenerated, MizePartGenerated,
MizePartGuard,
};
pub use core::*;
pub use mize_macros::*;
use std::path::PathBuf;
// platform specific stuff

0
parts/my_part.rs Normal file
View File

View File

@@ -0,0 +1,2 @@
mod my_part;