diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-06-27 17:46:29 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-06-27 17:46:29 +0800 |
| commit | 4f7bd4f6fa5d27cfe703c54aa029a321f40d19fb (patch) | |
| tree | 97c31ddbb905d8f0e70418b0970ee6420aeac611 /mingling_core/src/asset/global_resource.rs | |
| parent | 6cadc8d39adebbc263e8576c389b5ef491f10ace (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.rs | 38 |
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>> { |
