1use std::{any::TypeId, marker::PhantomData};
2
3use crate::scene::{HashTypeId2Data, Ready};
4pub trait InRefOrMut {
5 type AccessMode;
6 type Output;
7}
8pub 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 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}