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, Gd, GodotClass};
19
20#[derive(Debug)]
24pub struct GdRef<'a, T: GodotClass> {
25 guard: RefGuard<'a, T>,
26}
27
28impl<'a, T: GodotClass> GdRef<'a, T> {
29 pub(crate) fn from_guard(guard: RefGuard<'a, T>) -> Self {
30 Self { guard }
31 }
32}
33
34impl<T: GodotClass> Deref for GdRef<'_, T> {
35 type Target = T;
36
37 fn deref(&self) -> &T {
38 &self.guard
39 }
40}
41
42impl<T: GodotClass> Drop for GdRef<'_, T> {
43 fn drop(&mut self) {
44 out!("GdRef drop: {:?}", std::any::type_name::<T>());
45 }
46}
47
48#[derive(Debug)]
56pub struct GdMut<'a, T: GodotClass> {
57 guard: MutGuard<'a, T>,
58}
59
60impl<'a, T: GodotClass> GdMut<'a, T> {
61 pub(crate) fn from_guard(guard: MutGuard<'a, T>) -> Self {
62 Self { guard }
63 }
64}
65
66impl<T: GodotClass> Deref for GdMut<'_, T> {
67 type Target = T;
68
69 fn deref(&self) -> &T {
70 &self.guard
71 }
72}
73
74impl<T: GodotClass> DerefMut for GdMut<'_, T> {
75 fn deref_mut(&mut self) -> &mut T {
76 &mut self.guard
77 }
78}
79
80impl<T: GodotClass> Drop for GdMut<'_, T> {
81 fn drop(&mut self) {
82 out!("GdMut drop: {:?}", std::any::type_name::<T>());
83 }
84}
85
86trait ErasedGuard<'a>: 'a {}
90
91impl<'a, T: GodotClass> ErasedGuard<'a> for GdRef<'a, T> {}
92impl<'a, T: GodotClass> ErasedGuard<'a> for GdMut<'a, T> {}
93
94pub struct DynGdRef<'a, D: ?Sized> {
100 _guard: Box<dyn ErasedGuard<'a>>,
102 cached_ptr: *const D,
103}
104
105impl<'a, D> DynGdRef<'a, D>
106where
107 D: ?Sized + 'static,
108{
109 #[doc(hidden)]
110 pub fn from_guard<T: AsDyn<D>>(guard: GdRef<'a, T>) -> Self {
111 let obj = &*guard;
112 let dyn_obj = obj.dyn_upcast();
113
114 let cached_ptr = std::ptr::addr_of!(*dyn_obj);
117
118 Self {
119 _guard: Box::new(guard),
120 cached_ptr,
121 }
122 }
123}
124
125impl<D: ?Sized> Deref for DynGdRef<'_, D> {
126 type Target = D;
127
128 fn deref(&self) -> &D {
129 unsafe { &*self.cached_ptr }
131 }
132}
133
134impl<D: ?Sized> Drop for DynGdRef<'_, D> {
135 fn drop(&mut self) {
136 out!("DynGdRef drop: {:?}", std::any::type_name::<D>());
137 }
138}
139
140pub struct DynGdMut<'a, D: ?Sized> {
146 _guard: Box<dyn ErasedGuard<'a>>,
148 cached_ptr: *mut D,
149}
150
151impl<'a, D> DynGdMut<'a, D>
152where
153 D: ?Sized + 'static,
154{
155 #[doc(hidden)]
156 pub fn from_guard<T: AsDyn<D>>(mut guard: GdMut<'a, T>) -> Self {
157 let obj = &mut *guard;
158 let dyn_obj = obj.dyn_upcast_mut();
159
160 let cached_ptr = std::ptr::addr_of_mut!(*dyn_obj);
163
164 Self {
165 _guard: Box::new(guard),
166 cached_ptr,
167 }
168 }
169}
170
171impl<D: ?Sized> Deref for DynGdMut<'_, D> {
172 type Target = D;
173
174 fn deref(&self) -> &D {
175 unsafe { &*self.cached_ptr }
177 }
178}
179
180impl<D: ?Sized> DerefMut for DynGdMut<'_, D> {
181 fn deref_mut(&mut self) -> &mut D {
182 unsafe { &mut *self.cached_ptr }
184 }
185}
186
187impl<D: ?Sized> Drop for DynGdMut<'_, D> {
188 fn drop(&mut self) {
189 out!("DynGdMut drop: {:?}", std::any::type_name::<D>());
190 }
191}
192
193macro_rules! make_base_ref {
196 ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
197 #[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")]
200 #[doc = concat!("See [`", stringify!($doc_type), "::base()`](", stringify!($doc_path), "::base()) for usage.")]
201 pub struct $ident<'a, T: $bound> {
202 gd: Gd<T::Base>,
203 _instance: &'a T,
204 }
205
206 impl<'a, T: $bound> $ident<'a, T> {
207 pub(crate) fn new(gd: Gd<T::Base>, instance: &'a T) -> Self {
208 Self {
209 gd,
210 _instance: instance,
211 }
212 }
213 }
214
215 impl<T: $bound> Deref for $ident<'_, T> {
216 type Target = Gd<T::Base>;
217
218 fn deref(&self) -> &Gd<T::Base> {
219 &self.gd
220 }
221 }
222 };
223}
224
225macro_rules! make_base_mut {
228 ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
229 #[doc = concat!("See [`", stringify!($doc_type), "::base_mut()`](", stringify!($doc_path), "::base_mut()) for usage.\n")]
234 pub struct $ident<'a, T: $bound> {
235 gd: Gd<T::Base>,
236 _inaccessible_guard: InaccessibleGuard<'a, T>,
237 }
238
239 impl<'a, T: $bound> $ident<'a, T> {
240 pub(crate) fn new(
241 gd: Gd<T::Base>,
242 inaccessible_guard: InaccessibleGuard<'a, T>,
243 ) -> Self {
244 Self {
245 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.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.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);