godot_core/obj/
guards.rs

1/*
2 * Copyright (c) godot-rust; Bromeon and contributors.
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 */
7
8use 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/// Immutably/shared bound reference guard for a [`Gd`][crate::obj::Gd] smart pointer.
21///
22/// See [`Gd::bind`][crate::obj::Gd::bind] for usage.
23#[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// TODO Clone or Share
49
50// ----------------------------------------------------------------------------------------------------------------------------------------------
51
52/// Mutably/exclusively bound reference guard for a [`Gd`][crate::obj::Gd] smart pointer.
53///
54/// See [`Gd::bind_mut`][crate::obj::Gd::bind_mut] for usage.
55#[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
86// ----------------------------------------------------------------------------------------------------------------------------------------------
87// Type-erased Gd guards
88
89trait 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
94// ----------------------------------------------------------------------------------------------------------------------------------------------
95
96/// Shared reference guard for a [`DynGd`][crate::obj::DynGd] smart pointer.
97///
98/// Returned by [`DynGd::dyn_bind()`][crate::obj::DynGd::dyn_bind].
99pub struct DynGdRef<'a, D: ?Sized> {
100    /// Never accessed, but is kept alive to ensure dynamic borrow checks are upheld and the object isn't freed.
101    _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        // Note: this pointer is persisted because it is protected by the guard, and the original T instance is pinned during that.
115        // Caching prevents extra indirections; any calls through the dyn guard after the first is simply a Rust dyn-trait virtual call.
116        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        // SAFETY: pointer refers to object that is pinned while guard is alive.
130        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
140// ----------------------------------------------------------------------------------------------------------------------------------------------
141
142/// Mutably/exclusively bound reference guard for a [`DynGd`][crate::obj::DynGd] smart pointer.
143///
144/// Returned by [`DynGd::dyn_bind_mut()`][crate::obj::DynGd::dyn_bind_mut].
145pub struct DynGdMut<'a, D: ?Sized> {
146    /// Never accessed, but is kept alive to ensure dynamic borrow checks are upheld and the object isn't freed.
147    _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        // Note: this pointer is persisted because it is protected by the guard, and the original T instance is pinned during that.
161        // Caching prevents extra indirections; any calls through the dyn guard after the first is simply a Rust dyn-trait virtual call.
162        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        // SAFETY: pointer refers to object that is pinned while guard is alive.
176        unsafe { &*self.cached_ptr }
177    }
178}
179
180impl<D: ?Sized> DerefMut for DynGdMut<'_, D> {
181    fn deref_mut(&mut self) -> &mut D {
182        // SAFETY: pointer refers to object that is pinned while guard is alive.
183        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
193// ----------------------------------------------------------------------------------------------------------------------------------------------
194
195macro_rules! make_base_ref {
196    ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
197        /// Shared reference guard for a [`Base`](crate::obj::Base) pointer.
198        ///
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")]
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
225// ----------------------------------------------------------------------------------------------------------------------------------------------
226
227macro_rules! make_base_mut {
228    ($ident:ident, $bound:ident, $doc_type:ident, $doc_path:path, $object_name:literal) => {
229        /// Mutable/exclusive reference guard for a [`Base`](crate::obj::Base) pointer.
230        ///
231        /// This can be used to call methods on the base object of a Rust object, which takes `&self` or `&mut self` as the receiver.
232        ///
233        #[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);