ready_paint/
multi.rs

1use std::{any::TypeId, marker::PhantomData};
2
3use crate::scene::{HashTypeId2Data, Ready};
4pub trait InRefOrMut {
5    type AccessMode;
6    type Output;
7}
8/// # Safety
9/// 1. T1 and T2 .. T4 must be different types from each.
10/// 2. T1 and T2 .. T4 must be wrap in Ref<T> Or Mut<T>, T must be impl `Ready`.
11/// example:
12/// ```
13/// refs_muts::<(Ref<Data1>, Mut<Data2>)>(&mut data);
14/// ```
15pub fn refs_muts<T: TurpleAccess>(data: &mut HashTypeId2Data) -> T::Output<'_> {
16    T::accesss(data)
17}
18pub trait AccessMode {}
19pub struct Read;
20pub struct Write;
21impl AccessMode for Read {}
22impl AccessMode for Write {}
23pub trait RefOrMut {
24    type Target: 'static;
25    type Mode: AccessMode;
26    type Output<'a>: 'a
27    where
28        Self::Target: 'a;
29    fn process<'a>(data: &'a mut HashTypeId2Data) -> Self::Output<'a>;
30}
31pub struct Ref<T>(PhantomData<T>);
32impl<T: 'static + Ready> RefOrMut for Ref<T> {
33    type Target = T;
34    type Mode = Read;
35    type Output<'a> = &'a T;
36
37    fn process<'a>(data: &'a mut HashTypeId2Data) -> Self::Output<'a> {
38        data.get(&TypeId::of::<T>())
39            .and_then(|r| r.downcast_ref::<T>())
40            .expect(&format!(
41                "Failed to get resource of type: {}",
42                std::any::type_name::<T>()
43            ))
44    }
45}
46
47pub struct Mut<T>(PhantomData<T>);
48impl<T: 'static + Ready> RefOrMut for Mut<T> {
49    type Target = T;
50    type Mode = Write;
51    type Output<'a> = &'a mut T;
52
53    fn process<'a>(data: &'a mut HashTypeId2Data) -> Self::Output<'a> {
54        data.get_mut(&TypeId::of::<T>())
55            .and_then(|m| m.downcast_mut::<T>())
56            .expect(&format!(
57                "Failed to get mutable resource of type: {}",
58                std::any::type_name::<T>()
59            ))
60    }
61}
62pub trait TurpleAccess {
63    type Output<'a>;
64    fn accesss<'a>(data: &'a mut HashTypeId2Data) -> Self::Output<'a>;
65}
66impl<T1, T2> TurpleAccess for (T1, T2)
67where
68    T1: RefOrMut + 'static,
69    T2: RefOrMut + 'static,
70{
71    type Output<'a> = (T1::Output<'a>, T2::Output<'a>);
72
73    fn accesss<'a>(data: &'a mut HashTypeId2Data) -> Self::Output<'a> {
74        assert_ne!(TypeId::of::<T1>(), TypeId::of::<T2>());
75        unsafe {
76            // 使用原始指针来绕过借用检查
77            let data_ptr = data as *mut HashTypeId2Data;
78            (T1::process(&mut *data_ptr), T2::process(&mut *data_ptr))
79        }
80    }
81}
82
83impl<T1, T2, T3> TurpleAccess for (T1, T2, T3)
84where
85    T1: RefOrMut + 'static,
86    T2: RefOrMut + 'static,
87    T3: RefOrMut + 'static,
88{
89    type Output<'a> = (T1::Output<'a>, T2::Output<'a>, T3::Output<'a>);
90
91    fn accesss<'a>(data: &'a mut HashTypeId2Data) -> Self::Output<'a> {
92        assert_ne!(TypeId::of::<T1>(), TypeId::of::<T2>());
93        assert_ne!(TypeId::of::<T1>(), TypeId::of::<T3>());
94        assert_ne!(TypeId::of::<T2>(), TypeId::of::<T3>());
95        unsafe {
96            let data_ptr = data as *mut HashTypeId2Data;
97            (
98                T1::process(&mut *data_ptr),
99                T2::process(&mut *data_ptr),
100                T3::process(&mut *data_ptr),
101            )
102        }
103    }
104}
105
106impl<T1, T2, T3, T4> TurpleAccess for (T1, T2, T3, T4)
107where
108    T1: RefOrMut + 'static,
109    T2: RefOrMut + 'static,
110    T3: RefOrMut + 'static,
111    T4: RefOrMut + 'static,
112{
113    type Output<'a> = (
114        T1::Output<'a>,
115        T2::Output<'a>,
116        T3::Output<'a>,
117        T4::Output<'a>,
118    );
119
120    fn accesss<'a>(data: &'a mut HashTypeId2Data) -> Self::Output<'a> {
121        assert_ne!(TypeId::of::<T1>(), TypeId::of::<T2>());
122        assert_ne!(TypeId::of::<T1>(), TypeId::of::<T3>());
123        assert_ne!(TypeId::of::<T1>(), TypeId::of::<T4>());
124        assert_ne!(TypeId::of::<T2>(), TypeId::of::<T3>());
125        assert_ne!(TypeId::of::<T2>(), TypeId::of::<T4>());
126        assert_ne!(TypeId::of::<T3>(), TypeId::of::<T4>());
127        unsafe {
128            let data_ptr = data as *mut HashTypeId2Data;
129            (
130                T1::process(&mut *data_ptr),
131                T2::process(&mut *data_ptr),
132                T3::process(&mut *data_ptr),
133                T4::process(&mut *data_ptr),
134            )
135        }
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use std::any::TypeId;
142
143    use crate::{
144        gfx::Gfx,
145        multi::{refs_muts, Mut, Ref},
146        scene::{HashTypeId2Data, Ready},
147    };
148    #[derive(Debug)]
149    struct Data1 {
150        val: i32,
151    }
152    #[derive(Debug)]
153    struct Data2 {
154        val: i32,
155    }
156    impl Ready for Data1 {
157        fn ready(&mut self, _: &mut HashTypeId2Data, _: &Gfx) {}
158    }
159    impl Ready for Data2 {
160        fn ready(&mut self, _: &mut HashTypeId2Data, _: &Gfx) {}
161    }
162    #[test]
163    fn test() {
164        use std::any::Any;
165        use std::collections::HashMap;
166        let mut data: HashMap<TypeId, Box<dyn Any>> = HashMap::new();
167        data.insert(TypeId::of::<Data1>(), Box::new(Data1 { val: 42 }));
168        data.insert(TypeId::of::<Data2>(), Box::new(Data2 { val: 3 }));
169
170        let (r1, r2) = refs_muts::<(Ref<Data1>, Mut<Data2>)>(&mut data);
171        r2.val = 5;
172        assert_eq!(r1.val, 42);
173        assert_eq!(r2.val, 5);
174    }
175}