Trait veloren_client::LendJoin
pub unsafe trait LendJoin: for<'next> LendJoinඞType<'next> {
type Value;
type Mask: BitSetLike;
// Required methods
unsafe fn open(self) -> (Self::Mask, Self::Value);
unsafe fn get<'next>(value: &'next mut Self::Value, id: u32) -> Self::T;
// Provided methods
fn lend_join(self) -> JoinLendIter<Self>
where Self: Sized { ... }
fn maybe(self) -> MaybeJoin<Self>
where Self: Sized { ... }
fn is_unconstrained() -> bool { ... }
}
Expand description
Like the Join
trait except this is similar to a lending
iterator
in that only one item can be accessed at once.
The type returned from .lend_join()
,
[JoinLendIter
] does not implement Iterator
like
JoinIter
does. Instead, it provides a
next
method that exclusively borrows the
JoinLendIter
for the lifetime of the returned value.
This limitation allows freedom for more patterns to be soundly implemented.
Thus, LendJoin
acts as the “lowest common denominator” of the
Join
-like traits (i.e. if something can implement Join
it can also
implement LendJoin
).
In particular, Entries
only implements
LendJoin
. As another example,
RestrictedStorage
implements both
Join
and LendJoin
. However, for joining mutably, lend join variant
produces
PairedStorageWriteExclusive
values which have get_other
/get_other_mut
methods that aren’t provided
by PairedStorageWriteShared
.
Finally, these limitations allow providing the [JoinLendIter::get
] method
which can be useful to get a set of components from an entity without
calling get
individually on each storage (see the example in that method’s
docs).
Also see the lend_join
example.
§Safety
The Self::Mask
value returned with the Self::Value
must correspond such
that it is safe to retrieve items from Self::Value
whose presence is
indicated in the mask. As part of this, BitSetLike::iter
must not produce
an iterator that repeats an Index
value if the LendJoin::get
impl relies
on not being called twice with the same Index
.
Required Associated Types§
Required Methods§
unsafe fn open(self) -> (Self::Mask, Self::Value)
unsafe fn open(self) -> (Self::Mask, Self::Value)
Open this join by returning the mask and the storages.
§Safety
This is unsafe because implementations of this trait can permit the
Value
to be mutated independently of the Mask
. If the Mask
does
not correctly report the status of the Value
then illegal memory
access can occur.
Provided Methods§
fn lend_join(self) -> JoinLendIter<Self>where
Self: Sized,
fn lend_join(self) -> JoinLendIter<Self>where
Self: Sized,
Create a joined lending iterator over the contents.
fn maybe(self) -> MaybeJoin<Self>where
Self: Sized,
fn maybe(self) -> MaybeJoin<Self>where
Self: Sized,
Returns a structure that implements Join
/LendJoin
/MaybeJoin
if the
contained T
does and that yields all indices, returning None
for all
missing elements and Some(T)
for found elements.
To join over and optional component mutably this pattern can be used:
(&mut storage).maybe()
.
WARNING: Do not have a join of only MaybeJoin
s. Otherwise the join
will iterate over every single index of the bitset. If you want a
join with all MaybeJoin
s, add an EntitiesRes
to the join as well
to bound the join to all entities that are alive.
struct ExampleSystem;
impl<'a> System<'a> for ExampleSystem {
type SystemData = (
WriteStorage<'a, Pos>,
ReadStorage<'a, Vel>,
);
fn run(&mut self, (mut positions, velocities): Self::SystemData) {
let mut join = (&mut positions, velocities.maybe()).lend_join();
while let Some ((mut position, maybe_velocity)) = join.next() {
if let Some(velocity) = maybe_velocity {
position.x += velocity.x;
position.y += velocity.y;
}
}
}
}
fn main() {
let mut world = World::new();
let mut dispatcher = DispatcherBuilder::new()
.with(ExampleSystem, "example_system", &[])
.build();
dispatcher.setup(&mut world);
let e1 = world.create_entity()
.with(Pos { x: 0, y: 0 })
.with(Vel { x: 5, y: 2 })
.build();
let e2 = world.create_entity()
.with(Pos { x: 0, y: 0 })
.build();
dispatcher.dispatch(&mut world);
let positions = world.read_storage::<Pos>();
assert_eq!(positions.get(e1), Some(&Pos { x: 5, y: 2 }));
assert_eq!(positions.get(e2), Some(&Pos { x: 0, y: 0 }));
}
fn is_unconstrained() -> bool
fn is_unconstrained() -> bool
If this LendJoin
typically returns all indices in the mask, then
iterating over only it or combined with other joins that are also
dangerous will cause the JoinLendIter
to go through all indices which
is usually not what is wanted and will kill performance.