Skip to main content

BoundEntity

Struct BoundEntity 

Source
pub struct BoundEntity<'w> { /* private fields */ }
Expand description

An entity bound to a world reference for fluent, scoped access.

Created by calling EntityHandle::bind() or directly. Provides method chaining without repeatedly passing &World.

§Size

16 bytes (Entity + &World)

§Thread Safety

NOT Send - borrows &World so must stay on the creating thread.

Implementations§

Source§

impl<'w> BoundEntity<'w>

Source

pub const fn new(entity: Entity, world: &'w World) -> Self

Creates a new bound entity.

Source

pub const fn entity(self) -> Entity

Returns the underlying Entity.

Source

pub const fn handle(self) -> EntityHandle

Returns an EntityHandle for storage.

Source

pub fn get<T: Component>(self) -> Option<&'w T>

Gets a component from this entity.

Returns None if the entity doesn’t exist or doesn’t have the component.

Examples found in repository?
examples/mixed_usage.rs (line 74)
73fn find_team_member<'w>(leader: BoundEntity<'w>, target_name: &str) -> Option<BoundEntity<'w>> {
74    leader.get::<Team>().and_then(|team| {
75        team.0.iter().find_map(|h| {
76            let member = h.bind(leader.world());
77            if member.get::<Name>().map(|n| n.0) == Some(target_name) {
78                Some(member)
79            } else {
80                None
81            }
82        })
83    })
84}
85
86fn main() {
87    let mut world = World::new();
88
89    println!("=== Mixed Usage Example ===\n");
90
91    // Build a linked list: a -> b -> c -> d
92    println!("Building linked list: a -> b -> c -> d\n");
93
94    let d = world.spawn((Name("d"), LinkedList { next: None })).id();
95    let c = world
96        .spawn((
97            Name("c"),
98            LinkedList {
99                next: Some(EntityHandle::new(d)),
100            },
101        ))
102        .id();
103    let b = world
104        .spawn((
105            Name("b"),
106            LinkedList {
107                next: Some(EntityHandle::new(c)),
108            },
109        ))
110        .id();
111    let a = world
112        .spawn((
113            Name("a"),
114            LinkedList {
115                next: Some(EntityHandle::new(b)),
116            },
117        ))
118        .id();
119
120    // Store handle for later use (EntityHandle is Send + Sync)
121    let a_handle = EntityHandle::new(a);
122
123    // === BoundEntity approach ===
124    println!("--- BoundEntity Approach (explicit &World) ---");
125
126    let bound = a_handle.bind(&world);
127    let length = count_chain_length_bound(bound);
128    println!("Chain length from 'a': {}", length);
129    assert_eq!(length, 4);
130
131    // Get component with explicit world
132    let name = a_handle.get::<Name>(&world).unwrap().0;
133    println!("Starting node name: {}", name);
134
135    // === EntityPtr approach ===
136    println!("\n--- EntityPtr Approach (ergonomic) ---");
137
138    // No unsafe needed! WorldExt provides ergonomic access
139    let ptr = world.entity_ptr(a_handle.entity()); // Convert handle to ptr
140
141    let length = count_chain_length_ptr(ptr);
142    println!("Chain length from 'a': {}", length);
143    assert_eq!(length, 4);
144
145    // Convert back to handle
146    let back_to_handle = ptr.handle();
147    assert_eq!(back_to_handle.entity(), a_handle.entity());
148    println!("Round-trip handle conversion: OK");
149
150    // === Team example ===
151    println!("\n--- Team Example ---");
152
153    // Create team members
154    let alice = world.spawn((Name("Alice"), Health(100))).id();
155    let bob = world.spawn((Name("Bob"), Health(80))).id();
156    let charlie = world.spawn((Name("Charlie"), Health(120))).id();
157
158    // Create team leader with team
159    let leader = world
160        .spawn((
161            Name("Leader"),
162            Health(150),
163            Team(vec![
164                EntityHandle::new(alice),
165                EntityHandle::new(bob),
166                EntityHandle::new(charlie),
167            ]),
168        ))
169        .id();
170
171    // Calculate total team health using EntityPtr
172    let leader_ptr = world.entity_ptr(leader);
173    let total = team_health(leader_ptr);
174    println!("Total team health: {}", total);
175    println!("  Expected: 150 + 100 + 80 + 120 = 450");
176    assert_eq!(total, 450);
177
178    // Find team member using BoundEntity
179    let leader_bound = EntityHandle::new(leader).bind(&world);
180    let bob_bound = find_team_member(leader_bound, "Bob").unwrap();
181    let bob_health = bob_bound.get::<Health>().unwrap().0;
182    println!("Bob's health: {}", bob_health);
183    assert_eq!(bob_health, 80);
184
185    // === Stale Reference Handling ===
186    println!("\n--- Stale Reference Handling ---");
187
188    let temp = world.spawn((Name("Temporary"), Health(50))).id();
189    let temp_handle = EntityHandle::new(temp);
190
191    // Check it's alive
192    println!("Before despawn:");
193    println!("  is_alive: {}", temp_handle.is_alive(&world));
194    println!("  name: {:?}", temp_handle.get::<Name>(&world).map(|n| n.0));
195    assert!(temp_handle.is_alive(&world));
196
197    // Despawn the entity
198    world.despawn(temp);
199
200    // Handle gracefully returns None
201    println!("After despawn:");
202    println!("  is_alive: {}", temp_handle.is_alive(&world));
203    println!("  name: {:?}", temp_handle.get::<Name>(&world).map(|n| n.0));
204    assert!(!temp_handle.is_alive(&world));
205    assert!(temp_handle.get::<Name>(&world).is_none());
206
207    // === Mixing approaches in computation ===
208    println!("\n--- Mixing Approaches ---");
209
210    // Start with a stored handle
211    let leader_handle = EntityHandle::new(leader);
212
213    // Use BoundEntity for one part of the computation
214    let bound = leader_handle.bind(&world);
215    let leader_name = bound.get::<Name>().unwrap().0;
216
217    // Switch to EntityPtr for another part
218    let ptr = world.entity_ptr(leader_handle.entity());
219    let total_health = team_health(ptr);
220
221    println!(
222        "{}'s team has total health of {}",
223        leader_name, total_health
224    );
225
226    // Can also convert EntityPtr back to BoundEntity's handle
227    let ptr_handle = ptr.handle();
228    let rebound = ptr_handle.bind(&world);
229    assert_eq!(rebound.get::<Name>().unwrap().0, leader_name);
230    println!("Seamless conversion between approaches: OK");
231
232    println!("\nAll assertions passed!");
233}
Source

pub fn has<T: Component>(self) -> bool

Checks if this entity has a component of type T.

Returns false if the entity doesn’t exist.

Source

pub fn is_alive(self) -> bool

Checks if this entity is still alive.

Source

pub fn follow<T, F>(self, f: F) -> Option<BoundEntity<'w>>
where T: Component, F: FnOnce(&T) -> EntityHandle,

Follows a reference component to another entity.

The component must contain an EntityHandle. Use follow_opt for optional references.

Returns None if this entity doesn’t have the component.

Source

pub fn follow_opt<T, F>(self, f: F) -> Option<BoundEntity<'w>>

Follows an optional reference component to another entity.

The extractor function returns Option<EntityHandle>.

Returns None if this entity doesn’t have the component or the reference is None.

Examples found in repository?
examples/mixed_usage.rs (line 36)
32fn count_chain_length_bound(start: BoundEntity) -> usize {
33    let mut count = 1;
34    let mut current = start;
35
36    while let Some(next) = current.follow_opt::<LinkedList, _>(|l| l.next) {
37        count += 1;
38        current = next;
39    }
40
41    count
42}
Source

pub const fn nav(self) -> BoundEntityNav<'w>

Returns a navigator for this entity, enabling HasParent/HasChildren navigation.

This method is always available but navigation methods require the nav-traits feature.

Source

pub const fn world(self) -> &'w World

Returns the world reference.

This allows access to the underlying world for advanced use cases.

Examples found in repository?
examples/mixed_usage.rs (line 76)
73fn find_team_member<'w>(leader: BoundEntity<'w>, target_name: &str) -> Option<BoundEntity<'w>> {
74    leader.get::<Team>().and_then(|team| {
75        team.0.iter().find_map(|h| {
76            let member = h.bind(leader.world());
77            if member.get::<Name>().map(|n| n.0) == Some(target_name) {
78                Some(member)
79            } else {
80                None
81            }
82        })
83    })
84}

Trait Implementations§

Source§

impl<'w> Clone for BoundEntity<'w>

Source§

fn clone(&self) -> BoundEntity<'w>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BoundEntity<'_>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'w> Copy for BoundEntity<'w>

Auto Trait Implementations§

§

impl<'w> Freeze for BoundEntity<'w>

§

impl<'w> !RefUnwindSafe for BoundEntity<'w>

§

impl<'w> Send for BoundEntity<'w>

§

impl<'w> Sync for BoundEntity<'w>

§

impl<'w> Unpin for BoundEntity<'w>

§

impl<'w> !UnwindSafe for BoundEntity<'w>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,