moonshine_object/rebind.rs
1use std::marker::PhantomData;
2
3use bevy_ecs::prelude::*;
4use bevy_ecs::relationship::Relationship;
5use moonshine_kind::{prelude::*, Any, CastInto};
6
7use crate::{Object, ObjectHierarchy, ObjectRef, ObjectWorldRef};
8
9/// [`Object`] methods related to rebinding and casting.
10///
11/// These methods are available to any [`Object<T>`] or [`ObjectRef<T>`] type.
12pub trait ObjectRebind<T: Kind, R: Relationship>: ContainsInstance<T> + Sized {
13 #[doc(hidden)]
14 type Rebind<U: Kind, S: Relationship>: ObjectHierarchy<U, S>;
15
16 /// Rebinds this object to an [`Instance`] of another [`Kind`].
17 ///
18 /// # Usage
19 ///
20 /// This is useful when you have an [`Object<T>`] and an [`Instance<U>`]
21 /// but you want an [`Object<U>`].
22 ///
23 /// # Safety
24 /// This method assumes the given instance is valid.
25 ///
26 /// # Example
27 /// ```
28 /// # use bevy::prelude::*;
29 /// # use moonshine_object::prelude::*;
30 /// # use moonshine_kind::prelude::*;
31 ///
32 /// #[derive(Component)]
33 /// struct Apple {
34 /// worms: Vec<Instance<Worm>>,
35 /// }
36 ///
37 /// #[derive(Component)]
38 /// struct Worm;
39 ///
40 /// let mut app = App::new();
41 /// // ...
42 /// app.add_systems(Update, find_worms);
43 ///
44 /// fn find_worms(apples: Objects<Apple>, query: Query<&Apple>, worms: Query<&Worm>) {
45 /// for object in apples.iter() {
46 /// let apple = query.get(object.entity()).unwrap();
47 /// for worm in apple.worms.iter() {
48 /// if worms.contains(worm.entity()) {
49 /// // SAFE: We just checked that the worm exists
50 /// handle_worm(unsafe { object.rebind_as(*worm) });
51 /// }
52 /// }
53 /// }
54 /// }
55 ///
56 /// fn handle_worm(worm: Object<Worm>) {
57 /// println!("{:?} found! Gross!", worm);
58 /// }
59 /// ```
60 unsafe fn rebind_as<U: Kind>(&self, instance: Instance<U>) -> Self::Rebind<U, R>;
61
62 /// Rebinds this object to another [`Instance`] of the same [`Kind`].
63 ///
64 /// # Usage
65 ///
66 /// This is useful when you have an [`Object<T>`] and another [`Instance<T>`]
67 /// but you want another [`Object<T>`].
68 ///
69 /// # Safety
70 ///
71 /// This method assumes the given instance is valid.
72 ///
73 /// # Example
74 /// ```
75 /// # use bevy::prelude::*;
76 /// # use moonshine_object::prelude::*;
77 /// # use moonshine_kind::prelude::*;
78 ///
79 /// #[derive(Component)]
80 /// struct Person {
81 /// friends: Vec<Instance<Person>>,
82 /// }
83 ///
84 /// let mut app = App::new();
85 /// // ...
86 /// app.add_systems(Update, update_friends);
87 ///
88 /// fn update_friends(people: Objects<Person>, query: Query<&Person>) {
89 /// for object in people.iter() {
90 /// let person = query.get(object.entity()).unwrap();
91 /// for friend in person.friends.iter() {
92 /// if !people.contains(friend.entity()) {
93 /// continue;
94 /// }
95 /// // SAFE: We just checked that the friend exists
96 /// greet_friend(unsafe { object.rebind(*friend) });
97 /// }
98 /// }
99 /// }
100 ///
101 /// fn greet_friend(friend: Object<Person>) {
102 /// println!("Hello {:?}!", friend);
103 /// }
104 /// ```
105 unsafe fn rebind(&self, instance: Instance<T>) -> Self::Rebind<T, R> {
106 self.rebind_as(instance)
107 }
108
109 /// Rebinds this object to another [`Entity`].
110 ///
111 /// # Usage
112 ///
113 /// This is useful when you have an [`Object<T>`] but you want an [`Object`] for a different [`Entity`].
114 ///
115 /// # Safety
116 ///
117 /// This method assumes the given entity is valid.
118 unsafe fn rebind_any(&self, entity: Entity) -> Self::Rebind<Any, R> {
119 self.rebind_as(Instance::from(entity))
120 }
121
122 /// Casts this object into another of a related [`Kind`].
123 ///
124 /// # Usage
125 ///
126 /// This is useful when you have an [`Object<T>`] but you want an [`Object<U>`]
127 /// where [`Kind`] `T` is safely convertible to `U`.
128 ///
129 /// See [`CastInto`] for more information on kind conversion.
130 ///
131 /// # Example
132 /// ```
133 /// # use bevy::prelude::*;
134 /// # use moonshine_object::prelude::*;
135 /// # use moonshine_kind::prelude::*;
136 ///
137 /// #[derive(Component)]
138 /// struct Apple;
139 ///
140 /// #[derive(Component)]
141 /// struct Orange;
142 ///
143 /// struct Fruit;
144 ///
145 /// impl Kind for Fruit {
146 /// // Apples and Oranges are fruits.
147 /// type Filter = Or<(With<Apple>, With<Orange>)>;
148 /// }
149 ///
150 /// // Define related kinds:
151 /// impl CastInto<Fruit> for Apple {}
152 /// impl CastInto<Fruit> for Orange {}
153 ///
154 /// let mut app = App::new();
155 /// // ...
156 /// app.add_systems(Update, (eat_apples, eat_oranges));
157 ///
158 /// fn eat_apples(apples: Objects<Apple>) {
159 /// for apple in apples.iter() {
160 /// eat_fruit(apple.cast_into());
161 /// println!("Crunchy!")
162 /// }
163 /// }
164 ///
165 /// fn eat_oranges(oranges: Objects<Orange>) {
166 /// for orange in oranges.iter() {
167 /// eat_fruit(orange.cast_into());
168 /// println!("Juicy!")
169 /// }
170 /// }
171 ///
172 /// fn eat_fruit(fruit: Object<Fruit>) {
173 /// println!("{:?} is eaten!", fruit);
174 /// }
175 /// ```
176 fn cast_into<U: Kind>(self) -> Self::Rebind<U, R>
177 where
178 T: CastInto<U>,
179 {
180 // SAFE: T is safely convertible to U, and it is the same entity
181 unsafe { self.rebind_as(self.instance().cast_into()) }
182 }
183
184 /// Casts this object into an [`Object<Any>`].
185 ///
186 /// # Usage
187 ///
188 /// This is useful when you have an [`Object<T>`] but you want an [`Object<Any>`].
189 ///
190 /// All objects of any [`Kind`] can be cast into [`Object<Any>`].
191 fn cast_into_any(self) -> Self::Rebind<Any, R> {
192 // SAFE: T is safely convertible to Any, and it is the same entity
193 unsafe { self.rebind_as(self.instance().cast_into_any()) }
194 }
195
196 /// Casts this object into another of a different [`Kind`].
197 ///
198 /// # Usage
199 ///
200 /// This is useful when you have an [`Object<T>`] but you want an [`Object<U>`] and
201 /// you can guarantee that [`Kind`] `T` is safely convertible to `U`.
202 ///
203 /// # Safety
204 ///
205 /// It is assumed that [`Kind`] `T` is safely convertible to `U`.
206 unsafe fn cast_into_unchecked<U: Kind>(self) -> Self::Rebind<U, R> {
207 self.rebind_as(self.instance().cast_into_unchecked())
208 }
209
210 /// Returns this object as an [`Object<Any>`].
211 fn as_any(&self) -> Self::Rebind<Any, R> {
212 // SAFE: I'm valid if I'm valid.
213 unsafe { self.rebind_any(self.entity()) }
214 }
215}
216
217impl<'w, 's, 'a, T: Kind, R: Relationship> ObjectRebind<T, R> for Object<'w, 's, 'a, T, R> {
218 type Rebind<U: Kind, S: Relationship> = Object<'w, 's, 'a, U, S>;
219
220 unsafe fn rebind_as<U: Kind>(&self, instance: Instance<U>) -> Self::Rebind<U, R> {
221 Object {
222 instance,
223 hierarchy: self.hierarchy,
224 nametags: self.nametags,
225 }
226 }
227}
228
229impl<'w, 's, 'a, T: Kind, R: Relationship> ObjectRebind<T, R> for ObjectRef<'w, 's, 'a, T, R> {
230 type Rebind<U: Kind, S: Relationship> = ObjectRef<'w, 's, 'a, U, S>;
231
232 unsafe fn rebind_as<U: Kind>(&self, instance: Instance<U>) -> Self::Rebind<U, R> {
233 ObjectRef(self.0, self.1.rebind_as(instance))
234 }
235}
236
237impl<'w, T: Kind, R: Relationship> ObjectRebind<T, R> for ObjectWorldRef<'w, T, R> {
238 type Rebind<U: Kind, S: Relationship> = ObjectWorldRef<'w, U, S>;
239
240 unsafe fn rebind_as<U: Kind>(&self, instance: Instance<U>) -> Self::Rebind<U, R> {
241 ObjectWorldRef {
242 instance,
243 world: self.world,
244 _marker: PhantomData,
245 }
246 }
247}