1use std::ops::{Deref, DerefMut};
2
3use crate::{
4 access::{read::Read, write::Write},
5 entity::Index,
6 misc::BitAnd,
7 resource::{Ref, RefMut, Resource},
8};
9
10use super::{Join, ParJoin};
11
12macro_rules! define_tuple_join {
13 ($($from:ident),*) => {
14 impl<$($from,)*> Join for ($($from),*,)
15 where $($from: Join),*,
16 ($(<$from as Join>::Mask,)*): BitAnd,
17 {
18 type Type = ($($from::Type),*,);
19 type Value = ($($from::Value),*,);
20 type Mask = <($($from::Mask,)*) as BitAnd>::Value;
21
22 #[allow(non_snake_case)]
23 unsafe fn open(self) -> (Self::Mask, Self::Value) {
24 let ($($from,)*) = self;
25 let ($($from,)*) = ($($from.open(),)*);
26
27 (
28 ($($from.0),*,).and(),
29 ($($from.1),*,)
30 )
31 }
32
33 #[allow(non_snake_case)]
34 unsafe fn get(v: &mut Self::Value, i: Index) -> Self::Type {
35 let ($(ref mut $from,)*) = v;
36
37 ($($from::get($from, i),)*)
38 }
39
40 #[inline]
41 fn is_unconstrained() -> bool {
42 let mut unconstrained = true;
43
44 $( unconstrained = unconstrained && $from::is_unconstrained(); )*
45
46 unconstrained
47 }
48 }
49
50 impl<$($from,)*> ParJoin for ($($from),*,)
51 where $($from: ParJoin),*,
52 ($(<$from as Join>::Mask,)*): BitAnd,
53 {}
54 }
55}
56
57define_tuple_join! { A }
58define_tuple_join! { A, B }
59define_tuple_join! { A, B, C }
60define_tuple_join! { A, B, C, D }
61define_tuple_join! { A, B, C, D, E }
62define_tuple_join! { A, B, C, D, E, F }
63define_tuple_join! { A, B, C, D, E, F, G }
64define_tuple_join! { A, B, C, D, E, F, G, H }
65define_tuple_join! { A, B, C, D, E, F, G, H, I }
66define_tuple_join! { A, B, C, D, E, F, G, H, I, J }
67define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K }
68define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L }
69define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M }
70define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M, N }
71define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O }
72define_tuple_join! { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P }
73
74macro_rules! define_mutable_join {
75 ($ty:ty) => {
76 impl<'a, 'b, T> Join for &'a mut $ty
77 where
78 &'a mut T: Join,
79 T: Resource,
80 {
81 type Type = <&'a mut T as Join>::Type;
82 type Value = <&'a mut T as Join>::Value;
83 type Mask = <&'a mut T as Join>::Mask;
84
85 unsafe fn open(self) -> (Self::Mask, Self::Value) {
86 self.deref_mut().open()
87 }
88
89 unsafe fn get(v: &mut Self::Value, i: Index) -> Self::Type {
90 <&'a mut T as Join>::get(v, i)
91 }
92
93 #[inline]
94 fn is_unconstrained() -> bool {
95 <&'a mut T as Join>::is_unconstrained()
96 }
97 }
98
99 impl<'a, 'b, T> ParJoin for &'a mut $ty
100 where
101 &'a mut T: ParJoin,
102 T: Resource,
103 {
104 }
105 };
106}
107
108define_mutable_join!(Write<'b, T>);
109define_mutable_join!(RefMut<'b, T>);
110
111macro_rules! define_immutable_join {
112 ($ty:ty) => {
113 impl<'a, 'b, T> Join for &'a $ty
114 where
115 &'a T: Join,
116 T: Resource,
117 {
118 type Type = <&'a T as Join>::Type;
119 type Value = <&'a T as Join>::Value;
120 type Mask = <&'a T as Join>::Mask;
121
122 unsafe fn open(self) -> (Self::Mask, Self::Value) {
123 self.deref().open()
124 }
125
126 unsafe fn get(v: &mut Self::Value, i: Index) -> Self::Type {
127 <&'a T as Join>::get(v, i)
128 }
129
130 #[inline]
131 fn is_unconstrained() -> bool {
132 <&'a T as Join>::is_unconstrained()
133 }
134 }
135
136 impl<'a, 'b, T> ParJoin for &'a $ty
137 where
138 &'a T: ParJoin,
139 T: Resource,
140 {
141 }
142 };
143}
144
145define_immutable_join!(Read<'b, T>);
146define_immutable_join!(Ref<'b, T>);