1pub trait ProjectR<A: ?Sized, B: ?Sized>: Send + Sync {
3 fn project<'a>(&self, a: &'a A) -> &'a B;
4}
5
6impl<A: ?Sized, B: ?Sized, T> ProjectR<A, B> for T
7where
8 Self: Send + Sync,
9 T: for<'a> Fn(&'a A) -> &'a B,
10{
11 fn project<'a>(&self, a: &'a A) -> &'a B {
12 self(a)
13 }
14}
15
16pub trait ProjectW<A: ?Sized, B: ?Sized>: Send + Sync {
18 fn project_mut<'a>(&self, a: &'a mut A) -> &'a mut B;
19}
20
21impl<A: ?Sized, B: ?Sized, T> ProjectW<A, B> for T
22where
23 Self: Send + Sync,
24 T: for<'a> Fn(&'a mut A) -> &'a mut B,
25{
26 fn project_mut<'a>(&self, a: &'a mut A) -> &'a mut B {
27 self(a)
28 }
29}
30
31pub struct ProjectorRW<A: ?Sized, B: ?Sized> {
33 pub(crate) ro: Box<dyn ProjectR<A, B> + Send + Sync>,
34 pub(crate) rw: Box<dyn ProjectW<A, B> + Send + Sync>,
35}
36
37impl<A: ?Sized, B: ?Sized> ProjectorRW<A, B> {
38 pub fn new(ro: impl ProjectR<A, B> + 'static, rw: impl ProjectW<A, B> + 'static) -> Self {
39 Self {
40 ro: Box::new(ro),
41 rw: Box::new(rw),
42 }
43 }
44
45 pub fn project<'a>(&self, a: &'a A) -> &'a B {
46 self.ro.project(a)
47 }
48
49 pub fn project_mut<'a>(&self, a: &'a mut A) -> &'a mut B {
50 self.rw.project_mut(a)
51 }
52}
53
54pub struct Projector<A: ?Sized, B: ?Sized> {
56 ro: Box<dyn ProjectR<A, B> + Send + Sync>,
57}
58
59impl<A: ?Sized, B: ?Sized> Projector<A, B> {
60 pub fn new(ro: impl ProjectR<A, B> + 'static) -> Self {
61 Self { ro: Box::new(ro) }
62 }
63
64 pub fn project<'a>(&self, a: &'a A) -> &'a B {
65 self.ro.project(a)
66 }
67}
68
69impl<A: ?Sized, B: ?Sized> From<ProjectorRW<A, B>> for Projector<A, B> {
71 fn from(value: ProjectorRW<A, B>) -> Self {
72 Self { ro: value.ro }
73 }
74}
75
76#[macro_export]
91macro_rules! project {
92 ($x:ident : $type:ty, $expr:expr) => {{
93 let $x: [$type; 0] = [];
95 fn make_projection<A, B>(
96 _: &[A; 0],
97 a: impl (Fn(&A) -> &B) + Send + Sync + 'static,
98 b: impl (Fn(&mut A) -> &mut B) + Send + Sync + 'static,
99 ) -> $crate::ProjectorRW<A, B> {
100 $crate::ProjectorRW::new(a, b)
101 }
102 make_projection(&$x, |$x: _| &$expr, |$x: _| &mut $expr)
103 }};
104}
105
106#[macro_export]
120macro_rules! project_cast {
121 ($x:ident : $type:ty => $type2:ty) => {{
122 fn make_projection<A: ?Sized, B: ?Sized>(
124 a: impl (Fn(&A) -> &B) + Send + Sync + 'static,
125 b: impl (Fn(&mut A) -> &mut B) + Send + Sync + 'static,
126 ) -> $crate::ProjectorRW<A, B> {
127 $crate::ProjectorRW::new(a, b)
128 }
129 make_projection(
130 |$x: &$type| $x as &$type2,
131 |$x: &mut $type| $x as &mut $type2,
132 )
133 }};
134}
135
136pub trait Castable<T: 'static>
138where
139 T: ?Sized,
140{
141 fn cast<'a>(&'a self) -> &'a T
142 where
143 Self: 'a;
144 fn cast_mut<'a>(&'a mut self) -> &'a mut T
145 where
146 Self: 'a;
147}
148
149macro_rules! impl_castable_trait {
150 ($trait:path) => {
151 impl<T_> Castable<dyn $trait + 'static> for T_
152 where
153 T_: $trait + 'static,
154 {
155 fn cast<'a>(&'a self) -> &'a (dyn $trait + 'static)
156 where
157 Self: 'a,
158 {
159 self
160 }
161 fn cast_mut<'a>(&'a mut self) -> &'a mut (dyn $trait + 'static)
162 where
163 Self: 'a,
164 {
165 self
166 }
167 }
168 };
169}
170
171impl_castable_trait!(std::any::Any);
173impl_castable_trait!(std::fmt::Debug);
174impl_castable_trait!(std::fmt::Display);
175
176macro_rules! impl_castable_ref_trait {
177 ($type:ident, $trait:path) => {
178 impl<T_, $type: 'static> Castable<dyn $trait + 'static> for T_
179 where
180 T_: $trait + 'static,
181 $type: ?Sized,
182 {
183 fn cast<'a>(&'a self) -> &'a (dyn $trait + 'static)
184 where
185 Self: 'a,
186 {
187 self
188 }
189 fn cast_mut<'a>(&'a mut self) -> &'a mut (dyn $trait + 'static)
190 where
191 Self: 'a,
192 {
193 self
194 }
195 }
196 };
197}
198
199impl_castable_ref_trait!(T, std::convert::AsRef<T>);
201impl_castable_ref_trait!(T, std::convert::AsMut<T>);
202impl_castable_ref_trait!(T, std::ops::Deref<Target = T>);
203impl_castable_ref_trait!(T, std::ops::DerefMut<Target = T>);
204impl_castable_ref_trait!(T, std::borrow::Borrow<T>);
205impl_castable_ref_trait!(T, std::borrow::BorrowMut<T>);
206
207impl<U: 'static, const N: usize> Castable<[U]> for [U; N] {
208 fn cast<'a>(&'a self) -> &'a [U]
209 where
210 Self: 'a,
211 {
212 self
213 }
214 fn cast_mut<'a>(&'a mut self) -> &'a mut [U]
215 where
216 Self: 'a,
217 {
218 self
219 }
220}
221
222impl<T: ?Sized, U: ?Sized + 'static> ProjectR<T, U> for ()
223where
224 T: Castable<U>,
225{
226 fn project<'a>(&self, t: &'a T) -> &'a U {
227 t.cast()
228 }
229}
230
231impl<T: ?Sized, U: ?Sized + 'static> ProjectW<T, U> for ()
232where
233 T: Castable<U>,
234{
235 fn project_mut<'a>(&self, t: &'a mut T) -> &'a mut U {
236 t.cast_mut()
237 }
238}
239
240#[cfg(test)]
241mod test {
242 #[test]
243 fn test_projection() {
244 let x = (1, 2);
245 let projection1 = project!(x: (i32, i32), x.0);
246 let projection2 = project!(x: (i32, i32), x.1);
247 assert_eq!(1, *projection1.ro.project(&x));
248 assert_eq!(2, *projection2.ro.project(&x));
249 }
250
251 #[test]
252 fn test_projection_cast() {
253 trait AsRefMut<T: ?Sized>: AsRef<T> + AsMut<T> {}
254 impl AsRefMut<str> for String {}
255
256 let mut x: String = "123".into();
257 let projection = project_cast!(x: String => (dyn AsRefMut<str>));
258 assert_eq!(projection.project(&x).as_ref(), "123");
259 assert_eq!(projection.project_mut(&mut x).as_mut(), "123");
260 }
261
262 #[test]
263 fn test_projection_cast_array() {
264 let projection = project_cast!(x: [i32; 3] => dyn std::ops::IndexMut<usize, Output = i32>);
265 let mut x = [1, 2, 3];
266 projection.project_mut(&mut x)[0] = 11;
267 }
268}