aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-04-27 21:19:56 +0800
committer魏曹先生 <1992414357@qq.com>2026-04-27 21:19:56 +0800
commit2c32196bbc632411d4f6998a506ca262a805a666 (patch)
tree62934fbda52b11bfff984030dbbe52a1926fb4ac /mingling_core/src
parentad10b82c1e6785cbf88562117b1609905cfeb6dc (diff)
Add global resource system to Program
Diffstat (limited to 'mingling_core/src')
-rw-r--r--mingling_core/src/asset.rs3
-rw-r--r--mingling_core/src/asset/global_resource.rs116
-rw-r--r--mingling_core/src/lib.rs1
-rw-r--r--mingling_core/src/program.rs11
4 files changed, 129 insertions, 2 deletions
diff --git a/mingling_core/src/asset.rs b/mingling_core/src/asset.rs
index 234fec1..1ac37cb 100644
--- a/mingling_core/src/asset.rs
+++ b/mingling_core/src/asset.rs
@@ -12,6 +12,9 @@ pub mod dispatcher;
pub mod enum_tag;
#[doc(hidden)]
+pub mod global_resource;
+
+#[doc(hidden)]
pub mod node;
#[doc(hidden)]
diff --git a/mingling_core/src/asset/global_resource.rs b/mingling_core/src/asset/global_resource.rs
new file mode 100644
index 0000000..5667576
--- /dev/null
+++ b/mingling_core/src/asset/global_resource.rs
@@ -0,0 +1,116 @@
+use std::{
+ any::{Any, TypeId},
+ collections::HashMap,
+ sync::{Arc, Mutex},
+};
+
+use crate::{ChainProcess, Program, ProgramCollect};
+
+pub type GlobalResources = Arc<Mutex<HashMap<TypeId, Box<dyn Any + Sync + Send>>>>;
+
+impl<C> Program<C>
+where
+ C: ProgramCollect<Enum = C>,
+{
+ /// Insert a resource of the given type, cloning the provided value into the store
+ pub fn with_resource<Res: 'static + Send + Sync + ResourceMarker>(&mut self, res: Res) {
+ if let Ok(mut guard) = self.resources.lock() {
+ guard.insert(TypeId::of::<Res>(), Box::new(Arc::new(res)));
+ }
+ }
+
+ /// Modify a resource by type, applying a closure to the resource if present
+ pub fn modify_res<Res>(&self, f: impl FnOnce(&mut Res))
+ where
+ Res: 'static + Default + ResourceMarker + Send + Sync,
+ {
+ let mut guard = match self.resources.lock() {
+ Ok(guard) => guard,
+ Err(_) => {
+ return;
+ }
+ };
+ if let Some(arc_res) = guard
+ .get_mut(&TypeId::of::<Res>())
+ .and_then(|a| a.downcast_mut::<Arc<Res>>())
+ {
+ let mut new_res = match Arc::try_unwrap(std::mem::take(arc_res)) {
+ Ok(val) => val,
+ Err(arc) => (*arc).res_clone(),
+ };
+ f(&mut new_res);
+ *arc_res = Arc::new(new_res);
+ }
+ }
+
+ /// Get an resources by type, returning `Res` if present
+ pub fn res<Res: 'static + Send + Sync>(&self) -> Option<GlobalResource<Res>> {
+ let guard = self.resources.lock().ok()?;
+ let boxed_any = guard.get(&TypeId::of::<Res>())?;
+ let arc_res = boxed_any.as_ref().downcast_ref::<Arc<Res>>()?;
+ Some(GlobalResource::from(Arc::clone(arc_res)))
+ }
+
+ /// Get a resource by type, returning `GlobalResource<Res>` if present
+ pub fn res_or_route<Res: 'static + Send + Sync>(
+ &self,
+ route: ChainProcess<C>,
+ ) -> Result<GlobalResource<Res>, ChainProcess<C>> {
+ match self.res() {
+ Some(r) => Ok(r),
+ None => Err(route),
+ }
+ }
+
+ /// Get a resource by type, returning `GlobalResource<Res>` or inserting a default
+ pub fn res_or_default<Res: 'static + Send + Sync + ResourceMarker>(
+ &self,
+ ) -> GlobalResource<Res> {
+ self.res()
+ .unwrap_or_else(|| GlobalResource::from(Arc::new(Res::res_default())))
+ }
+}
+
+/// Global assets for storing Program global state information
+pub struct GlobalResource<ResType: 'static + Send + Sync> {
+ res_arc: Arc<ResType>,
+}
+
+impl<ResType: 'static + Send + Sync> GlobalResource<ResType> {
+ /// Create a new `GlobalAsset` from an `AssetType` value.
+ pub fn new(res: ResType) -> Self {
+ Self {
+ res_arc: Arc::new(res),
+ }
+ }
+}
+
+impl<ResType: 'static + Send + Sync> From<Arc<ResType>> for GlobalResource<ResType> {
+ fn from(arc: Arc<ResType>) -> Self {
+ Self { res_arc: arc }
+ }
+}
+
+impl<ResType: 'static + Send + Sync> std::ops::Deref for GlobalResource<ResType> {
+ type Target = ResType;
+
+ fn deref(&self) -> &Self::Target {
+ &self.res_arc
+ }
+}
+
+/// Resource marker trait, types that implement the Clone and Default traits can be considered as resources
+pub trait ResourceMarker {
+ fn res_clone(&self) -> Self;
+ fn res_default() -> Self;
+}
+
+impl<T: Default + Clone> ResourceMarker for T {
+ fn res_clone(&self) -> Self {
+ Clone::clone(self)
+ }
+
+ fn res_default() -> Self {
+ Default::default()
+ }
+}
diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs
index 9e65e40..b9fa816 100644
--- a/mingling_core/src/lib.rs
+++ b/mingling_core/src/lib.rs
@@ -24,6 +24,7 @@ pub use crate::asset::chain::*;
pub use crate::asset::comp::*;
pub use crate::asset::dispatcher::*;
pub use crate::asset::enum_tag::*;
+pub use crate::asset::global_resource::*;
pub use crate::asset::help::*;
pub use crate::asset::node::*;
pub use crate::asset::renderer::*;
diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs
index 949dd45..1505480 100644
--- a/mingling_core/src/program.rs
+++ b/mingling_core/src/program.rs
@@ -8,11 +8,15 @@ use crate::error::GeneralRendererSerializeError;
use std::env;
use crate::{
- AnyOutput, ChainProcess, RenderResult,
+ AnyOutput, ChainProcess, GlobalResources, RenderResult,
asset::dispatcher::Dispatcher,
error::{ChainProcessError, ProgramExecuteError},
};
-use std::{fmt::Display, sync::OnceLock};
+use std::{
+ collections::HashMap,
+ fmt::Display,
+ sync::{Arc, Mutex, OnceLock},
+};
#[cfg(feature = "async")]
use std::pin::Pin;
@@ -66,6 +70,8 @@ where
#[cfg(feature = "general_renderer")]
pub general_renderer_name: GeneralRendererSetting,
+
+ pub(crate) resources: GlobalResources,
}
impl<C> Program<C>
@@ -101,6 +107,7 @@ where
#[cfg(feature = "general_renderer")]
general_renderer_name: GeneralRendererSetting::Disable,
+ resources: Arc::new(Mutex::new(HashMap::new())),
}
}