aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/src/asset/global_resource.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-27 17:46:29 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-27 17:46:29 +0800
commit4f7bd4f6fa5d27cfe703c54aa029a321f40d19fb (patch)
tree97c31ddbb905d8f0e70418b0970ee6420aeac611 /mingling_core/src/asset/global_resource.rs
parent6cadc8d39adebbc263e8576c389b5ef491f10ace (diff)
feat(macros): add async mutable resource injection for `#[chain]`
Support `&mut T` resource parameters in async chain functions by using an extract-store pattern that avoids holding mutable borrows across await points. Remove the previous compile-time rejection of this combination.
Diffstat (limited to 'mingling_core/src/asset/global_resource.rs')
-rw-r--r--mingling_core/src/asset/global_resource.rs38
1 files changed, 38 insertions, 0 deletions
diff --git a/mingling_core/src/asset/global_resource.rs b/mingling_core/src/asset/global_resource.rs
index 83a779d..651655a 100644
--- a/mingling_core/src/asset/global_resource.rs
+++ b/mingling_core/src/asset/global_resource.rs
@@ -74,6 +74,44 @@ where
}
}
+ /// Internal syntax for the `&mut MyResource` syntax of async #[chain], do not use directly.
+ ///
+ /// Extracts a mutable resource from the global store (clone-out), returning an
+ /// owned value. The caller must call [`__store_res`] to write back modifications.
+ #[doc(hidden)]
+ #[must_use]
+ pub fn __extract_res_mut<Res: 'static + Default + ResourceMarker + Send + Sync>(
+ &self,
+ ) -> Res {
+ let Ok(mut guard) = self.resources.lock() else {
+ return Res::res_default();
+ };
+ if let Some(arc_res) = guard
+ .get_mut(&TypeId::of::<Res>())
+ .and_then(|a| a.downcast_mut::<Arc<Res>>())
+ {
+ match Arc::try_unwrap(std::mem::take(arc_res)) {
+ Ok(val) => val,
+ Err(arc) => (*arc).res_clone(),
+ }
+ } else {
+ Res::res_default()
+ }
+ }
+
+ /// Internal syntax for the `&mut MyResource` syntax of async #[chain], do not use directly.
+ ///
+ /// Stores a modified resource value back into the global store.
+ #[doc(hidden)]
+ pub fn __store_res<Res: 'static + Send + Sync + ResourceMarker>(
+ &self,
+ val: Res,
+ ) {
+ if let Ok(mut guard) = self.resources.lock() {
+ guard.insert(TypeId::of::<Res>(), Box::new(Arc::new(val)));
+ }
+ }
+
/// Get an resources by type, returning `Res` if present
#[must_use]
pub fn res<Res: 'static + Send + Sync>(&self) -> Option<GlobalResource<Res>> {