gdnative_core/object/
bounds.rs

1//! Various traits to verify memory policy, ownership policy or lifetime bounds
2//!
3//! The symbols defined in this module are internal and used to enhance type safety.
4//! You typically will not need to work with them.
5
6use crate::object::memory::*;
7use crate::object::ownership::*;
8use crate::object::*;
9
10// ----------------------------------------------------------------------------------------------------------------------------------------------
11// Implementation for Memory policy
12
13/// Specialization trait depending on [`Memory`]. This is an internal interface.
14pub trait MemorySpec: Sized {
15    /// Pointer wrapper that may be `Drop` or not.
16    #[doc(hidden)]
17    type PtrWrapper: PtrWrapper;
18
19    #[doc(hidden)]
20    unsafe fn impl_from_maybe_ref_counted<T: GodotObject<Memory = Self>>(
21        ptr: NonNull<sys::godot_object>,
22    ) -> Option<Ref<T, Unique>>
23    where
24        Self: Memory;
25
26    #[doc(hidden)]
27    unsafe fn impl_assume_safe<'a, T: GodotObject<Memory = Self>>(
28        this: &Ref<T, Shared>,
29    ) -> TRef<'a, T, Shared>
30    where
31        Self: Memory;
32
33    #[doc(hidden)]
34    unsafe fn impl_assume_unique<T: GodotObject<Memory = Self>>(
35        this: Ref<T, Shared>,
36    ) -> Ref<T, Unique>
37    where
38        Self: Memory;
39
40    #[doc(hidden)]
41    unsafe fn maybe_add_ref<T: GodotObject<Memory = Self>>(raw: &RawObject<T>)
42    where
43        Self: Memory;
44
45    #[doc(hidden)]
46    unsafe fn maybe_init_ref<T: GodotObject<Memory = Self>>(raw: &RawObject<T>)
47    where
48        Self: Memory;
49}
50
51impl MemorySpec for ManuallyManaged {
52    type PtrWrapper = Forget;
53
54    #[inline(always)]
55    unsafe fn impl_from_maybe_ref_counted<T: GodotObject<Memory = Self>>(
56        ptr: NonNull<sys::godot_object>,
57    ) -> Option<Ref<T, Unique>> {
58        if RawObject::<ReferenceCountedClassPlaceholder>::try_from_sys_ref(ptr).is_some() {
59            drop(Ref::<ReferenceCountedClassPlaceholder, Unique>::init_from_sys(ptr));
60            None
61        } else {
62            let obj = Ref::<ManuallyManagedClassPlaceholder, Unique>::init_from_sys(ptr);
63
64            if obj.as_raw().is_class::<T>() {
65                Some(obj.cast_unchecked())
66            } else {
67                obj.free();
68                None
69            }
70        }
71    }
72
73    #[inline(always)]
74    unsafe fn impl_assume_safe<'a, T: GodotObject<Memory = Self>>(
75        this: &Ref<T, Shared>,
76    ) -> TRef<'a, T, Shared> {
77        debug_assert!(
78            this.is_instance_sane(),
79            "assume_safe called on an invalid pointer"
80        );
81        this.assume_safe_unchecked()
82    }
83
84    #[inline(always)]
85    unsafe fn impl_assume_unique<T: GodotObject<Memory = Self>>(
86        this: Ref<T, Shared>,
87    ) -> Ref<T, Unique> {
88        debug_assert!(
89            this.is_instance_sane(),
90            "assume_unique called on an invalid pointer"
91        );
92        this.cast_access()
93    }
94
95    #[inline]
96    unsafe fn maybe_add_ref<T: GodotObject<Memory = Self>>(_raw: &RawObject<T>) {}
97    #[inline]
98    unsafe fn maybe_init_ref<T: GodotObject<Memory = Self>>(_raw: &RawObject<T>) {}
99}
100
101impl MemorySpec for RefCounted {
102    type PtrWrapper = UnRef;
103
104    #[inline(always)]
105    unsafe fn impl_from_maybe_ref_counted<T: GodotObject<Memory = Self>>(
106        ptr: NonNull<sys::godot_object>,
107    ) -> Option<Ref<T, Unique>> {
108        if RawObject::<ReferenceCountedClassPlaceholder>::try_from_sys_ref(ptr).is_some() {
109            let obj = Ref::<ReferenceCountedClassPlaceholder, Unique>::init_from_sys(ptr);
110
111            if obj.as_raw().is_class::<T>() {
112                Some(obj.cast_unchecked())
113            } else {
114                None
115            }
116        } else {
117            RawObject::<ManuallyManagedClassPlaceholder>::from_sys_ref_unchecked(ptr).free();
118            None
119        }
120    }
121
122    #[inline(always)]
123    unsafe fn impl_assume_safe<'a, T: GodotObject<Memory = Self>>(
124        this: &Ref<T, Shared>,
125    ) -> TRef<'a, T, Shared> {
126        this.assume_safe_unchecked()
127    }
128
129    #[inline(always)]
130    unsafe fn impl_assume_unique<T: GodotObject<Memory = Self>>(
131        this: Ref<T, Shared>,
132    ) -> Ref<T, Unique> {
133        this.cast_access()
134    }
135
136    #[inline]
137    unsafe fn maybe_add_ref<T: GodotObject<Memory = Self>>(raw: &RawObject<T>) {
138        raw.add_ref();
139    }
140
141    #[inline]
142    unsafe fn maybe_init_ref<T: GodotObject<Memory = Self>>(raw: &RawObject<T>) {
143        raw.init_ref_count();
144    }
145}
146
147// ----------------------------------------------------------------------------------------------------------------------------------------------
148// Drop strategy
149
150/// Specialization trait for `Drop` behavior.
151pub trait PtrWrapper {
152    fn new(ptr: NonNull<sys::godot_object>) -> Self;
153    fn as_non_null(&self) -> NonNull<sys::godot_object>;
154
155    #[inline]
156    fn as_ptr(&self) -> *mut sys::godot_object {
157        self.as_non_null().as_ptr()
158    }
159}
160
161/// Simply releases the held object without deallocating it.
162#[derive(Copy, Clone)]
163pub struct Forget(NonNull<sys::godot_object>);
164impl PtrWrapper for Forget {
165    #[inline]
166    fn new(ptr: NonNull<sys::godot_object>) -> Self {
167        Forget(ptr)
168    }
169
170    #[inline]
171    fn as_non_null(&self) -> NonNull<sys::godot_object> {
172        self.0
173    }
174}
175
176/// Decrements the reference count on the held object, deallocating it if it's the last ref.
177pub struct UnRef(NonNull<sys::godot_object>);
178impl PtrWrapper for UnRef {
179    #[inline]
180    fn new(ptr: NonNull<sys::godot_object>) -> Self {
181        UnRef(ptr)
182    }
183
184    #[inline]
185    fn as_non_null(&self) -> NonNull<sys::godot_object> {
186        self.0
187    }
188}
189impl Drop for UnRef {
190    #[inline]
191    fn drop(&mut self) {
192        unsafe {
193            let raw = RawObject::<ReferenceCountedClassPlaceholder>::from_sys_ref_unchecked(self.0);
194            raw.unref_and_free_if_last();
195        }
196    }
197}
198
199// ----------------------------------------------------------------------------------------------------------------------------------------------
200// assume_safe and lifetime bounds
201
202/// Trait for constraining `assume_safe` lifetimes to the one of `&self` when `T` is
203/// reference-counted. This is an internal interface.
204pub trait LifetimeConstraint<Kind: Memory> {}
205
206/// Type used to check lifetime constraint depending on `Memory`. Internal interface.
207#[doc(hidden)]
208pub struct AssumeSafeLifetime<'a, 'r> {
209    _marker: PhantomData<(&'a (), &'r ())>,
210}
211
212impl<'a, 'r> LifetimeConstraint<ManuallyManaged> for AssumeSafeLifetime<'a, 'r> {}
213impl<'a, 'r: 'a> LifetimeConstraint<RefCounted> for AssumeSafeLifetime<'a, 'r> {}
214
215// ----------------------------------------------------------------------------------------------------------------------------------------------
216// SafeDeref, SafeAsRaw
217
218/// Trait for combinations of `Memory` and `Ownership` that can be dereferenced safely.
219/// This is an internal interface.
220pub unsafe trait SafeDeref<Kind: Memory, Own: Ownership> {
221    /// Returns a safe reference to the underlying object.
222    #[doc(hidden)]
223    fn impl_as_ref<T: GodotObject<Memory = Kind>>(this: &Ref<T, Own>) -> TRef<'_, T, Own>;
224}
225
226/// Trait for persistent `Ref`s that point to valid objects. This is an internal interface.
227pub unsafe trait SafeAsRaw<Kind: Memory, Own: Ownership> {
228    /// Returns a raw reference to the underlying object.
229    #[doc(hidden)]
230    fn impl_as_raw<T: GodotObject<Memory = Kind>>(this: &Ref<T, Own>) -> &RawObject<T>;
231}
232
233// ----------------------------------------------------------------------------------------------------------------------------------------------
234// RefImplBound
235
236/// Struct to be used for various `Ref` trait bounds.
237pub struct RefImplBound {
238    _private: (),
239}
240
241unsafe impl SafeDeref<ManuallyManaged, Unique> for RefImplBound {
242    #[inline]
243    fn impl_as_ref<T: GodotObject<Memory = ManuallyManaged>>(
244        this: &Ref<T, Unique>,
245    ) -> TRef<'_, T, Unique> {
246        unsafe { this.assume_safe_unchecked() }
247    }
248}
249
250unsafe impl<Own: LocalThreadOwnership> SafeDeref<RefCounted, Own> for RefImplBound {
251    #[inline]
252    fn impl_as_ref<T: GodotObject<Memory = RefCounted>>(this: &Ref<T, Own>) -> TRef<'_, T, Own> {
253        unsafe { this.assume_safe_unchecked() }
254    }
255}
256
257unsafe impl SafeAsRaw<ManuallyManaged, Unique> for RefImplBound {
258    #[inline]
259    fn impl_as_raw<T: GodotObject<Memory = ManuallyManaged>>(
260        this: &Ref<T, Unique>,
261    ) -> &RawObject<T> {
262        unsafe { this.as_raw_unchecked() }
263    }
264}
265
266unsafe impl<Own: Ownership> SafeAsRaw<RefCounted, Own> for RefImplBound {
267    #[inline]
268    fn impl_as_raw<T: GodotObject<Memory = RefCounted>>(this: &Ref<T, Own>) -> &RawObject<T> {
269        unsafe { this.as_raw_unchecked() }
270    }
271}