mf_state/resource.rs
1use std::any::Any;
2use std::any::TypeId;
3use std::sync::Arc;
4
5pub trait Resource: Any + Send + Sync + 'static {}
6
7impl dyn Resource {
8 #[inline(always)]
9 fn is<T: Resource>(&self) -> bool {
10 self.type_id() == TypeId::of::<T>()
11 }
12
13 #[inline(always)]
14 #[allow(clippy::needless_lifetimes)]
15 pub fn downcast_arc<'a, T: Resource>(
16 self: &'a Arc<Self>
17 ) -> Option<&'a Arc<T>> {
18 if self.is::<T>() {
19 let ptr = self as *const Arc<_> as *const Arc<T>;
20 // SAFETY: 这个转换是安全的,因为:
21 // 1. 我们通过 `self.is::<T>()` 验证了运行时类型匹配(TypeId 相等)
22 // 2. T 实现了 Resource trait,确保 T: Any + Send + Sync + 'static
23 // 3. Arc<dyn Resource> 和 Arc<T> 具有相同的内存布局和大小
24 // (Arc 是指针包装器,存储堆上的数据指针和引用计数)
25 // 4. 我们只改变了指针的类型标注,不改变底层数据
26 // 5. 生命周期 'a 保持不变,确保借用检查器的安全性
27 // 6. 返回的是不可变引用,不会破坏内存安全
28 Some(unsafe { &*ptr })
29 } else {
30 None
31 }
32 }
33 #[inline(always)]
34 #[allow(clippy::needless_lifetimes)]
35 pub fn downcast<'a, T: Resource>(&'a self) -> Option<&'a T> {
36 if self.is::<T>() {
37 let ptr = self as *const dyn Resource as *const T;
38 // SAFETY: 这个转换是安全的,因为:
39 // 1. 我们通过 `self.is::<T>()` 验证了运行时类型匹配(TypeId 相等)
40 // 2. T 实现了 Resource trait,确保 T: Any + Send + Sync + 'static
41 // 3. dyn Resource 和 T 的内存布局兼容
42 // 4. 我们只改变了指针的类型标注,不改变底层数据
43 // 5. 生命周期 'a 保持不变,确保借用检查器的安全性
44 // 6. 返回的是不可变引用,不会破坏内存安全
45 Some(unsafe { &*ptr })
46 } else {
47 None
48 }
49 }
50}