1use std::fmt::Debug;
9use std::ops::{Deref, DerefMut};
10
11#[cfg(feature = "experimental-threads")] #[cfg_attr(published_docs, doc(cfg(feature = "experimental-threads")))]
12use godot_cell::blocking::{InaccessibleGuard, MutGuard, RefGuard};
13#[cfg(not(feature = "experimental-threads"))] #[cfg_attr(published_docs, doc(cfg(not(feature = "experimental-threads"))))]
14use godot_cell::panicking::{InaccessibleGuard, MutGuard, RefGuard};
15use godot_ffi::out;
16
17use crate::obj::script::ScriptInstance;
18use crate::obj::{AsDyn, BorrowedGd, Gd, GodotClass};
19
20#[derive(Debug)]
25pub struct GdRef<'a, T: GodotClass> {
26 guard: RefGuard<'a, T>,
27}
28
29impl<'a, T: GodotClass> GdRef<'a, T> {
30 pub(crate) fn from_guard(guard: RefGuard<'a, T>) -> Self {
31 crate::task::await_point_inc();
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 crate::task::await_point_dec();
47 out!("GdRef drop: {:?}", std::any::type_name::<T>());
48 }
49}
50
51#[derive(Debug)]
57pub struct GdMut<'a, T: GodotClass> {
58 guard: MutGuard<'a, T>,
59}
60
61impl<'a, T: GodotClass> GdMut<'a, T> {
62 pub(crate) fn from_guard(guard: MutGuard<'a, T>) -> Self {
63 crate::task::await_point_inc();
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 crate::task::await_point_dec();
85 out!("GdMut drop: {:?}", std::any::type_name::<T>());
86 }
87}
88
89trait ErasedGuard<'a>: 'a {}
93
94impl<'a, T: GodotClass> ErasedGuard<'a> for GdRef<'a, T> {}
95impl<'a, T: GodotClass> ErasedGuard<'a> for GdMut<'a, T> {}
96
97pub struct DynGdRef<'a, D: ?Sized> {
103 _guard: Box<dyn ErasedGuard<'a>>,
105 cached_ptr: *const D,
106}
107
108impl<'a, D> DynGdRef<'a, D>
109where
110 D: ?Sized + 'static,
111{
112 pub(crate) 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 pub(crate) fn from_guard<T: AsDyn<D>>(mut guard: GdMut<'a, T>) -> Self {
158 let obj = &mut *guard;
159 let dyn_obj = obj.dyn_upcast_mut();
160
161 let cached_ptr = std::ptr::addr_of_mut!(*dyn_obj);
164
165 Self {
166 _guard: Box::new(guard),
167 cached_ptr,
168 }
169 }
170}
171
172impl<D: ?Sized> Deref for DynGdMut<'_, D> {
173 type Target = D;
174
175 fn deref(&self) -> &D {
176 unsafe { &*self.cached_ptr }
178 }
179}
180
181impl<D: ?Sized> DerefMut for DynGdMut<'_, D> {
182 fn deref_mut(&mut self) -> &mut D {
183 unsafe { &mut *self.cached_ptr }
185 }
186}
187
188impl<D: ?Sized> Drop for DynGdMut<'_, D> {
189 fn drop(&mut self) {
190 out!("DynGdMut drop: {:?}", std::any::type_name::<D>());
191 }
192}
193
194macro_rules! make_base_ref {
197 ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
198 #[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")]
201 #[doc = concat!("See [`", stringify!($doc_type), "::base()`](", stringify!($doc_path), "::base()) for usage.")]
202 pub struct $ident<'a, T: $bound> {
203 borrowed_gd: BorrowedGd<'a, T::Base>,
205 }
206
207 impl<'a, T: $bound> $ident<'a, T> {
208 pub(crate) fn new(borrowed_gd: BorrowedGd<'a, T::Base>) -> Self {
209 Self { borrowed_gd }
210 }
211 }
212
213 impl<T: $bound> Deref for $ident<'_, T> {
214 type Target = Gd<T::Base>;
215
216 fn deref(&self) -> &Gd<T::Base> {
217 &self.borrowed_gd
218 }
219 }
220 };
221}
222
223macro_rules! make_base_mut {
226 ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
227 #[doc = concat!("See [`", stringify!($doc_type), "::base_mut()`](", stringify!($doc_path), "::base_mut()) for usage.\n")]
232 pub struct $ident<'a, T: $bound> {
233 borrowed_gd: BorrowedGd<'a, T::Base>,
234 _inaccessible_guard: InaccessibleGuard<'a, T>,
235 }
236
237 impl<'a, T: $bound> $ident<'a, T> {
238 pub(crate) fn new(
241 borrowed_gd: BorrowedGd<'a, T::Base>,
242 inaccessible_guard: InaccessibleGuard<'a, T>,
243 ) -> Self {
244 Self {
245 borrowed_gd,
246 _inaccessible_guard: inaccessible_guard,
247 }
248 }
249 }
250
251 impl<T: $bound> Deref for $ident<'_, T> {
252 type Target = Gd<T::Base>;
253
254 fn deref(&self) -> &Gd<T::Base> {
255 &self.borrowed_gd
256 }
257 }
258
259 impl<T: $bound> DerefMut for $ident<'_, T> {
260 fn deref_mut(&mut self) -> &mut Gd<T::Base> {
261 &mut self.borrowed_gd
262 }
263 }
264 };
265}
266
267make_base_ref!(
268 BaseRef,
269 GodotClass,
270 WithBaseField,
271 super::WithBaseField,
272 "Rust object"
273);
274make_base_mut!(
275 BaseMut,
276 GodotClass,
277 WithBaseField,
278 super::WithBaseField,
279 "Rust object"
280);
281
282make_base_ref!(
283 ScriptBaseRef,
284 ScriptInstance,
285 SiMut,
286 crate::obj::script::SiMut,
287 "[`ScriptInstance`]"
288);
289make_base_mut!(
290 ScriptBaseMut,
291 ScriptInstance,
292 SiMut,
293 crate::obj::script::SiMut,
294 "[`ScriptInstance`]"
295);