Skip to content

Commit 9b60160

Browse files
authored
Merge pull request #2 from luca-della-vedova/luca/buffered_macros
Use macros for tuple implementations of various types
2 parents 31b92e9 + c97a7fc commit 9b60160

File tree

6 files changed

+365
-637
lines changed

6 files changed

+365
-637
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ authors = ["Grey <[email protected]>"]
99
[dependencies]
1010
bevy = "0.11"
1111
arrayvec = "*"
12+
itertools = "*"
1213
smallvec = "*"
1314
crossbeam = "*"
1415
futures = "0.3"

src/buffer/bufferable.rs

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*
1616
*/
1717

18+
use bevy::utils::all_tuples;
1819
use smallvec::SmallVec;
1920

2021
use crate::{
@@ -76,36 +77,26 @@ impl<T: 'static + Send + Sync> Bufferable for Output<T> {
7677
}
7778
}
7879

79-
impl<T0, T1> Bufferable for (T0, T1)
80-
where
81-
T0: Bufferable,
82-
T1: Bufferable,
83-
{
84-
type BufferType = (T0::BufferType, T1::BufferType);
85-
fn as_buffer(self, builder: &mut Builder) -> Self::BufferType {
86-
(
87-
self.0.as_buffer(builder),
88-
self.1.as_buffer(builder),
89-
)
90-
}
91-
}
92-
93-
impl<T0, T1, T2> Bufferable for (T0, T1, T2)
94-
where
95-
T0: Bufferable,
96-
T1: Bufferable,
97-
T2: Bufferable,
98-
{
99-
type BufferType = (T0::BufferType, T1::BufferType, T2::BufferType);
100-
fn as_buffer(self, builder: &mut Builder) -> Self::BufferType {
101-
(
102-
self.0.as_buffer(builder),
103-
self.1.as_buffer(builder),
104-
self.2.as_buffer(builder),
105-
)
80+
macro_rules! impl_bufferable_for_tuple {
81+
($($T:ident),*) => {
82+
#[allow(non_snake_case)]
83+
impl<$($T: Bufferable),*> Bufferable for ($($T,)*)
84+
{
85+
type BufferType = ($($T::BufferType,)*);
86+
fn as_buffer(self, builder: &mut Builder) -> Self::BufferType {
87+
let ($($T,)*) = self;
88+
($(
89+
$T.as_buffer(builder),
90+
)*)
91+
}
92+
93+
}
10694
}
10795
}
10896

97+
// Implements the `Bufferable` trait for all tuples between size 2 and 12
98+
// (inclusive) made of types that implement `Bufferable`
99+
all_tuples!(impl_bufferable_for_tuple, 2, 12, T);
109100

110101
impl<T: Bufferable, const N: usize> Bufferable for [T; N] {
111102
type BufferType = [T::BufferType; N];

src/buffer/buffered.rs

Lines changed: 52 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
use bevy::prelude::{Entity, World};
19+
use bevy::utils::all_tuples;
1920

2021
use smallvec::SmallVec;
2122

@@ -121,100 +122,63 @@ impl<T: 'static + Send + Sync + Clone> Buffered for CloneFromBuffer<T> {
121122
}
122123
}
123124

124-
impl<T0, T1> Buffered for (T0, T1)
125-
where
126-
T0: Buffered,
127-
T1: Buffered,
128-
{
129-
fn buffered_count(
130-
&self,
131-
session: Entity,
132-
world: &World,
133-
) -> Result<usize, OperationError> {
134-
Ok([
135-
self.0.buffered_count(session, world)?,
136-
self.1.buffered_count(session, world)?,
137-
].iter().copied().min().unwrap_or(0))
138-
}
125+
macro_rules! impl_buffered_for_tuple {
126+
($($T:ident),*) => {
127+
#[allow(non_snake_case)]
128+
impl<$($T: Buffered),*> Buffered for ($($T,)*)
129+
{
130+
fn buffered_count(
131+
&self,
132+
session: Entity,
133+
world: &World,
134+
) -> Result<usize, OperationError> {
135+
let ($($T,)*) = self;
136+
Ok([
137+
$(
138+
$T.buffered_count(session, world)?,
139+
)*
140+
].iter().copied().min().unwrap_or(0))
141+
}
139142

140-
type Item = (T0::Item, T1::Item);
141-
fn pull(
142-
&self,
143-
session: Entity,
144-
world: &mut World,
145-
) -> Result<Self::Item, OperationError> {
146-
let t0 = self.0.pull(session, world)?;
147-
let t1 = self.1.pull(session, world)?;
148-
Ok((t0, t1))
149-
}
143+
type Item = ($($T::Item),*);
144+
fn pull(
145+
&self,
146+
session: Entity,
147+
world: &mut World,
148+
) -> Result<Self::Item, OperationError> {
149+
let ($($T,)*) = self;
150+
Ok(($(
151+
$T.pull(session, world)?,
152+
)*))
153+
}
150154

151-
fn listen(
152-
&self,
153-
listener: Entity,
154-
world: &mut World,
155-
) -> OperationResult {
156-
self.0.listen(listener, world)?;
157-
self.1.listen(listener, world)?;
158-
Ok(())
159-
}
155+
fn listen(
156+
&self,
157+
listener: Entity,
158+
world: &mut World,
159+
) -> OperationResult {
160+
let ($($T,)*) = self;
161+
$(
162+
$T.listen(listener, world)?;
163+
)*
164+
Ok(())
165+
}
160166

161-
fn as_input(&self) -> SmallVec<[Entity; 8]> {
162-
let mut inputs = SmallVec::new();
163-
inputs.extend(self.0.as_input());
164-
inputs.extend(self.1.as_input());
165-
inputs
167+
fn as_input(&self) -> SmallVec<[Entity; 8]> {
168+
let mut inputs = SmallVec::new();
169+
let ($($T,)*) = self;
170+
$(
171+
inputs.extend($T.as_input());
172+
)*
173+
inputs
174+
}
175+
}
166176
}
167177
}
168178

169-
impl<T0, T1, T2> Buffered for (T0, T1, T2)
170-
where
171-
T0: Buffered,
172-
T1: Buffered,
173-
T2: Buffered,
174-
{
175-
fn buffered_count(
176-
&self,
177-
session: Entity,
178-
world: &World,
179-
) -> Result<usize, OperationError> {
180-
Ok([
181-
self.0.buffered_count(session, world)?,
182-
self.1.buffered_count(session, world)?,
183-
self.2.buffered_count(session, world)?,
184-
].iter().copied().min().unwrap_or(0))
185-
}
186-
187-
type Item = (T0::Item, T1::Item, T2::Item);
188-
fn pull(
189-
&self,
190-
session: Entity,
191-
world: &mut World,
192-
) -> Result<Self::Item, OperationError> {
193-
let t0 = self.0.pull(session, world)?;
194-
let t1 = self.1.pull(session, world)?;
195-
let t2 = self.2.pull(session, world)?;
196-
Ok((t0, t1, t2))
197-
}
198-
199-
fn listen(
200-
&self,
201-
listener: Entity,
202-
world: &mut World,
203-
) -> OperationResult {
204-
self.0.listen(listener, world)?;
205-
self.1.listen(listener, world)?;
206-
self.2.listen(listener, world)?;
207-
Ok(())
208-
}
209-
210-
fn as_input(&self) -> SmallVec<[Entity; 8]> {
211-
let mut inputs = SmallVec::new();
212-
inputs.extend(self.0.as_input());
213-
inputs.extend(self.1.as_input());
214-
inputs.extend(self.2.as_input());
215-
inputs
216-
}
217-
}
179+
// Implements the `Buffered` trait for all tuples between size 2 and 12
180+
// (inclusive) made of types that implement `Buffered`
181+
all_tuples!(impl_buffered_for_tuple, 2, 12, T);
218182

219183
impl<T: Buffered, const N: usize> Buffered for [T; N] {
220184
fn buffered_count(

src/chain/fork_clone_builder.rs

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*
1616
*/
1717

18+
use bevy::utils::all_tuples;
19+
1820
use crate::{
1921
Chain, UnusedTarget, AddOperation, ForkClone, ForkTargetStorage, Builder,
2022
Output,
@@ -30,65 +32,57 @@ pub trait ForkCloneBuilder<Response> {
3032
) -> Self::Outputs;
3133
}
3234

33-
impl<R, F0, U0, F1, U1> ForkCloneBuilder<R> for (F0, F1)
34-
where
35-
R: 'static + Send + Sync + Clone,
36-
F0: FnOnce(Chain<R>) -> U0,
37-
F1: FnOnce(Chain<R>) -> U1,
38-
{
39-
type Outputs = (U0, U1);
35+
macro_rules! impl_forkclonebuilder_for_tuple {
36+
($(($F:ident, $U:ident)),*) => {
37+
#[allow(non_snake_case)]
38+
impl<R: 'static + Send + Sync + Clone, $($F: FnOnce(Chain<R>) -> $U),*, $($U),*> ForkCloneBuilder<R> for ($($F,)*)
39+
{
40+
type Outputs = ($($U,)*);
41+
fn build_fork_clone(
42+
self,
43+
source: Output<R>,
44+
builder: &mut Builder,
45+
) -> Self::Outputs {
46+
let targets =
47+
[
48+
$(
49+
{
50+
// Variable is only used to make sure this cycle is repeated once
51+
// for each instance of the $T type, but the type itself is not
52+
// used.
53+
#[allow(unused)]
54+
let $F = std::marker::PhantomData::<$F>;
55+
builder.commands.spawn(UnusedTarget).id()
56+
},
57+
)*
58+
];
4059

41-
fn build_fork_clone(
42-
self,
43-
source: Output<R>,
44-
builder: &mut Builder,
45-
) -> Self::Outputs {
46-
let target_0 = builder.commands.spawn(UnusedTarget).id();
47-
let target_1 = builder.commands.spawn(UnusedTarget).id();
48-
49-
builder.commands.add(AddOperation::new(
50-
Some(source.scope()),
51-
source.id(),
52-
ForkClone::<R>::new(
53-
ForkTargetStorage::from_iter([target_0, target_1])
54-
)
55-
));
56-
57-
let u_0 = (self.0)(Chain::new(target_0, builder));
58-
let u_1 = (self.1)(Chain::new(target_1, builder));
59-
(u_0, u_1)
60+
builder.commands.add(AddOperation::new(
61+
Some(source.scope()),
62+
source.id(),
63+
ForkClone::<R>::new(
64+
ForkTargetStorage::from_iter(targets)
65+
)
66+
));
67+
let ($($F,)*) = self;
68+
// The compiler throws a warning when implementing this for
69+
// tuple sizes that wouldn't use the result of the first _idx = _idx + 1
70+
// so we add a leading underscore to suppress the warning
71+
let mut _idx = 0;
72+
(
73+
$(
74+
{
75+
let res = ($F)(Chain::new(targets[_idx], builder));
76+
_idx = _idx + 1;
77+
res
78+
},
79+
)*
80+
)
81+
}
82+
}
6083
}
6184
}
6285

63-
impl<R, F0, U0, F1, U1, F2, U2> ForkCloneBuilder<R> for (F0, F1, F2)
64-
where
65-
R: 'static + Send + Sync + Clone,
66-
F0: FnOnce(Chain<R>) -> U0,
67-
F1: FnOnce(Chain<R>) -> U1,
68-
F2: FnOnce(Chain<R>) -> U2,
69-
{
70-
type Outputs = (U0, U1, U2);
71-
72-
fn build_fork_clone(
73-
self,
74-
source: Output<R>,
75-
builder: &mut Builder,
76-
) -> Self::Outputs {
77-
let target_0 = builder.commands.spawn(UnusedTarget).id();
78-
let target_1 = builder.commands.spawn(UnusedTarget).id();
79-
let target_2 = builder.commands.spawn(UnusedTarget).id();
80-
81-
builder.commands.add(AddOperation::new(
82-
Some(source.scope()),
83-
source.id(),
84-
ForkClone::<R>::new(
85-
ForkTargetStorage::from_iter([target_0, target_1, target_2])
86-
)
87-
));
88-
89-
let u_0 = (self.0)(Chain::new(target_0, builder));
90-
let u_1 = (self.1)(Chain::new(target_1, builder));
91-
let u_2 = (self.2)(Chain::new(target_2, builder));
92-
(u_0, u_1, u_2)
93-
}
94-
}
86+
// Implements the `ForkCloneBUilder` trait for all tuples between size 2 and 12
87+
// (inclusive)
88+
all_tuples!(impl_forkclonebuilder_for_tuple, 2, 12, F, U);

0 commit comments

Comments
 (0)