1#[cfg(not(feature = "experimental-threads"))] #[cfg_attr(published_docs, doc(cfg(not(feature = "experimental-threads"))))]
9use godot_cell::panicking::{InaccessibleGuard, MutGuard, RefGuard};
10
11#[cfg(feature = "experimental-threads")] #[cfg_attr(published_docs, doc(cfg(feature = "experimental-threads")))]
12use godot_cell::blocking::{InaccessibleGuard, MutGuard, RefGuard};
13
14use godot_ffi::out;
15
16use std::fmt::Debug;
17use std::ops::{Deref, DerefMut};
18
19use crate::obj::script::ScriptInstance;
20use crate::obj::{AsDyn, Gd, GodotClass};
21
22#[derive(Debug)]
26pub struct GdRef<'a, T: GodotClass> {
27 guard: RefGuard<'a, T>,
28}
29
30impl<'a, T: GodotClass> GdRef<'a, T> {
31 pub(crate) fn from_guard(guard: RefGuard<'a, T>) -> Self {
32 Self { guard }
33 }
34}
35
36impl<T: GodotClass> Deref for GdRef<'_, T> {
37 type Target = T;
38
39 fn deref(&self) -> &T {
40 &self.guard
41 }
42}
43
44impl<T: GodotClass> Drop for GdRef<'_, T> {
45 fn drop(&mut self) {
46 out!("GdRef drop: {:?}", std::any::type_name::<T>());
47 }
48}
49
50#[derive(Debug)]
58pub struct GdMut<'a, T: GodotClass> {
59 guard: MutGuard<'a, T>,
60}
61
62impl<'a, T: GodotClass> GdMut<'a, T> {
63 pub(crate) fn from_guard(guard: MutGuard<'a, T>) -> Self {
64 Self { guard }
65 }
66}
67
68impl<T: GodotClass> Deref for GdMut<'_, T> {
69 type Target = T;
70
71 fn deref(&self) -> &T {
72 &self.guard
73 }
74}
75
76impl<T: GodotClass> DerefMut for GdMut<'_, T> {
77 fn deref_mut(&mut self) -> &mut T {
78 &mut self.guard
79 }
80}
81
82impl<T: GodotClass> Drop for GdMut<'_, T> {
83 fn drop(&mut self) {
84 out!("GdMut drop: {:?}", std::any::type_name::<T>());
85 }
86}
87
88trait ErasedGuard<'a>: 'a {}
92
93impl<'a, T: GodotClass> ErasedGuard<'a> for GdRef<'a, T> {}
94impl<'a, T: GodotClass> ErasedGuard<'a> for GdMut<'a, T> {}
95
96pub struct DynGdRef<'a, D: ?Sized> {
102 _guard: Box<dyn ErasedGuard<'a>>,
104 cached_ptr: *const D,
105}
106
107impl<'a, D> DynGdRef<'a, D>
108where
109 D: ?Sized + 'static,
110{
111 #[doc(hidden)]
112 pub fn from_guard<T: AsDyn<D>>(guard: GdRef<'a, T>) -> Self {
113 let obj = &*guard;
114 let dyn_obj = obj.dyn_upcast();
115
116 let cached_ptr = std::ptr::addr_of!(*dyn_obj);
119
120 Self {
121 _guard: Box::new(guard),
122 cached_ptr,
123 }
124 }
125}
126
127impl<D: ?Sized> Deref for DynGdRef<'_, D> {
128 type Target = D;
129
130 fn deref(&self) -> &D {
131 unsafe { &*self.cached_ptr }
133 }
134}
135
136impl<D: ?Sized> Drop for DynGdRef<'_, D> {
137 fn drop(&mut self) {
138 out!("DynGdRef drop: {:?}", std::any::type_name::<D>());
139 }
140}
141
142pub struct DynGdMut<'a, D: ?Sized> {
148 _guard: Box<dyn ErasedGuard<'a>>,
150 cached_ptr: *mut D,
151}
152
153impl<'a, D> DynGdMut<'a, D>
154where
155 D: ?Sized + 'static,
156{
157 #[doc(hidden)]
158 pub fn from_guard<T: AsDyn<D>>(mut guard: GdMut<'a, T>) -> Self {
159 let obj = &mut *guard;
160 let dyn_obj = obj.dyn_upcast_mut();
161
162 let cached_ptr = std::ptr::addr_of_mut!(*dyn_obj);
165
166 Self {
167 _guard: Box::new(guard),
168 cached_ptr,
169 }
170 }
171}
172
173impl<D: ?Sized> Deref for DynGdMut<'_, D> {
174 type Target = D;
175
176 fn deref(&self) -> &D {
177 unsafe { &*self.cached_ptr }
179 }
180}
181
182impl<D: ?Sized> DerefMut for DynGdMut<'_, D> {
183 fn deref_mut(&mut self) -> &mut D {
184 unsafe { &mut *self.cached_ptr }
186 }
187}
188
189impl<D: ?Sized> Drop for DynGdMut<'_, D> {
190 fn drop(&mut self) {
191 out!("DynGdMut drop: {:?}", std::any::type_name::<D>());
192 }
193}
194
195macro_rules! make_base_ref {
198 ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
199 #[doc = concat!("This can be used to call methods on the base object of a ", $object_name, " that takes `&self` as the receiver.\n\n")]
202 #[doc = concat!("See [`", stringify!($doc_type), "::base()`](", stringify!($doc_path), "::base()) for usage.")]
203 pub struct $ident<'a, T: $bound> {
204 gd: Gd<T::Base>,
205 _instance: &'a T,
206 }
207
208 impl<'a, T: $bound> $ident<'a, T> {
209 pub(crate) fn new(gd: Gd<T::Base>, instance: &'a T) -> Self {
210 Self {
211 gd,
212 _instance: instance,
213 }
214 }
215 }
216
217 impl<T: $bound> Deref for $ident<'_, T> {
218 type Target = Gd<T::Base>;
219
220 fn deref(&self) -> &Gd<T::Base> {
221 &self.gd
222 }
223 }
224 };
225}
226
227macro_rules! make_base_mut {
230 ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
231 #[doc = concat!("See [`", stringify!($doc_type), "::base_mut()`](", stringify!($doc_path), "::base_mut()) for usage.\n")]
236 pub struct $ident<'a, T: $bound> {
237 gd: Gd<T::Base>,
238 _inaccessible_guard: InaccessibleGuard<'a, T>,
239 }
240
241 impl<'a, T: $bound> $ident<'a, T> {
242 pub(crate) fn new(
243 gd: Gd<T::Base>,
244 inaccessible_guard: InaccessibleGuard<'a, T>,
245 ) -> Self {
246 Self {
247 gd,
248 _inaccessible_guard: inaccessible_guard,
249 }
250 }
251 }
252
253 impl<T: $bound> Deref for $ident<'_, T> {
254 type Target = Gd<T::Base>;
255
256 fn deref(&self) -> &Gd<T::Base> {
257 &self.gd
258 }
259 }
260
261 impl<T: $bound> DerefMut for $ident<'_, T> {
262 fn deref_mut(&mut self) -> &mut Gd<T::Base> {
263 &mut self.gd
264 }
265 }
266 };
267}
268
269make_base_ref!(
270 BaseRef,
271 GodotClass,
272 WithBaseField,
273 super::WithBaseField,
274 "rust object"
275);
276make_base_mut!(
277 BaseMut,
278 GodotClass,
279 WithBaseField,
280 super::WithBaseField,
281 "rust object"
282);
283
284make_base_ref!(
285 ScriptBaseRef,
286 ScriptInstance,
287 SiMut,
288 crate::obj::script::SiMut,
289 "[`ScriptInstance`]"
290);
291make_base_mut!(
292 ScriptBaseMut,
293 ScriptInstance,
294 SiMut,
295 crate::obj::script::SiMut,
296 "['ScriptInstance']"
297);