Skip to content

Commit 4dcf072

Browse files
committed
Move several verifying traits: object -> object::bounds
1 parent b7759fa commit 4dcf072

File tree

6 files changed

+292
-268
lines changed

6 files changed

+292
-268
lines changed

gdnative-core/src/nativescript/class.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ use crate::core_types::{
55
};
66
use crate::nativescript::init::ClassBuilder;
77
use crate::nativescript::{Map, MapMut, MapOwned, UserData};
8+
use crate::object::bounds::{
9+
AssumeSafeLifetime, LifetimeConstraint, RefImplBound, SafeAsRaw, SafeDeref,
10+
};
811
use crate::object::memory::{ManuallyManaged, RefCounted};
912
use crate::object::ownership::{NonUniqueThreadAccess, Shared, ThreadAccess, ThreadLocal, Unique};
10-
use crate::object::{
11-
AssumeSafeLifetime, LifetimeConstraint, QueueFree, RawObject, Ref, RefImplBound, SafeAsRaw,
12-
SafeDeref, TRef,
13-
};
1413
use crate::object::{GodotObject, Instanciable};
14+
use crate::object::{QueueFree, RawObject, Ref, TRef};
1515
use crate::private::{get_api, ReferenceCountedClassPlaceholder};
1616

1717
use super::class_registry;

gdnative-core/src/object/bounds.rs

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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+
6+
use crate::object::memory::*;
7+
use crate::object::ownership::*;
8+
use crate::object::*;
9+
10+
// ----------------------------------------------------------------------------------------------------------------------------------------------
11+
// Implementation for RefKind policy
12+
13+
/// Specialization trait depending on [`RefKind`]. This is an internal interface.
14+
pub trait RefKindSpec: 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<RefKind = Self>>(
21+
ptr: NonNull<sys::godot_object>,
22+
) -> Option<Ref<T, Unique>>
23+
where
24+
Self: RefKind;
25+
26+
#[doc(hidden)]
27+
unsafe fn impl_assume_safe<'a, T: GodotObject<RefKind = Self>>(
28+
this: &Ref<T, Shared>,
29+
) -> TRef<'a, T, Shared>
30+
where
31+
Self: RefKind;
32+
33+
#[doc(hidden)]
34+
unsafe fn impl_assume_unique<T: GodotObject<RefKind = Self>>(
35+
this: Ref<T, Shared>,
36+
) -> Ref<T, Unique>
37+
where
38+
Self: RefKind;
39+
40+
#[doc(hidden)]
41+
unsafe fn maybe_add_ref<T: GodotObject<RefKind = Self>>(raw: &RawObject<T>)
42+
where
43+
Self: RefKind;
44+
45+
#[doc(hidden)]
46+
unsafe fn maybe_init_ref<T: GodotObject<RefKind = Self>>(raw: &RawObject<T>)
47+
where
48+
Self: RefKind;
49+
}
50+
51+
impl RefKindSpec for ManuallyManaged {
52+
type PtrWrapper = Forget;
53+
54+
#[inline(always)]
55+
unsafe fn impl_from_maybe_ref_counted<T: GodotObject<RefKind = 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<RefKind = 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<RefKind = 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<RefKind = Self>>(_raw: &RawObject<T>) {}
97+
#[inline]
98+
unsafe fn maybe_init_ref<T: GodotObject<RefKind = Self>>(_raw: &RawObject<T>) {}
99+
}
100+
101+
impl RefKindSpec for RefCounted {
102+
type PtrWrapper = UnRef;
103+
104+
#[inline(always)]
105+
unsafe fn impl_from_maybe_ref_counted<T: GodotObject<RefKind = 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<RefKind = 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<RefKind = 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<RefKind = Self>>(raw: &RawObject<T>) {
138+
raw.add_ref();
139+
}
140+
141+
#[inline]
142+
unsafe fn maybe_init_ref<T: GodotObject<RefKind = Self>>(raw: &RawObject<T>) {
143+
raw.init_ref_count();
144+
}
145+
}
146+
147+
// ----------------------------------------------------------------------------------------------------------------------------------------------
148+
// Drop strategy
149+
150+
/// Specialization trait for `Drop` behavior.
151+
pub 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)]
163+
pub struct Forget(NonNull<sys::godot_object>);
164+
impl 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.
177+
pub struct UnRef(NonNull<sys::godot_object>);
178+
impl 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+
}
189+
impl 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.
204+
pub trait LifetimeConstraint<Kind: RefKind> {}
205+
206+
/// Type used to check lifetime constraint depending on `RefKind`. Internal interface.
207+
#[doc(hidden)]
208+
pub struct AssumeSafeLifetime<'a, 'r> {
209+
_marker: PhantomData<(&'a (), &'r ())>,
210+
}
211+
212+
impl<'a, 'r> LifetimeConstraint<ManuallyManaged> for AssumeSafeLifetime<'a, 'r> {}
213+
impl<'a, 'r: 'a> LifetimeConstraint<RefCounted> for AssumeSafeLifetime<'a, 'r> {}
214+
215+
// ----------------------------------------------------------------------------------------------------------------------------------------------
216+
// SafeDeref, SafeAsRaw
217+
218+
/// Trait for combinations of `RefKind` and `ThreadAccess` that can be dereferenced safely.
219+
/// This is an internal interface.
220+
pub unsafe trait SafeDeref<Kind: RefKind, Access: ThreadAccess> {
221+
/// Returns a safe reference to the underlying object.
222+
#[doc(hidden)]
223+
fn impl_as_ref<T: GodotObject<RefKind = Kind>>(this: &Ref<T, Access>) -> TRef<'_, T, Access>;
224+
}
225+
226+
/// Trait for persistent `Ref`s that point to valid objects. This is an internal interface.
227+
pub unsafe trait SafeAsRaw<Kind: RefKind, Access: ThreadAccess> {
228+
/// Returns a raw reference to the underlying object.
229+
#[doc(hidden)]
230+
fn impl_as_raw<T: GodotObject<RefKind = Kind>>(this: &Ref<T, Access>) -> &RawObject<T>;
231+
}
232+
233+
// ----------------------------------------------------------------------------------------------------------------------------------------------
234+
// RefImplBound
235+
236+
/// Struct to be used for various `Ref` trait bounds.
237+
pub struct RefImplBound {
238+
_private: (),
239+
}
240+
241+
unsafe impl SafeDeref<ManuallyManaged, Unique> for RefImplBound {
242+
#[inline]
243+
fn impl_as_ref<T: GodotObject<RefKind = ManuallyManaged>>(
244+
this: &Ref<T, Unique>,
245+
) -> TRef<'_, T, Unique> {
246+
unsafe { this.assume_safe_unchecked() }
247+
}
248+
}
249+
250+
unsafe impl<Access: LocalThreadAccess> SafeDeref<RefCounted, Access> for RefImplBound {
251+
#[inline]
252+
fn impl_as_ref<T: GodotObject<RefKind = RefCounted>>(
253+
this: &Ref<T, Access>,
254+
) -> TRef<'_, T, Access> {
255+
unsafe { this.assume_safe_unchecked() }
256+
}
257+
}
258+
259+
unsafe impl SafeAsRaw<ManuallyManaged, Unique> for RefImplBound {
260+
#[inline]
261+
fn impl_as_raw<T: GodotObject<RefKind = ManuallyManaged>>(
262+
this: &Ref<T, Unique>,
263+
) -> &RawObject<T> {
264+
unsafe { this.as_raw_unchecked() }
265+
}
266+
}
267+
268+
unsafe impl<Access: ThreadAccess> SafeAsRaw<RefCounted, Access> for RefImplBound {
269+
#[inline]
270+
fn impl_as_raw<T: GodotObject<RefKind = RefCounted>>(this: &Ref<T, Access>) -> &RawObject<T> {
271+
unsafe { this.as_raw_unchecked() }
272+
}
273+
}

gdnative-core/src/object/memory.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Marker types to express the memory management method of Godot types.
22
3-
use crate::object::RefKindSpec;
3+
use crate::object::bounds::RefKindSpec;
44

55
/// Marker that indicates that a type is manually managed.
66
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
@@ -10,8 +10,7 @@ pub struct ManuallyManaged;
1010
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
1111
pub struct RefCounted;
1212

13-
/// Trait to parameterize over the memory management markers
14-
/// [`ManuallyManaged`](struct.ManuallyManaged.html) and [`RefCounted`](struct.RefCounted.html).
13+
/// Trait to parameterize over the memory management markers [`ManuallyManaged`] and [`RefCounted`].
1514
///
1615
/// This trait is sealed and has no public members.
1716
pub trait RefKind: RefKindSpec + private::Sealed {}
@@ -21,7 +20,6 @@ impl private::Sealed for ManuallyManaged {}
2120

2221
impl RefKind for RefCounted {}
2322
impl private::Sealed for RefCounted {}
24-
2523
mod private {
2624
pub trait Sealed {}
2725
}

0 commit comments

Comments
 (0)